We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I'm trying to manually mix ARGB pixels and the mix is coming out rather dull.
Is there a better way to manually mix ARGB?
EDIT: I found the correct way to do this. The corrected program is down a few posts ( if anyone is interested in the method).
PImage A, B,C;
boolean showMix = false;
void setup(){
size(600,600);
A = createImage(600,600,ARGB);
B = createImage(600,600,ARGB);
C = createImage(600,600,ARGB);
A.loadPixels();
for(int i = 0; i < 300; i++){
for(int j = 0;j < 300; j++){
A.pixels[i * 600 + j]= 0x7FFF0000;
}
}
A.updatePixels();
B.loadPixels();
for(int i = 150; i < 450; i++){
for(int j = 150;j < 450; j++){
B.pixels[i * 600 + j]= 0x7F00FF00;
}
}
B.updatePixels();
mix();
}
void draw(){
background(255);
if(showMix)
image(C,0,0);
else{
image(A,0,0);
image(B,0,0);
}
}
void keyPressed(){
showMix = !showMix;
}
void mix(){
float ba,br,bg,bb; //background a,r,g,b
float fa,fr,fg,fb; //foreground
float oa, or,og,ob; //output
int a,r,g,b;
A.loadPixels();
B.loadPixels();
C.loadPixels();
for(int i = 0; i < 600;i++){
for(int j= 0;j<600;j++){
int index = i * 600 + j;
ba=A.pixels[index]>>24 & 0xFF; fa=B.pixels[index]>>24 & 0xFF;
br=A.pixels[index]>>16 & 0xFF; fr=B.pixels[index]>>16 & 0xFF;
bg=A.pixels[index]>>8 & 0xFF; fg=B.pixels[index]>>8 & 0xFF;
bb=A.pixels[index] & 0xFF; fb=B.pixels[index] & 0xFF;
ba/=255;fa/=255; //convert alpha to 0.0 - 1.0
oa = fa + ba *(1.0-fa);
or = (fr * fa) + ( br*ba*(1.0-fa) );
og = (fg * fa) + ( bg*ba*(1.0-fa) );
ob = (fb * fa) + ( bb*ba*(1.0-fa) );
oa *= 255; // convert to 0-255
a=Math.round(oa); r=Math.round(or); g=Math.round(og); b=Math.round(ob);
C.pixels[index]= a<<24|r<<16|g<<8|b;
}
}
C.updatePixels();
}
Answers
Assuming you want red and green to mix to yellow rather then brown
convert A and B to HSB
mix them the way you're doing it now,
convert A and B back to RGB
I am working on shader functions that can be very useful for these sorts of thing where your'e looping through lots of pixels.
https://github.com/Prince-Polka/HSB-HSV----RGB
This is the math behind it http://www.rapidtables.com/convert/color/rgb-to-hsv.htm
Note that hsb = hsv, but hsl is different.
You could write java functions doing it but you're kind of re-inventing the wheel as lerpColor() exists.
Thanks for the response. I'm going to give it a try. The problem I see is processing is not displaying the alpha as I mix it or how I expect. Changing color modes might fix it.
I tried another technique. I have a drawing routine that works great when mixing colors on an opaque white canvas. I tried using that same routine and stripping away the white and using what was taken away to create the alpha. If it worked, I could place the white stripped image over a white background and it would look like the original. I could place it over any other image and it should look mixed with the other image. But it doesn't work when displaying the images with:
If you had a rgb pixel that was say 255, 200, 45, I tried stripping the white by subtracting 45 from each color component and making the alpha value 45. I wind up with a ARGB pixel 45,210,155,0. That didn't work and the lower alpha pixels tend to be gray.
I could write my own display routine to mix these pixels how I expect ( i.e., r+backgroundR,g+backgroundG, b+backgroundB ) but the alpha .png image couldn't be used elsewhere and surely my manual mixing would be much slower than image(img,0,0);
I'm going to try the different color mode. I'll let you know.
I found the correct way to do this. The algorithm I was using wasn't right. I found the correct way on this site : https://www.gamedev.net/forums/topic/387607-rgba--rgba--/
Here's the corrected test program. Edit: Since this uses floating point division, the values or the red green and blue components should be checked to make sure they are not NaN as division by 0 is possible. ( simple check and fix if( red!=red) red = 0).