├── LICENSE ├── tests ├── test-all.R └── testthat │ └── test-adobecolor.R ├── .Rbuildignore ├── .gitignore ├── inst └── palettes │ ├── omega_nebula.ase │ ├── herbs_and_spice.ase │ ├── keep_the_change.ase │ └── tomorrow_night_eighties.aco ├── README_files └── figure-markdown_github │ ├── unnamed-chunk-4-1.png │ ├── unnamed-chunk-5-1.png │ ├── unnamed-chunk-6-1.png │ ├── unnamed-chunk-7-1.png │ └── unnamed-chunk-8-1.png ├── NAMESPACE ├── R ├── adobecolor-package.R ├── acov1.R ├── utils.R ├── asev1.R ├── acov2.R └── adobecolor.R ├── man ├── adobecolor.Rd ├── show_palette.Rd ├── read_ase.Rd └── read_aco.Rd ├── adobecolor.Rproj ├── DESCRIPTION ├── src └── float.c ├── README.Rmd └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2015 2 | COPYRIGHT HOLDER: Bob Rudis 3 | -------------------------------------------------------------------------------- /tests/test-all.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | test_check("adobecolor") 3 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.travis\.yml$ 4 | ^.*md$ 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Rproj 5 | src/*.o 6 | src/*.so 7 | src/*.dll 8 | -------------------------------------------------------------------------------- /inst/palettes/omega_nebula.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/inst/palettes/omega_nebula.ase -------------------------------------------------------------------------------- /inst/palettes/herbs_and_spice.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/inst/palettes/herbs_and_spice.ase -------------------------------------------------------------------------------- /inst/palettes/keep_the_change.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/inst/palettes/keep_the_change.ase -------------------------------------------------------------------------------- /inst/palettes/tomorrow_night_eighties.aco: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/inst/palettes/tomorrow_night_eighties.aco -------------------------------------------------------------------------------- /README_files/figure-markdown_github/unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/README_files/figure-markdown_github/unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /README_files/figure-markdown_github/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/README_files/figure-markdown_github/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /README_files/figure-markdown_github/unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/README_files/figure-markdown_github/unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /README_files/figure-markdown_github/unnamed-chunk-7-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/README_files/figure-markdown_github/unnamed-chunk-7-1.png -------------------------------------------------------------------------------- /README_files/figure-markdown_github/unnamed-chunk-8-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/adobecolor/HEAD/README_files/figure-markdown_github/unnamed-chunk-8-1.png -------------------------------------------------------------------------------- /tests/testthat/test-adobecolor.R: -------------------------------------------------------------------------------- 1 | context("basic functionality") 2 | test_that("we can do something", { 3 | 4 | #expect_that(some_function(), is_a("data.frame")) 5 | 6 | }) 7 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2 (4.1.0): do not edit by hand 2 | 3 | export(read_aco) 4 | export(read_ase) 5 | export(show_palette) 6 | import(httr) 7 | import(pack) 8 | useDynLib(adobecolor,r_floatraw2numeric) 9 | -------------------------------------------------------------------------------- /R/adobecolor-package.R: -------------------------------------------------------------------------------- 1 | #' A package to read (and eventually write) Adobe color/swatch files (.aco / .ase) 2 | #' @name adobecolor 3 | #' @docType package 4 | #' @author Bob Rudis (@@hrbrmstr) 5 | #' @import pack httr 6 | NULL 7 | -------------------------------------------------------------------------------- /man/adobecolor.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/adobecolor-package.R 3 | \docType{package} 4 | \name{adobecolor} 5 | \alias{adobecolor} 6 | \alias{adobecolor-package} 7 | \title{A package to read (and eventually write) Adobe color/swatch files (.aco / .ase)} 8 | \description{ 9 | A package to read (and eventually write) Adobe color/swatch files (.aco / .ase) 10 | } 11 | \author{ 12 | Bob Rudis (@hrbrmstr) 13 | } 14 | 15 | -------------------------------------------------------------------------------- /adobecolor.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageBuildArgs: --resave-data 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: adobecolor 2 | Type: Package 3 | Title: A package to read (and eventually write) Adobe color swatch files (.aco / .ase) 4 | Version: 0.2 5 | Date: 2015-03-29 6 | Author: Bob Rudis (@hrbrmstr) 7 | Maintainer: Bob Rudis 8 | Description: A package to read (and eventually write) Adobe color swatch files (.aco / .ase). Omega Nebula palette CC-BY-SA davidgav 9 | URL: http://github.com/hrbrmstr/adobecolor 10 | BugReports: https://github.com/hrbrmstr/adobecolor/issues 11 | License: MIT + file LICENSE 12 | Imports: 13 | httr 14 | Suggests: 15 | testthat 16 | Depends: 17 | R (>= 3.0.0), 18 | pack 19 | -------------------------------------------------------------------------------- /man/show_palette.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/adobecolor.R 3 | \name{show_palette} 4 | \alias{show_palette} 5 | \title{Display a color palette} 6 | \usage{ 7 | show_palette(palette) 8 | } 9 | \arguments{ 10 | \item{palette}{vector of character hex RGB values} 11 | } 12 | \description{ 13 | Given a character vector (hex RGB values), display palette in graphics window. 14 | } 15 | \examples{ 16 | \dontrun{ 17 | # built in palette 18 | keep_the_change <- read_ase(system.file("palettes", "keep_the_change.ase", package="adobecolor")) 19 | print(keep_the_change) 20 | show_palette(keep_the_change) 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/float.c: -------------------------------------------------------------------------------- 1 | /** =========================================================================== 2 | ** R-Package: rdyncall 3 | ** File: src/rutils_float.c 4 | ** Description: Utility functions for handling C float data types. 5 | **/ 6 | 7 | #define USE_RINTERNALS 8 | #include 9 | #include 10 | 11 | /* Float utils */ 12 | 13 | SEXP r_as_floatraw(SEXP x) { 14 | SEXP ans; 15 | int i, n; 16 | double *dp; 17 | float *fp; 18 | 19 | dp = (double*) REAL(x); 20 | 21 | n = LENGTH(x); 22 | if (n < 1) { 23 | error("length of x should be >= 1"); 24 | return R_NilValue; 25 | } 26 | 27 | ans = PROTECT( Rf_allocVector(RAWSXP, sizeof(float)*n) ); 28 | 29 | fp = (float*) RAW(ans); 30 | 31 | for(i = 0 ; i < n ; ++i ) 32 | fp[i] = (float) dp[i]; 33 | 34 | UNPROTECT(1); 35 | return ans; 36 | } 37 | 38 | SEXP r_floatraw2numeric(SEXP x) { 39 | SEXP ans; 40 | int i, n; 41 | float *fp; 42 | double *dp; 43 | 44 | fp = (float*) RAW(x); 45 | 46 | n = LENGTH(x) / sizeof(float); 47 | ans = PROTECT( Rf_allocVector(REALSXP, n) ); 48 | 49 | dp = (double*) REAL(ans); 50 | 51 | for(i = 0 ; i < n ; ++i ) 52 | dp[i] = (double) fp[i]; 53 | 54 | UNPROTECT(1); 55 | return ans; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /R/acov1.R: -------------------------------------------------------------------------------- 1 | decode_aco_v1 <- function(aco, n_colors) { 2 | 3 | palette <- sapply(1:n_colors, function(i) { 4 | 5 | start <- 5 + (10*(i-1)) 6 | 7 | colorspace <- b2i(aco[start:(start+1)]) 8 | 9 | start <- start + 2 10 | w <- b2i(aco[start:(start+1)]) 11 | 12 | start <- start + 2 13 | x <- b2i(aco[start:(start+1)]) 14 | 15 | start <- start + 2 16 | y <- b2i(aco[start:(start+1)]) 17 | 18 | start <- start + 2 19 | z <- b2i(aco[start:(start+1)]) 20 | 21 | color <- "" 22 | 23 | if (colorspace == 0) { # RGB 24 | color <- rgb(w, x, y, maxColorValue=65535) 25 | } else if (colorspace == 1) { # HSB 26 | color <- hsv((w/182.04)/360, ((x/655.35)/360), ((y/655.35)/360)) 27 | } else if (colorspace == 2) { # CMYK 28 | color <- cmyk((100-w/655.35), (100-x/655.35), (100-y/655.35), (100-z/655.35)) 29 | } else if (colorspace == 7) { # Lab 30 | message("Lab not supported yet") 31 | color <- NA 32 | } else if (colorspace == 8) { # Grayscale 33 | message("Greyscale not supported yet") 34 | color <- w/39.0625 35 | } else if (colorspace == 9) { # Wide CMYK 36 | color <- cmyk(w/100, x/100, y/100, z/100) 37 | } else { 38 | message("Unknown") 39 | color <- NA 40 | } 41 | 42 | return(color) 43 | 44 | }) 45 | 46 | return(palette) 47 | 48 | } 49 | -------------------------------------------------------------------------------- /man/read_ase.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/adobecolor.R 3 | \name{read_ase} 4 | \alias{read_ase} 5 | \title{Read colors from Adobe Swatch Exchange (ASE) files} 6 | \usage{ 7 | read_ase(path, use_names = TRUE, .verbose = FALSE) 8 | } 9 | \arguments{ 10 | \item{path}{partial or full file path or URL to an ASE file} 11 | 12 | \item{use_names}{add color names to the vector (defaults to \code{TRUE}). See NOTE} 13 | 14 | \item{.verbose}{show extra information about ASE file processing} 15 | } 16 | \description{ 17 | Given a path or URL to an \code{.ase} file, this function will return 18 | a named character vector (if color names are present) of hex RGB colors. 19 | } 20 | \note{ 21 | When using named color palettes in a \code{ggplot2} \code{scale_} context, you 22 | must \code{unname} them or set \code{use_names} to \code{FALSE}. 23 | Not sure if this is a bug or a deliberate feature in ggplot2. Also, Neither Lab nor 24 | greyscale colors are supported. 25 | } 26 | \examples{ 27 | \dontrun{ 28 | # built in palette 29 | keep_the_change <- read_ase(system.file("palettes", "keep_the_change.ase", package="adobecolor")) 30 | print(keep_the_change) 31 | show_palette(keep_the_change) 32 | 33 | # from the internet directly 34 | metal <- read_ase("https://github.com/picwellwisher12pk/en_us/raw/master/Swatches/Metal.ase") 35 | print(metal) 36 | show_palette(metal) 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /man/read_aco.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.0): do not edit by hand 2 | % Please edit documentation in R/adobecolor.R 3 | \name{read_aco} 4 | \alias{read_aco} 5 | \title{Read colors from Adobe Color (ACO) files} 6 | \usage{ 7 | read_aco(path, use_names = TRUE, .verbose = FALSE) 8 | } 9 | \arguments{ 10 | \item{path}{partial or full file path or URL to an ACO file} 11 | 12 | \item{use_names}{add color names to the vector (defaults to \code{TRUE}). See NOTE} 13 | 14 | \item{.verbose}{show extra information about ACO file processing#'} 15 | } 16 | \description{ 17 | Given a path or URL to an \code{.aco} file, this function will return 18 | a named character vector (if color names are present) of hex RGB colors. 19 | } 20 | \note{ 21 | When using named color palettes in a \code{ggplot2} \code{scale_} context, you 22 | must \code{unname} them or set \code{use_names} to \code{FALSE}. 23 | Not sure if this is a bug or a deliberate feature in ggplot2. Also, Neither Lab nor 24 | greyscale colors are supported. 25 | } 26 | \examples{ 27 | \dontrun{ 28 | # built in palette 29 | eighties <- read_ase(system.file("palettes", "tomorrow_night_eighties.aco", package="adobecolor")) 30 | print(eighties) 31 | show_palette(eighties) 32 | 33 | # from the internet directly 34 | url <- "https://github.com/chriskempson/tomorrow-theme/raw/master/Photoshop\%20Color\%20Swatchesdi/Tomorrow\%20Night.aco" 35 | tomorrow_night <- read_ase(url) 36 | print(tomorrow_night) 37 | show_palette(tomorrow_night) 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | cmyk <- function(C, M, Y, K) { 2 | 3 | C <- C / 100.0 4 | M <- M / 100.0 5 | Y <- Y / 100.0 6 | K <- K / 100.0 7 | 8 | n.c <- (C * (1-K) + K) 9 | n.m <- (M * (1-K) + K) 10 | n.y <- (Y * (1-K) + K) 11 | 12 | r.col <- ceiling(255 * (1-n.c)) 13 | g.col <- ceiling(255 * (1-n.m)) 14 | b.col <- ceiling(255 * (1-n.y)) 15 | 16 | return(sprintf("#%02s%02s%02s", as.hexmode(r.col), 17 | as.hexmode(g.col), as.hexmode(b.col))) 18 | 19 | } 20 | 21 | b2i <- function(two_bytes) { 22 | as.numeric(unpack("v", two_bytes[2:1])) 23 | } 24 | 25 | b2li <- function(four_bytes) { 26 | as.numeric(unpack("V", four_bytes[c(4,3,2,1)])) 27 | } 28 | 29 | b2f <- function(four_bytes) { 30 | floatraw2numeric(four_bytes[c(4,3,2,1)]) 31 | } 32 | 33 | is_url <-function(x) { grepl("www.|http:|https:", x) } 34 | 35 | #' @useDynLib adobecolor r_floatraw2numeric 36 | floatraw2numeric <- function(x) { 37 | stopifnot(is.raw(x)) 38 | stopifnot(length(x) >= 4) 39 | .Call(r_floatraw2numeric, x) 40 | } 41 | 42 | # #' @export 43 | # lab2rgb <- function(L, A, B) { 44 | # 45 | # R <- G <- B <- 0 46 | # 47 | # vY <- (L + 16.0) / 116.0 48 | # vX <- (A / 500.0) + vY 49 | # vZ <- vY - (B / 200.0) 50 | # 51 | # if (vY^3 > 0.008856) { vY <- vY^3 } else { vY <- ( vY - 16.0 / 116.0 ) / 7.787 } 52 | # if (vX^3 > 0.008856) { vX <- vX^3 } else { vX <- ( vX - 16.0 / 116.0 ) / 7.787 } 53 | # if (vZ^3 > 0.008856) { vZ <- vZ^3 } else { vZ <- ( vZ - 16.0 / 116.0 ) / 7.787 } 54 | # 55 | # X <- 95.047 * vX 56 | # Y <- 100.000 * vY 57 | # Z <- 108.883 * vZ 58 | # 59 | # vX <- X / 100.0 60 | # vY <- Y / 100.0 61 | # vZ <- Z / 100.0 62 | # 63 | # vR <- (vX * 3.2406) + (vY * -1.5372) + (vZ * -0.4986) 64 | # vG <- (vX * -0.9689) + (vY * 1.8758) + (vZ * 0.0415) 65 | # vB <- (vX * 0.0557) + (vY * -0.2040) + (vZ * 1.0570) 66 | # 67 | # if (vR > 0.0031308) { vR <- (1.055 * vR^(1/2.4)) - 0.55 } else { vR <- 12.92 * vR } 68 | # if (vG > 0.0031308) { vG <- (1.055 * vG^(1/2.4)) - 0.55 } else { vG <- 12.92 * vG } 69 | # if (vB > 0.0031308) { vB <- (1.055 * vB^(1/2.4)) - 0.55 } else { vB <- 12.92 * vB } 70 | # 71 | # message(vR, " ", vG, " ", vB) 72 | # 73 | # return(rgb(abs(vR), abs(vG), abs(vB))) 74 | # # 75 | # # R <- vR * 255.0 76 | # # G <- vG * 255.0 77 | # # B <- vB * 255.0 78 | # 79 | # } -------------------------------------------------------------------------------- /R/asev1.R: -------------------------------------------------------------------------------- 1 | GROUP_START <- 0xc001 2 | GROUP_END <- 0xc002 3 | COLOR_START <- 0x0001 4 | 5 | decode_ase <- function(ase, block_count) { 6 | 7 | con <- rawConnection(ase) 8 | on.exit(close(con)) 9 | 10 | tmp <- readBin(con, "raw", 12, endian="big") 11 | 12 | val <- sapply(1:block_count, function(i) { 13 | parse_block(con) 14 | }) 15 | 16 | val[!is.na(val)] 17 | 18 | } 19 | 20 | parse_block <- function(con) { 21 | 22 | block_type <- try(readBin(con, "raw", 2, endian="big")) 23 | 24 | if (!inherits(block_type, "try-error")) { 25 | 26 | block_type <- b2i(block_type) 27 | 28 | if (block_type == COLOR_START) { 29 | 30 | block_length <- b2li(readBin(con, "raw", 4, endian="big")) 31 | data <- readBin(con, "raw", block_length, endian="big") 32 | 33 | label_length <- b2i(data[1:2]) * 2 34 | label <- data[3:(3+label_length)] 35 | label <- rawToChar(label[1:(length(label)-1)], multiple=TRUE) 36 | label <- paste(label, sep="", collapse="") 37 | 38 | color_data <- try(data[3+label_length:length(data)]) 39 | 40 | if (!inherits(color_data, "try-error")) { 41 | 42 | color_mode <- gsub("\ +$", "", rawToChar(color_data[1:4])) 43 | 44 | color <- NA 45 | 46 | if (color_mode == "RGB") { 47 | 48 | R <- b2f(color_data[5:8]) 49 | G <- b2f(color_data[9:12]) 50 | B <- b2f(color_data[13:16]) 51 | color <- as.character(rgb(R, G, B)) 52 | 53 | } else if (color_mode == "CMYK") { 54 | 55 | C <- b2f(color_data[5:8]) 56 | M <- b2f(color_data[9:12]) 57 | Y <- b2f(color_data[13:16]) 58 | K <- b2f(color_data[17:20]) 59 | color <- as.character(cmyk(C*100, M*100, Y*100, K*100)) 60 | 61 | } else if (color_mode == "LAB") { 62 | 63 | message("LAB") 64 | 65 | L <- b2f(color_data[5:8]) 66 | A <- b2f(color_data[9:12]) 67 | B <- b2f(color_data[13:16]) 68 | color <- list(L, A, B) 69 | 70 | } else if (color_mode == "Grey") { 71 | 72 | message("Grey") 73 | 74 | G <- b2f(color_data[5:8]) 75 | color <- G 76 | 77 | } 78 | 79 | color_type <- b2i(color_data[(length(color_data)-1):length(color_data)]) 80 | 81 | names(color) <- label 82 | 83 | return(color) 84 | 85 | } 86 | 87 | } else if (block_type == GROUP_START) { 88 | 89 | block_length <- b2li(readBin(con, "raw", 4, endian="big")) 90 | data <- readBin(con, "raw", block_length, endian="big") 91 | 92 | label_length <- b2i(data[1:2]) * 2 93 | label <- data[3:(3+label_length)] 94 | label <- rawToChar(label[1:(length(label)-1)], multiple=TRUE) 95 | label <- paste(label, sep="", collapse="") 96 | 97 | color_data <- try(data[3+label_length:length(data)]) 98 | 99 | return(NA) 100 | 101 | } else if (block_type == GROUP_END) { 102 | tmp <- readBin(con, "raw", 4, endian="big") 103 | return(NA) 104 | } else { 105 | message("Invalid block type [", block_type, "]. Possible corrupted ASE file") 106 | return(NA) 107 | } 108 | 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /R/acov2.R: -------------------------------------------------------------------------------- 1 | decode_aco_v2 <- function(aco, n_colors) { 2 | 3 | con <- rawConnection(aco) 4 | on.exit(close(con)) 5 | 6 | tmp <- readBin(con, "raw", 4, endian="big") 7 | 8 | val <- sapply(1:n_colors, function(i) { 9 | parse_aco_v2_block(con) 10 | }) 11 | 12 | val[!is.na(val)] 13 | 14 | } 15 | 16 | parse_aco_v2_block <- function(con) { 17 | 18 | colorspace <- b2i(readBin(con, "raw", 2, endian="big")) 19 | 20 | color <- NA 21 | 22 | if (colorspace == 0) { # RGB 23 | 24 | w <- b2i(readBin(con, "raw", 2, endian="big")) 25 | x <- b2i(readBin(con, "raw", 2, endian="big")) 26 | y <- b2i(readBin(con, "raw", 2, endian="big")) 27 | z <- b2i(readBin(con, "raw", 2, endian="big")) 28 | 29 | color <- rgb(w, x, y, maxColorValue=65535) 30 | 31 | } else if (colorspace == 1) { # HSB 32 | 33 | w <- b2i(readBin(con, "raw", 2, endian="big")) 34 | x <- b2i(readBin(con, "raw", 2, endian="big")) 35 | y <- b2i(readBin(con, "raw", 2, endian="big")) 36 | z <- b2i(readBin(con, "raw", 2, endian="big")) 37 | 38 | color <- hsv((w/182.04)/360, ((x/655.35)/360), ((y/655.35)/360)) 39 | 40 | } else if (colorspace == 2) { # CMYK 41 | 42 | w <- b2i(readBin(con, "raw", 2, endian="big")) 43 | x <- b2i(readBin(con, "raw", 2, endian="big")) 44 | y <- b2i(readBin(con, "raw", 2, endian="big")) 45 | z <- b2i(readBin(con, "raw", 2, endian="big")) 46 | 47 | color <- cmyk((100-w/655.35), (100-x/655.35), (100-y/655.35), (100-z/655.35)) 48 | 49 | } else if (colorspace == 7) { # Lab 50 | 51 | w <- b2i(readBin(con, "raw", 2, endian="big")) 52 | x <- readBin(con, "integer", 1, 2, signed=TRUE, endian="big") 53 | y <- readBin(con, "integer", 1, 2, signed=TRUE, endian="big") 54 | z <- b2i(readBin(con, "raw", 2, endian="big")) 55 | 56 | # color <- LAB(w/100, x/100, y/100) 57 | 58 | color <- NA 59 | 60 | message("Lab colors not supported yet") 61 | 62 | } else if (colorspace == 8) { # Grayscale 63 | 64 | w <- b2i(readBin(con, "raw", 2, endian="big")) 65 | x <- b2i(readBin(con, "raw", 2, endian="big")) 66 | y <- b2i(readBin(con, "raw", 2, endian="big")) 67 | z <- b2i(readBin(con, "raw", 2, endian="big")) 68 | 69 | message("Grayscale not supported yet") 70 | 71 | color <- w/39.0625 72 | 73 | } else if (colorspace == 9) { # Wide CMYK 74 | 75 | w <- b2i(readBin(con, "raw", 2, endian="big")) 76 | x <- b2i(readBin(con, "raw", 2, endian="big")) 77 | y <- b2i(readBin(con, "raw", 2, endian="big")) 78 | z <- b2i(readBin(con, "raw", 2, endian="big")) 79 | 80 | color <- cmyk(w/100, x/100, y/100, z/100) 81 | 82 | } else { 83 | 84 | w <- b2i(readBin(con, "raw", 2, endian="big")) 85 | x <- b2i(readBin(con, "raw", 2, endian="big")) 86 | y <- b2i(readBin(con, "raw", 2, endian="big")) 87 | z <- b2i(readBin(con, "raw", 2, endian="big")) 88 | 89 | message("Color format unknown") 90 | 91 | color <- NA 92 | } 93 | 94 | tmp <- readBin(con, "raw", 2, endian="big") 95 | 96 | label <- "" 97 | label_length <- b2i(readBin(con, "raw", 2, endian="big")) * 2 98 | if (label_length > 0) { 99 | label <- readBin(con, "raw", label_length-2, endian="big") 100 | label <- rawToChar(label[1:length(label)], multiple=TRUE) 101 | label <- paste(label, sep="", collapse="") 102 | } 103 | 104 | names(color) <- label 105 | 106 | tmp <- readBin(con, "raw", 2, endian="big") 107 | 108 | return(color) 109 | 110 | } -------------------------------------------------------------------------------- /R/adobecolor.R: -------------------------------------------------------------------------------- 1 | #' Read colors from Adobe Color (ACO) files 2 | #' 3 | #' Given a path or URL to an \code{.aco} file, this function will return 4 | #' a named character vector (if color names are present) of hex RGB colors. 5 | #' 6 | #' @param path partial or full file path or URL to an ACO file 7 | #' @param use_names add color names to the vector (defaults to \code{TRUE}). See NOTE 8 | #' @param .verbose show extra information about ACO file processing#' @export 9 | #' @note When using named color palettes in a \code{ggplot2} \code{scale_} context, you 10 | #' must \code{unname} them or set \code{use_names} to \code{FALSE}. 11 | #' Not sure if this is a bug or a deliberate feature in ggplot2. Also, Neither Lab nor 12 | #' greyscale colors are supported. 13 | #' @export 14 | #' @examples \dontrun{ 15 | #' # built in palette 16 | #' eighties <- read_ase(system.file("palettes", "tomorrow_night_eighties.aco", package="adobecolor")) 17 | #' print(eighties) 18 | #' show_palette(eighties) 19 | #' 20 | #' # from the internet directly 21 | #' url <- "https://github.com/chriskempson/tomorrow-theme/raw/master/Photoshop%20Color%20Swatchesdi/Tomorrow%20Night.aco" 22 | #' tomorrow_night <- read_ase(url) 23 | #' print(tomorrow_night) 24 | #' show_palette(tomorrow_night) 25 | #' } 26 | read_aco <- function(path, use_names=TRUE, .verbose=FALSE) { 27 | 28 | if (is_url(path)) { 29 | tf <- tempfile() 30 | stop_for_status(GET(path, write_disk(tf))) 31 | path <- tf 32 | } 33 | 34 | aco <- readBin(path.expand(path), "raw", 35 | file.info(path.expand(path))$size, endian="big") 36 | 37 | version <- unpack("v", aco[2:1])[[1]] 38 | n_colors <- unpack("v", aco[4:3])[[1]] 39 | 40 | if (.verbose) { 41 | message("ACO Version: ", version) 42 | message("# Colors: " , n_colors) 43 | } 44 | 45 | pal <- NULL 46 | 47 | if (version == 1) { 48 | pal <- decode_aco_v1(aco, n_colors) 49 | } else { 50 | pal <- decode_aco_v2(aco, n_colors) 51 | } 52 | 53 | if (!use_names) { pal <- unname(pal) } 54 | 55 | pal 56 | 57 | } 58 | 59 | #' Read colors from Adobe Swatch Exchange (ASE) files 60 | #' 61 | #' Given a path or URL to an \code{.ase} file, this function will return 62 | #' a named character vector (if color names are present) of hex RGB colors. 63 | #' 64 | #' @param path partial or full file path or URL to an ASE file 65 | #' @param use_names add color names to the vector (defaults to \code{TRUE}). See NOTE 66 | #' @param .verbose show extra information about ASE file processing 67 | #' @note When using named color palettes in a \code{ggplot2} \code{scale_} context, you 68 | #' must \code{unname} them or set \code{use_names} to \code{FALSE}. 69 | #' Not sure if this is a bug or a deliberate feature in ggplot2. Also, Neither Lab nor 70 | #' greyscale colors are supported. 71 | #' @export 72 | #' @examples \dontrun{ 73 | #' # built in palette 74 | #' keep_the_change <- read_ase(system.file("palettes", "keep_the_change.ase", package="adobecolor")) 75 | #' print(keep_the_change) 76 | #' show_palette(keep_the_change) 77 | #' 78 | #' # from the internet directly 79 | #' metal <- read_ase("https://github.com/picwellwisher12pk/en_us/raw/master/Swatches/Metal.ase") 80 | #' print(metal) 81 | #' show_palette(metal) 82 | #' } 83 | read_ase <- function(path, use_names=TRUE, .verbose=FALSE) { 84 | 85 | if (is_url(path)) { 86 | tf <- tempfile() 87 | stop_for_status(GET(path, write_disk(tf))) 88 | path <- tf 89 | } 90 | 91 | ase <- readBin(path, "raw", 92 | file.info(path.expand(path))$size, endian="big") 93 | 94 | if (unpack("A4", ase[1:4])[[1]] != "ASEF") { 95 | message("Not a valid ASE file") 96 | stop() 97 | } 98 | 99 | version <- sprintf("%d.%d", b2i(ase[5:6]), b2i(ase[7:8])) 100 | 101 | block_count <- b2li(ase[9:12]) 102 | 103 | if (.verbose) { 104 | message("ASE Version: ", version) 105 | message("Block count: ", block_count) 106 | } 107 | 108 | pal <- decode_ase(ase, block_count) 109 | 110 | if (!use_names) { pal <- unname(pal) } 111 | pal 112 | 113 | } 114 | 115 | #' Display a color palette 116 | #' 117 | #' Given a character vector (hex RGB values), display palette in graphics window. 118 | #' 119 | #' @param palette vector of character hex RGB values 120 | #' @export 121 | #' @examples \dontrun{ 122 | #' # built in palette 123 | #' keep_the_change <- read_ase(system.file("palettes", "keep_the_change.ase", package="adobecolor")) 124 | #' print(keep_the_change) 125 | #' show_palette(keep_the_change) 126 | #' } 127 | show_palette <- function(palette) { 128 | n <- length(palette) 129 | if (length(palette > 0)) { 130 | image(1:n, 1, as.matrix(1:n), col = palette, 131 | xlab = "", ylab = "", xaxt = "n", yaxt = "n", 132 | bty = "n") 133 | 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "README" 3 | author: "Bob Rudis" 4 | date: March 20, 2015 5 | output: 6 | md_document: 7 | variant: markdown_github 8 | --- 9 | 10 | [![Build Status](https://travis-ci.org/hrbrmstr/adobecolor.svg)](https://travis-ci.org/hrbrmstr/adobecolor) 11 | 12 | adobecolor is a package to read (and eventually write) Adobe color (ASE/ACO) files 13 | 14 | In _Envisioning Information_, Edward Tufte says _"…avoiding catastrophe becomes the first 15 | principle in bringing color to information: Above all, do no harm."_ R users gain a quick upper hand 16 | in adhering to this "do no harm" thanks to sane defaults in `ggplot2` and packages like [ggthemes](http://cran.r-project.org/web/packages/ggthemes/index.html) and 17 | [RColorBrewer](http://cran.r-project.org/web/packages/RColorBrewer/index.html) that enable use of established, good color palettes. 18 | 19 | If you do visualization work in conjunction with a design shop or organization that establishes their own 20 | palettes and themes there will often be standard palettes that must be adhered to. These are usually stored and 21 | shared in some type of Adobe swatch file format. There are also many sites like [Adobe Color CC](https://color.adobe.com/) and 22 | [COLOUR Lovers](http://www.colourlovers.com/) where folks can create and share color palettes. 23 | 24 | This package enables you to use the colors straight from `.ase` or `.aso` files and avoid the cutting/pasting of hex codes 25 | or using color pickers to extract the color information. You can read these swatch files directly from the internet and/or 26 | include the files directly in your R projects. This will make it easier to modify a resource versus change code. 27 | 28 | NOTE that just beacuse an ASE or ACO file exists on the internet does _not_ mean that it will let you "do no harm". You 29 | still need to use good judgement from knowledge/experience (or advice from experts) to ensure you are using colors effectively. 30 | This package just opens up the world of colors in R a little bit more. 31 | 32 | The following functions are implemented: 33 | 34 | - `read_aco` : Read colors from Adobe Color (ACO) files 35 | - `read_ase` : Read colors from Adobe Swatch Exchange (ASE) files 36 | - `show_palette` :Display a color palette 37 | 38 | ### TODO 39 | 40 | - Grayscale support (just need to find or gen Grayscale ASE/ACO files, if you have a few please hook me up) 41 | - LAB support (could use some help with this) 42 | - Writing out ACO or ASE files (not sure this is needed, tho) 43 | 44 | ### News 45 | 46 | - Version `0.1` released 47 | - Version `0.2` released : ACO v2 support 48 | 49 | ### Installation 50 | 51 | ```{r eval=FALSE} 52 | devtools::install_github("hrbrmstr/adobecolor") 53 | ``` 54 | 55 | ```{r echo=FALSE, message=FALSE, warning=FALSE, error=FALSE} 56 | options(width=80) 57 | ``` 58 | 59 | ### Usage & Exposition 60 | 61 | ```{r} 62 | library(adobecolor) 63 | 64 | # current verison 65 | packageVersion("adobecolor") 66 | 67 | ``` 68 | 69 | One good source for palettes is the ["Most Popular" section](https://color.adobe.com/explore/most-popular/?time=all) on 70 | Adobe Color CC. If you use the Adobe ecosystem, you can sync ASE palette files directly locally or download them directly 71 | (registration required). 72 | 73 | ![](https://www.evernote.com/shard/s1/sh/357686a4-3688-4f01-887d-463a259fc5ec/a83815d1519e5db35f80f5e5c52e15e3/deep/0/Explore---Most-Popular---Adobe-Color-CC.png) 74 | 75 | The "Herbs and Spice" and "Keep the Change" palettes are kinda nifty, and also included in this package (since Adobe has yet to 76 | release the new API for the color site for automatic downloading). We can take a quick look at both of them. Here they are from the web site: 77 | 78 | ![](http://note.io/1I51HRo) 79 | 80 | And, there they are via this package: 81 | 82 | ```{r fig.height=2.5} 83 | herbs_and_spice <- read_ase(system.file("palettes", "herbs_and_spice.ase", package="adobecolor")) 84 | print(herbs_and_spice) 85 | show_palette(herbs_and_spice) 86 | ``` 87 | 88 | ```{r fig.height=2.5} 89 | keep_the_change <- read_ase(system.file("palettes", "keep_the_change.ase", package="adobecolor")) 90 | print(keep_the_change) 91 | show_palette(keep_the_change) 92 | ``` 93 | 94 | As said earlier, you can also read directly from a URL. Here is a "metal" palette ripped straight [from github](https://github.com/picwellwisher12pk/en_us/): 95 | 96 | ```{r fig.height=2.5} 97 | metal <- read_ase("https://github.com/picwellwisher12pk/en_us/raw/master/Swatches/Metal.ase") 98 | print(metal) 99 | show_palette(metal) 100 | ``` 101 | 102 | As you can see, this "metal" palette actually had named colors (albeit bland, CMYK value names). 103 | 104 | Some palettes, like the Omega Nebula (CC-BY-SA [davidgav](http://www.colourlovers.com/lover/davidgav/loveNote)) one included with the package, have license restrictions (the mind _boggles_), so be aware of that when blatantly using others' designs without attribution. David's palette has much better names: 105 | 106 | ```{r fig.height=2.5} 107 | omega_nebula <- read_ase(system.file("palettes", "omega_nebula.ase", package="adobecolor")) 108 | print(omega_nebula) 109 | show_palette(omega_nebula) 110 | ``` 111 | 112 | For some reason (I haven't poked at the source code yet or talked to @hadleywickham), ggplot `scale_*_manual` (color/fill)'s do _not_ 113 | like named color vectors. So you need to use `unname` (or `use_names=FALSE` in `read_ase` or `read_aco`) before using them as `values`: 114 | 115 | ```{r fig.height=4} 116 | library(ggplot2) 117 | gg <- ggplot(mtcars, aes(x=mpg, y=disp)) 118 | gg <- gg + geom_point(aes(col=factor(gear)), size=3) 119 | gg <- gg + scale_color_manual(values=unname(keep_the_change)) 120 | gg <- gg + theme_bw() 121 | gg 122 | ``` 123 | 124 | ### Test Results 125 | 126 | ```{r} 127 | library(adobecolor) 128 | library(testthat) 129 | 130 | date() 131 | 132 | test_dir("tests/") 133 | ``` 134 | 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/hrbrmstr/adobecolor.svg)](https://travis-ci.org/hrbrmstr/adobecolor) 2 | 3 | ## THIS PROJECT HAS MOVED over to http://github.com/hrbrmstr/swatches since it was unlikely it'd get into CRAN with this name 4 | 5 | ----------- 6 | 7 | adobecolor is a package to read (and eventually write) Adobe color (ASE/ACO) files 8 | 9 | In *Envisioning Information*, Edward Tufte says *"…avoiding catastrophe becomes the first principle in bringing color to information: Above all, do no harm."* R users gain a quick upper hand in adhering to this "do no harm" thanks to sane defaults in `ggplot2` and packages like [ggthemes](http://cran.r-project.org/web/packages/ggthemes/index.html) and [RColorBrewer](http://cran.r-project.org/web/packages/RColorBrewer/index.html) that enable use of established, good color palettes. 10 | 11 | If you do visualization work in conjunction with a design shop or organization that establishes their own palettes and themes there will often be standard palettes that must be adhered to. These are usually stored and shared in some type of Adobe swatch file format. There are also many sites like [Adobe Color CC](https://color.adobe.com/) and [COLOUR Lovers](http://www.colourlovers.com/) where folks can create and share color palettes. 12 | 13 | This package enables you to use the colors straight from `.ase` or `.aso` files and avoid the cutting/pasting of hex codes or using color pickers to extract the color information. You can read these swatch files directly from the internet and/or include the files directly in your R projects. This will make it easier to modify a resource versus change code. 14 | 15 | NOTE that just beacuse an ASE or ACO file exists on the internet does *not* mean that it will let you "do no harm". You still need to use good judgement from knowledge/experience (or advice from experts) to ensure you are using colors effectively. This package just opens up the world of colors in R a little bit more. 16 | 17 | The following functions are implemented: 18 | 19 | - `read_aco` : Read colors from Adobe Color (ACO) files 20 | - `read_ase` : Read colors from Adobe Swatch Exchange (ASE) files 21 | - `show_palette` :Display a color palette 22 | 23 | ### TODO 24 | 25 | - Grayscale support (just need to find or gen Grayscale ASE/ACO files, if you have a few please hook me up) 26 | - LAB support (could use some help with this) 27 | - Writing out ACO or ASE files (not sure this is needed, tho) 28 | 29 | ### News 30 | 31 | - Version `0.1` released 32 | - Version `0.2` released : ACO v2 support 33 | 34 | ### Installation 35 | 36 | ``` r 37 | devtools::install_github("hrbrmstr/adobecolor") 38 | ``` 39 | 40 | ### Usage & Exposition 41 | 42 | ``` r 43 | library(adobecolor) 44 | ``` 45 | 46 | ## Loading required package: pack 47 | 48 | ``` r 49 | # current verison 50 | packageVersion("adobecolor") 51 | ``` 52 | 53 | ## [1] '0.2' 54 | 55 | One good source for palettes is the ["Most Popular" section](https://color.adobe.com/explore/most-popular/?time=all) on Adobe Color CC. If you use the Adobe ecosystem, you can sync ASE palette files directly locally or download them directly (registration required). 56 | 57 | ![](https://www.evernote.com/shard/s1/sh/357686a4-3688-4f01-887d-463a259fc5ec/a83815d1519e5db35f80f5e5c52e15e3/deep/0/Explore---Most-Popular---Adobe-Color-CC.png) 58 | 59 | The "Herbs and Spice" and "Keep the Change" palettes are kinda nifty, and also included in this package (since Adobe has yet to release the new API for the color site for automatic downloading). We can take a quick look at both of them. Here they are from the web site: 60 | 61 | ![](http://note.io/1I51HRo) 62 | 63 | And, there they are via this package: 64 | 65 | ``` r 66 | herbs_and_spice <- read_ase(system.file("palettes", "herbs_and_spice.ase", package="adobecolor")) 67 | print(herbs_and_spice) 68 | ``` 69 | 70 | ## 71 | ## "#5A1F00" "#D1570D" "#FDE792" "#477725" "#A9CC66" 72 | 73 | ``` r 74 | show_palette(herbs_and_spice) 75 | ``` 76 | 77 | ![](README_files/figure-markdown_github/unnamed-chunk-4-1.png) 78 | 79 | ``` r 80 | keep_the_change <- read_ase(system.file("palettes", "keep_the_change.ase", package="adobecolor")) 81 | print(keep_the_change) 82 | ``` 83 | 84 | ## 85 | ## "#6B0C22" "#D9042B" "#F4CB89" "#588C8C" "#011C26" 86 | 87 | ``` r 88 | show_palette(keep_the_change) 89 | ``` 90 | 91 | ![](README_files/figure-markdown_github/unnamed-chunk-5-1.png) 92 | 93 | As said earlier, you can also read directly from a URL. Here is a "metal" palette ripped straight [from github](https://github.com/picwellwisher12pk/en_us/): 94 | 95 | ``` r 96 | metal <- read_ase("https://github.com/picwellwisher12pk/en_us/raw/master/Swatches/Metal.ase") 97 | print(metal) 98 | ``` 99 | 100 | ## C=0 M=0 Y=30 K=0 C=2 M=20 Y=94 K=0 C=0 M=6 Y=47 K=0 101 | ## "#ffffb3" "#fbcc0f" "#feef89" 102 | ## C=20 M=40 Y=96 K=7 C=16 M=32 Y=82 K=5 C=4 M=14 Y=60 K=8 103 | ## "#bf9009" "#cba62c" "#e2cc5e" 104 | ## C=1 M=19 Y=90 K=0 C=0 M=5 Y=42 K=5 C=8 M=4 Y=3 K=27 105 | ## "#fccf1b" "#f2e78c" "#acb3b5" 106 | ## C=17 M=8 Y=5 K=39 C=2 M=0 Y=4 K=16 C=6 M=7 Y=4 K=22 107 | ## "#829094" "#d2d7ce" "#bdbbc1" 108 | ## C=11 M=13 Y=8 K=38 C=8 M=9 Y=6 K=28 C=3 M=4 Y=3 K=14 109 | ## "#8d8a91" "#a9a7ad" "#d3d2d5" 110 | ## C=1 M=1 Y=1 K=7 C=4 M=3 Y=3 K=7 C=18 M=8 Y=10 K=48 111 | ## "#ececed" "#e3e6e6" "#6e7c79" 112 | ## C=10 M=5 Y=6 K=24 C=17 M=11 Y=13 K=0 C=31 M=24 Y=25 K=0 113 | ## "#b0b9b7" "#d5e3de" "#b0c4c0" 114 | ## C=64 M=47 Y=52 K=19 C=51 M=37 Y=40 K=4 C=71 M=53 Y=57 K=32 115 | ## "#4a6e64" "#7a9c94" "#33524b" 116 | ## C=0 M=7 Y=24 K=5 C=18 M=43 Y=89 K=7 C=1 M=12 Y=50 K=6 1 117 | ## "#f3e3bb" "#c4871b" "#edd378" 118 | ## C=21 M=49 Y=100 K=7 C=16 M=38 Y=79 K=6 C=0 M=19 Y=54 K=8 119 | ## "#bd7a00" "#ca9434" "#ebbf6c" 120 | ## C=0 M=5 Y=15 K=4 C=1 M=12 Y=50 K=6 C=1 M=8 Y=32 K=5 121 | ## "#f5e9d1" "#edd378" "#f1dea4" 122 | ## C=6 M=4 Y=3 K=39 C=5 M=4 Y=2 K=29 1 C=3 M=3 Y=1 K=16 123 | ## "#939697" "#acadb0" "#d1d1d4" 124 | ## C=39 M=83 Y=92 K=42 C=22 M=57 Y=86 K=23 1 C=0 M=52 Y=86 K=29 125 | ## "#5a190d" "#99551c" "#b6581a" 126 | ## C=0 M=15 Y=36 K=9 1 C=6 M=39 Y=74 K=22 1 C=25 M=43 Y=65 K=17 127 | ## "#e9c695" "#ba7934" "#9f794b" 128 | ## C=14 M=32 Y=51 K=11 C=0 M=21 Y=35 K=17 C=33 M=31 Y=46 K=11 129 | ## "#c49a6f" "#d4a88a" "#999c7a" 130 | ## C=76 M=41 Y=68 K=35 C=67 M=42 Y=54 K=5 C=78 M=45 Y=56 K=3 131 | ## "#296335" "#518d70" "#36876c" 132 | ## C=0 M=0 Y=0 K=100 C=0 M=0 Y=0 K=78 1 C=0 M=0 Y=0 K=42 1 133 | ## "#000000" "#3a3a3a" "#949494" 134 | ## C=0 M=0 Y=0 K=26 1 C=0 M=0 Y=0 K=66 1 C=0 M=0 Y=0 K=10 1 135 | ## "#bdbdbd" "#565656" "#e6e6e6" 136 | ## C=0 M=0 Y=0 K=0 137 | ## "#ffffff" 138 | 139 | ``` r 140 | show_palette(metal) 141 | ``` 142 | 143 | ![](README_files/figure-markdown_github/unnamed-chunk-6-1.png) 144 | 145 | As you can see, this "metal" palette actually had named colors (albeit bland, CMYK value names). 146 | 147 | Some palettes, like the Omega Nebula (CC-BY-SA [davidgav](http://www.colourlovers.com/lover/davidgav/loveNote)) one included with the package, have license restrictions (the mind *boggles*), so be aware of that when blatantly using others' designs without attribution. David's palette has much better names: 148 | 149 | ``` r 150 | omega_nebula <- read_ase(system.file("palettes", "omega_nebula.ase", package="adobecolor")) 151 | print(omega_nebula) 152 | ``` 153 | 154 | ## distance between Pale Clay Snow forest III 155 | ## "#9D7E79" "#CCAC95" "#9A947C" "#748B83" 156 | ## Aqua Smoke 157 | ## "#5B756C" 158 | 159 | ``` r 160 | show_palette(omega_nebula) 161 | ``` 162 | 163 | ![](README_files/figure-markdown_github/unnamed-chunk-7-1.png) 164 | 165 | For some reason (I haven't poked at the source code yet or talked to @hadleywickham), ggplot `scale_*_manual` (color/fill)'s do *not* like named color vectors. So you need to use `unname` (or `use_names=FALSE` in `read_ase` or `read_aco`) before using them as `values`: 166 | 167 | ``` r 168 | library(ggplot2) 169 | gg <- ggplot(mtcars, aes(x=mpg, y=disp)) 170 | gg <- gg + geom_point(aes(col=factor(gear)), size=3) 171 | gg <- gg + scale_color_manual(values=unname(keep_the_change)) 172 | gg <- gg + theme_bw() 173 | gg 174 | ``` 175 | 176 | ![](README_files/figure-markdown_github/unnamed-chunk-8-1.png) 177 | 178 | ### Test Results 179 | 180 | ``` r 181 | library(adobecolor) 182 | library(testthat) 183 | 184 | date() 185 | ``` 186 | 187 | ## [1] "Fri Mar 20 18:20:33 2015" 188 | 189 | ``` r 190 | test_dir("tests/") 191 | ``` 192 | 193 | ## basic functionality : 194 | --------------------------------------------------------------------------------