├── .Rbuildignore ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── eyedropper.R ├── generate-palette.R ├── helpers.R └── pencil-case.R ├── README.Rmd ├── README.md ├── cran-comments.md ├── dev ├── images │ ├── belize-output-12.png │ ├── belize-output-s.png │ ├── belize-s.jpg │ ├── belize-swatch.png │ ├── belize.jpg │ ├── calibrate.png │ ├── cat4.png │ ├── catedral-s.png │ ├── eyedropper.gif │ ├── eyedropper1.jpg │ ├── feature.png.png │ ├── hex-amatic.png │ ├── misc │ │ └── graffiti.png │ ├── mountains-in-autumn.png │ ├── mountains-selector.png │ ├── mountains.png │ ├── pencil-case │ │ ├── mastodon-blood-mountain.png │ │ ├── mastodon-crack-the-skye.png │ │ ├── mastodon-empoeror-of-sands.png │ │ ├── mastodon-hushed-and-grim.png │ │ ├── mastodon-leviathan.png │ │ ├── mastodon-once-more-around-the-sun.png │ │ ├── mastodon-remission.png │ │ ├── mastodon-the-hunter.png │ │ ├── motley-crue.png │ │ ├── mountains-in-autumn.png │ │ ├── tool-10000-days.png │ │ ├── tool-fear-inoculum.png │ │ └── tool-lateralus.png │ ├── show-pencil-case.png │ ├── snes │ │ ├── mana.png │ │ ├── secret-of-mana-40p.png │ │ ├── secret-of-mana-80p.png │ │ ├── secret-of-mana-og.png │ │ └── secret-of-mana.png │ ├── sunset-sampler-s.png │ ├── sunset-sampler.png │ ├── sunset-south-coast-output-s.png │ ├── sunset-south-coast-output.png │ ├── sunset-south-coast-s.jpg │ └── sunset-south-coast.jpg ├── scripts │ ├── dev.R │ ├── hex.R │ ├── show-pal.R │ ├── tests.R │ └── tsp.R └── tests │ └── tests.R ├── eyedroppeR.Rproj ├── inst └── images │ ├── calibration.png │ ├── hex.png │ └── sunset.png └── man ├── choose_font_colour.Rd ├── extract_pal.Rd ├── eyedropper.Rd ├── generate_palette.Rd ├── make_output.Rd ├── min_max.Rd ├── modify_saturation.Rd ├── palette.Rd ├── paste_pal_code.Rd ├── pencil_case.Rd ├── show_pal.Rd ├── show_pencil_case.Rd ├── sort_pal.Rd ├── sort_pal_auto.Rd └── swatch.Rd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | README.Rmd 4 | README.md 5 | README_files 6 | ^cran-comments\.md$ 7 | ^CRAN-SUBMISSION$ 8 | LICENSE.md 9 | dev 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | dev/images/too-big 6 | dev/images/pencil-case/ 7 | dev/images/albums/ 8 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: eyedroppeR 2 | Type: Package 3 | Title: Extract Hex Codes by Clicking an Image 4 | Version: 0.3.0 5 | Authors@R: 6 | c(person(given = "Daniel", 7 | family = "Oehm", 8 | role = c("aut", "cre"), 9 | email = "danieloehm@gmail.com")) 10 | Description: Plots an image either locally or from a URL and allows the user 11 | to click the image to save the hex of the pixel. User can select multiple 12 | colours or automatically select a user specified number of colours. 13 | Depends: 14 | R (>= 3.5.0) 15 | Imports: 16 | ggplot2, 17 | purrr, 18 | grid, 19 | glue, 20 | ggpath, 21 | magick, 22 | stringr, 23 | gridExtra, 24 | crayon, 25 | snakecase, 26 | ggtext, 27 | TSP, 28 | tidyr, 29 | gt, 30 | openai, 31 | dplyr 32 | License: MIT + file LICENSE 33 | URL: https://github.com/doehm/eyedroppeR 34 | BugReports: https://github.com/doehm/eyedroppeR/issues 35 | Encoding: UTF-8 36 | LazyData: true 37 | RoxygenNote: 7.2.3 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2022 2 | COPYRIGHT HOLDER: Daniel Oehm 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## MIT License 2 | 3 | Copyright (c) 2022 Daniel Oehm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(extract_pal) 4 | export(eyedropper) 5 | export(generate_palette) 6 | export(modify_saturation) 7 | export(palette) 8 | export(pencil_case) 9 | export(show_pal) 10 | export(show_pencil_case) 11 | export(sort_pal) 12 | export(sort_pal_auto) 13 | export(swatch) 14 | import(dplyr) 15 | import(ggplot2) 16 | importFrom(TSP,as.TSP) 17 | importFrom(TSP,solve_TSP) 18 | importFrom(crayon,cyan) 19 | importFrom(crayon,white) 20 | importFrom(ggpath,geom_from_path) 21 | importFrom(ggplot2,ggsave) 22 | importFrom(ggtext,geom_richtext) 23 | importFrom(glue,glue) 24 | importFrom(grDevices,col2rgb) 25 | importFrom(grDevices,hsv) 26 | importFrom(grDevices,rgb2hsv) 27 | importFrom(grid,grid.locator) 28 | importFrom(gridExtra,grid.arrange) 29 | importFrom(gt,cell_text) 30 | importFrom(gt,cells_body) 31 | importFrom(gt,cols_hide) 32 | importFrom(gt,cols_width) 33 | importFrom(gt,default_fonts) 34 | importFrom(gt,google_font) 35 | importFrom(gt,gt) 36 | importFrom(gt,px) 37 | importFrom(gt,tab_header) 38 | importFrom(gt,tab_options) 39 | importFrom(gt,tab_style) 40 | importFrom(gt,text_transform) 41 | importFrom(magick,image_append) 42 | importFrom(magick,image_data) 43 | importFrom(magick,image_info) 44 | importFrom(magick,image_read) 45 | importFrom(magick,image_resize) 46 | importFrom(magick,image_scale) 47 | importFrom(magick,image_write) 48 | importFrom(openai,create_image) 49 | importFrom(purrr,map_chr) 50 | importFrom(purrr,map_dbl) 51 | importFrom(purrr,map_dfr) 52 | importFrom(purrr,reduce) 53 | importFrom(snakecase,to_snake_case) 54 | importFrom(stats,dist) 55 | importFrom(stats,kmeans) 56 | importFrom(stringr,str_detect) 57 | importFrom(stringr,str_length) 58 | importFrom(stringr,str_remove) 59 | importFrom(stringr,str_remove_all) 60 | importFrom(stringr,str_split) 61 | importFrom(tidyr,everything) 62 | importFrom(tidyr,pivot_wider) 63 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # eyedroppeR 0.1.0 2 | 3 | * New release 4 | * Added a `NEWS.md` file to track changes to the package. 5 | -------------------------------------------------------------------------------- /R/eyedropper.R: -------------------------------------------------------------------------------- 1 | utils::globalVariables(c("x", "y", "id", "bg", "name", "text")) 2 | 3 | #' Eyedropper 4 | #' 5 | #' Plots an image and allows the user to click on the image to 6 | #' return the hex of the pixel. Can select multiple colours at 7 | #' once by setting \code{n}. 8 | #' 9 | #' @param n Number of colours to extract from the image 10 | #' @param img_path Path to image. Can be local or from a URL. If left \code{NULL}, 11 | #' \code{eyedropper} will read the image address directly from the clipboard. 12 | #' @param label Label for the palette. 13 | #' @param inc_palette Logical. If \code{TRUE} it will automatically extract a palette 14 | #' first and then you can select the desired colours. 15 | #' @param n_swatches Number of swatches to extract from the image prior to selecting colours. 16 | #' @param print_output Print output to console to easily copy and paste into your script. 17 | #' @param calibrate Set to `TRUE` to calibrate the plot coordinates. Given the monitor 18 | #' resolution, scaling, etc it can throw off the pixel selection. Runs but default the first 19 | #' time the function is used. 20 | #' @param swatch_radius Radius of the image for the swatch. Default 50 to make it a circle. Use 5 for rounded edges. 21 | #' @param pixelate If `TRUE` or some numeric value, a low-res image will be displayed so that it is easier to select the right colour. Pixelate 22 | #' is set to `40` pixels. To make it more pixelated use a lower number of pixels e.g. `pixelate = 40`. If 23 | #' pixelate is used the palette selector at the bottom of the image won't be shown. 24 | #' 25 | #' @details Use \code{eyedropper} with the following steps: 26 | #' \enumerate{ 27 | #' \item{Find the image you want to pick colours from online.} 28 | #' \item{Right-click and 'copy image address'.} 29 | #' \item{Choose how many colours to pick e.g. \code{n = 5}.} 30 | #' \item{Run \code{pal <- eyedropper(n = 5, img_path = 'paste-image-path-here')}.} 31 | #' \item{Click 5 areas of the image. Thes image will be stretched to the borders of the window, but that's OK.} 32 | #' \item{Done! Copy the returned string / message and add it to you script and start using \code{pal}} 33 | #' } 34 | #' 35 | #' The first time the function is run it will initiate a calibration set. This is so the `y` coordinates are 36 | #' scaled properly as this can depend on the monitors resolution, scaling, etc. In only takes a couple of seconds 37 | #' and you only have to do it once. 38 | #' 39 | #' Make sure you click as near as practicable to the top and bottom of the border of the windew within the dot. 40 | #' 41 | #' @return A character vector of hex codes 42 | #' @export 43 | #' 44 | #' @import ggplot2 45 | #' @importFrom magick image_read image_data image_write image_info image_resize image_append image_scale 46 | #' @importFrom purrr map_chr map_dbl reduce 47 | #' @importFrom grid grid.locator 48 | #' @importFrom glue glue 49 | #' @importFrom ggpath geom_from_path 50 | #' @importFrom stringr str_remove str_split 51 | #' @importFrom stats kmeans dist 52 | #' @importFrom gridExtra grid.arrange 53 | #' @importFrom crayon white cyan 54 | #' @importFrom snakecase to_snake_case 55 | #' @importFrom TSP as.TSP solve_TSP 56 | #' @importFrom ggtext geom_richtext 57 | #' @importFrom grDevices col2rgb 58 | #' @importFrom ggplot2 ggsave 59 | #' 60 | #' @examples \dontrun{ 61 | #' 62 | #' path <- file.path(system.file(package = "eyedroppeR"), "images", "hex.png") 63 | #' 64 | #' # Run eyedropper and click on 4 colours 65 | #' pal <- eyedropper(n = 4, path) 66 | #' 67 | #' pal 68 | #' 69 | #' } 70 | eyedropper <- function( 71 | n, 72 | img_path = NULL, 73 | label = NULL, 74 | inc_palette = TRUE, 75 | n_swatches = 24, 76 | print_output = TRUE, 77 | calibrate = FALSE, 78 | swatch_radius = 50, 79 | pixelate = FALSE 80 | ) { 81 | 82 | # name palette 83 | # keeping this here in case I add back in the parameter 84 | if(is.null(label)) label <- "pal" 85 | 86 | # calibrate 87 | if(calibrate | !exists("eyedropper_calibration", mode = "environment")) { 88 | plt_calibrate <- tibble( 89 | x = 0.5, 90 | y = c(0.9, 0.1), 91 | text = c("To calibrate,\nfirst click here\nwithin the dot", "Then click here\nwithin the dot") 92 | ) %>% 93 | ggplot() + 94 | annotation_raster(image_read(file.path(system.file(package = "eyedroppeR"), "images", "calibration.png")), xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) + 95 | geom_text(aes(x-0.1, y, label = text), size = 8, hjust = 1, lineheight = 0.8) + 96 | ylim(0, 1) + 97 | xlim(0, 1) + 98 | theme_void() 99 | print(plt_calibrate) 100 | 101 | calibration_points <- list() 102 | lab <- c("Top", "Bottom") 103 | for(k in 1:2) { 104 | cat(lab[k]) 105 | calibration_points[[k]] <- grid.locator(unit = "npc") 106 | cat(" ✔\n") 107 | } 108 | cat("-- Calibration done --\n") 109 | 110 | # create a new environment to store the calibration points 111 | eyedropper_calibration <<- new.env() 112 | 113 | # calculate min and max y 114 | eyedropper_calibration$max_y <- as.numeric(calibration_points[[1]]$y) 115 | eyedropper_calibration$min_y <- as.numeric(calibration_points[[2]]$y) 116 | 117 | } 118 | 119 | # if no image is given use the standard 120 | img_shadow <- TRUE 121 | if(is.null(img_path)) { 122 | img_path <- file.path(system.file(package = "eyedroppeR"), "images", "hex.png") 123 | img_shadow <- FALSE 124 | } 125 | 126 | err_bad_link <- simpleError("Incorrect path. Please supply the correct link to img_path") 127 | tryCatch( 128 | { 129 | # include palette? 130 | if(inc_palette) { 131 | ex_pal <- suppressMessages(extract_pal(n_swatches, img_path, plot_output = FALSE, save_output = TRUE)) 132 | img <- image_read(img_path) 133 | } else { 134 | img <- image_read(img_path) 135 | } 136 | }, 137 | error = function(e) stop(err_bad_link) 138 | ) 139 | 140 | # resize and write image 141 | info <- image_info(img) 142 | ht <- min(info$height, 800) 143 | wd <- info$width*ht/info$height 144 | img_rs <- image_resize(img, geometry = paste0(ht, "x", wd)) 145 | temp <- tempfile() 146 | image_write(img_rs, path = temp) 147 | 148 | # plot image with extracted palette 149 | temp_selector <- tempfile(fileext = ".png") 150 | ggsave(plot = show_pal(ex_pal$pal), filename = temp_selector, height = ht/10, width = wd, units = "px") 151 | img_selector <- image_append(image_scale(c(img_rs, image_read(temp_selector)), as.character(ht)), stack = TRUE) 152 | 153 | # pixelate 154 | if(pixelate | is.numeric(pixelate)) { 155 | if(is.numeric(pixelate)) { 156 | geo <- glue("{pixelate}x") 157 | } else { 158 | geo <- "40x" 159 | } 160 | img_selector <- image_resize(img, geometry = geo, filter = "Point") 161 | } 162 | 163 | # plot image for clicking 164 | print(ggplot() + 165 | annotation_raster(img_selector, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf)) 166 | 167 | # pick colours 168 | eye_ls <- list() 169 | message(white("\nClick on image to select colours\n")) 170 | for(k in 1:n) { 171 | cat(glue("Colours selected: {k-1}/{n}\r")) 172 | eye_ls[[k]] <- grid.locator(unit = "npc") 173 | if(info$width*as.numeric(eye_ls[[k]]$x) < 0) stop("...eyedropper killed\n") 174 | } 175 | cat(glue("Colours selected: {n}/{n}\n\n")) 176 | 177 | # get image data and extract from image 178 | img_dat <- image_data(img_selector) 179 | dims <- dim(img_dat) 180 | 181 | pal <- map_chr(eye_ls, ~{ 182 | coords <- as.numeric(str_remove(reduce(.x, c), "npc")) 183 | coords[2] <- 1-min_max(coords[2], 0, 1, a0 = eyedropper_calibration$min_y, b0 = eyedropper_calibration$max_y) 184 | xpx <- ceiling(coords[1]*dims[2]) 185 | ypx <- ceiling(coords[2]*dims[3]) 186 | paste0("#", paste0(img_dat[, xpx, ypx][1:3], collapse = "")) 187 | }) 188 | 189 | # print pal to copy + paste 190 | if(print_output) paste_pal_code(pal, label) 191 | 192 | # make plot output 193 | if(label == "pal") label <- NULL 194 | print(swatch(pal, img = img_path, label = label, img_shadow = img_shadow, radius = swatch_radius)) 195 | 196 | # return 197 | list( 198 | pal = pal, 199 | img_path = img_path 200 | ) 201 | 202 | } 203 | 204 | 205 | #' Extracts palette from an image 206 | #' 207 | #' The image is read in using \code{magick}, converted to RGB and clustered using kmeans. The user 208 | #' must specify the number of clusters. The cluster centroids become the palette values. 209 | #' The function will ask the user to sort the palette values after clustering 210 | #' 211 | #' @param n Number of colours to extract 212 | #' @param img_path Path to image. If `NULL` the function will read from the clipboard 213 | #' @param label Label for the palette. 214 | #' @param sort Sort method. Either 'manual' or 'auto' 215 | #' @param plot_output logical. Default \code{TRUE}. Plots the output of the extracted palette. 216 | #' @param save_output logical. Default \code{FALSE}. Save the output of the extracted palette. 217 | #' @param print_output Print output to console to easily copy and paste into your script. 218 | #' @param swatch_radius Radius of the image for the swatch. Default 50 to make it a circle. Use 5 for rounded edges. 219 | #' 220 | #' @return Returns a character vector of hex codes 221 | #' @export 222 | #' 223 | #' @examples 224 | #' path <- file.path(system.file(package = "eyedroppeR"), "images", "sunset.png") 225 | #' 226 | #' \dontrun{ 227 | #' extract_pal(8, path) 228 | #' } 229 | extract_pal <- function( 230 | n, 231 | img_path, 232 | label = NULL, 233 | sort = "auto", 234 | plot_output = TRUE, 235 | save_output = FALSE, 236 | print_output = TRUE, 237 | swatch_radius = 50 238 | ) { 239 | 240 | err_bad_link <- simpleError("Incorrect path. Please supply the correct link to img_path") 241 | tryCatch( 242 | { 243 | img <- image_read(img_path) 244 | }, 245 | error = function(e) stop(err_bad_link) 246 | ) 247 | 248 | # name palette 249 | if(is.null(label)) label <- "pal" 250 | 251 | # resize and write image 252 | info <- image_info(img) 253 | ht <- min(info$height, 600) 254 | wd <- info$width*ht/info$height 255 | img_rs <- image_resize(img, geometry = paste0(ht, "x", wd)) 256 | temp <- tempfile() 257 | image_write(img_rs, path = temp) 258 | 259 | # setting array for clustering 260 | x <- as.integer(as.array(image_data(img_rs, "rgb"))) 261 | rgb_mat <- unique(apply(x, 3, "c")) 262 | 263 | # kmeans 264 | km <- kmeans(rgb_mat, n) 265 | km <- round(km$centers) 266 | 267 | # pal from centers 268 | pal <- map_chr(1:n, ~rgb(km[.x,1], km[.x,2], km[.x,3], maxColorValue = 255)) 269 | 270 | # sort 271 | pal <- sort_pal_auto(pal, label) 272 | if(sort == "manual") { 273 | print(show_pal(pal)) 274 | nx <- as.numeric(readline("How many colours to pick? ")) 275 | pal <- sort_pal(pal, n = nx) 276 | } 277 | 278 | # print pal 279 | if(print_output) paste_pal_code(pal, label) 280 | 281 | # make plot output 282 | temp_final <- NULL 283 | if(label == "pal") label <- NULL 284 | if(plot_output) print(swatch(pal, temp, label = label, radius = swatch_radius)) 285 | 286 | # return 287 | list( 288 | pal = pal, 289 | img_path = temp 290 | ) 291 | 292 | } 293 | 294 | 295 | -------------------------------------------------------------------------------- /R/generate-palette.R: -------------------------------------------------------------------------------- 1 | 2 | #' Generate palette 3 | #' 4 | #' ⚠️ DEPRECATED: openai has been archived and I have to work out how to generate 5 | #' images with {ellmer} and the new APIs. 6 | #' 7 | #' @param n Number of colours in the palette 8 | #' @param prompt Prompt 9 | #' 10 | #' @importFrom openai create_image 11 | #' @importFrom stringr str_length 12 | #' 13 | #' @return A vector of hex codes 14 | #' @export 15 | #' 16 | #' @examples 17 | #' # x <- generate_palette(4, 'a trail in a dense rainforest') 18 | generate_palette <- function(n, prompt) { 19 | x <- create_image(prompt) 20 | d <- extract_pal(n, x$data$url, plot_output = FALSE, save_output = TRUE) 21 | print(swatch(d$pal, d$img_path, padding = 1)) 22 | list( 23 | pal = d$pal, 24 | eyedropper = d, 25 | img = x$data$url 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /R/helpers.R: -------------------------------------------------------------------------------- 1 | #' Show palette 2 | #' 3 | #' Plots the supplied palette for quick inspection 4 | #' 5 | #' @param pal Palette. Vector of hex codes 6 | #' 7 | #' @return ggplot 8 | #' @export 9 | #' 10 | #' @examples 11 | #' pal <- c('#57364e', '#566f1b', '#97a258', '#cac58b', '#dbedd5') 12 | #' show_pal(pal) 13 | show_pal <- function(pal) { 14 | ggplot(data.frame(x = 1:length(pal),y = 1)) + 15 | geom_col(aes(x, y), fill = pal, width = 1) + 16 | theme_void() + 17 | theme( 18 | plot.margin = margin(l=-12,r=-12,t=-20,b=-20) 19 | ) 20 | } 21 | 22 | #' Swatch of colour palette 23 | #' 24 | #' @param pal Vector of colours 25 | #' @param img Image address. Either local file or URL 26 | #' @param label Label for the palette. 27 | #' @param padding To add whitespace to the top of image 28 | #' @param radius The radius of the feature image. Choose 50 for a circle, less then 50 for rounded square/rectangle. 29 | #' @param ncols Number of cols in a row 30 | #' @param img_shadow Logical. Apply a shadow to the feature image output. 31 | #' @param shape Either 'original' for the original image dimensions or "square" 32 | #' to crop to square with rounded corners. A high enough radius will turn the square to a circle. 33 | #' 34 | #' @return html doc 35 | #' @export 36 | #' 37 | #' @importFrom gt gt tab_style tab_header tab_options cells_body google_font cell_text default_fonts text_transform px 38 | #' @importFrom tidyr pivot_wider everything 39 | #' @importFrom stringr str_remove_all str_detect 40 | #' @import dplyr 41 | #' 42 | #' @examples 43 | #' url <- "https://github.com/doehm/eyedroppeR/raw/main/dev/images/sunset-south-coast.jpg" 44 | #' x <- extract_pal(4, url) 45 | #' swatch(x$pal, url) 46 | swatch <- function( 47 | pal, 48 | img = NULL, 49 | label = NULL, 50 | padding = 0, 51 | radius = 20, 52 | ncols = 8, 53 | img_shadow = TRUE, 54 | shape = "original" 55 | ) { 56 | 57 | # set the number of cols for the swatch 58 | if(length(pal) > ncols & length(pal) < 2*ncols) { 59 | ncols <- ceiling(length(pal)/2) 60 | } else { 61 | ncols <- min(ncols, length(pal)) 62 | } 63 | 64 | padding <- paste0(rep("
", padding), collapse = "") 65 | nrows <- ceiling(length(pal)/ncols) 66 | 67 | # radius on x and y for the rounded corners of the image 68 | rx <- radius 69 | ry <- radius 70 | 71 | # css and function for the main image 72 | img_style <- glue("border-radius: {rx}px {ry}px; box-shadow: 0 0 10px 2px rgba(0,0,0,{0.3*img_shadow}); object-fit: cover;") 73 | img_header <- function(tbl) { 74 | if(is.null(img)) { 75 | out <- tbl 76 | } else { 77 | if(shape == "original") { 78 | info <- image_read(img) |> 79 | image_info() 80 | wd <- info$width/info$height*300 81 | } else { 82 | wd <- 300 83 | } 84 | out <- tbl |> 85 | tab_header( 86 | title = gt::html(glue("{padding}")), 87 | subtitle = gt::html(glue("{label}")) 88 | ) 89 | } 90 | } 91 | 92 | # function and css for the colour dots 93 | dot_ <- function(bg, circle) { 94 | 95 | txt <- choose_font_colour(bg) 96 | 97 | str_remove_all(glue("height: 150px; 98 | width: 150px; 99 | background-color: {bg}; 100 | color: {txt}; 101 | font-weight: 400; 102 | font-size: 12px; 103 | border-radius: 50%; 104 | display: inline-block; 105 | box-shadow: 0 0 10px 2px rgba(0,0,0,0.3);"), 106 | "\\n[:space:]") 107 | } 108 | 109 | # if the image is from a url do this thing so it works in {gt} 110 | if(!is.null(img)) { 111 | if(!str_detect(img, "http")) { 112 | uri <- gt:::get_image_uri(img) 113 | } else { 114 | uri <- img 115 | } 116 | } 117 | 118 | # make the table 119 | tibble( 120 | id = 1:length(pal), 121 | pal = pal 122 | ) |> 123 | mutate( 124 | row = ceiling(id/ncols), 125 | col = (id-1) %% ncols + 1, 126 | col = ifelse(row %% 2 == 0, max(col) - col + 1, col) 127 | ) |> 128 | select(row, col, pal) |> 129 | pivot_wider(id_cols = row, names_from = "col", values_from = "pal") |> 130 | select(-row) |> 131 | gt() |> 132 | tab_style( 133 | style = cell_text( 134 | font = c( 135 | google_font(name = "Poppins"), 136 | default_fonts() 137 | ) 138 | ), 139 | locations = cells_body(columns = everything()) 140 | ) |> 141 | text_transform( 142 | locations = cells_body( 143 | columns = everything() 144 | ), 145 | fn = function(k, i){ 146 | col_rgb <- map_chr(1:nrows, ~paste0("rgb(", paste(as.numeric(t(col2rgb(k[.x]))), collapse = ", "), ")")) 147 | map_chr(1:nrows, ~{ 148 | if(is.na(k[.x])) { 149 | out <- "" 150 | } else { 151 | out <- glue("

