Convert RGB to RGBA - colors

I am trying to play with HTML5 canvas, and I want to get the color of the fillStyle right from my CSS, but also with some transparency. When I use jQuery to read CSS style, a rgb value is returned instead of hex.
fillColor = $(".myClass").css("background-color"); // return rgb(x, x, x)
At first it look it's convinient to me that I don't need to convert it again, but I find that I cannot add the alpha to the RGB value, so I have to convert it into Hex, then convert it to RGBA with an alpha value.
function convertHexToRGB(hex)
{
var red = hex.substr(1, 2), green = hex.substr(3, 2), blue = hex.substr(5, 2), alpha = arguments[1];
color = "rgba(" + parseInt(red, 16) + "," + parseInt(green, 16) + "," + parseInt(blue, 16) + "," + alpha + ")";
return color;
}
Now that make my code looks stink and inefficient, is there any way to add a alpha value to a RGB value. Or some function that converts RGB to RGBA?

Couldn't you just retrieve the opacity value from your css like this:
fillOpacity = $(".myClass").css("opacity"); // return 0.x
And then translate the opacity value into the 'A' channel you need:
var alpha = fillOpacity * 255;
And then append that to you rgb value (in int form)?
EDIT:
I should mention that the HTML5 canvas element works with bitmaps effectively so whilst you can do some combination bits and bobs, so there is no direct concept of layers, in that you can't (as far as I'm aware) tell a canvas element to be r,g,b,a because there is nothing for it to combine with underneath. Unless of course you are trying to place a semi-opaque canvas over a background image of some form. Or, combine an underlying image via say, multiply blending with your original CSS colour, to achieve the affect of a semi-transparent layer over an image.

Related

Calculate a colour in a linear gradient

I'd like to implement something like the powerpoint image below. A gradient that goes between three values.
It starts at A (-1), the mid point is B (0), and the end is C (1).
I have realised that I can save some effort by calculating the 'start' as a-to-b, and the 'end' as b-to-c. I can do as 2 sets of 2 gradients, instead of 1 gradient with three values.
But I'm stumped (despite googling) on how to get from one colour to another - ideally in the RGB colour space.
I'd like to be able to have something like this -
const colourSpace = (value, startColor, endColor) => {...}
colorSpace(-0.25, red, yellow) // some sort of orangey color
colorSpace(1, yellow, green) // fully green
colorSpace(0.8, yellow, green) // mostly green
This isn't a front-end application, so no CSS gradients - which is what google was mostly referencing.
Thanks all,
Ollie
If you aren't too worried about being perceptually consistent across the color space (you would need to work in something like LAB mode to do that), you can just take the linear interpolation in RGB space. Basically you take a distance (between 0 and 1), multiply it by the different in the coordinates, and add it to the first one. This will allow you to find arbitrary points (i.e colors) along the line between any two colors.
For example between red and yellow:
let canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
let rgb1 = [255, 0, 0] // red
let rgb2 = [255, 255, 0] // yellow
function getPoint(d, a1, a2) {
// find a color d% between a1 and a2
return a1.map((p, i) => Math.floor(a1[i] + d * (a2[i] - a1[i])))
}
// for demo purposes fill a canvas
for (let i = 0, j = 0; i < 1; i += .002, j++) {
let rgb = getPoint(i, rgb1, rgb2)
ctx.fillStyle = `rgba(${rgb.join(",")}, 1)`
ctx.fillRect(j, 0, 1, 200);
}
<canvas id="canvas" width="500"></canvas>
You can repeat this to get multiple 'stops' in the gradient.
I ended up using Chroma for converting between colour spaces.

Setting color variable

