R: RGB to HSV Conversion

rgb2hsv {grDevices} | R Documentation

## RGB to HSV Conversion

### Description

`rgb2hsv` transforms colors from RGB space (red/green/blue) into HSV space (hue/saturation/value).

### Usage

    rgb2hsv(r, g = NULL, b = NULL, gamma = 1, maxColorValue = 255)

### Arguments

`r` | vector of ‘red’ values in [0,M], (M =`maxColorValue`) or 3-row rgb matrix.
`g` | vector of ‘green’ values, or `NULL` when `r` is a matrix.
`b` | vector of ‘blue’ values, or `NULL` when `r` is a matrix.
`gamma` | a gamma-correction (supposedly applied to the r,g,b values previously), see `hsv(...., gamma)`.
`maxColorValue` | number giving the maximum of the RGB color values range. The default `255` corresponds to the typical `0:255` RGB coding as in `col2rgb()`.

### Details

Value (brightness) gives the amount of light in the color.
Hue describes the dominant wavelength.
Saturation is the amount of Hue mixed into the color.

### Value

A matrix with a column for each color. The three rows of the matrix indicate hue, saturation and value and are named `"h"`, `"s"`, and `"v"` accordingly.

### Author(s)

R interface by Wolfram Fischer wolfram@fischer-zim.ch;
C code mainly by Nicholas Lewin-Koh nikko@hailmail.net.

### See Also

`hsv`, `col2rgb`, `rgb`.

### Examples

    ## These (saturated, bright ones) only differ by hue
    (rc <- col2rgb(c("red", "yellow","green","cyan", "blue", "magenta")))
    (hc <- rgb2hsv(rc))
    6 * hc["h",] # the hues are equispaced

    (rgb3 <- floor(256 * matrix(stats::runif(3*12), 3,12)))
    (hsv3 <- rgb2hsv(rgb3))
    ## Consistency :
    stopifnot(rgb3 == col2rgb(hsv(h=hsv3[1,], s=hsv3[2,], v=hsv3[3,])),
              all.equal(hsv3, rgb2hsv(rgb3/255, maxColorValue = 1)))

    ## A (simplified) pure R version -- originally by Wolfram Fischer --
    ## showing the exact algorithm:
    rgb2hsvR <- function(rgb, gamma = 1, maxColorValue = 255)
    {
        if(!is.numeric(rgb)) stop("rgb matrix must be numeric")
        d <- dim(rgb)
        if(d[1] != 3) stop("rgb matrix must have 3 rows")
        n <- d[2]
        if(n == 0) return(cbind(c(h=1,s=1,v=1))[,0])
        rgb <- rgb/maxColorValue
        if(gamma != 1) rgb <- rgb ^ (1/gamma)

        ## get the max and min
        v <- apply( rgb, 2, max)
        s <- apply( rgb, 2, min)
        D <- v - s # range

        ## set hue to zero for undefined values (gray has no hue)
        h <- numeric(n)
        notgray <- ( s != v )

        ## blue hue
        idx <- (v == rgb[3,] & notgray )
        if (any (idx))
            h[idx] <- 2/3 + 1/6 * (rgb[1,idx] - rgb[2,idx]) / D[idx]
        ## green hue
        idx <- (v == rgb[2,] & notgray )
        if (any (idx))
            h[idx] <- 1/3 + 1/6 * (rgb[3,idx] - rgb[1,idx]) / D[idx]
        ## red hue
        idx <- (v == rgb[1,] & notgray )
        if (any (idx))
            h[idx] <-       1/6 * (rgb[2,idx] - rgb[3,idx]) / D[idx]

        ## correct for negative red
        idx <- (h < 0)
        h[idx] <- 1+h[idx]

        ## set the saturation
        s[! notgray] <- 0;
        s[notgray] <- 1 - s[notgray] / v[notgray]

        rbind( h=h, s=s, v=v )
    }

    ## confirm the equivalence:
    all.equal(rgb2hsv (rgb3),
              rgb2hsvR(rgb3), tol=1e-14) # TRUE

[Package grDevices version 2.8.1 Index]