I have been looking around for a long time, but I can’t seem to find out how to draw an Image semi-transparently onto a Graphics object. Could someone help me out? I don’t mean gifs or pngs, I mean taking an image and making it all semi-transparent.
Graphics2D g2d = (Graphics2D)g;
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
g2d.drawImage(img,x,y,null);
Thanks. I would have never found that on my own.
isn’t it faster if you change the bits in your image to make it translucent and then draw that image instead of using composite on the fly?
if it is, you can make all the translucent images at startup
if your not going to be changing the level of translucency, then yeah I guess it would be a little quicker.
To Pre-generate the alpha there are 2 ways of going it, the complex way (1), and the dead ez way (2)
- the complex, horribly ugly way…
public BufferedImage makeTranslucent(BufferedImage source, float alpha)
{
WritableRaster wr = source.getAlphaRaster();
//use setSamples to alter the alpha component for each pixel.
//^^ that bit is harder than it seems :P
return source;
}
- the incredibly simple way…
public BufferedImage makeTranslucent(BufferedImage source, float alpha)
{
Graphics2D g2d = source.createGraphics();
g2d.setComposite(AlphaComposite.SRC,alpha);
g2d.drawImage(source,0,0,null);
g2d.dispose();
return source;
}
here’s what i use…
public Image[] makeTranslucentImages(Image[] src) {
Image[] transImages = new Image[src.length];
int width = src[0].getWidth(null);
int height = src[0].getHeight(null);
for (int i = 0; i < src.length; i++) {
int[] pixels = new int[width * height];
PixelGrabber pg = new PixelGrabber(src[i], 0, 0, width, height, pixels, 0, width);
try {
pg.grabPixels();
}
catch (InterruptedException e) {
logger.error(getClass(), "Error grabbing pixels.");
}
for (int k = 0; k < pixels.length; k++) {
int alpha = (pixels[k] >> 24) & 0xff;
if (alpha != 0)
pixels[k] = 0x4F000000 | (pixels[k] & 0x00FFFFFF);
}
transImages[i] = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width, height, pixels, 0, width));
}
return transImages;
}
damn 1.1 is ugly
sure is
What I was looking for was transparent for game menus mostly, although I could use it in applications. While we are on the subject, could someone explain to me how to edit an image pixel-by-pixel? I have had to resort to draw a 1 by 1 rectangle, and that likely is not very efficient. Or is it?
for per-pixel rendering in java1.1,
you have java.awt.image.PixelGrabber.
For per-pixel rendering in 1.2 onwards, you have BufferedImage/DataBufferInt, which is much more efficient.
BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
DataBufferInt dbi = (DataBufferInt)(bi.getRaster().getDataBuffer());
int [] pixels = dbi.getData();
Or perhaps an ImageProducer or MemoryImageSource if you need 1.1 compatibility… depends exactly what you mean by “edit” the two classes I just mentioned can be used in conjunction with data from the PixelGrabber, or you can generate the entire image from scratch.
The best solution of course is to let 1.1 die the death that is long overdue and use Java 2 APIs.
How do you set a color with a plain-old integer? What’s all this 0x00FFFFFF and 0x4F000000 business?
its the ARGB integer packed 32bits per pixel color format.
0xFF000000 masks out the alpha (A)
0x00FF0000 masks out the Red ®
0x0000FF00 masks out the Green (G)
0x000000FF masks out the Blue (B)
hence, a fully opaque white pixel is represented as 0xFFFFFFFF
(which, if interpreted as a twos compliment numeric value, has the value of -1)
Wait… transparent is 00 and opaque is FF?
Ooops, gotta fix a filter.
A quick side note is that by grabbing the pixel data for the BufferedImage it can no longer be accelerated.
Cool. Thanks for all the help.