Convert RGBA to RGB taking background into consideration [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert RGBA color to RGB
I'm trying to convert a RGBA color, with a alpha < 1 into a solid RGB representation taking into account the background color.
Using the algorithm provided at this question I manage to get correct conversion to a solid RGB color - BUT ONLY when alpha = 0.5.
Here's my test code:
<!DOCTYPE html>
<html>
<head></head>
<body>
<script type="text/javascript">
// Basic RGB(A) to CSS property value
function _toString(obj) {
var type = 'rgb', out = obj.red + ', ' + obj.green + ', ' + obj.blue;
if (obj.alpha !== undefined) {
type += 'a';
out += ', ' + obj.alpha;
}
return type + '(' + out + ')';
}
// Background color, assume this is always RGB
var bg = {red: 255, green: 51, blue: 0};
// RGBA color
var RGBA = {red: 0, green: 102, blue: 204, alpha: 0};
// Output RGB
var RGB = {red: null, green: null, blue: null};
// Just a cache...
var alpha;
while (RGBA.alpha < 1) {
alpha = 1 - RGBA.alpha;
RGB.red = Math.round((alpha * (RGBA.red / 255) + ((1 - RGBA.alpha) * (bg.red / 255))) * 255);
RGB.green = Math.round((alpha * (RGBA.green / 255) + ((1 - RGBA.alpha) * (bg.green / 255))) * 255);
RGB.blue = Math.round((alpha * (RGBA.blue / 255) + ((1 - RGBA.alpha) * (bg.blue / 255))) * 255);
document.write('<div style="display: block; width: 150px; height: 100px; background-color: ' + _toString(bg) + '">\
<div style="color: #fff; width: 50px; height: 50px; background-color: ' + _toString(RGBA) + '"><small>RGBA<br>' + RGBA.alpha + '</small></div>\
<div style="color: #fff; width: 50px; height: 50px; background-color: ' + _toString(RGB) + '"><small>RGB<br>' + RGBA.alpha + '</small></div>\
</div>');
// Increment alpha
RGBA.alpha += 0.25;
}
</script>
</body>
</html>
Running the above in both Chrome and Firefox results in successful RGBA->RGB when alpha is 0.5, any deviation away from 0.5 results in a mismatch, very subtle if the deviation is very small (i.e. it's possible to notice the issue when alpha is 0.55).
I've rewritten the logic several times, fully expanding the logic into its most basic parts but I've failed to be successful.

It looks like you're trying to use the common method for blending, but the incremental loop is throwing me off. Pulled from the OpenGL FAQ:
"The typical use described above [for blending] modifies the incoming color by its associated alpha value and modifies the destination color by one minus the incoming alpha value. The sum of these two colors is then written back into the framebuffer."
So instead of a while loop, use:
alpha = 1 - RGBA.alpha;
RGB.red = Math.round((RGBA.alpha * (RGBA.red / 255) + (alpha * (bg.red / 255))) * 255);
RGB.green = Math.round((RGBA.alpha * (RGBA.green / 255) + (alpha * (bg.green / 255))) * 255);
RGB.blue = Math.round((RGBA.alpha * (RGBA.blue / 255) + (alpha * (bg.blue / 255))) * 255);

Related

Random RGB color generator with JavaScript

I am trying to get something like this:
rbg(random, random, random);
Now when I put in Math.floor(Math.random() * 255) + 1 into the area, it works but for some reason most of the numbers are stuck in 255 and rarely change.
My code is:
function colorGen() {
document.getElementById("color1").style.backgroundColor = 'rgb('+
Math.floor(Math.random() * 255) + 1 + ',' + Math.floor(Math.random() * 255) + 1
+',' + Math.floor(Math.random() * 255) + 1 +')';
}
When I put brackets () around - ( Math.floor(Math.random() * 255) + 1 ) -, it works much better.
Why is this so?
#Xufox has the right answer in the comment there. For clarity, you'll want to restructure your code a little (and let's also fix that bug where you'll never get zero for any channel due to the +1):
function colorGen() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
document.getElementById("color1").style.backgroundColor = "rgb(" + r + "," + g + "," + b + ")";
}
When you use +1 inside a string it will generate as string and not as mathematical expression when you use () it generate as mathematical expression.
My reccomand:
Use params to random colors
function colorGen() {
var color1=Math.floor(Math.random() * 255) + 1;
var color2=Math.floor(Math.random() * 255) + 1;
var color3=Math.floor(Math.random() * 255) + 1;
document.getElementById("color1").style.backgroundColor = 'rgb('+ color1
+ ',' + color2
+',' + color3 +')';
}
<button id="color1" onclick="colorGen()">click me to change color</button>
When you “add” 1, it gets concatenated as a string, since you’re starting with "rgb(" +, and the result of “string + number” will be another string. Wrapping numerical expressions in parentheses makes the + operator do addition instead of concatenation.
The reason you get 255 is because the numbers you generate end up looking like this:
11
21
31
41
…
2531
2541
2551
The backgroundColor setter caps 8-bit values (ranging from 0 to 255) at a maximum of 255 (and a minimum of 0). This means, setting element.style.backgroundColor = "rgb(10000, -10000, 128)" results in a backgroundColor of "rgb(255, 0, 128)"
So when Math.floor(Math.random() * 255) generates a number from 1 to 25, then the highest resulting number becomes 251, which is below 255. Any other value — i.e. from 26 to 255 — results in a value higher than 255, so it just becomes 255 automatically.
The parentheses make the arithmetic expression to be evaluated before the concatenation.

How do you get random RGB in Javascript? [duplicate]

This question already has answers here:
Random color generator
(64 answers)
Closed 8 years ago.
I have this code that uses RGB color selection and I was wondering how to make JavaScript do a random color using the RGB method and remember it throughout the code.
EDIT: I tried this:
var RGBColor1 = (Math.round, Math.random, 255)
var RGBColor2 = (Math.round, Math.random, 255)
var RGBColor3 = (Math.round, Math.random, 255)
but it doesn't work. Help please!
EDIT 2: The code uses this:
g.fillStyle="rgba(R,G,B,0.2)";
g.strokeStyle="rgba(R,G,B,0.3)";
E();
The letters represent the color of RGB.
EDIT 3: The doubles of this question are using HEX values, not RGB values.
function random_rgba() {
var o = Math.round, r = Math.random, s = 255;
return 'rgba(' + o(r()*s) + ',' + o(r()*s) + ',' + o(r()*s) + ',' + r().toFixed(1) + ')';
}
var color = random_rgba();
g.fillStyle = color;
g.strokeStyle = color;
FIDDLE
const randomBetween = (min, max) => min + Math.floor(Math.random() * (max - min + 1));
const r = randomBetween(0, 255);
const g = randomBetween(0, 255);
const b = randomBetween(0, 255);
const rgb = `rgb(${r},${g},${b})`; // Collect all to a css color string
Here's a very simple method that works off of a single random number generation. Basically, it generates a number between 0 and 0xfffff (or 2^24, the highest number you can get from 24 bits). The highest value you can get from 8 bits is 255. This algorithm takes the left-most 8 bits of the random number for RED, the middle 8 bits for GREEN, and the last 8 bits for BLUE, using all 24 bits of the random number.
function getRandomRgb() {
var num = Math.round(0xffffff * Math.random());
var r = num >> 16;
var g = num >> 8 & 255;
var b = num & 255;
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
for (var i = 0; i < 10; i++) {
console.log(getRandomRgb());
}
Console output (sample):
rgb(2, 71, 181)
rgb(193, 253, 111)
rgb(172, 127, 203)
rgb(203, 53, 175)
rgb(226, 45, 44)
rgb(102, 181, 19)
rgb(92, 165, 221)
rgb(250, 40, 162)
rgb(250, 252, 120)
rgb(67, 59, 246)
Adapted from source.

Add third color level to Javascript/JQuery HTML Table Heatmap

I'm using a HTML table heatmap JQuery script by:
http://www.designchemical.com/blog/index.php/jquery/jquery-tutorial-create-a-flexible-data-heat-map/
I've been able to modify it and get it cleaned up and working with our data sets. However, the current script only allows for two colors and does not calculate the medium with a standard deviation to include a third color such as yellow.
Here is the current script below:
<script type="text/JavaScript">
$(document).ready(function () {
// Function to get the Max value in Array
Array.max = function (array) {
return Math.max.apply(Math, array);
};
// get all values
var counts = $('.heatmap tbody td').not('.first_row').map(function () {
return parseInt($(this).text().replace(/,/g, "").replace(/\(|\)/g, ""));
}).get();
// return max value
var max = Array.max(counts);
// red color for lowest data
xr = 251;
xg = 121;
xb = 105;
// green color for highest data
yr = 138;
yg = 251;
yb = 107;
n = 100;
// add classes to cells based on nearest 10 value
$('.heatmap tbody td').not('.first_row').each(function () {
var val = parseInt($(this).text().replace(/,/g, "").replace(/\(|\)/g, ""));
var pos = parseInt((Math.round((val / max) * 100)).toFixed(0));
red = parseInt((xr + ((pos * (yr - xr)) / (n - 1))).toFixed(0));
green = parseInt((xg + ((pos * (yg - xg)) / (n - 1))).toFixed(0));
blue = parseInt((xb + ((pos * (yb - xb)) / (n - 1))).toFixed(0));
clr = 'rgb(' + red + ',' + green + ',' + blue + ')';
$(this).css({
backgroundColor: clr
});
});
});
</script>
The heatmap currently goes from red to green and I want to add a calculation that adds yellow for the medium range. I've created a jsFiddle here: http://jsfiddle.net/7z8D4/ with the script and heatmap table structure I'm using.
For Example, if I have the following data sets, it should be colored such as:
1 red
2 red
3 pink
4 pink
5 yellow
6 yellow
7 lime green
8 lime green
9 green
10 green
I really appreciate any insights on this. :)
red (at 0%) to yellow (at 50%) to green (at 100%)
var pos = val / (max * 1.0);
red = Math.round(pos < 0.5 ? 255 : ((1 - pos) * 2) * 255);
green = Math.round(pos < 0.5 ? (pos * 2) * 255 : 255);
blue = 0;
I've created a pretty simple JavaScript function (see http://jsfiddle.net/4vCfc/) that provides an RGB color on a Red through yellow and then blue color gradient that I'm using for a heatmap to demonstrate usage of fields in a form.
Here's the function definition:
function getHeatColorAsRbg(percentage) //percent is a number between 0 and 1.
{
//RED - YELLOW (255, 0, 0) to (255, 255, 0)
//THEN YELLOW TO BLUE (255,255,0) to (0, 0, 255)
var red = 0;
var blue = 0;
var green = 0;
//Two cases - 1.0 down to 0.5 and 0.5 down to 0.
if(percentage >= 0.5)
{
red = 255;
green = Math.round(255 * 2 * (1 - percentage));
blue = 0;
}
else
{
blue = 255 - Math.round((percentage/0.5)*255);
red = 255 - blue;
green = red;
}
return "rgb(" + red + "," + green + "," + blue + ")";
}
Without finding the Minimum in array your methods are just half-methods.))