I need to compare colors. I want to set a color into a variable and then compare that it a value obtained using getPixel.
However, the following does not work. It seems like ImageJ does not know that the value in basecolor is a color.
basecolor = 0xFFFFFF;
rightpixel = getPixel(x, y);
if (rightpixel == basecolor) count++;
Your problem is in getPixel which does not yield a color written in hex.
I present to you your best friend on ImageJ : the built-in macro functions code
https://imagej.nih.gov/ij/developer/macro/functions.html
which documents built-in pixel functions such as getPixel().
For getPixel(), it is stated "Note that pixels in RGB images contain red, green and blue components that need to be extracted using shifting and masking. See the Color Picker Tool macro for an example that shows how to do this. ", and the Color Picker Tool macro tells us how to go from color "bits" to RGB.
So if you wish to compare colors, you do :
basecolor=newArray(0,0,0);
rightpixel = getPixel(x,y);
//from the Color Picker Tool macro
//converts what getPixel returns into RGB (values red, green and blue)
if (bitDepth==24) {
red = (v>>16)&0xff; // extract red byte (bits 23-17)
green = (v>>8)&0xff; // extract green byte (bits 15-8)
blue = v&0xff; // extract blue byte (bits 7-0)
}
//compare the color with your color
if(red==basecolor[0] && green==basecolor[1] && blue==basecolor[2]){
print("Same Color");
count++;
}
//you can also work with hex by converting the rgb to hex and then
//comparing the strings like you did

How to use HSLA colors with RMagick?

