ARGB Image, set all visible pixels to white

I have a ARGB pic (PNG) and I want to set all pixels that are not transparent to white (255,255,255,255)

what is the fastest way performance wise ?

I think it might be something like

for loop
if (pic.getRGB(x,y) == transparent) pic.setRGB(0xFFFFFFFF);

but you do you even know if a pixel is transparent ?

if the first two bytes are > 0 … ?

If I’m not wrong:

aRGB is with an alpha channel (0xAARRGGBB). Alpha specifies the transparency of the pixel with 0x00 to be fully transparent and 0xff to be white background.

Hi,
getRGBA returns an int value, you need to do some bitshifting. i’ve a blog entry here.

short story:

private static int[] getARGB(int rgb) {
	int[] value = new int[4];

	// alpha
	value[0] = (rgb >> 24) & 0xFF;

	// red
	value[1] = (rgb >> 16) & 0xFF;

	// green
	value[2] = (rgb >> 8 ) & 0xFF;

	// blue
	value[3] = (rgb) & 0xFF;

	return value;
}

private static int getARGB(int a, int r, int g, int b) {
	int rgb = ((a & 0xFF) << 24) |
	       	      ((r & 0xFF) << 16) |
		      ((g & 0xFF) << 8 )  |
		      ((b & 0xFF));

	return rgb;
}

opaque: alpha value is 255
semi transparent: alpha value is > 0 && < 255
invisible: alpha value is 0

Couldn’t you just:

oldImage.getGraphics().setColor(Color.WHITE);
oldImage.getGraphics().fillRect(visibleX, visibleY, visibleW, visibleH);

[quote]getRGBA returns an int value, you need to do some bitshifting. i’ve a blog entry here.
[/quote]
awesome thanks

how would I get the visible values and also this is a sprite with something on it, not a rect
and if I would do multiple rect in a loop, I might aswell use setRGB on pixels, which is also faster

I guess I didn’t understand what you’re asking. To me, visible is pretty much always determined by a rect, because it’s dependent upon screen/window size. That’s why I was referring to rects.

nah, was just talking about the background in a sprites frame ( png)

anyway works great

If you already have an image using bit shifting and manual manipulation of RGBA values is definitely the wrong way to go.

Do what Demonpants suggested, just make sure you are using the correct Alpha Composite rule(s). Then you may even get hardware acceleration.

Either you misunderstand what I wanted to do, or I have completely no idea how to use fillRect to do it

http://img18.imageshack.us/img18/9136/whiteout.jpg

The purple background is of course transparent in the png, just to show you the boundaries I guess

I do that by


picture = whiteOutImg(picture);

...

public BufferedImage whiteOutImg(BufferedImage in)
{
    BufferedImage out = in;

    for (int x = 0; x < (int)out.getWidth(); x++)
    {
        for (int y = 0; y < (int)out.getHeight(); y++)
        {
            if (getARGB(out.getRGB(x, y))[0] > 0) out.setRGB(x, y, 0xFFFFFFFF);
        }
    }

    return out;
}

private static int[] getARGB(int rgb)
{
    int[] value = new int[4];

    // alpha
    value[0] = (rgb >> 24) & 0xFF;

    // red
    value[1] = (rgb >> 16) & 0xFF;

    // green
    value[2] = (rgb >> 8 ) & 0xFF;

    // blue
    value[3] = (rgb) & 0xFF;

    return value;
}

I mean of course

if (getARGB(out.getRGB(x, y))[0] >= 10) out.getGraphics().fillRect(x, y, 1, 1);

works too. But it’s the exact amount of operations, so whats the point ?

and really really think that fillRect is slower than setRGB

I haven’t tested it in realtime yet though

getRGB doesn’t return alpha values, it’s even in the name…

you need to access the AlphaRaster of the BufferedImage

i just build a simple test case. it’s working as expected:

[quote]package test;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

/**

  • Test.java

  • Simple test case

  • @author Robin Rowinski
    */
    public class Test {

    public static void main(String[] args) throws Exception {
    BufferedImage image = ImageIO.read(new File(“data/test.png”));
    int width = image.getWidth();
    int height = image.getHeight();

     System.out.println("Alpha values for input image:");
     for (int y = 0; y < height; y += 1) {
     	for (int x = 0; x < width; x += 1) {
     		if (x > 0) {
     			System.out.print(",");
     		}
     		System.out.print(getARGB(image.getRGB(x, y))[0]);
     	}
     	System.out.println();
     }
     
     for (int y = 0; y < height; y += 1) {
     	for (int x = 0; x < width; x += 1) {
     		int alpha = getARGB(image.getRGB(x, y))[0];
     		
     		if (alpha != 0) {
     			image.setRGB(x, y, 0xFFFFFFFF);
     		}
     	}
     }
     
     ImageIO.write(image, "png", new File("data/test_out.png"));
    

    }

    private static int[] getARGB(int rgb) {
    int[] value = new int[4];

     // alpha
     value[0] = (rgb >> 24) & 0xFF;
    
     // red
     value[1] = (rgb >> 16) & 0xFF;
    
     // green
     value[2] = (rgb >> 8 ) & 0xFF;
    
     // blue
     value[3] = (rgb) & 0xFF;
    
     return value;
    

    }

    private static int getARGB(int a, int r, int g, int b) {
    int rgb = ((a & 0xFF) << 24) |
    ((r & 0xFF) << 16) |
    ((g & 0xFF) << 8 ) |
    ((b & 0xFF));

     return rgb;
    

    }

}
[/quote]
Images are attached.

BTW:
After warm-up of the VM my MBP needed 26 ms for processing a 256 x 256 x 32 image.

Edit:
Oh and i know, it’s not java like but low level :wink:

ya, thanks for doing that =D
26 ms for processing a 256 x 256 x 32 image seems ok to me

I want to use this effect like when you do damage to an enemy, you know like the blink white, indicating that you do damage

so really, that should work

[quote]getRGB doesn’t return alpha values
[/quote]
fortunately it does.

ya I just tested a 112x160x32 PNG

using setRGB, after warm up, it was 34ms

and using fillRect, 150-210ms

so thats clear.

mhm,
for realtime effects i would use a premade image (could be loaded / generated into ram at start-up). cause it’s faster to “draw an image” than “alter an image and draw an image”.

of course but for this specific effect its just not worth it
I mean an enemy has various animations and I really dont know before hand
so he just has to blink
and doing this once a frame should be ok

well turns out I was wrong

its fine when I do it like up to three times a frame

but with 10 or something like that performance drops a little

so… alternatives ? alphaRaster ? how does that work ?

i don’t know your implementation, but couldn’t you just load the default spritesheet (animation and so on) and create a copy of that image on the fly with altered image data (white for alpha >= 10)? when rendering just switch between them as needed.

sure I could.
But consider this: A character in my game has now 166 sprites total

if I would load for every frame/sprite, for every enemy, a white image

thats double the memory I would need and an extraordinary waste, dont you think

especially when its just a little effect (blinking)