Run trough one rgba to another based on percentage

Let's say i have this both rgba codes:
rgba(150, 160, 255, 1) and rgba(195, 0, 0, 1)
I want to pass from one to another by a 0/100 percentage.
0% will be rgba(150, 160, 255, 1)
100% will be rgba(195, 0, 0, 1)
I'm trying to make a HeatMap with this.
How can i determinate what rgba will be at let say... 30%!?
For each value x in your code:
x = min_x + (max_x - min_x)*percentage/100
(Note: max_x can be smaller than min_x)
For each component, you just have to do start+(end-start)*percentage
So for your 30% you'd have:
red = 150 + (195 - 150) * 0.3 = 205.5
green = 160 + (0 - 160) * 0.3 = 112
blue = 255 + (0 - 255) * 0.3 = 178.5
alpha = 1 + (1 - 1) * 0.3 = 1
Your final colour will therefore be rgba(206, 112, 179, 1)

Javascript hex number interpolation between several numbers

I'm creating a "characters remaining" type counter for a site of mine, and am trying to get smooth color transitions.
How would I go about creating a function to obtain the hex value for a color if I pass the maximum number (in this case 300) and the current char count assuming the pattern is green, yellow, orange, red?
This is in Javascript. Here is what I have so far:
function commentcounter(val) {
max = 300;
if(val >= max){
color = '#FF0000';
}else if(val > (max / 2)){
color = '#FF9900';
}else{
color = '#00FF00';
}
display = '<span style="color:' + color + '">' + val + '/' + max + '</span>';
document.getElementById('counter').innerHTML = display;
}
As you can see, this doesn't really interpolate, just goes from green to orange to red.
You need to interpolate each color component individually from 0 to 255 (or vice-versa).
This will be much easier if you use color: rgb(0, 255, 0).
"rgb("+Math.round(Math.min((((chars+(max/2))*2/max)-1)*255,255))+","+Math.round(Math.min(((chars*-2/max)+2)*255,255))+",0)";
This worked better than rgb() for me:
var pct = val / max;
var h = pct * 120;
var newColor = 'hsl(' + h + ', 80%, 50%)';
http://jsfiddle.net/ehUHp/

Categories

Resources