Convert RGBA to HEX - html

Given a css color value like:
rgba(0, 0, 0, 0.86)
How do I convert that to a RGB hex value that takes the alpha component into account, assuming a white background?

Since alpha value both attenuates the background color and the color value, something like this could do the trick:
function rgba2rgb(RGB_background, RGBA_color)
{
var alpha = RGBA_color.a;
return new Color(
(1 - alpha) * RGB_background.r + alpha * RGBA_color.r,
(1 - alpha) * RGB_background.g + alpha * RGBA_color.g,
(1 - alpha) * RGB_background.b + alpha * RGBA_color.b
);
}
(Try it interactively: https://marcodiiga.github.io/rgba-to-rgb-conversion)

Assuming that the values are 0...1 per channel.
And assuming that the abbreviation in the method / function call in the question correspond to the arguments, the following should work.
A = 255 * 0.86
R = 255 * 0
G = 255 * 0
B = 255 * 0
Note you may want to change how it rounds off here as it may give inaccuracies in colours.
At this point, the values are in fact still floating point values, but casting them to a byte or a char (depending on language), should in theory work.
var _A = (byte)219.3
var _R = (byte)0
var _G = (byte)0
var _B = (byte)0
Now all you have to do is convert them to a hexadecimal string each, and concatenate them (ARGB) and put a nice little hash tag in front (#)
In C# you could do something akin to:
var hexString = string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", _A, _R, _G, _B);
Yielding a final result of something like:
#DB000000

you can convert red,green and blue individually using .toString(16) and then combine the result in a case, if you just want to convert a rgb to hex... since you are searching to convert rgba to hex i thought it would be better to convert the rgba to rgb and then to hex as i did in the following Fiddle, which would also consider the background-color of the parent div.

The rgba value you are having is:
rgba(0, 0, 0, 0.86)
First 0 stands for RED
Second 0 stands for GREEN
Third 0 stands for BLUE
and the last digit 0.86 stands for alpha/opacity
Here are some links for rgb to hex converter:
http://www.javascripter.net/faq/rgbtohex.htm
http://www.rgbtohex.net/
http://www.yellowpipe.com/yis/tools/hex-to-rgb/color-converter.php
with you digits 0, 0, 0. The Hex Code will be
#000000
Following is the code for low opacity with a white background
HTML
<div id="parentDiv">
<div id="childDiv">
</div>
</div>
CSS
#parentDiv
{
height:100px; /* The property of Child is Inherit */
width:100px; /* The property of Child is Inherit*/
background-color:#ffffff;
}
#childDiv
{
height:inherit;
width:inherit;
background-color:#000000;
opacity:0.86;
filter:alpha(opacity="86");
}
Now the parent Div is the background with
#ffffff (White color)

Related

CSS equivalent for Text Tint

I'm trying to export files from Adobe InDesign to basic HTML + CSS.
A user can select some text and change the text colour. Using the InDesign SDK I can fetch the RGB values for that colour and in the CSS file declare color: rgb(R,G,B) which works perfectly fine.
You can also change the text tint value. Upto now I was just taking the tint value, converting it to the range 0-1 and in the CSS putting an entry as color: rgba(R,G,B,Tint)
During testing I realized that tint = 0 should actually mean white text, but it didn't show on the HTML because A (in RGBA) = 0 means transparent!!!
Anyone knows how to handle tint values in CSS?
There is no tint, hue,saturation or brightness in CSS. You should "build" these properties into your RGB color. To apply tint on your RGB, use this expression:
when R,G,B are from 0..255, tint from 0..1
new R = tint*R + (1-tint)*255;
new G = tint*G + (1-tint)*255;
new B = tint*B + (1-tint)*255;
Tint is the convex combination of your color and white color. See Wikipedia.
Ivan Kuckir's solution is correct, I'm just adding an explanation as it might help someone later.
Explanation - Tint means adding white to a colour.
Tint %X implies = there is a mixture of white and your color where white is (100-X)% of the mixture and your color constitutes X% in the mixture.
Thus, say for color Red (255,0,0) and tint .6 => Create a mixture with 60% RED and 40% WHITE.
Hence, the resulting mixture should be something like -
.6 * RED + .4 * WHITE
This can be followed for mixing any 2 colors (C1, C2) in a certain proportion = p:q
new R = p/(p+q) * R1 + q/(p+q) * R2
new G = p/(p+q) * G1 + q/(p+q) * G2
new B = p/(p+q) * B1 + q/(p+q) * B2
For tint, (R2,G2,B2) = (255,255,255)
new R = tint*R + (1-tint)*255;
new G = tint*G + (1-tint)*255;
new B = tint*B + (1-tint)*255;
Unfortunately there's no way of doing text tint using plain CSS.
Colors in CSS can be specified by the following methods:
Hexadecimal colors - #RRGGBB
RGB colors - rgb(red, green, blue)
RGBA colors - rgb(red, green, blue, alpha)
HSL colors - hsl(hue, saturation, lightness)
HSLA colors - hsl(hue, saturation, lightness, alpha)
Predefined/Cross-browser color names - 'red','aqua', etc
Source
So you would need a JS script for that.
(See Ivan Kuckir's answer);
You can use CSS variables to do this - see this example. Define R, G, B and tint as four different CSS variables.
body {
--content-R: 100%;
--content-G: 0%;
--content-B: 0%;
--text-tint: 0.5;
}
You can then use this as:
.content {
color: rgb(
calc(var(--content-R) * var(--text-tint) + 100% - 100% * var(--text-tint)),
calc(var(--content-G) * var(--text-tint) + 100% - 100% * var(--text-tint)),
calc(var(--content-B) * var(--text-tint) + 100% - 100% * var(--text-tint))
);
}
Note:
It only works if the colors are defined using percentages 0% to 100% (instead of integers 0 to 255). This is because the rgb function will accept floating point numbers for percentages. Trying to use integer 255 would have a calculated value of say 255 * 0.5 which is 127.5 which is not a valid integer color value (so the rgb color won't work). You also need to be careful with the limitations of the calc function.
You can independently vary the colours and tints on child elements using the cascading styles (it didn't work when I put the rgb calc into its own body CSS variable).
I only tried this on Chrome 65 - other browsers may act differently!
It might have negative performance implications on the CSS style engine within the browser?
.Less has a very easy implementation for this.
After you add the .less files you can darken and lighten at will
.element{
color:darken(#444,20%);
// or
// color: lighten(#444,50%);
}
taken from less.org
// Variables
#link-color: #428bca; // sea blue
#link-color-hover: darken(#link-color, 10%);

What does the mask parameter do in the threshold method of the BitmapData class?

I'm trying to replace a color and colors near it in a bitmap.
threshold() seems to work but it seems to be that you have to specify the exact color "==" or all colors before or after the exact color "<" & ">" plus "<=" and ">=". I am hoping that the mask parameter will help me find a way to find a color and a dynamic range of colors before and after it to be replaced. What is its intended usage?
Per the comment below Example 1 and 2:
bit.threshold(bit, bit.rect, point, ">", 0xff000000, 0xffff0000, 0x00FF0000);
bit.threshold(bit, bit.rect, point, ">", 0xff000000, 0xffff0000, 0x00EE0000);
If you're trying to do a flood fill, I don't think the mask parameter will help you. The mask parameter lets you ignore parts of the color in the test. In your case, you want to take into account all the channels of the color, you just want the matching to be fuzzy.
e.g. If you want to replace all pixels where the red component is 0, you can set mask to 0x00FF0000, so it will ignore the other channels.
The implementation pseudo-code probably looks something like this:
input = readPixel()
value = input & mask
if(value operation threshold)
{
writePixel(color)
}
Neither of your samples will produce anything because the mask limits the values to be between 0x00000000 and 0x00FF0000, then tests if they're greater than 0xFF000000.
I have also done this and eventually, I have found it best to create my own threshold-method. You can find it below. Everything is explained in comment.
//_snapshot is a bitmapData-object
for(var i:int = 0; i <= _snapshot.width; i++)
{
for(var j:int = 0; j <= _snapshot.height; j++)
{
//We get the color of the current pixel.
var _color:uint = _snapshot.getPixel(i, j);
//If the color of the selected pixel is between certain values set by the user,
//set the filtered pixel data to green.
//Threshold is a number (can be quite high, up to 50000) to look for adjacent colors in the colorspace.
//_colorToCompare is the color you want to look for.
if((_colorToCompare - (100 * _threshold)) <= _color && _color <= (_colorToCompare + (100 * _threshold)))
{
//This sets the pixel value.
_snapshot.setPixel(i, j, 0x00ff00);
}
else
{
//If the pixel color is not within the desired range, set it's value to black.
_snapshot.setPixel(i, j, 0x000000);
}
}
}

Can alpha transparency fill or stroke style be set separately from RGB in Canvas HTML5?

In Canvas/HTML5, I know you can use RGBA to set color and alpha transparency for fillStyle or strokeStyle. You can also use just RGB to set color with no alpha channel. is there a way you can change the alpha value of an item without also supplying the color.
My example would be wanting to change the fillStyle or strokeStyle above a canvas section whose color was random or no longer known. Is there a way to change the alpha through another attribute or by passing nothing to the color (e.g. ctx.fillStyle = 'rgba(,,,alphaValue)';)
There are a few ways.
First, the globalAlpha attribute of the context.
As you ask in the title, it will allow transparency to be set independently of fill or stroke.
You could then use the getImageData on a point to find out the color and save that info, clear that area with clearRect, set globalAlpha, and then redraw that area with the color you saved.
Of course, you don't need globalAlpha at all. You could also do the above and instead of setting global alpha, just modify the alpha of the color that you saved.
If you want to make a large, complex area of canvas more transparent, then you will want to change the globalAlpha and then draw the canvas onto itself using drawImage.
Here's an example of that. I draw two rectangles, then make a rectangular area between them more transparent.
You can use a function to extract the RGB values from whatever is set for the style you are interested in, and then set it with the desired alpha:
var rgb = hexToRgb(canvasCtx.fillStyle);
canvasCtx.fillStyle = "rgba(" + rgb["r"] + "," +rgb["g"] + "," + rgb["b"] + ",0.2)";
You can use an hexToRgb function like this one, taken from this other answer:
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}

HTML Color Codes: Red to Yellow to Green

I would like to come up with as many HEX HTML values to have a smooth color gradient from red to green:
I would like this to be similar to the following:
http://www.utexas.edu/learn/html/colors.html
I don't have the best eye for color choices, so I'm hoping a standard chart is already put together showing how to transition from red through yellow to green smoothly.
On that website "1 of 6" is most similar to what I'm looking for, but that example is limited to 11 colors:
(1) FF0000 Red,
(2) FF3300 Red(Orange)
(3) ff6600
(4) ff9900
(5) FFCC00 Gold
(6) FFFF00 Yellow
(7) ccff00
(8) 99ff00
(9) 66ff00
(10) 33ff00
(11) 00FF00 Lime
It would be great to be able to double the number of colors, but yet make them transition smoothly.
Thanks for any insights and help.
Depending on how many colors you want to end up with, the solution is just to keep incrementing the green value by a certain amount, and then when green is maxed (FF), decrement the red value repeatedly by the same amount.
Pseudo-code:
int red = 255; //i.e. FF
int green = 0;
int stepSize = ?//how many colors do you want?
while(green < 255)
{
green += stepSize;
if(green > 255) { green = 255; }
output(red, green, 0); //assume output is function that takes RGB
}
while(red > 0)
{
red -= stepSize;
if(red < 0) { red = 0; }
output(red, green, 0); //assume output is function that takes RGB
}
Generating by hand, you can simply increment by 16, like so:
FF0000
FF1000
FF2000
FF3000
FF4000
FF5000
FF6000
FF7000
FF8000
FF9000
FFA000
FFB000
FFC000
FFD000
FFE000
FFF000
FFFF00 //max, step by 15
F0FF00 //cheat, start with a -15 to simplify the rest
E0FF00
D0FF00
C0FF00
B0FF00
A0FF00
90FF00
80FF00
70FF00
60FF00
50FF00
40FF00
30FF00
20FF00
10FF00
The best way to do this is to understand what the hex color codes actually mean. Once you grasp this, it will become clear how to make gradients of arbitrary smoothness. The hex color codes are triplets representing the red, green and blue components of the color respectively. So for example in the color FF0000, the red component is FF, the green component is 00 and the blue component is 00. FF0000 looks red because the red component is dialed all the way up to FF and the green and blue are dialed all the way down to 00. Similarly, pure green is 00FF00 and pure blue is 0000FF. If you convert the hex numbers to decimal, you'll get a value in between 0 and 255.
So now how does one make a gradient transitioning from red to yellow to green? Easy; you take the end points, decide how many steps you want in between, and then evenly step through each of the 3 color channels to transition from one color to the next color. Below is an example going in steps of 11 hex (17 in decimal):
FF0000 <-- red
FF1100
FF2200
FF3300
FF4400
FF5500
FF6600
FF7700
FF8800
FF9900
FFAA00
FFBB00
FFCC00
FFDD00
FFEE00
FFFF00 <-- yellow
EEFF00
DDFF00
CCFF00
BBFF00
AAFF00
99FF00
88FF00
77FF00
66FF00
55FF00
44FF00
33FF00
22FF00
11FF00
00FF00 <-- green
Here is nice looking gradient from green to red
/* Green - Yellow - Red */
.gradient_0 {background: #57bb8a;}
.gradient_5 {background: #63b682;}
.gradient_10 {background: #73b87e;}
.gradient_15 {background: #84bb7b;}
.gradient_20 {background: #94bd77;}
.gradient_25 {background: #a4c073;}
.gradient_30 {background: #b0be6e;}
.gradient_35 {background: #c4c56d;}
.gradient_40 {background: #d4c86a;}
.gradient_45 {background: #e2c965;}
.gradient_50 {background: #f5ce62;}
.gradient_55 {background: #f3c563;}
.gradient_60 {background: #e9b861;}
.gradient_65 {background: #e6ad61;}
.gradient_70 {background: #ecac67;}
.gradient_75 {background: #e9a268;}
.gradient_80 {background: #e79a69;}
.gradient_85 {background: #e5926b;}
.gradient_90 {background: #e2886c;}
.gradient_95 {background: #e0816d;}
.gradient_100 {background: #dd776e;}
/* Red - Yellow - Green */
.anti-gradient_100 {background: #57bb8a;}
.anti-gradient_95 {background: #63b682;}
.anti-gradient_90 {background: #73b87e;}
.anti-gradient_85 {background: #84bb7b;}
.anti-gradient_80 {background: #94bd77;}
.anti-gradient_75 {background: #a4c073;}
.anti-gradient_70 {background: #b0be6e;}
.anti-gradient_65 {background: #c4c56d;}
.anti-gradient_60 {background: #d4c86a;}
.anti-gradient_55 {background: #e2c965;}
.anti-gradient_50 {background: #f5ce62;}
.anti-gradient_45 {background: #f3c563;}
.anti-gradient_40 {background: #e9b861;}
.anti-gradient_35 {background: #e6ad61;}
.anti-gradient_30 {background: #ecac67;}
.anti-gradient_25 {background: #e9a268;}
.anti-gradient_20 {background: #e79a69;}
.anti-gradient_15 {background: #e5926b;}
.anti-gradient_10 {background: #e2886c;}
.anti-gradient_5 {background: #e0816d;}
.anti-gradient_0 {background: #dd776e;}
<div class="gradient_0">0</div>
<div class="gradient_5">5</div>
<div class="gradient_10">10</div>
<div class="gradient_15">15</div>
<div class="gradient_20">20</div>
<div class="gradient_25">25</div>
<div class="gradient_30">30</div>
<div class="gradient_35">35</div>
<div class="gradient_40">40</div>
<div class="gradient_45">45</div>
<div class="gradient_50">50</div>
<div class="gradient_55">55</div>
<div class="gradient_60">60</div>
<div class="gradient_65">65</div>
<div class="gradient_70">70</div>
<div class="gradient_75">75</div>
<div class="gradient_80">80</div>
<div class="gradient_85">85</div>
<div class="gradient_90">90</div>
<div class="gradient_95">95</div>
<div class="gradient_100">100</div>
I just had a project and began with more or less similar solution to jball and Asaph. That is, smoothly incrementing from red (FF0000) to (FFFF00) to (00FF00).
However, I found that, visually, the changes seemed to be much more drastic around "yellow," while they were barely noticeable around "red" and "green." I found that I could compensate for this by making the changes exponential rather than linear, causing the increments to be smaller around "yellow" and larger around "red" and "green". The solution (in Javascript) I worked out looked like this:
/**
* Converts integer to a hexidecimal code, prepad's single
* digit hex codes with 0 to always return a two digit code.
*
* #param {Integer} i Integer to convert
* #returns {String} The hexidecimal code
*/
function intToHex(i) {
var hex = parseInt(i).toString(16);
return (hex.length < 2) ? "0" + hex : hex;
}
/**
* Return hex color from scalar *value*.
*
* #param {float} value Scalar value between 0 and 1
* #return {String} color
*/
function makeColor(value) {
// value must be between [0, 510]
value = Math.min(Math.max(0,value), 1) * 510;
var redValue;
var greenValue;
if (value < 255) {
redValue = 255;
greenValue = Math.sqrt(value) * 16;
greenValue = Math.round(greenValue);
} else {
greenValue = 255;
value = value - 255;
redValue = 256 - (value * value / 255)
redValue = Math.round(redValue);
}
return "#" + intToHex(redValue) + intToHex(greenValue) + "00";
}
This yielded a much smoother gradient as I changed the value, and changing inputValue by a certain seemed to affect the color to more or less the same degree regardless of the starting point.
Looking at any chart will give the illusion that "color codes" are individual values that you must lookup. In fact, the smoothest transition you can get is to simply increment the amount of green in the color and decrement the amount of red.
See, the cryptic hexidecimal codes are actually not at all cryptic. They have six digits, where the first two show the amount of red in the color, the middle two show the amount of green, and the last two show the amount of blue.
And unlike human counting where when we get from 0 to 9 we move to the next place value and get 10, with hexidecimal we count all the way up to F. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10
So your goal is to get from FF 00 00 (red only, no green or blue) to FF FF 00 (red mixed with green, which is yellow), and finally to 00 FF 00.
How can you do that? Just keep adding a little bit at a time to the green amount until it gets all the way up to FF, and then start taking a little bit away from the red amount until it gets down to 00.
And how much is "a little bit"? However much you think it takes to get a smooth transition. You could add 30 at a time and get pretty major jumps from one color to another, or add 1 at a time and have the transition progress more smoothly (but perhaps also more slowly). Experiment and see what works for you.
My reason for finding this question was that I was trying to make a colored uptime indicator for a table full of devices that "check-in" hourly. The idea being that it would be red at 0%, transition to yellow at 50%, and be green at 100%. This is of course pretty useless but it was an easy way to make a table look more impressive than it actually was. Given a min, max, and value it returns rgb 0-255 values for the correct color. Assumes valid input.
function redYellowGreen(min, max, value)
{
var green_max = 220;
var red_max = 220;
var red = 0;
var green = 0;
var blue = 0;
if (value < max/2)
{
red = red_max;
green = Math.round((value/(max/2))*green_max);
}
else
{
green = green_max;
red = Math.round((1-((value-(max/2))/(max/2)))*red_max);
}
var to_return = new Object();
to_return.red = red;
to_return.green = green;
to_return.blue = blue;
return to_return;
}
Nowadays all modern browsers support color gradients in CSS which allow totally smooth gradients over any width/height. However, still not all browsers support the official CSS linear-gradient, so in order to support all browsers, use the following CSS class:
.gradient {
background: -moz-linear-gradient(left, red, yellow, green); /* FF3.6+ */
background: -webkit-gradient(linear, left top, right top, color-stop(0%, red), color-stop(50%, yellow), color-stop(100%, green)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(left, red, yellow, green); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(left, red, yellow, green); /* Opera 11.10+ */
background: -ms-linear-gradient(left, red, yellow, green); /* IE10+ */
background: linear-gradient(to right, red, yellow, green); /* W3C */
}
For further reference of the CSS gradient functions, see the following articles in the Mozilla Developer Network:
linear-gradient (also lists the supported browsers)
Using CSS gradients
A very good web site to quickly generate completely customized color gradients for all browsers is the Ultimate CSS Gradient Generator.
I came to this post because looking for a simple way to generate a list of colors red-yellow-green for a set of values.
Useful when programming dashboards or reports that need to show "what-if" analysis and enhance good vs average vs bad values. Found interesing articles on several sources, but came out to this very simple JavaScript function:
function fSemaphor(minimal, maximal, value) {
var difference = maximal - minimal;
var medium = (minimal + difference / 2) | 0; // |0 returns INT
var RED = 255,
GREEN = 255;
if (value <= medium)
GREEN = (GREEN * (value / medium)) | 0;
else
RED = (RED * (1.0 - value / maximal)) | 0;
// returns HEX color, for usage in CSS or any style
return ("#" + (('0') + RED.toString(16)).substr(-2) + ('0' + GREEN.toString(16)).substr(-2) + '00'); // blue
}
I even provide a full example of it's usage. Just copy and paste to an HTML page, and see what it does.
Max value: <input value=0 id="minim" /> Min value: <input value=20 id="maxim" />
<input type=submit value="Calculate colors" onClick="fCalcul()">
<table id=tColors border=2></table>
<script>
function fCalcul() {
var i;
var tblRows = "<tr><th>value</th><th>Color</th></tr>";
var minValue = parseInt(minim.value);
var maxValue = parseInt(maxim.value);
var tblBody = "";
var increment = 1;
if ((maxValue - minValue) > 40) // don't show more than 40 rows, for sample sake
increment = ((maxValue - minValue) / 40) | 0;
for (i = minValue; i <= maxValue; i += increment) {
tblBody += "<tr><td>" + i + "</td><td style='background: " +
fSemaphor(minValue, maxValue, i) + "'>" +
fSemaphor(minValue, maxValue, i) + "</td></tr>";
}
tColors.innerHTML = tblRows + tblBody;
}
function fSemaphor(minimal, maximal, value) {
var difference = maximal - minimal;
var medium = (minimal + difference / 2) | 0; // |0 returns INT
var RED = 255,
GREEN = 255;
if (value <= medium)
GREEN = (GREEN * (value / medium)) | 0;
else
RED = (RED * (1.0 - value / maximal)) | 0;
// returns HEX color, for usage in CSS or any style
return ("#" + (('0') + RED.toString(16)).substr(-2) + ('0' + GREEN.toString(16)).substr(-2) + '00'); // blue
}
</script>
Special thanks to Ovid blog in http://blogs.perl.org/users/ovid/2010/12/perl101-red-to-green-gradient.html, who gave a technical explanation that helped me simplify it
Works in Chrome & Safari only
From NiceWebType.com:
<style type="text/css">
h1 {
position: relative;
font-size: 60px;
line-height: 60px;
text-shadow: 0px 0px 3px #000;
}
h1 a {
position: absolute;
top: 0; z-index: 2;
color: #F00;
-webkit-mask-image: -webkit-gradient(linear, left center, right center, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
}
h1:after {
content: "CSS Text Gradient (Webkit)";
color: #0F0;
}
</style>
<h1><a>CSS Text Gradient (Webkit)</a></h1>
When I had to do this my choice was to switch from hex to rgb code, which seemed more calculation-friendly.
You can read the details here:
http://blog.pathtosharepoint.com/2009/11/02/visualization-calculated-color-gradients/
Here is a simple, yet dirty, way to generate these colors:
COLORS = [ "FF00%0.2XFF" % x for x in range(0,260,5) ] + [ "FF00FF%0.2X" % x for x in range(250,-1,-5) ]
The color encoding is for Google maps: aabbggrr.
This will give you a list of 103 colors. I removed three and then indexed the list with using a percentage as an integer.
On my side, I solved the issue with 2 brushes:
float sweepAngle = 45.0F; // angle you want ...
LinearGradientBrush linGrBrushUp = new LinearGradientBrush(
new Point(0, 0), new Point(w, 0),
Color.FromArgb(255, 0, 255, 0), // green
Color.FromArgb(255, 255, 255, 0) // yellow
);
LinearGradientBrush linGrBrushDown = new LinearGradientBrush(
new Point(w, 0), new Point(0, 0),
Color.FromArgb(255, 255, 255, 0), // yellow
Color.FromArgb(255, 255, 0, 0) // red
);
g.DrawArc( new Pen(linGrBrushUp, 5), x, y, w, h, 180.0F, sweepAngle>180.0F?180.0F:sweepAngle );
g.DrawArc( new Pen(linGrBrushDown, 5), x, y, w, h, 0.0F, sweepAngle>180.0F?sweepAngle-180.0F:0 );
I used this in a php page:
$percent = .....; //whatever the percentage you want to colour
If ($percent <= 50) {
$red = 255;
$green = $percent * 5.1;
}
If ($percent >= 50) {
$green = 255;
$red = 255 - ($percent - 50) * 5.1;
}
$blue = 0;
Your RGB is then ($red, $green, $blue)
Note: The 5.1 factor dervies from 255/50

How to cut a "hole" inside a rectangular Sprite to see the Sprite underneath? (ActionScript 3)

Everytime I google this question I see confusing information about masks and blends, none of which seems to directly apply to what I think should be an easy thing...
There are three Sprites involved here...the lowest layer sprite is pretty much a background. I want to overlay a translucent Sprite on top of the background and then I want the third, top-most Sprite to act as a hole, so that the area inside the third Sprite is completely transparent, so that the background sprite is completely visible.
How would I go about doing this dynamically (i.e. dynamically drawing the masking sprite and hole using the Actionscript graphics calls)?
I know it's been a long time ago, but just for people who might look for the same problem.
It's actually quite easy (as long as draw your Sprite with the graphics class).
1) Inflexible hole cutting:
this.graphics.beginFill(0x666666);
this.graphics.drawRect(0,0,256, 256);
this.graphics.drawCircle(128,128,32);
this.graphics.endFill();
this will create a rectangle of 256 by 256 with a 64px hole in it.
2) Flexible hole cutting:
Obviously this will not work when you're not using the graphics class. In That case I would go with BlendMode.ERASE.
var spr:Sprite = new Sprite();
var msk:Sprite = new Sprite();
addChild(spr);
spr.addChild(msk)
spr.graphics.beginFill(0x666666);
spr.graphics.drawRect(0,0,256, 256);
spr.graphics.endFill();
msk.graphics.beginFill(0x000000);
msk.graphics.drawEllipse(0,0,64,64);
msk.graphics.endFill();
msk.x = 128;
msk.y = 128;
spr.blendMode = BlendMode.LAYER;
msk.blendMode = BlendMode.ERASE;
When using BlendMode.ERASE you must ALWAYS set the parentcontainer's blendmode to BlendMode.LAYER, otherwise it won't work.
I hope this might help someone
If I recall it correctly, if you draw two overlapping objects on the same graphics without stopping the fill, they will work pretty much like blendmode.erase. Pseudo-code would look like this:
graphics.beginFill (any color, any alpha);
graphics.drawRect(0,0,256, 256);
graphics.drawRect(128,128,64, 64);
graphics.endfill ();
If this actually works (and I think I used this solution many years ago and just recently saw that SVG files work this way), this should give you a much better performance.
EDIT: I have just used this myself in one of my games.
Not an AS developer, but take a look at this: http://code.google.com/p/gpcas/
This should enable you to do boolean "cutout" operations on two polygons.
OK, what I want can be done as simple as calling drawRect twice on the translucent layer...once to draw the translucent rectangle, and again to draw the "hole"
Details here:
http://www.actionscript.org/forums/showthread.php3?p=965632
Not exactly a mask, but good enough for my purposes.
Check out this method, it allows for an optional "hole" parameter. This is found in the ProgrammaticSkin class of the flex framework.
http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/frameworks/projects/framework/src/mx/skins/ProgrammaticSkin.as
/**
* Programatically draws a rectangle into this skin's Graphics object.
*
* <p>The rectangle can have rounded corners.
* Its edges are stroked with the current line style
* of the Graphics object.
* It can have a solid color fill, a gradient fill, or no fill.
* A solid fill can have an alpha transparency.
* A gradient fill can be linear or radial. You can specify
* up to 15 colors and alpha values at specified points along
* the gradient, and you can specify a rotation angle
* or transformation matrix for the gradient.
* Finally, the rectangle can have a rounded rectangular hole
* carved out of it.</p>
*
* <p>This versatile rectangle-drawing routine is used by many skins.
* It calls the <code>drawRect()</code> or
* <code>drawRoundRect()</code>
* methods (in the flash.display.Graphics class) to draw into this
* skin's Graphics object.</p>
*
* #param x Horizontal position of upper-left corner
* of rectangle within this skin.
*
* #param y Vertical position of upper-left corner
* of rectangle within this skin.
*
* #param width Width of rectangle, in pixels.
*
* #param height Height of rectangle, in pixels.
*
* #param cornerRadius Corner radius/radii of rectangle.
* Can be <code>null</code>, a Number, or an Object.
* If it is <code>null</code>, it specifies that the corners should be square
* rather than rounded.
* If it is a Number, it specifies the same radius, in pixels,
* for all four corners.
* If it is an Object, it should have properties named
* <code>tl</code>, <code>tr</code>, <code>bl</code>, and
* <code>br</code>, whose values are Numbers specifying
* the radius, in pixels, for the top left, top right,
* bottom left, and bottom right corners.
* For example, you can pass a plain Object such as
* <code>{ tl: 5, tr: 5, bl: 0, br: 0 }</code>.
* The default value is null (square corners).
*
* #param color The RGB color(s) for the fill.
* Can be <code>null</code>, a uint, or an Array.
* If it is <code>null</code>, the rectangle not filled.
* If it is a uint, it specifies an RGB fill color.
* For example, pass <code>0xFF0000</code> to fill with red.
* If it is an Array, it should contain uints
* specifying the gradient colors.
* For example, pass <code>[ 0xFF0000, 0xFFFF00, 0x0000FF ]</code>
* to fill with a red-to-yellow-to-blue gradient.
* You can specify up to 15 colors in the gradient.
* The default value is null (no fill).
*
* #param alpha Alpha value(s) for the fill.
* Can be null, a Number, or an Array.
* This argument is ignored if <code>color</code> is null.
* If <code>color</code> is a uint specifying an RGB fill color,
* then <code>alpha</code> should be a Number specifying
* the transparency of the fill, where 0.0 is completely transparent
* and 1.0 is completely opaque.
* You can also pass null instead of 1.0 in this case
* to specify complete opaqueness.
* If <code>color</code> is an Array specifying gradient colors,
* then <code>alpha</code> should be an Array of Numbers, of the
* same length, that specifies the corresponding alpha values
* for the gradient.
* In this case, the default value is <code>null</code> (completely opaque).
*
* #param gradientMatrix Matrix object used for the gradient fill.
* The utility methods <code>horizontalGradientMatrix()</code>,
* <code>verticalGradientMatrix()</code>, and
* <code>rotatedGradientMatrix()</code> can be used to create the value for
* this parameter.
*
* #param gradientType Type of gradient fill. The possible values are
* <code>GradientType.LINEAR</code> or <code>GradientType.RADIAL</code>.
* (The GradientType class is in the package flash.display.)
*
* #param gradientRatios (optional default [0,255])
* Specifies the distribution of colors. The number of entries must match
* the number of colors defined in the <code>color</code> parameter.
* Each value defines the percentage of the width where the color is
* sampled at 100%. The value 0 represents the left-hand position in
* the gradient box, and 255 represents the right-hand position in the
* gradient box.
*
* #param hole (optional) A rounded rectangular hole
* that should be carved out of the middle
* of the otherwise solid rounded rectangle
* { x: #, y: #, w: #, h: #, r: # or { br: #, bl: #, tl: #, tr: # } }
*
* #see flash.display.Graphics#beginGradientFill()
*
* #langversion 3.0
* #playerversion Flash 9
* #playerversion AIR 1.1
* #productversion Flex 3
*/
protected function drawRoundRect(
x:Number, y:Number, width:Number, height:Number,
cornerRadius:Object = null,
color:Object = null,
alpha:Object = null,
gradientMatrix:Matrix = null,
gradientType:String = "linear",
gradientRatios:Array /* of Number */ = null,
hole:Object = null):void
{
var g:Graphics = graphics;
// Quick exit if weight or height is zero.
// This happens when scaling a component to a very small value,
// which then gets rounded to 0.
if (width == 0 || height == 0)
return;
// If color is an object then allow for complex fills.
if (color !== null)
{
if (color is uint)
{
g.beginFill(uint(color), Number(alpha));
}
else if (color is Array)
{
var alphas:Array = alpha is Array ?
alpha as Array :
[ alpha, alpha ];
if (!gradientRatios)
gradientRatios = [ 0, 0xFF ];
g.beginGradientFill(gradientType,
color as Array, alphas,
gradientRatios, gradientMatrix);
}
}
var ellipseSize:Number;
// Stroke the rectangle.
if (!cornerRadius)
{
g.drawRect(x, y, width, height);
}
else if (cornerRadius is Number)
{
ellipseSize = Number(cornerRadius) * 2;
g.drawRoundRect(x, y, width, height,
ellipseSize, ellipseSize);
}
else
{
GraphicsUtil.drawRoundRectComplex(g,
x, y, width, height,
cornerRadius.tl, cornerRadius.tr,
cornerRadius.bl, cornerRadius.br);
}
// Carve a rectangular hole out of the middle of the rounded rect.
if (hole)
{
var holeR:Object = hole.r;
if (holeR is Number)
{
ellipseSize = Number(holeR) * 2;
g.drawRoundRect(hole.x, hole.y, hole.w, hole.h,
ellipseSize, ellipseSize);
}
else
{
GraphicsUtil.drawRoundRectComplex(g,
hole.x, hole.y, hole.w, hole.h,
holeR.tl, holeR.tr, holeR.bl, holeR.br);
}
}
if (color !== null)
g.endFill();
}
}
In case someone needs to have a gradient hole, it's possible using trick from Raimundas. Let's say you want elliptical gradient coming from inside to the outside (inner radius alpha = 0, outer radius alpha = 1).
First draw the background without the ellipse
var gfx:Graphics;
gfx.clear();
gfx.beginFill(color, alpha );
gfx.drawRect(0, 0, width, height); // fullscreen
gfx.drawEllipse(e_x, e_y, e_width, e_height); // trick - drawn in the same beginFill
gfx.endFill();
Then draw the gradient ellipse, inside the result hole!
var mat : Matrix = new Matrix();
mat.createGradientBox(width, height, 0, e_x, e_y);
gfx.lineStyle(); // I think it resets lineStyle
gfx.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, mat);
gfx.drawEllipse(e_x, e_y, width, height);
gfx.endFill();
The ellipse will match hole exactly, pixel-perfect.