I'm trying (In Java) to get the resulting color when I combine 2 colors, the one on top having an alpha transparency. Basically, I'm trying to assign a background color to an image, but I've broken it down to each pixel being changed individually. I've looked at several articles, including this one, to no avail. Does anybody know how to perform this kind of RGBA/RGB color mixing? My current code uses this png:
And produces this JPG:
This is the function that I'm currently using. The background for the demo images was set to full blue, or an int of 255.
public static void PNGToJPEGConvert(String PNGPath, String NewJPEGPath, int BackColor) throws IOException {
try {
BufferedImage bufferedImage = ImageIO.read(new File(PNGPath));
BufferedImage newImage;
int R1, G1, B1, R2 = (BackColor & 0xFF0000) >> 16, G2 = (BackColor & 0xFF00) >> 8, B2 = (BackColor & 0xFF), W1, W2, W3, M1, M2, R3, G3, B3;
float br;
newImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
for(int x=0; x < bufferedImage.getWidth(); x++) {
for(int y=0; y < bufferedImage.getHeight(); y++) {
R1 = BufferedImageGetPixelARGB(bufferedImage, "R", x, y);
G1 = BufferedImageGetPixelARGB(bufferedImage, "G", x, y);
B1 = BufferedImageGetPixelARGB(bufferedImage, "B", x, y);
W1 = Math.min(R1, Math.min(G1, B1));
W2 = Math.min(R2, Math.min(G2, B2));
R1 -= W1;
G1 -= W1;
B1 -= W1;
R2 -= W2;
G2 -= W2;
M1 = Math.max(R1, Math.max(G1, B1));
M2 = Math.max(R2, Math.max(G2, B2));
br = (M1 + M2)/(2*BufferedImageGetPixelARGB(bufferedImage, "A", x, y));
R3 = (int) ((R1 + R2) * br);
G3 = (int) ((G1 + G2) * br);
B3 = (int) ((B1 + B2) * br);
W3 = (W1 + W2) / 2;
R3 += W3;
G3 += W3;
B3 += W3;
newImage.setRGB(x, y, RGBValuesToInt(R3, G3, B3));
}
}
try {
ImageIO.write(newImage, "jpg", new File(NewJPEGPath));
} catch(Exception e) {
}
} catch(Exception e) {
}
}
Thanks for the help, -Neil
Basically it is
float masking_factor = mask_value/255.0;
composed_value = int(
source_pixel_value * (1 - masking_factor) +
overlay_pixel_value * masking_factor
);
We suppose that all values are 8-bit, that is, 0 to 255, and mask
is monochrome. Where mask
is completely black, it is fully transparent, and only source pixels are visible. Where mask
is completely white, it is fully opaque, and only overlay pixels are visible. Values in between give intermediate opacity.
But if alpha blending is the only thing you want to implement, there are better ways to do it than working with individual pixels. See Graphics2D
and its .setComposite()
method.