Skip to content

Commit

Permalink
Fix #23
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasp85 committed May 8, 2024
1 parent 6aa6387 commit 7872ff9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 52 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# farver (development version)

* make sure output channels are always named (#23)

# farver 2.1.1

* Added input checking to a range of functions to guard against segfaults with
Expand Down
58 changes: 29 additions & 29 deletions R/convert_colour.R
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
#' Convert between colour spaces
#'
#' This function lets you convert between different representations of colours.
#'
#' This function lets you convert between different representations of colours.
#' The API is reminiscent of [grDevices::convertColor()], but the performance is
#' much better. It is not assured that `grDevices::convertColor()` and
#' much better. It is not assured that `grDevices::convertColor()` and
#' `convert_colour()` provide numerically equivalent conversion at 16bit level as
#' the formula used are potentially slightly different. For all intend and
#' the formula used are potentially slightly different. For all intend and
#' purpose, the resulting colours will be equivalent though.
#'
#'
#' @section Handling of non-finite and out of bounds values:
#' `NA`, `NaN`, `-Inf`, and `Inf` are treated as invalid input and will result
#' in `NA` values for the colour. If a given colourspace has finite bounds in
#' `NA`, `NaN`, `-Inf`, and `Inf` are treated as invalid input and will result
#' in `NA` values for the colour. If a given colourspace has finite bounds in
#' some of their channels, the input will be capped before conversion, and the
#' output will be capped before returning, so that both input and output colours
#' are valid colours in their respective space. This means that converting back
#' and forth between two colourspaces may result in a change in the colour if
#' the gamut of one of the spaces is less than the other.
#'
#' @param colour A numeric matrix (or an object coercible to one) with colours
#' encoded in the rows and the different colour space values in the columns. For
#' all colourspaces except `'cmyk'` this will mean a matrix with three columns -
#'
#' @param colour A numeric matrix (or an object coercible to one) with colours
#' encoded in the rows and the different colour space values in the columns. For
#' all colourspaces except `'cmyk'` this will mean a matrix with three columns -
#' for `'cmyk'` it means four columns.
#'
#' @param from,to The input and output colour space. Allowed values are: `"cmy"`,
#' `"cmyk"`, `"hsl"`, `"hsb"`, `"hsv"`, `"lab"` (CIE L*ab), `"hunterlab"`
#' (Hunter Lab), `"oklab"`, `"lch"` (CIE Lch(ab) / polarLAB), `"luv"`,
#'
#' @param from,to The input and output colour space. Allowed values are: `"cmy"`,
#' `"cmyk"`, `"hsl"`, `"hsb"`, `"hsv"`, `"lab"` (CIE L*ab), `"hunterlab"`
#' (Hunter Lab), `"oklab"`, `"lch"` (CIE Lch(ab) / polarLAB), `"luv"`,
#' `"rgb"` (sRGB), `"xyz"`, `"yxy"` (CIE xyY), `"hcl"` (CIE Lch(uv) / polarLuv),
#' or `"oklch"` (Polar form of oklab)
#'
#' @param white_from,white_to The white reference of the from and to colour
#' space. Will only have an effect for relative colour spaces such as Lab and
#'
#' @param white_from,white_to The white reference of the from and to colour
#' space. Will only have an effect for relative colour spaces such as Lab and
#' luv. Any value accepted by [as_white_ref()] allowed.
#'
#' @return A numeric matrix with the same number of rows as `colour` and either
#' 3 or 4 columns depending on the value of `to`. If `colour` is given as a
#'
#' @return A numeric matrix with the same number of rows as `colour` and either
#' 3 or 4 columns depending on the value of `to`. If `colour` is given as a
#' `data.frame` the output will be a data.frame as well
#'
#'
#' @note This function and [convertColor()] are not
#' numerically equivalent due to rounding errors, but for all intend and purpose
#' they give the same results.
#'
#'
#' @seealso [grDevices::convertColor()], [grDevices::col2rgb()]
#'
#'
#' @export
#'
#'
#' @examples
#' spectrum <- decode_colour(rainbow(10))
#' spec_lab <- convert_colour(spectrum, 'rgb', 'lab')
#' spec_lab
#'
#'
#' # Convert between different white references
#' convert_colour(spec_lab, 'lab', 'lab', white_from = 'D65', white_to = 'F10')
#'
#'
convert_colour <- function(colour, from, to, white_from = 'D65', white_to = white_from) {
res <- convert_c(colour, colourspace_match(from), colourspace_match(to), as_white_ref(white_from), as_white_ref(white_to))
colnames(res) <- colour_dims[[to]]
colnames(res) <- colour_dims[[tolower(to)]]
if (is.data.frame(colour)) res <- as.data.frame(res)
res
}

convert_c <- function(colour, from, to, white_from, white_to) {
.Call(`farver_convert_c`, as.matrix(colour), as.integer(from), as.integer(to),
.Call(`farver_convert_c`, as.matrix(colour), as.integer(from), as.integer(to),
as.numeric(white_from), as.numeric(white_to))
}
46 changes: 23 additions & 23 deletions R/decode.R
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
#' Decode RGB hex-strings into colour values
#'
#'
#' This is a version of [grDevices::col2rgb()] that returns the colour values in
#' the standard form expected by farver (matrix with a row per colour). As with
#' [encode_colour()] it can do colour conversion on the fly, meaning that you can
#' [encode_colour()] it can do colour conversion on the fly, meaning that you can
#' decode a hex string directly into any of the supported colour spaces.
#'
#'
#' @inheritSection convert_colour Handling of non-finite and out of bounds values
#'
#'
#' @param colour A character vector of hex-encoded values or a valid colour name
#' as given in [grDevices::colours()].
#' @param alpha If `TRUE` the alpha channel will be returned as well (scaled
#' between 0 and 1). If no alpha channel exists in the colour it will be
#' @param alpha If `TRUE` the alpha channel will be returned as well (scaled
#' between 0 and 1). If no alpha channel exists in the colour it will be
#' assumed 1. If `FALSE` any alpha channel is ignored.
#' @param to The output colour space. Allowed values are: `"cmy"`,
#' `"cmyk"`, `"hsl"`, `"hsb"`, `"hsv"`, `"lab"` (CIE L*ab), `"hunterlab"`
#' (Hunter Lab), `"oklab"`, `"lch"` (CIE Lch(ab) / polarLAB), `"luv"`,
#' @param to The output colour space. Allowed values are: `"cmy"`,
#' `"cmyk"`, `"hsl"`, `"hsb"`, `"hsv"`, `"lab"` (CIE L*ab), `"hunterlab"`
#' (Hunter Lab), `"oklab"`, `"lch"` (CIE Lch(ab) / polarLAB), `"luv"`,
#' `"rgb"` (sRGB), `"xyz"`, `"yxy"` (CIE xyY), `"hcl"` (CIE Lch(uv) / polarLuv),
#' or `"oklch"` (Polar form of oklab)
#' @param white The white reference of the output colour space. Will only have
#' an effect for relative colour spaces such as Lab and luv. Any value accepted
#' @param white The white reference of the output colour space. Will only have
#' an effect for relative colour spaces such as Lab and luv. Any value accepted
#' by [as_white_ref()] allowed.
#' @param na_value A valid colour string or `NA` to use when `colour` contains
#' `NA` elements. The general approach in farver is to carry `NA` values over,
#' but if you want to mimick [col2rgb()] you should set
#' but if you want to mimick [col2rgb()] you should set
#' `na_value = 'transparent'`, i.e. treat `NA` as transparent white.
#'
#'
#' @return A numeric matrix with a row for each element in `colour` and either
#'
#'
#' @return A numeric matrix with a row for each element in `colour` and either
#' 3, 4, or 5 columns depending on the value of `alpha` and `to`.
#'
#'
#' @family encoding and decoding functions
#'
#'
#' @export
#'
#' @examples
#'
#' @examples
#' # basic use
#' decode_colour(c('#43e1f6', 'steelblue', '#67ce9fe4'))
#'
#'
#' # Return alpha as well (no alpha value is interpreted as 1)
#' decode_colour(c('#43e1f6', 'steelblue', '#67ce9fe4'), alpha = TRUE)
#'
#'
#' # Decode directly into specific colour space
#' decode_colour(c('#43e1f6', 'steelblue', '#67ce9fe4'), to = 'lch')
#'
#'
decode_colour <- function(colour, alpha = FALSE, to = 'rgb', white = 'D65', na_value = NA) {
if (to != 'rgb') {
white <- as_white_ref(white)
}
alpha <- isTRUE(alpha)
colours <- decode_c(colour, alpha, colourspace_match(to), white, na_value)
colnames(colours) <- c(colour_dims[[to]], if (alpha) 'alpha' else NULL)
colnames(colours) <- c(colour_dims[[tolower(to)]], if (alpha) 'alpha' else NULL)
colours
}

Expand Down

0 comments on commit 7872ff9

Please sign in to comment.