{k[.x]}
{col_rgb[.x]}
") 152 | } 153 | out 154 | }) 155 | } 156 | ) |> 157 | img_header() |> 158 | tab_options( 159 | column_labels.font.size = 0, 160 | table_body.hlines.width = px(0), 161 | table_body.border.top.width = px(0), 162 | table_body.border.bottom.width = px(0), 163 | heading.border.bottom.width = px(0), 164 | table.border.bottom.width = px(0), 165 | table.border.top.width = px(0), 166 | column_labels.border.top.width = px(0), 167 | column_labels.border.bottom.width = px(0), 168 | data_row.padding = px(10), 169 | data_row.padding.horizontal = px(10) 170 | ) 171 | } 172 | 173 | #' Manually sort a palette 174 | #' 175 | #' The palette is displayed in the plotting window where you can click 176 | #' the colours in the order you want to sort them. The sorted palette 177 | #' will be returned. This saves you copy/pasting hex codes in your script. 178 | #' 179 | #' @param pal Palette. Character vector of hex codes 180 | #' @param n Number of colours to choose 181 | #' @param label Label for the palette. 182 | #' @param print_output Print output to console to easily copy and paste into your script. 183 | #' 184 | #' @return Character vector 185 | #' @export 186 | #' 187 | #' @examples \dontrun{ 188 | #' pal <- sample(c('#57364e', '#566f1b', '#97a258', '#cac58b', '#dbedd5')) 189 | #' sort_pal(pal) 190 | #' } 191 | sort_pal <- function(pal, n = NULL, label = NULL, print_output = TRUE) { 192 | 193 | # show initial palette for clicking on 194 | print(show_pal(pal)) 195 | 196 | # loop to click on image 197 | if(is.null(n)) n <- length(pal) 198 | message(white(glue("Click {n} colours in the desired order\n\n"))) 199 | pos_ls <- list() 200 | for(k in 1:n) { 201 | pos_ls[[k]] <- grid.locator(unit = "npc") 202 | cat(glue("colours sorted: {k}/{n}\r")) 203 | } 204 | 205 | # sort from user input 206 | id <- map_dbl(pos_ls, ~as.numeric(.x$x)) 207 | new_pal_order <- floor(id*length(pal)) + 1 208 | pal <- pal[new_pal_order] 209 | print(show_pal(pal)) 210 | 211 | # print palette code 212 | if(print_output) { 213 | cat("\n") 214 | paste_pal_code(pal, label) 215 | } 216 | 217 | pal 218 | 219 | } 220 | 221 | #' Auto palette sort 222 | #' 223 | #' Automatically sorts the palette. May not give the desired result. If not you 224 | #' can run `sort_pal()` to manually sort. 225 | #' 226 | #' @param pal Input palette 227 | #' @param label Label for the palette. 228 | #' @param plot_output Logical. Default \code{FALSE}. 229 | #' 230 | #' @return Returns a character vector of hex codes 231 | #' @export 232 | #' 233 | #' @examples 234 | #' pal <- sample(colours(), 8) 235 | #' sort_pal_auto(pal, 'test') 236 | sort_pal_auto <- function(pal, label, plot_output = FALSE) { 237 | 238 | rgb <- col2rgb(pal) 239 | tsp <- as.TSP(dist(t(rgb))) 240 | sol <- solve_TSP(tsp, control = list(repetitions = 1e3)) 241 | pal <- pal[sol] 242 | x <- colSums(col2rgb(pal)) 243 | max_k <- which.min(x)[1] 244 | if(max_k != 1) pal <- pal[c(max_k:length(pal), 1:(max_k-1))] 245 | if(plot_output) print(show_pal(pal)) 246 | 247 | pal 248 | } 249 | 250 | #' Makes eyedroppers output 251 | #' 252 | #' Plots the palette and places the image and label over the top. 253 | #' 254 | #' @param obj Output from \code{extract_pal} or \code{eyedropper} 255 | #' @param pal Palette 256 | #' @param img_path Image path 257 | #' 258 | #' @return ggplot object 259 | make_output <- function(obj = NULL, pal, img_path) { 260 | 261 | if(!is.null(obj)) { 262 | pal <- obj$pal 263 | img_path <- obj$img_path 264 | } 265 | 266 | # read in image 267 | img_rs <- image_read(img_path) 268 | info <- image_info(img_rs) 269 | ht <- info$height 270 | wd <- info$width 271 | 272 | # temp file for output 273 | temp_output <- tempfile(fileext = ".png") 274 | temp_output_stack <- tempfile(fileext = ".png") 275 | 276 | # saving palette 277 | ggsave(plot = show_pal(pal), filename = temp_output, height = 100, width = 1000, units = "px") 278 | 279 | # stack and output 280 | img_selector <- image_append(image_scale(c(img_rs, image_read(temp_output)), "1000"), stack = TRUE) 281 | image_write(img_selector, path = temp_output_stack) 282 | 283 | ggplot() + 284 | geom_from_path(aes(wd/2, ht/2, path = temp_output_stack)) + 285 | xlim(0, wd) + 286 | ylim(0, ht) + 287 | theme_void() + 288 | theme( 289 | plot.background = element_blank() 290 | ) 291 | 292 | } 293 | 294 | 295 | #' Copy + Pasteable palette vector 296 | #' 297 | #' Prints a message to console so you can easily copy and paste the palette 298 | #' 299 | #' @param pal Palette vector 300 | #' @param label Label 301 | #' 302 | #' @return a message 303 | paste_pal_code <- function(pal, label = NULL) { 304 | if(is.null(label)) label <- "pal" 305 | message(cyan(paste0("\n", to_snake_case(label)," <- c('", paste0(pal, collapse = "', '"), "')\n"))) 306 | } 307 | 308 | 309 | #' Choose font colour 310 | #' 311 | #' @param bg Background 312 | #' @param light The light text colour 313 | #' @param dark The dark text colour 314 | #' @param threshold The threshold for switching 315 | #' 316 | #' @return hex code 317 | choose_font_colour <- function(bg, light = "#ffffff", dark = "#000000", threshold = 170) { 318 | x <- drop(c(0.299, 0.587, 0.114) %*% col2rgb(bg) > threshold) 319 | out <- ifelse(x, dark, light) 320 | ifelse(is.na(bg), light, out) 321 | } 322 | 323 | 324 | #' Modify the saturation of a colour palette 325 | #' 326 | #' @param cols Vector of colours 327 | #' @param sat Factor to adjust the saturation 328 | #' 329 | #' @importFrom grDevices rgb2hsv hsv 330 | #' 331 | #' @return A vector of hex codes 332 | #' @export 333 | modify_saturation <- function(cols, sat = 1.2) { 334 | X <- diag(c(1, sat, 1)) %*% rgb2hsv(col2rgb(cols)) 335 | hsv(X[1,], pmin(X[2,], 1), X[3,]) 336 | } 337 | 338 | 339 | #' Min-max scale function 340 | #' 341 | #' @param x Vector of values 342 | #' @param a Min 343 | #' @param b Max 344 | #' @param a0 Min bound 345 | #' @param b0 Max bound 346 | #' 347 | #' @return numeric vector 348 | min_max <- function(x, a, b, a0 = NULL, b0 = NULL) { 349 | if(is.null(a0) & is.null(b0)) { 350 | a0 <- min(x) 351 | b0 <- max(x) 352 | } 353 | (b - a) * (x - a0) / (b0 - a0) + a 354 | } 355 | -------------------------------------------------------------------------------- /R/pencil-case.R: -------------------------------------------------------------------------------- 1 | #' Pencil Case 2 | #' 3 | #' A list of palettes 4 | #' 5 | #' @importFrom purrr map_dfr 6 | #' 7 | #' @export 8 | pencil_case <- list( 9 | secret_of_mana = list( 10 | cat = c('#E92E2C', '#F1E32F', '#91A14A', '#373321') 11 | ), 12 | super_mario_world = list( 13 | cat = c('#37e605', '#0d6cfd', '#fdfc05', '#fe0000') 14 | ), 15 | super_ghouls_and_ghosts = list( 16 | cat = c('#CF2023', '#EF7434', '#89883D', '#6C6E85') 17 | ), 18 | super_probotector = list( 19 | div = c('#373140', '#79484D', '#CB4C45', '#E09D5C', '#E1D4C8', '#9C99A9', '#536E9A', '#134B8A'), 20 | cat = c('#373140', '#134B8A', '#9C99A9', '#CB4C45') 21 | ), 22 | paw_patrol = list( 23 | cat = c('#11c1b9', '#fde55d', '#f13837', '#2f406e', '#f37c3e', '#6fb455', '#b4485e') 24 | ), 25 | skittles = list( 26 | cat = c('#05beed', '#10df0b', '#fdf405', '#f67a19', '#f11941') 27 | ), 28 | bright = list( 29 | cat = c("#540d6e", "#ee4266", "#ffd23f", "#3bceac") 30 | ), 31 | blue_pink = list( 32 | cat = c('#587DB3', '#42BFDD', '#BBE6E4', '#F0F6F6', '#FF66B3') 33 | ), 34 | blue_orange = list( 35 | cat = c('#244157', '#219ebc', '#88B2C7', '#ffb703', '#fb8500', '#AD5A00') 36 | ), 37 | prgr = list( 38 | div = c('#231942', '#3D3364', '#584E87', '#7566A0', '#937CB6', '#AAA1BC', '#BDD0B7', '#BFE7B2', '#A6DCAE', '#8ACFAB', '#5FBFAB', '#35B0AB') 39 | ), 40 | lakes = list( 41 | cat = c("#788FCE", "#e07a5f", "#f2cc8f", "#81b29a", "#f4f1de") 42 | ), 43 | spec = list( 44 | div = c("#005f73", "#0a9396", "#94d2bd", "#e9d8a6", "#ee9b00", "#ca6702", "#bb3e03", "#ae2012", "#9b2226") 45 | ), 46 | d5 = list( 47 | cat = c("#ef476f", "#ffd166", "#06d6a0", "#118ab2", "#073b4c") 48 | ), 49 | d10 = list( 50 | cat = c("#788FCE", "#BD8184", "#E6956F", "#F2CC8F", "#A6BA96", "#C5E8E3", "#F4F1DE", "#CDC3D4", "#A88AD2", "#60627C") 51 | ), 52 | mt_fuji = list( 53 | cat = c("#3F3A3F", "#AF8290", "#D3C6DA", "#6F96D0") 54 | ), 55 | remission = list( 56 | div = c('#5C4155', '#865D7B', '#98819D', '#7791A8', '#446783', '#2F485C'), 57 | cat = c('#61542a', '#446783', '#865d7b', '#0a080b', '#7791a8', '#98819d', '#8996a7', '#352b43'), 58 | seq = c('#0a080b', '#352b43', '#865d7b', '#98819d') 59 | ), 60 | leviathan = list( 61 | cat = c('#66211C', '#7C6A3F', '#0C87A2', '#355355'), 62 | seq = c('#C2D2D0', '#97AFAE', '#5F8B8C', '#355355') 63 | ), 64 | crack_the_skye = list( 65 | cat = c('#912716', '#bf7b29', '#4b7d57', '#2f3c68', '#8d7ca9', '#b2b7a6', '#332b28', '#151413') 66 | ), 67 | once_more_around_the_sun = list( 68 | div = c('#720F08', '#C41C0C', '#C47020', '#90952E', '#4D732F', '#2A4831'), 69 | cat = c('#151412', '#720f08', '#d9200d', '#b7a62e', '#cecfc0', '#769879', '#577e2f', '#2a4831') 70 | ), 71 | emperor_of_sand = list( 72 | div = c('#392B26', '#614640', '#978E86', '#EBD0A2', '#F6B45C', '#EF7945', '#C86446', '#984E3A'), 73 | seq = c('#EBD0A2', '#F6B45C', '#EF7945', '#C86446', '#984E3A') 74 | ), 75 | mountains_in_autumn = list( 76 | div = c('#965b0d', '#c06e08', '#da980a', '#355238', '#093c34', '#131c0d'), 77 | cat = c('#c06e08', '#da980a', '#68603c', '#355238', '#093c34', '#131c0d', '#245f84', '#3298d1') 78 | ), 79 | jupiter = list( 80 | div = c('#38343a', '#564b4a', '#d2bca8', '#c59784', '#9c6861') 81 | ), 82 | colorado_mountains = list( 83 | div = c('#49392D', '#664F3D', '#826952', '#9D8468', '#C8A887', '#D8D2CC', '#919AA0', '#545E5F', '#384945', '#1D3335'), 84 | cat = c('#0F1713', '#2B291F', '#49392D', '#664F3D', '#826952', '#9D8468', '#C8A887', '#D8D2CC', '#919AA0', '#545E5F', '#384945', '#1D3335') 85 | ), 86 | graffiti = list( 87 | div = c('#2A1E0F', '#516367', '#7AA3BA', '#D4E2E4', '#E1CF8C', '#CBAA4C', '#BE8311', '#7C490E'), 88 | seq = c('#E1CF8C', '#CBAA4C', '#BE8311', '#7C490E') 89 | ) 90 | ) 91 | 92 | 93 | #' Shows all palettes in the pencil case 94 | #' 95 | #' @param offset Controls the overlapping circles 96 | #' 97 | #' @return graphic of colour palettes 98 | #' @export 99 | #' 100 | #' @importFrom gt cols_hide cols_width 101 | #' 102 | #' @examples 103 | #' show_pencil_case() 104 | show_pencil_case <- function(offset = 50) { 105 | df <- map_dfr(1:length(pencil_case), ~{ 106 | pal <- pencil_case[[.x]][[1]] 107 | bg <- map_chr(2:length(pal), function(k) { 108 | glue("{(k-1)*offset}px 0 0 -1px {pal[k]}") 109 | }) |> 110 | paste0(collapse = ", ") 111 | 112 | tibble( 113 | id = .x, 114 | name = snakecase::to_title_case(names(pencil_case)[[.x]]), 115 | first = pal[1], 116 | bg = bg 117 | ) 118 | }) 119 | 120 | df |> 121 | gt() |> 122 | cols_width( 123 | bg ~ px(700) 124 | ) |> 125 | text_transform( 126 | fn = function(k, i) { 127 | glue("") 133 | }, 134 | locations = cells_body( 135 | columns = bg 136 | ) 137 | ) |> 138 | tab_style( 139 | style = cell_text( 140 | size = px(24), 141 | align = "right", 142 | font = c( 143 | google_font(name = "Lexend"), 144 | default_fonts() 145 | ) 146 | ), 147 | locations = cells_body(columns = c(id, name)) 148 | ) |> 149 | cols_hide("first") |> 150 | tab_options( 151 | column_labels.font.size = 0, 152 | table_body.hlines.width = px(0), 153 | table_body.border.top.width = px(0), 154 | table_body.border.bottom.width = px(0), 155 | heading.border.bottom.width = px(0), 156 | table.border.bottom.width = px(0), 157 | table.border.top.width = px(0), 158 | column_labels.border.top.width = px(0), 159 | column_labels.border.bottom.width = px(0), 160 | data_row.padding = px(10), 161 | data_row.padding.horizontal = px(10) 162 | ) 163 | } 164 | 165 | #' Easily get a palette from the pencil case 166 | #' 167 | #' @param id Number 168 | #' 169 | #' @return A vector of hexcodes 170 | #' @export 171 | #' 172 | #' @examples 173 | #' palette(1) 174 | palette <- function(id) { 175 | pencil_case[[id]][[1]] 176 | } 177 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | # eyedroppeR 6 | 7 | There are fancy ways to extract colours from images but sometimes it's easier if you could simply click on the image and choose the colours you want. 8 | 9 | With `eyedroppeR` you can click on the image and it will return the hex codes of the selected pixel all within R. 10 | 11 | ## Installation 12 | 13 | ```{r, eval = FALSE} 14 | devtools::install_github("doehm/eyedroppeR") 15 | ``` 16 | 17 | ## Usage 18 | 19 | Use `eyedropper` with the following steps: 20 | 21 | 1. Find the image you want to pick colours from online. Local images cn be used as well. 22 | 2. Right-click and 'copy image address'. As an example copy the following image (right-click > copy image address). 23 | 24 | 25 | 26 | 3. Choose how many colours to pick e.g. `n = 8`. 27 | 4. Run `eyedropper(n = 8, img_path = '', label = "Sunset on the South Coast")`. 28 | 5. If it's the first time you have run `eyedropper` complete the calibration setup. It only needs to be done once, just click the top dot and then the bottom dot. (This is temporary until I find an automated way to do it that works for everyone's system setup. It only takes a few seconds, and trust me it's more efficient than selecting the wrong colours and trying to work out why.) 29 | 30 | 31 | 32 | 33 | 34 | 6. Click the 8 desired colours. You can click on either the image itself or the swatch at the bottom. The image will be stretched to the borders of the window, but that's OK. 35 | 7. Done! Copy the returned string and add it to your script and start using `pal`. 36 | 37 | 38 | 39 | The palette, image that is saved at the temporary address, and the label will also be returned by the function. It will also output to console a message that can be copied and pasted directly to your code. That's the best part! 40 | 41 | 42 | ## Use `pixelate` to easily select the right colour 43 | 44 | By setting `pixelate = TRUE` the original image will be converted to a low resolution so that it's easily to select the right colour. The default pixelation is set to 40 (pixels on the x and y). You can adjust that higher or lower as needed. 45 | 46 | 47 | 48 | 49 | ```{r, eval = FALSE} 50 | eyedropper(n = 5, img_path = '', pixelate = TRUE) 51 | ``` 52 | 53 | 54 | 55 | 56 | 57 | When `pixelate` is the swatch banner at the bottom won't be displayed because it's not really needed. 58 | 59 | ## Automatically extract a palette with `extract_pal` 60 | 61 | To speed up the process and if you're not looking for specific colours you can run `extract_pal` to automatically select some for you. 62 | 63 | ```{r, eval = FALSE} 64 | 65 | library(eyedroppeR) 66 | 67 | path <- "https://github.com/doehm/eyedroppeR/blob/main/dev/images/belize.jpg?raw=true" 68 | extract_pal(12, path, label = "Caye Caulker, Belize") 69 | 70 | ``` 71 | 72 | 73 | 74 | ``` 75 | caye_caulker_belize <- c('#477d7c', '#4f967e', '#a1d6f5', '#cbe8f4', '#f0e4c6', '#d8c09c', '#adae46', '#a6954f', '#e14f16', '#a92613', '#cf4959', '#d78462') 76 | 77 | $label 78 | [1] "Caye Caulker, Belize" 79 | 80 | $pal 81 | [1] "#477d7c" "#4f967e" "#a1d6f5" "#cbe8f4" "#f0e4c6" "#d8c09c" "#adae46" "#a6954f" "#e14f16" "#a92613" 82 | [11] "#cf4959" "#d78462" 83 | 84 | $img_path 85 | [1] "C:\\Users\\Dan\\AppData\\Local\\Temp\\RtmpIN1NcN\\file70302f63b83" 86 | ``` 87 | 88 | 89 | Often you won't quite get what you're after and you'll want to use `eyedropper` instead. 90 | 91 | ## Use `swatch()` to view a palette 92 | 93 | ```{r, echo = FALSE} 94 | suppressPackageStartupMessages(library(eyedroppeR)) 95 | ``` 96 | 97 | 98 | ```{r, eval=FALSE} 99 | path <- "https://github.com/doehm/eyedroppeR/blob/main/dev/images/belize.jpg?raw=true" 100 | x <- extract_pal(4, path) 101 | 102 | swatch(x$pal, path) 103 | ``` 104 | 105 | 106 | 107 | ## Other functions 108 | 109 | * `sort_pal`: Allows you to manually sort a palette by clicking on the colours in order. It also allows you to select a specified number of colours if you don't want them all. 110 | 111 | * `show_pencil_case`: There are a bunch of palettes stored in the `pencil_case`. This will plot them all so you can easily choose the one you want. 112 | 113 | * `palette`: Helper to read a palette from the `pencil_case`. e.g. `palette(1)` 114 | 115 | ## Palettes in the `pencil_case` 116 | 117 | ```{r, eval=FALSE} 118 | show_pencil_case() 119 | ``` 120 | 121 | 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # eyedroppeR 3 | 4 | There are fancy ways to extract colours from images but sometimes it’s 5 | easier if you could simply click on the image and choose the colours you 6 | want. 7 | 8 | With `eyedroppeR` you can click on the image and it will return the hex 9 | codes of the selected pixel all within R. 10 | 11 | ## Installation 12 | 13 | ``` r 14 | devtools::install_github("doehm/eyedroppeR") 15 | ``` 16 | 17 | ## Usage 18 | 19 | Use `eyedropper` with the following steps: 20 | 21 | 1. Find the image you want to pick colours from online. Local images cn 22 | be used as well. 23 | 24 | 2. Right-click and ‘copy image address’. As an example copy the 25 | following image (right-click \> copy image address). 26 | 27 | 28 | 29 | 3. Choose how many colours to pick e.g. `n = 8`. 30 | 31 | 4. Run 32 | `eyedropper(n = 8, img_path = '', label = "Sunset on the South Coast")`. 33 | 34 | 5. If it’s the first time you have run `eyedropper` complete the 35 | calibration setup. It only needs to be done once, just click the top 36 | dot and then the bottom dot. (This is temporary until I find an 37 | automated way to do it that works for everyone’s system setup. It 38 | only takes a few seconds, and trust me it’s more efficient than 39 | selecting the wrong colours and trying to work out why.) 40 | 41 | 42 | 43 | 44 | 45 | 6. Click the 8 desired colours. You can click on either the image 46 | itself or the swatch at the bottom. The image will be stretched to 47 | the borders of the window, but that’s OK. 48 | 49 | 7. Done! Copy the returned string and add it to your script and start 50 | using `pal`. 51 | 52 | 53 | 54 | The palette, image that is saved at the temporary address, and the label 55 | will also be returned by the function. It will also output to console a 56 | message that can be copied and pasted directly to your code. That’s the 57 | best part! 58 | 59 | ## Use `pixelate` to easily select the right colour 60 | 61 | By setting `pixelate = TRUE` the original image will be converted to a 62 | low resolution so that it’s easily to select the right colour. The 63 | default pixelation is set to 40 (pixels on the x and y). You can adjust 64 | that higher or lower as needed. 65 | 66 | 67 | 68 | ``` r 69 | eyedropper(n = 5, img_path = '', pixelate = TRUE) 70 | ``` 71 | 72 | 73 | 74 | 75 | 76 | When `pixelate` is the swatch banner at the bottom won’t be displayed 77 | because it’s not really needed. 78 | 79 | ## Automatically extract a palette with `extract_pal` 80 | 81 | To speed up the process and if you’re not looking for specific colours 82 | you can run `extract_pal` to automatically select some for you. 83 | 84 | ``` r 85 | library(eyedroppeR) 86 | 87 | path <- "https://github.com/doehm/eyedroppeR/blob/main/dev/images/belize.jpg?raw=true" 88 | extract_pal(12, path, label = "Caye Caulker, Belize") 89 | ``` 90 | 91 | 92 | 93 | caye_caulker_belize <- c('#477d7c', '#4f967e', '#a1d6f5', '#cbe8f4', '#f0e4c6', '#d8c09c', '#adae46', '#a6954f', '#e14f16', '#a92613', '#cf4959', '#d78462') 94 | 95 | $label 96 | [1] "Caye Caulker, Belize" 97 | 98 | $pal 99 | [1] "#477d7c" "#4f967e" "#a1d6f5" "#cbe8f4" "#f0e4c6" "#d8c09c" "#adae46" "#a6954f" "#e14f16" "#a92613" 100 | [11] "#cf4959" "#d78462" 101 | 102 | $img_path 103 | [1] "C:\\Users\\Dan\\AppData\\Local\\Temp\\RtmpIN1NcN\\file70302f63b83" 104 | 105 | 106 | 107 | Often you won’t quite get what you’re after and you’ll want to use 108 | `eyedropper` instead. 109 | 110 | ## Use `swatch()` to view a palette 111 | 112 | ``` r 113 | path <- "https://github.com/doehm/eyedroppeR/blob/main/dev/images/belize.jpg?raw=true" 114 | x <- extract_pal(4, path) 115 | 116 | swatch(x$pal, path) 117 | ``` 118 | 119 | 120 | 121 | ## Other functions 122 | 123 | - `sort_pal`: Allows you to manually sort a palette by clicking on the 124 | colours in order. It also allows you to select a specified number of 125 | colours if you don’t want them all. 126 | 127 | - `show_pencil_case`: There are a bunch of palettes stored in the 128 | `pencil_case`. This will plot them all so you can easily choose the 129 | one you want. 130 | 131 | - `palette`: Helper to read a palette from the `pencil_case`. 132 | e.g. `palette(1)` 133 | 134 | ## Palettes in the `pencil_case` 135 | 136 | ``` r 137 | show_pencil_case() 138 | ``` 139 | 140 | 141 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 0 note 4 | 5 | * This is a new release. 6 | 7 | ## Test environments 8 | 9 | rhub: 10 | * x86_64-w64-mingw32 (64-bit) 11 | * Windows Server 2022, R-devel, 64 bit 12 | * Ubuntu Linux 20.04.1 LTS, R-release, GCC 13 | * Fedora Linux, R-devel, clang, gfortran 14 | * Debian Linux, R-devel, clang, ISO-8859-15 locale 15 | * Debian Linux, R-devel, GCC 16 | * Debian Linux, R-devel, GCC, no long double 17 | * Debian Linux, R-patched, GCC 18 | * Debian Linux, R-release, GCC 19 | -------------------------------------------------------------------------------- /dev/images/belize-output-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/belize-output-12.png -------------------------------------------------------------------------------- /dev/images/belize-output-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/belize-output-s.png -------------------------------------------------------------------------------- /dev/images/belize-s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/belize-s.jpg -------------------------------------------------------------------------------- /dev/images/belize-swatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/belize-swatch.png -------------------------------------------------------------------------------- /dev/images/belize.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/belize.jpg -------------------------------------------------------------------------------- /dev/images/calibrate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/calibrate.png -------------------------------------------------------------------------------- /dev/images/cat4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/cat4.png -------------------------------------------------------------------------------- /dev/images/catedral-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/catedral-s.png -------------------------------------------------------------------------------- /dev/images/eyedropper.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/eyedropper.gif -------------------------------------------------------------------------------- /dev/images/eyedropper1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/eyedropper1.jpg -------------------------------------------------------------------------------- /dev/images/feature.png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/feature.png.png -------------------------------------------------------------------------------- /dev/images/hex-amatic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/hex-amatic.png -------------------------------------------------------------------------------- /dev/images/misc/graffiti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/misc/graffiti.png -------------------------------------------------------------------------------- /dev/images/mountains-in-autumn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/mountains-in-autumn.png -------------------------------------------------------------------------------- /dev/images/mountains-selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/mountains-selector.png -------------------------------------------------------------------------------- /dev/images/mountains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/mountains.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-blood-mountain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-blood-mountain.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-crack-the-skye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-crack-the-skye.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-empoeror-of-sands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-empoeror-of-sands.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-hushed-and-grim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-hushed-and-grim.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-leviathan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-leviathan.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-once-more-around-the-sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-once-more-around-the-sun.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-remission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-remission.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mastodon-the-hunter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mastodon-the-hunter.png -------------------------------------------------------------------------------- /dev/images/pencil-case/motley-crue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/motley-crue.png -------------------------------------------------------------------------------- /dev/images/pencil-case/mountains-in-autumn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/mountains-in-autumn.png -------------------------------------------------------------------------------- /dev/images/pencil-case/tool-10000-days.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/tool-10000-days.png -------------------------------------------------------------------------------- /dev/images/pencil-case/tool-fear-inoculum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/tool-fear-inoculum.png -------------------------------------------------------------------------------- /dev/images/pencil-case/tool-lateralus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/pencil-case/tool-lateralus.png -------------------------------------------------------------------------------- /dev/images/show-pencil-case.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/show-pencil-case.png -------------------------------------------------------------------------------- /dev/images/snes/mana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/snes/mana.png -------------------------------------------------------------------------------- /dev/images/snes/secret-of-mana-40p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/snes/secret-of-mana-40p.png -------------------------------------------------------------------------------- /dev/images/snes/secret-of-mana-80p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/snes/secret-of-mana-80p.png -------------------------------------------------------------------------------- /dev/images/snes/secret-of-mana-og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/snes/secret-of-mana-og.png -------------------------------------------------------------------------------- /dev/images/snes/secret-of-mana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/snes/secret-of-mana.png -------------------------------------------------------------------------------- /dev/images/sunset-sampler-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/sunset-sampler-s.png -------------------------------------------------------------------------------- /dev/images/sunset-sampler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/sunset-sampler.png -------------------------------------------------------------------------------- /dev/images/sunset-south-coast-output-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/sunset-south-coast-output-s.png -------------------------------------------------------------------------------- /dev/images/sunset-south-coast-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/sunset-south-coast-output.png -------------------------------------------------------------------------------- /dev/images/sunset-south-coast-s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/sunset-south-coast-s.jpg -------------------------------------------------------------------------------- /dev/images/sunset-south-coast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/dev/images/sunset-south-coast.jpg -------------------------------------------------------------------------------- /dev/scripts/dev.R: -------------------------------------------------------------------------------- 1 | 2 | library(tidyverse) 3 | library(magick) 4 | library(grid) 5 | library(gridExtra) 6 | 7 | img_path <- "dev/images/test.png" 8 | 9 | ggplot() + 10 | ggpubr::background_image(image_read(img_path)) 11 | 12 | n <- 6 13 | eye_ls <- list() 14 | for(k in 1:n) { 15 | eye_ls[[k]] <- grid::grid.locator(unit = "npc") 16 | } 17 | 18 | eye_ls 19 | pal <- map_chr(eye_ls, ~{ 20 | coords <- as.numeric(str_remove(reduce(.x, c), "npc")) 21 | coords[2] <- 2-coords[2] 22 | img_dat <- image_data(image_read(img_path)) 23 | dims <- dim(img_dat) 24 | xpx <- round(coords[1]*dims[2]) 25 | ypx <- round(coords[2]*dims[3]) 26 | paste0("#", paste0(img_dat[, xpx, ypx][1:3], collapse = "")) 27 | }) 28 | 29 | scales::show_col(pal) 30 | 31 | 32 | g1 <- tibble( 33 | x = 1:length(x), 34 | y = 1 35 | ) |> 36 | ggplot() + 37 | geom_chicklet(aes(x, y), fill = x, radius = grid::unit(9, "pt")) + 38 | theme_void() 39 | 40 | g2 <- ggplot() + 41 | ggpath::geom_from_path(aes(0, 0, path = path), width = 0.9) + 42 | theme_void() 43 | 44 | g2 + g1 45 | 46 | 47 | 48 | 49 | # 🔪 hex ------------------------------------------------------------------ 50 | 51 | library(showtext) 52 | library(ggtext) 53 | 54 | font_add_google("Caveat", "caveat") 55 | font_add("fa-solid", regular = "C:/Users/Dan/Documents/R/repos/survivorDev/assets/fonts/fontawesome-free-6.2.0-web/webfonts/fa-solid-900.ttf") 56 | showtext_auto() 57 | 58 | txt <- "grey20" 59 | icon <- glue("") 60 | 61 | ggplot() + 62 | geom_from_path(aes(0, -0.1, path = "dev/images/eyedropper.jpg")) + 63 | geom_richtext(aes(0, -0.05, label = icon), size = 100, label.color = NA, fill = NA) + 64 | geom_text(aes(0, -0.2, label = "eyedroppeR"), colour = txt, size = 48, fontface = "bold", family = "caveat") + 65 | # annotate("rect", xmin = 1, xmax = length(pal), ymin = 0.45, ymax = 0.55, fill = "grey90", alpha = 0.5) + 66 | # annotate("text", (length(pal)+1)/2, y = 0.5, label = "---- palette ----", size = 12) + 67 | ylim(-0.5, 0.3) + 68 | theme_void() + 69 | theme(plot.background = element_rect(fill = "skyblue")) 70 | 71 | ggsave("dev/images/hex.png", height = 5, width = 5) 72 | 73 | image_read(cropcircles::hex_crop("dev/images/hex.png")) |> 74 | image_write("dev/images/hex1.png") 75 | 76 | 77 | 78 | # sort pal ---------------------------------------------------------------- 79 | 80 | pal <- y 81 | 82 | show_pal(pal) 83 | 84 | pos_ls <- list() 85 | for(k in 1:length(pal)) { 86 | pos_ls[[k]] <- grid::grid.locator(unit = "npc") 87 | } 88 | 89 | id <- as.numeric(map_chr(pos_ls, "x")) 90 | new_pal <- purrr::map_dbl(id, ~which(sort(id) == .x)) 91 | show_pal(pal[new_pal]) 92 | 93 | 94 | pal <- c('#F4F3E6', '#DDC6B3', '#AD908D', '#866D6C', '#664B39', '#040305', '#C57850', '#1B1B1F', '#35140E', '#698795', '#36353D', '#664B39', '#9C5B37', '#698795', '#EC5921', '#C8121F', '#621615', '#97201A', '#F00C1D', '#565171', '#040305') 95 | -------------------------------------------------------------------------------- /dev/scripts/hex.R: -------------------------------------------------------------------------------- 1 | library(magick) 2 | library(cropcircles) 3 | library(ggtext) 4 | 5 | img <- image_read("dev/images/eyedropper1.jpg") 6 | 7 | img_crop <- hex_crop(img, border_size = 16) 8 | 9 | image_read(img_crop) 10 | 11 | font_add("fa-brands", regular = "C:/Users/Dan/Documents/R/repos/survivorDev/assets/fonts/fontawesome-free-6.2.0-web/webfonts/fa-brands-400.ttf") 12 | font_add("fa-solid", regular = "C:/Users/Dan/Documents/R/repos/survivorDev/assets/fonts/fontawesome-free-6.2.0-web/webfonts/fa-solid-900.ttf") 13 | font_add("fa-reg", regular = "C:/Users/Dan/Documents/R/repos/survivorDev/assets/fonts/fontawesome-free-6.2.0-web/webfonts/fa-regular-400.ttf") 14 | mastodon <- glue("") 15 | twitter <- glue("") 16 | github <- glue("") 17 | space <- glue("'") 18 | space2 <- glue("--") # can't believe I'm doing this 19 | caption <- glue("{mastodon}{space2}@danoehm@{space}fosstodon.org{space2}{twitter}{space2}@danoehm{space2}{github}{space2}doehm/tidytuesday{space2}{floppy}{space2}Bob Ross Paintings data") 20 | 21 | 22 | library(showtext) 23 | 24 | font_add_google("Amatic SC", "amatic") 25 | showtext_auto() 26 | ft <- "amatic" 27 | 28 | ggplot() + 29 | geom_from_path(aes(0.5, 0.5, path = img_crop)) + 30 | annotate("text", x=0.68, y = 0.2, label = "EYEDROPPER", family = ft, size = 70, angle = 30, colour = "black", fontface = "bold") + 31 | annotate("richtext", x=0.51, y = 0.005, label = " doehm/eyedroppeR", 32 | family = ft, size = 14, angle = 30, colour = "black", fontface = "bold", hjust = 0, label.color = NA, fill = NA) + 33 | xlim(0, 1) + 34 | ylim(0, 1) + 35 | theme_void() 36 | 37 | ggsave("dev/images/hex-amatic.png", height = 6, width = 6) 38 | image_read("dev/images/hex-amatic.png") |> 39 | image_fill("none", fuzz = 10) |> 40 | image_fill("none", point = "+1000+5", fuzz = 10) |> 41 | image_write("dev/images/hex-amatic.png") 42 | -------------------------------------------------------------------------------- /dev/scripts/show-pal.R: -------------------------------------------------------------------------------- 1 | 2 | library(ggforce) 3 | library(ggfx) 4 | library(dplyr) 5 | library(tidyr) 6 | library(gt) 7 | library(gtExtras) 8 | library(stringr) 9 | library(magick) 10 | library(showtext) 11 | 12 | font_add_google("Poppins", "poppins") 13 | showtext_auto() 14 | 15 | x <- generate_palette(4, "anime style picture, hi-res, japanese cherry blossoms and mount fuji") 16 | pal <- x$pal 17 | pal <- c('#3F3A3F', '#AF8290', '#D3C6DA', '#6F96D0') 18 | swatch(pal, x$eyedropper$img_path, .padding = 4) 19 | 20 | swatch(pal, "C:\\Users\\danie\\AppData\\Local\\Temp\\RtmpKan5Pm\\file64a02c6c5ea7", .padding = 4) 21 | 22 | x <- extract_pal(6, "https://i.ebayimg.com/images/g/ZJIAAOSwvsVkPy-Z/s-l1600.jpg") 23 | swatch(x$pal, x$img_path, .padding = 1) 24 | 25 | pal <- x$pal[c(1, 3, 6, 8)] 26 | ft <- "poppins" 27 | txt <- c(4, 4, 1, 1) 28 | .folder <- "misty-forest" 29 | 30 | for(k in 1:length(pal)) { 31 | 32 | .rgb <- paste0(as.numeric(t(col2rgb(pal[k]))), collapse = ", ") 33 | 34 | ggplot() + 35 | geom_circle(aes(x0 = 0.5, y0 = 0.5, r = 0.5), fill = pal[k], colour = NA) + 36 | annotate("text", x = 0.5, y = 0.84, label = "Hex", colour = pal[txt[k]], family = ft, size = 20) + 37 | annotate("text", x = 0.5, y = 0.8, label = pal[k], colour = pal[txt[k]], family = ft, size = 32) + 38 | annotate("text", x = 0.5, y = 0.74, label = "RGB", colour = pal[txt[k]], family = ft, size = 20) + 39 | annotate("text", x = 0.5, y = 0.7, label = .rgb, colour = pal[txt[k]], family = ft, size = 32) + 40 | xlim(0, 1) + 41 | ylim(0, 1) + 42 | theme_void() 43 | 44 | ggsave(glue("C:/Users/danie/OneDrive/Pictures/palettes/{.folder}/swatch-{k}.png"), height = 9, width = 9) 45 | 46 | } 47 | 48 | 49 | 50 | 51 | # urls -------------------------------------------------------------------- 52 | 53 | urls <- list( 54 | super_mario_world = "https://i.ebayimg.com/images/g/ZJIAAOSwvsVkPy-Z/s-l1600.jpg", 55 | secret_of_mana = "https://i.ebayimg.com/images/g/vMAAAOSwi85dfvZb/s-l1200.jpg", 56 | super_ghouls_and_ghosts = "https://i.ebayimg.com/images/g/DmQAAOSwH~5kXsAY/s-l1200.webp", 57 | super_probotector = "C:/Users/danie/OneDrive/Pictures/palettes/super-probotector/box-art.png" 58 | ) 59 | 60 | # swatches ---------------------------------------------------------------- 61 | 62 | swatch(pencil_case$super_mario_world$cat, urls$super_mario_world, .padding = 4, .radius = 5) 63 | swatch(pencil_case$secret_of_mana$cat, urls$secret_of_mana, .padding = 4, .radius = 5) 64 | swatch(pencil_case$super_ghouls_and_ghosts$cat, urls$super_ghouls_and_ghosts, .padding = 4, .radius = 5) 65 | swatch(pencil_case$super_probotector$cat, urls$super_probotector, .padding = 4, .radius = 5) 66 | 67 | 68 | 69 | css <- str_remove_all("width: 115px; 70 | height: 100px; 71 | background-image: 72 | radial-gradient(circle at 50px 50px, #F00 0, #F00 50px, transparent 50px), 73 | radial-gradient(circle at 55px 50px, #FF0 0, #FF0 50px, transparent 50px), 74 | radial-gradient(circle at 60px 50px, #080 0, #080 50px, transparent 50px), 75 | radial-gradient(circle at 65px 50px, #00F 0, #00F 50px, transparent 50px);", "\\n[:space:]") 76 | 77 | tibble(x = glue("")) |> 78 | gt() |> 79 | text_transform( 80 | fn = function(x) { 81 | gt::html(x) 82 | }, 83 | locations = cells_body( 84 | columns = everything() 85 | ) 86 | ) 87 | glue("") 88 | 89 | tibble(x = "hi") |> 90 | gt() |> 91 | text_transform( 92 | fn = function(k) { 93 | gt::html(glue("")) 101 | }, 102 | locations = cells_body( 103 | columns = everything() 104 | ) 105 | ) |> 106 | tab_options(data_row.padding.horizontal = px(100)) 107 | 108 | 109 | 110 | pal <- pencil_case$secret_of_mana$cat 111 | map_chr(1:length(pal), function(k) { 112 | glue("{k*offset}px 0 0 -{k}px {pal[k]}") 113 | }) |> 114 | paste0(collapse = ", ") 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /dev/scripts/tests.R: -------------------------------------------------------------------------------- 1 | 2 | test_pal <- function(.label) { 3 | 4 | iris <- iris |> 5 | janitor::clean_names() |> 6 | as_tibble() 7 | 8 | g_hist <- ggplot() + 9 | geom_histogram(aes(displ, fill = class), mpg, colour = "black") + 10 | scale_fill_manual(values = pencil_case[[.label]]$cat) + 11 | theme_minimal() 12 | 13 | g_point <- ggplot() + 14 | geom_point(aes(petal_length, petal_width, colour = species), iris, size = 5, alpha = 0.5) + 15 | scale_colour_manual(values = pencil_case[[.label]]$cat) + 16 | theme_minimal() 17 | 18 | print(g_hist + g_point) 19 | } 20 | 21 | test_pal("remission") 22 | test_pal("leviathan") 23 | -------------------------------------------------------------------------------- /dev/scripts/tsp.R: -------------------------------------------------------------------------------- 1 | # tsp 2 | 3 | pal <- c('#211B1F', '#515979', '#98B878', '#CBD293', '#EEEEB6', '#C4A65F', '#7B8747', '#605216') 4 | show_pal(pal[-7]) 5 | pal <- c('#283746', '#A74822', '#E7DBB8', '#BCB297', '#868D8C', '#576570', '#155EB2', '#11437D') 6 | pal <- sample(pal, 8) 7 | 8 | sort_on <- c("r", "g", "b", "h", "s", "v") 9 | sort_on <- c("r", "v") 10 | 11 | # convert to rgb 12 | rgb <- col2rgb(pal)/255 13 | rownames(rgb) <- c("r", "g", "b") 14 | hsv <- rgb2hsv(rgb, maxColorValue = 1) 15 | 16 | mat <- cbind(t(rgb), t(hsv)) 17 | mat <- mat[,sort_on] 18 | 19 | dmat <- as.matrix(dist(mat)) 20 | 21 | total_dist <- rep(NA, length(pal)) 22 | for(start in 1:length(pal)) { 23 | dmat_k <- dmat[start,] 24 | id <- sort(dmat_k, index.return = TRUE) 25 | total_dist[start] <- sum(diff(dmat[start, id$ix])) 26 | } 27 | 28 | dmat_k <- dmat[which.min(start),] 29 | id <- sort(dmat_k, index.return = TRUE) 30 | pal_ordered <- pal[id$ix] 31 | show_pal(pal_ordered) 32 | 33 | 34 | pal_ordered <- t(hsv) |> 35 | as_tibble() |> 36 | mutate(pal = pal) |> 37 | arrange(h, s, v) 38 | 39 | show_pal(pal_ordered$pal) 40 | -------------------------------------------------------------------------------- /dev/tests/tests.R: -------------------------------------------------------------------------------- 1 | 2 | # tests 3 | 4 | # extract_pal 5 | extract_pal(7, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", "Paw Patrol") 6 | 7 | extract_pal(6, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", "Paw Patrol") 8 | 9 | extract_pal(7, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg") 10 | 11 | extract_pal(7, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", print_output = FALSE) 12 | 13 | 14 | # eyedropper 15 | eyedropper(3, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", "Paw Patrol") 16 | 17 | eyedropper(4, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", "Paw Patrol") 18 | 19 | eyedropper(3, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg") 20 | 21 | eyedropper(3, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", print_output = FALSE) 22 | 23 | eyedropper(3, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", calibrate = TRUE) 24 | 25 | eyedropper(3, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", pixelate = TRUE) 26 | 27 | eyedropper(3, "https://mediaproxy.tvtropes.org/width/1200/https://static.tvtropes.org/pmwiki/pub/images/tumblr_static_byogb2dbbsowcgc4gowcwwggg.jpg", pixelate = 20) 28 | -------------------------------------------------------------------------------- /eyedroppeR.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: 43c09e2c-564a-4a94-917a-74da686646a0 3 | 4 | RestoreWorkspace: Default 5 | SaveWorkspace: Default 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | PackageRoxygenize: rd,collate,namespace,vignette 23 | -------------------------------------------------------------------------------- /inst/images/calibration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/inst/images/calibration.png -------------------------------------------------------------------------------- /inst/images/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/inst/images/hex.png -------------------------------------------------------------------------------- /inst/images/sunset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doehm/eyedroppeR/321d372fc2a866e3287a321118dfa27df50046e6/inst/images/sunset.png -------------------------------------------------------------------------------- /man/choose_font_colour.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{choose_font_colour} 4 | \alias{choose_font_colour} 5 | \title{Choose font colour} 6 | \usage{ 7 | choose_font_colour(bg, light = "#ffffff", dark = "#000000", threshold = 170) 8 | } 9 | \arguments{ 10 | \item{bg}{Background} 11 | 12 | \item{light}{The light text colour} 13 | 14 | \item{dark}{The dark text colour} 15 | 16 | \item{threshold}{The threshold for switching} 17 | } 18 | \value{ 19 | hex code 20 | } 21 | \description{ 22 | Choose font colour 23 | } 24 | -------------------------------------------------------------------------------- /man/extract_pal.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/eyedropper.R 3 | \name{extract_pal} 4 | \alias{extract_pal} 5 | \title{Extracts palette from an image} 6 | \usage{ 7 | extract_pal( 8 | n, 9 | img_path, 10 | label = NULL, 11 | sort = "auto", 12 | plot_output = TRUE, 13 | save_output = FALSE, 14 | print_output = TRUE, 15 | swatch_radius = 50 16 | ) 17 | } 18 | \arguments{ 19 | \item{n}{Number of colours to extract} 20 | 21 | \item{img_path}{Path to image. If `NULL` the function will read from the clipboard} 22 | 23 | \item{label}{Label for the palette.} 24 | 25 | \item{sort}{Sort method. Either 'manual' or 'auto'} 26 | 27 | \item{plot_output}{logical. Default \code{TRUE}. Plots the output of the extracted palette.} 28 | 29 | \item{save_output}{logical. Default \code{FALSE}. Save the output of the extracted palette.} 30 | 31 | \item{print_output}{Print output to console to easily copy and paste into your script.} 32 | 33 | \item{swatch_radius}{Radius of the image for the swatch. Default 50 to make it a circle. Use 5 for rounded edges.} 34 | } 35 | \value{ 36 | Returns a character vector of hex codes 37 | } 38 | \description{ 39 | The image is read in using \code{magick}, converted to RGB and clustered using kmeans. The user 40 | must specify the number of clusters. The cluster centroids become the palette values. 41 | The function will ask the user to sort the palette values after clustering 42 | } 43 | \examples{ 44 | path <- file.path(system.file(package = "eyedroppeR"), "images", "sunset.png") 45 | 46 | \dontrun{ 47 | extract_pal(8, path) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /man/eyedropper.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/eyedropper.R 3 | \name{eyedropper} 4 | \alias{eyedropper} 5 | \title{Eyedropper} 6 | \usage{ 7 | eyedropper( 8 | n, 9 | img_path = NULL, 10 | label = NULL, 11 | inc_palette = TRUE, 12 | n_swatches = 24, 13 | print_output = TRUE, 14 | calibrate = FALSE, 15 | swatch_radius = 50, 16 | pixelate = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{n}{Number of colours to extract from the image} 21 | 22 | \item{img_path}{Path to image. Can be local or from a URL. If left \code{NULL}, 23 | \code{eyedropper} will read the image address directly from the clipboard.} 24 | 25 | \item{label}{Label for the palette.} 26 | 27 | \item{inc_palette}{Logical. If \code{TRUE} it will automatically extract a palette 28 | first and then you can select the desired colours.} 29 | 30 | \item{n_swatches}{Number of swatches to extract from the image prior to selecting colours.} 31 | 32 | \item{print_output}{Print output to console to easily copy and paste into your script.} 33 | 34 | \item{calibrate}{Set to `TRUE` to calibrate the plot coordinates. Given the monitor 35 | resolution, scaling, etc it can throw off the pixel selection. Runs but default the first 36 | time the function is used.} 37 | 38 | \item{swatch_radius}{Radius of the image for the swatch. Default 50 to make it a circle. Use 5 for rounded edges.} 39 | 40 | \item{pixelate}{If `TRUE` or some numeric value, a low-res image will be displayed so that it is easier to select the right colour. Pixelate 41 | is set to `40` pixels. To make it more pixelated use a lower number of pixels e.g. `pixelate = 40`. If 42 | pixelate is used the palette selector at the bottom of the image won't be shown.} 43 | } 44 | \value{ 45 | A character vector of hex codes 46 | } 47 | \description{ 48 | Plots an image and allows the user to click on the image to 49 | return the hex of the pixel. Can select multiple colours at 50 | once by setting \code{n}. 51 | } 52 | \details{ 53 | Use \code{eyedropper} with the following steps: 54 | \enumerate{ 55 | \item{Find the image you want to pick colours from online.} 56 | \item{Right-click and 'copy image address'.} 57 | \item{Choose how many colours to pick e.g. \code{n = 5}.} 58 | \item{Run \code{pal <- eyedropper(n = 5, img_path = 'paste-image-path-here')}.} 59 | \item{Click 5 areas of the image. Thes image will be stretched to the borders of the window, but that's OK.} 60 | \item{Done! Copy the returned string / message and add it to you script and start using \code{pal}} 61 | } 62 | 63 | The first time the function is run it will initiate a calibration set. This is so the `y` coordinates are 64 | scaled properly as this can depend on the monitors resolution, scaling, etc. In only takes a couple of seconds 65 | and you only have to do it once. 66 | 67 | Make sure you click as near as practicable to the top and bottom of the border of the windew within the dot. 68 | } 69 | \examples{ 70 | \dontrun{ 71 | 72 | path <- file.path(system.file(package = "eyedroppeR"), "images", "hex.png") 73 | 74 | # Run eyedropper and click on 4 colours 75 | pal <- eyedropper(n = 4, path) 76 | 77 | pal 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /man/generate_palette.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/generate-palette.R 3 | \name{generate_palette} 4 | \alias{generate_palette} 5 | \title{Generate palette} 6 | \usage{ 7 | generate_palette(n, prompt) 8 | } 9 | \arguments{ 10 | \item{n}{Number of colours in the palette} 11 | 12 | \item{prompt}{Prompt} 13 | } 14 | \value{ 15 | A vector of hex codes 16 | } 17 | \description{ 18 | ⚠️ DEPRECATED: openai has been archived and I have to work out how to generate 19 | images with {ellmer} and the new APIs. 20 | } 21 | \examples{ 22 | # x <- generate_palette(4, 'a trail in a dense rainforest') 23 | } 24 | -------------------------------------------------------------------------------- /man/make_output.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{make_output} 4 | \alias{make_output} 5 | \title{Makes eyedroppers output} 6 | \usage{ 7 | make_output(obj = NULL, pal, img_path) 8 | } 9 | \arguments{ 10 | \item{obj}{Output from \code{extract_pal} or \code{eyedropper}} 11 | 12 | \item{pal}{Palette} 13 | 14 | \item{img_path}{Image path} 15 | } 16 | \value{ 17 | ggplot object 18 | } 19 | \description{ 20 | Plots the palette and places the image and label over the top. 21 | } 22 | -------------------------------------------------------------------------------- /man/min_max.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{min_max} 4 | \alias{min_max} 5 | \title{Min-max scale function} 6 | \usage{ 7 | min_max(x, a, b, a0 = NULL, b0 = NULL) 8 | } 9 | \arguments{ 10 | \item{x}{Vector of values} 11 | 12 | \item{a}{Min} 13 | 14 | \item{b}{Max} 15 | 16 | \item{a0}{Min bound} 17 | 18 | \item{b0}{Max bound} 19 | } 20 | \value{ 21 | numeric vector 22 | } 23 | \description{ 24 | Min-max scale function 25 | } 26 | -------------------------------------------------------------------------------- /man/modify_saturation.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{modify_saturation} 4 | \alias{modify_saturation} 5 | \title{Modify the saturation of a colour palette} 6 | \usage{ 7 | modify_saturation(cols, sat = 1.2) 8 | } 9 | \arguments{ 10 | \item{cols}{Vector of colours} 11 | 12 | \item{sat}{Factor to adjust the saturation} 13 | } 14 | \value{ 15 | A vector of hex codes 16 | } 17 | \description{ 18 | Modify the saturation of a colour palette 19 | } 20 | -------------------------------------------------------------------------------- /man/palette.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pencil-case.R 3 | \name{palette} 4 | \alias{palette} 5 | \title{Easily get a palette from the pencil case} 6 | \usage{ 7 | palette(id) 8 | } 9 | \arguments{ 10 | \item{id}{Number} 11 | } 12 | \value{ 13 | A vector of hexcodes 14 | } 15 | \description{ 16 | Easily get a palette from the pencil case 17 | } 18 | \examples{ 19 | palette(1) 20 | } 21 | -------------------------------------------------------------------------------- /man/paste_pal_code.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{paste_pal_code} 4 | \alias{paste_pal_code} 5 | \title{Copy + Pasteable palette vector} 6 | \usage{ 7 | paste_pal_code(pal, label = NULL) 8 | } 9 | \arguments{ 10 | \item{pal}{Palette vector} 11 | 12 | \item{label}{Label} 13 | } 14 | \value{ 15 | a message 16 | } 17 | \description{ 18 | Prints a message to console so you can easily copy and paste the palette 19 | } 20 | -------------------------------------------------------------------------------- /man/pencil_case.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pencil-case.R 3 | \docType{data} 4 | \name{pencil_case} 5 | \alias{pencil_case} 6 | \title{Pencil Case} 7 | \format{ 8 | An object of class \code{list} of length 24. 9 | } 10 | \usage{ 11 | pencil_case 12 | } 13 | \description{ 14 | A list of palettes 15 | } 16 | \keyword{datasets} 17 | -------------------------------------------------------------------------------- /man/show_pal.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{show_pal} 4 | \alias{show_pal} 5 | \title{Show palette} 6 | \usage{ 7 | show_pal(pal) 8 | } 9 | \arguments{ 10 | \item{pal}{Palette. Vector of hex codes} 11 | } 12 | \value{ 13 | ggplot 14 | } 15 | \description{ 16 | Plots the supplied palette for quick inspection 17 | } 18 | \examples{ 19 | pal <- c('#57364e', '#566f1b', '#97a258', '#cac58b', '#dbedd5') 20 | show_pal(pal) 21 | } 22 | -------------------------------------------------------------------------------- /man/show_pencil_case.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pencil-case.R 3 | \name{show_pencil_case} 4 | \alias{show_pencil_case} 5 | \title{Shows all palettes in the pencil case} 6 | \usage{ 7 | show_pencil_case(offset = 50) 8 | } 9 | \arguments{ 10 | \item{offset}{Controls the overlapping circles} 11 | } 12 | \value{ 13 | graphic of colour palettes 14 | } 15 | \description{ 16 | Shows all palettes in the pencil case 17 | } 18 | \examples{ 19 | show_pencil_case() 20 | } 21 | -------------------------------------------------------------------------------- /man/sort_pal.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{sort_pal} 4 | \alias{sort_pal} 5 | \title{Manually sort a palette} 6 | \usage{ 7 | sort_pal(pal, n = NULL, label = NULL, print_output = TRUE) 8 | } 9 | \arguments{ 10 | \item{pal}{Palette. Character vector of hex codes} 11 | 12 | \item{n}{Number of colours to choose} 13 | 14 | \item{label}{Label for the palette.} 15 | 16 | \item{print_output}{Print output to console to easily copy and paste into your script.} 17 | } 18 | \value{ 19 | Character vector 20 | } 21 | \description{ 22 | The palette is displayed in the plotting window where you can click 23 | the colours in the order you want to sort them. The sorted palette 24 | will be returned. This saves you copy/pasting hex codes in your script. 25 | } 26 | \examples{ 27 | \dontrun{ 28 | pal <- sample(c('#57364e', '#566f1b', '#97a258', '#cac58b', '#dbedd5')) 29 | sort_pal(pal) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /man/sort_pal_auto.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{sort_pal_auto} 4 | \alias{sort_pal_auto} 5 | \title{Auto palette sort} 6 | \usage{ 7 | sort_pal_auto(pal, label, plot_output = FALSE) 8 | } 9 | \arguments{ 10 | \item{pal}{Input palette} 11 | 12 | \item{label}{Label for the palette.} 13 | 14 | \item{plot_output}{Logical. Default \code{FALSE}.} 15 | } 16 | \value{ 17 | Returns a character vector of hex codes 18 | } 19 | \description{ 20 | Automatically sorts the palette. May not give the desired result. If not you 21 | can run `sort_pal()` to manually sort. 22 | } 23 | \examples{ 24 | pal <- sample(colours(), 8) 25 | sort_pal_auto(pal, 'test') 26 | } 27 | -------------------------------------------------------------------------------- /man/swatch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{swatch} 4 | \alias{swatch} 5 | \title{Swatch of colour palette} 6 | \usage{ 7 | swatch( 8 | pal, 9 | img = NULL, 10 | label = NULL, 11 | padding = 0, 12 | radius = 20, 13 | ncols = 8, 14 | img_shadow = TRUE, 15 | shape = "original" 16 | ) 17 | } 18 | \arguments{ 19 | \item{pal}{Vector of colours} 20 | 21 | \item{img}{Image address. Either local file or URL} 22 | 23 | \item{label}{Label for the palette.} 24 | 25 | \item{padding}{To add whitespace to the top of image} 26 | 27 | \item{radius}{The radius of the feature image. Choose 50 for a circle, less then 50 for rounded square/rectangle.} 28 | 29 | \item{ncols}{Number of cols in a row} 30 | 31 | \item{img_shadow}{Logical. Apply a shadow to the feature image output.} 32 | 33 | \item{shape}{Either 'original' for the original image dimensions or "square" 34 | to crop to square with rounded corners. A high enough radius will turn the square to a circle.} 35 | } 36 | \value{ 37 | html doc 38 | } 39 | \description{ 40 | Swatch of colour palette 41 | } 42 | \examples{ 43 | url <- "https://github.com/doehm/eyedroppeR/raw/main/dev/images/sunset-south-coast.jpg" 44 | x <- extract_pal(4, url) 45 | swatch(x$pal, url) 46 | } 47 | --------------------------------------------------------------------------------