Grayscale as Alpha channel

Hi all,

What is the simplest/most efficient way (compared to manipulating pixel arrays directly) of copying the grayscale values of one image to the alpha channel of another?

Thanks.

Found one solution, looks simple enough:
http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=2D;action=display;num=1076186639;start=2#2

Which leads to another qn, would “getAlphaRaster()” result in a permanently “unmanaged” image (ie, similar to calling getRaster )?

I don’t think so - its grabbing the DataBuffer (of the Raster) that prevents the image being managed.

Yes, my experiences confirm what stated above by Abuse.

Mik.

Fantastico. That settles the issue I guess. Some of the sources I’ve read regarding this were ambiguous on this point (ie, whether it was getRaster() or getRaster().getDataBuffer() that actually caused “unmanagement”).

Only grabbing the databuffer will result in loss of manageability. Note, however, that some of our raster manipulation code may get the databuffer, so you can still lose acceleration even if your code doesn’t do it explicitly.

[quote]Only grabbing the databuffer will result in loss of manageability. Note, however, that some of our raster manipulation code may get the databuffer, so you can still lose acceleration even if your code doesn’t do it explicitly.
[/quote]
So you’re saying that certain methods in Raster / WritableRaster can cause acceleration to be lost if used?

EDIT:
In summary, to get an accelerated image with alpha in 1.4.x as the grayscale of another image:

  1. Create the destination image as BufferedImage.TYPE_4BYTE_ABGR ( i was stumped on this for awhile)

  2. Create / Load the grayscale image ( must have only 1 band and using DataBufferByte for storage of raw values, mostly, an image in the ColorSpace.CS_GRAY automatically has these properties )

  3. Get the alpha raster of the destination image. Note that if you created the image using BufferedImage.TYPE_INT_ARGB or most cases of Transparency.TRANSLUCENT createCompatibleImage() instead, you would end up with an incompatible (IntegerInterleavedRaster) WritableRaster with the grayscale one (ByteInterleavedRaster).

  4. Copy the grayscale raster onto the alpha raster of the dest image using setDataElements(0, 0, grayscale.getRaster())

  5. Copy the destination image onto a “managed” image created with createCompatibleImage(Transparency.TRANSLUCENT)

Sounds like it should work - thought its abit of a round-about way of doing it.
You could write your own implementation of Composite, that did the desired composition (dst.alpha = src.color).
Dunno if that would be faster or slower than the way you are doing it already (my guess is it would be faster)

So, your end code would look something like :-

public BufferedImage copyColorIntoAlpha(BufferedImage colorImg, BufferedImage alphaImg)
{
BufferedImage managedImage = gc.createCompatibleImage(img.getWidth(),imt.getHeight(),Transparency.TRANSLCUENT);
Graphics2D g2d = managedImage.createGraphics();
g2d.setComposite(AlphaComposite.SRC);
g2d.drawImage(colorImg,0,0,null);
g2d.setComposite(new ColorIntoAlphaComposite());
g2d.drawImage(alphaImg,0,0,null);
g2d.dispose();
return managedImage;
}

The time consuming bit would be writing the ColorIntoAlphaComposite class - i’ll leave that upto you :smiley:
It shouldn’t be too hard though, CompositeContext gives you :-

void compose(Raster src, Raster dstIn, WritableRaster dstOut)

you just need a loop to go over src, copying the values into the correct band of dstOut.

[quote]Sounds like it should work - thought its abit of a round-about way of doing it.
You could write your own implementation of Composite, that did the desired composition (dst.alpha = src.color).
Dunno if that would be faster or slower than the way you are doing it already (my guess is it would be faster)

So, your end code would look something like :-

public BufferedImage copyColorIntoAlpha(BufferedImage colorImg, BufferedImage alphaImg)
{
BufferedImage managedImage = gc.createCompatibleImage(img.getWidth(),imt.getHeight(),Transparency.TRANSLCUENT);
Graphics2D g2d = managedImage.createGraphics();
g2d.setComposite(AlphaComposite.SRC);
g2d.drawImage(colorImg,0,0,null);
g2d.setComposite(new ColorIntoAlphaComposite());
g2d.drawImage(alphaImg,0,0,null);
g2d.dispose();
return managedImage;
}

The time consuming bit would be writing the ColorIntoAlphaComposite class - i’ll leave that upto you :smiley:
It shouldn’t be too hard though, CompositeContext gives you :-

void compose(Raster src, Raster dstIn, WritableRaster dstOut)

you just need a loop to go over src, copying the values into the correct band of dstOut.
[/quote]
Performance-wise, a ColorToAlphaComposite class is definitely going to be slow - I’m basically getting and setting invididual pixels from Raster objects. Of course I COULD make sure that such a class works with normally incompatible ColorModels/SampleModels/Rasters, but I’d rather not delve into all that. Not fun . :stuck_out_tongue:

It’s a good idea, but I think I’d much rather stick to 5 lines of code (for now) than write a new class that does exactly the same thing.