How to set an arbitrary HSLA color instead of gray20?
draw = Magick::Draw.new
draw.font_family = 'arial'
draw.pointsize = 12
draw.gravity = Magick::CenterGravity
draw.annotate(#canvas, size,size, x,y, text) { self.fill = 'gray20' }
Also, using gc.rectangle, how to set the HSLA color of the fill?
gc = Magick::Draw.new
gc.fill ????
gc.rectangle(x,y, x + size,y + size)
From the RMagick documentation:
Many RMagick methods expect color name arguments or return color names. A color name can be
an X11 color name such as "red", "chocolate", or "lightslategray".
an SVG color name (similar to the X color names), or
a string in one of the formats shown in the following table.
...
hsla(h,s,l,a)
And HSL documentation
hsla(33.3333%, 100%, 50%, 1.0) green with an alpha value of 1.0
hsla(120, 255, 127.5, 1.0) green with an alpha value of 1.0
So, use a string: fill 'hsl(0%,100%,100%,1)'

Given an RGB value, how do I create a tint (or shade)?

Given an RGB value, like 168, 0, 255, how do I create tints (make it lighter) and shades (make it darker) of the color?
Among several options for shading and tinting:
For shades, multiply each component by 1/4, 1/2, 3/4, etc., of its
previous value. The smaller the factor, the darker the shade.
For tints, calculate (255 - previous value), multiply that by 1/4,
1/2, 3/4, etc. (the greater the factor, the lighter the tint), and add that to the previous value (assuming each.component is a 8-bit integer).
Note that color manipulations (such as tints and other shading) should be done in linear RGB. However, RGB colors specified in documents or encoded in images and video are not likely to be in linear RGB, in which case a so-called inverse transfer function needs to be applied to each of the RGB color's components. This function varies with the RGB color space. For example, in the sRGB color space (which can be assumed if the RGB color space is unknown), this function is roughly equivalent to raising each sRGB color component (ranging from 0 through 1) to a power of 2.2. (Note that "linear RGB" is not an RGB color space.)
See also Violet Giraffe's comment about "gamma correction".
Some definitions
A shade is produced by "darkening" a hue or "adding black"
A tint is produced by "ligthening" a hue or "adding white"
Creating a tint or a shade
Depending on your Color Model, there are different methods to create a darker (shaded) or lighter (tinted) color:
RGB:
To shade:
newR = currentR * (1 - shade_factor)
newG = currentG * (1 - shade_factor)
newB = currentB * (1 - shade_factor)
To tint:
newR = currentR + (255 - currentR) * tint_factor
newG = currentG + (255 - currentG) * tint_factor
newB = currentB + (255 - currentB) * tint_factor
More generally, the color resulting in layering a color RGB(currentR,currentG,currentB) with a color RGBA(aR,aG,aB,alpha) is:
newR = currentR + (aR - currentR) * alpha
newG = currentG + (aG - currentG) * alpha
newB = currentB + (aB - currentB) * alpha
where (aR,aG,aB) = black = (0,0,0) for shading, and (aR,aG,aB) = white = (255,255,255) for tinting
HSV or HSB:
To shade: lower the Value / Brightness or increase the Saturation
To tint: lower the Saturation or increase the Value / Brightness
HSL:
To shade: lower the Lightness
To tint: increase the Lightness
There exists formulas to convert from one color model to another. As per your initial question, if you are in RGB and want to use the HSV model to shade for example, you can just convert to HSV, do the shading and convert back to RGB. Formula to convert are not trivial but can be found on the internet. Depending on your language, it might also be available as a core function :
RGB to HSV color in javascript?
Convert RGB value to HSV
Comparing the models
RGB has the advantage of being really simple to implement, but:
you can only shade or tint your color relatively
you have no idea if your color is already tinted or shaded
HSV or HSB is kind of complex because you need to play with two parameters to get what you want (Saturation & Value / Brightness)
HSL is the best from my point of view:
supported by CSS3 (for webapp)
simple and accurate:
50% means an unaltered Hue
>50% means the Hue is lighter (tint)
<50% means the Hue is darker (shade)
given a color you can determine if it is already tinted or shaded
you can tint or shade a color relatively or absolutely (by just replacing the Lightness part)
If you want to learn more about this subject: Wiki: Colors Model
For more information on what those models are: Wikipedia: HSL and HSV
I'm currently experimenting with canvas and pixels... I'm finding this logic works out for me better.
Use this to calculate the grey-ness ( luma ? )
but with both the existing value and the new 'tint' value
calculate the difference ( I found I did not need to multiply )
add to offset the 'tint' value
var grey = (r + g + b) / 3;
var grey2 = (new_r + new_g + new_b) / 3;
var dr = grey - grey2 * 1;
var dg = grey - grey2 * 1
var db = grey - grey2 * 1;
tint_r = new_r + dr;
tint_g = new_g + dg;
tint_b = new_b _ db;
or something like that...

How to alter brightness of a single rgb color simply and easily via php?

A quesion about RGB color and finding the simplest, tiniest, php conversion code for manipulating the lightness/darkness of a given RGB hue.
Imagine a variable $colorA containning a valid six char RGB color, like F7A100 which we want to make a bit lighter and/or darker:
$color = B1B100; // original RGB color manually set.
Then, at any page have that color bit darker/lighter on the fly:
$colorX = someFunction($color, +10); // original color 10 steps lighter
$colorY = someFunction($color, -25); // original color 25 steps darker
What would be YOUR way of solving this? Keep the RGB as is or first change it to HSL? Hints and suggestions are welcome. Your sample/code is welcome too.
This really focuses to the TINIES / SIMPLES / SHORTEST possible code to just make the same hue bit darker/lighter.
I deliberately do not suggest my code, as I want to keep possibilities open in here.
The absolutely simplest solution is to add some constant (like 1) to each part of the color representation: [R, G, B]. This is due to the fact that max values of all [R, G, B] represent white, while min values - black. In pseudo-code (assuming 255 is max, sorry, I don't know PHP):
lighter(R, G, B) = [
min(255, R + 1),
min(255, G + 1),
min(255, B + 1)
]
You must keep in mind though that this transformation is way too simplistic and the proper implementation would be to convert to HSL/HSB, increase H and transform back to RGB.
For slight alteration of brightness you can convert the hexadecimal values to decimal, manipulate them and convert back to hexadecimal like this:
function alterBrightness($color, $amount) {
$rgb = hexdec($color); // convert color to decimal value
//extract color values:
$red = $rgb >> 16;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;
//manipulate and convert back to hexadecimal
return dechex(($red + $amount) << 16 | ($green + $amount) << 8 | ($blue + $amount));
}
echo alterColor('eeeeee', -10); //outputs e4e4e4
Beware that this code does not handle overflow for one color - if one color value becomes less than 0 or more than 255 you will get an invalid color value. This should be easy enough to add.
For drastic changes in brightness, convert to HSL and manipulate the lightness.
Using the functions from the Drupal code, this can be done like this:
$hsl = _color_rgb2hsl(_color_unpack('eeeeee'));
$hsl[2] -= 10;
$rgb = _color_pack(_color_hsl2rgb($hsl));
echo $rgb; //outputs e4e4e4

Resources