In SpriteKit, how is the default blending mode (SKBlendModeAlpha) calculated? Can you please verify that it works on my example points below? All nodes below use the default SKBlendModeAlpha.
My scene has a white background and two identical child nodes of uniform color that partially intersect each other. The true RGB of each node is (16, 195, 117) and alpha = 0.4.
When I look at the blended color of the node sitting on the white background, the color is (158, 221, 190). (This was confirmed by doing a screen capture and checking in gimp).
How was this calculated by SpriteKit?
When I look at the blended color of the intersected area of two nodes on the white background, the RGB is (112, 203, 153).
How was this calculated by SpriteKit?
Thanks!
Thanks Okapi. That was the key to finding the answer. Using "Display native values" helped me see that for each RGB component, it's:
final_color = previous_final_color * (1 - alpha) + new_color * alpha.
For one layer on white, I indeed get an RGB of
(159, 231, 200) = floor(0.6 * (255, 255, 255) + 0.4 * (16, 195, 117))
For the two layers on white, I get an RGB of
(101, 216, 166) = floor(0.6 * (159, 231, 200) + 0.4 * (16, 195, 117))
Related
Below COLOR/INDEX are information that I want to use for heatmap color palette
COLOR= ['#36abdf','#84d9a3','#f4d646','#e86000','#ff0000','#671b1b']
INDEX= [0, 0.001, 10, 25, 50, 75, 1]
I'm trying to make some HEATMAP which havs continuous (Gradient) color value.
My original Intension was that
Set Blue color ('#36abdf') for only '0' vlaue,
If value is bigger than 0, must start with green color('#84d9a3') and be gradually changed within color set for bigger value.
I found some code that can make LinearColormap through branca.colormap
cmap = b_cm.LinearColormap(colors=['#36abdf','#84d9a3','#f4d646','#e86000','#ff0000','#671b1b'], index=[0,0.001,25,50,75,90],vmin=0,vmax=100)
but it seems that I cannot use LinearColormap for color palette in seaborn/matplotlib heatmap
please let me introduce code that make color palette that I want.
I will be so appreciate if you let me know.
thx!!
I'm trying to blend two circles, one black and the other white. The parts where they intersect must be in grey.
I tried to use blend functions but I don't get the expected results.
The objective is to mix ONLY this two elements, other elements (like the background) can't mix there, and I don't know how to do this maintaining the 100% of the alpha channel.
This is my current render code, circle1 and circle2 are TextureRegion.
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.enableBlending();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE);
batch.draw(circle1, c1.getX(), getY(), getWidth(), getHeight());
batch.draw(circle2, c2.getX(), getY(), getWidth(), getHeight());
}
This is an example of the color mix.
EDIT: Problem solved.
I did a test using Spritebatch, I drew a third circle with reduced opacity, this is the code used to test and the result:
Gdx.gl20.glEnable(GL20.GL_BLEND);
Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(1, 1, 1, 1f);
shapeRenderer.circle(15, 5, 5);
shapeRenderer.setColor(0, 0, 0, 1f);
shapeRenderer.circle(19, 5,5);
shapeRenderer.setColor(1, 1, 1, 0.5f);
shapeRenderer.circle(15, 5, 5);
shapeRenderer.end();
Gdx.gl20.glDisable(GL20.GL_BLEND);
I've never used libGDX so I'm not sure how the specific implementation goes, but I'll give you the general outline of what you're trying to achieve.
The most basic blending you can achieve is a linear blend between two colors with a single parameter t. Consider this example - let's say each color is represented by a single channel value for simplicity - black is 0.0 and white is 1.0. What you want to achieve is the mid range gray that is 0.5, to do this you would blend by scaling each channel appropriately ( black * 0.5 + white * 0.5 = 0.0 * 0.5 + 1.0 * 0.5 = 0.5)
A more sophisticated way of blending colors is by using the source alpha channel to govern the blend weight, so say you have a color black and a color white with 0.4 alpha, or opacity. You would blend using the following method black * 0.6 + white * 0.4 (your alpha sums up to 1.0), which would give you 0.4 a slightly "darker" than mid range gray.
To tie this back to your question, you specify the blend method as ONE, ONE, i.e, you're doing black * 1 + white * 1 which should result in 1 (all white).
Looking over the docs for libGDX, you have either the GL_ONE_MINUS_CONSTANT_ALPHA option for constant weight blend, or if you want to do "alpha blending" you could go for GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA.
Hope this helps and clears up blending a bit :)
Explanation
I have a semi-transparent color of unknown value.
I have a sample of this unknown color composited over a black background and another sample over a white background.
How do I find the RGBA value of the unknown color?
Example
Note: RGB values of composites are calculated using formulas from the Wikipedia article on alpha compositing
Composite over black:
rgb(103.5, 32.5, 169.5)
Composite over white:
rgb(167.25, 96, 233.25)
Calculated value of unknown color will be:
rgba(138, 43, 226, 0.75)
What I've Read
Manually alpha blending an RGBA pixel with an RGB pixel
Calculate source RGBA value from overlay
It took some experimentation, but I think I figured it out.
Subtracting any of the color component values between the black and white composite should give you the inverse of the original color's alpha value, eg:
A_original = 1 - ((R_white_composite - R_black_composite) / 255) // in %, 0.0 to 1.0
It should yield the same value whether you use the R, G, or B component. Now that you have the original alpha, finding the new components is as easy as:
R_original = R_black_composite / A_original
G_original = G_black_composite / A_original
B_original = B_black_composite / A_original
I'm not really getting the glBlendFunc() function and how it works.
Is there a blend mode that lets destination black be black while overriding any other dst colour?
I have a black and white canvas containing colouring edges and shapes. I'd like to draw a brush anywhere over the canvas but not overriding the edges so they remain black once the image is fully coloured. Ideally, since the destination has some grey around the edges for smoothness, the grey shades would be tinted with the brush colour.
Thank you!
I believe what you need is glBlendFunc(GL_DST_COLOR, GL_ZERO).
To explain you how the blend function works:
When blending you have 2 colours, source and destination. Source is the colour you are trying to apply (a textel, a solid colour...). Destination is the colour currently on the buffer. The 2 parameters in the glBlendFunc tell how to multiply the source and destination colour before adding them together to get the result colour.
So in the case of glBlendFunc(GL_DST_COLOR, GL_ZERO) and having a black and white destination buffer (as you described) will act like this:
if destination colour is white (1,1,1,1) and you will apply some colour for instance (.1, .2, .3, 1) the result will be R = (.1, .2, .3, 1)*(1,1,1,1) + (1,1,1,1)*(0,0,0,0) = (.1, .2, .3, 1)
if destination colour is black (0,0,0,0) and you will apply some colour for instance (.1, .2, .3, 1) the result will be R = (.1, .2, .3, 1)*(0,0,0,0) + (0,0,0,0)*(0,0,0,0) = (0, 0, 0, 0)
if destination colour is grey (.5,.5,.5,1.0) and you will apply some colour for instance (.1, .2, .3, 1) the result will be R = (.1, .2, .3, 1)*(.5,.5,.5,1.0) + (.5,.5,.5,1.0)*(0,0,0,0) = (.05, .1, .15, 1)
This case of yours is a bit specific but in most cases the alpha channel is only used. For instance most common blending is glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) which means the source colour will be multiplied with source alpha while the destination colour will be multiplied with 1.0-source alpha, so a white shape with alpha of .75 over a grey background RGB .5 (any alpha) will result in RGB all 1.0*.75 + .5*(1.0-.75) = .75 + .125 = .875.
Note that this procedure of yours might cost you if you will need some other blending type on the overlay. In that case you will need to look into stencil buffers. Another issue is you might not want to see the black and white part on places you do not draw the overlay. In this case you can simply use the destination alpha to do this blending for you: glColorMask can help you draw only to the alpha channel of your buffer where you can use alpha .0 for "black" areas and 1.0 for "white" areas, when drawing a shape over the buffer you would then use glBlendFunc(GL_DST_ALPHA, GL_ZERO).
Suppose there are two colors defined in CMYK:
color1 = 30, 40, 50, 60
color2 = 50, 60, 70, 80
If they were to be printed what values would the resulting color have?
color_new = min(cyan1 + cyan2, 100), min(magenta1 + magenta2, 100), min(yellow1 + yellow2, 100), min(black1 + black2, 100)?
Suppose there is a color defined in CMYK:
color = 40, 30, 30, 100
It is possible to print a color at partial intensity, i.e. as a tint. What values would have a 50% tint of that color?
color_new = cyan / 2, magenta / 2, yellow / 2, black / 2?
I'm asking this to better understand the "tintTransform" function in PDF Reference 1.7, 4.5.5 Special Color Spaces, DeviceN Color Spaces
Update:
To better clarify: I'm not entirely concerned with human perception or how the CMYK dyies react to the paper. If someone specifies 90% tint which, when printed, looks like full intensity colorant, that's ok.
In other words, if I asking how to compute 50% of cmyk(40, 30, 30, 100) I'm asking how to compute the new values, regardless of whether the result looks half-dark or not.
Update 2:
I'm confused now. I checked this in InDesign and Acrobat. For example Pantone 3005 has CMYK 100, 34, 0, 2, and its 25% tint has CMYK 25, 8.5, 0, 0.5.
Does it mean I can "monkey around in a linear way"?
No, in general you can't monkey around in a linear way with arbitrary color spaces and hope to see a result that corresponds to human perception. The general strategy is to convert from your color space into CIE Lab or Luv color space, do the transformation, then go back to your color space (which is lossy).
Excellent FAQ: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html
Supposing C,M,Y,K are the % of ink to print. Adding two colors would be:
C = min(100,C1+C2)
M = min(100,M1+M2)
Y = min(100,Y1+Y2)
K = min(100,K1+K2)
And then they must be normalized, because usually no more than three inks are printed, and an equal amount of C,M,Y is replaced by the same amount of black.
G = min(C,M,Y) // Black amount produced by C,M,Y
C -= G
M -= G
Y -= G
K = min(100,K+G)
At this point, you may want to limit C+M+Y+K to some value like 240. You can also try G=min(C,M,Y,100-K).
If you're just doing tints of colours then a straight multiplication will be fine - this ensures that the inks will all be in the same ratios.
You can see this by bringing up the Colors panel in InDesign, and holding down shift and dragging one of the colour sliders. The other sliders will move proportionally.
Adding two colours has the same effect as overprinting (where one colour is printed directly over another colour). So if 100% magenta and 100% cyan were printed, and then 100% black were printed on top, the result would be exactly the same as 100% magenta, 100% cyan and 100% black.
To answer your first question:
color_new = min(cyan1 + cyan2, 100),
min(magenta1 + magenta2, 100),
min(yellow1 + yellow2, 100),
min(black1 + black2, 100)
If this had been RGB values it would result in saturated colours (i.e. colours at or near white). The converse will be true for the CMY part of the CMYK colour - they will tend to black (well practically dark brown). The addition of black means that you get pure black (thanks Skilldrick). After all if you have 100% black and any combination of CMY the result will be black.
Re your second update I would expect that the results you obtained from Acrobat would apply universally.
Using Photoshop's multiply blend as a guide in CMYK mode I came to the following conclusion:
mix = colour1 + colour2 - color1 * color2
So 50% magenta blended with 50% magenta would equate to
50% + 50% - 50% * 50%
100% - 25%
75% magenta
100% black and 100% black would come to (100% + 100% - 100% * 100%) = 100%
It's seems to at least tally with the tests I did in Photoshop and multiply blends. Whether that is right for print, I can't say.