• Advertisement
Sign in to follow this  

[java] Transparent Images in awt

This topic is 4672 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I load the image somthing like that:
Image img=Toolkit.getDefaultToolkit().createImage(fileName);
mdtr.addImage(img,0);try
{
   mdtr.waitForID(0);
}
catch (InterruptedException e)
{
   System.out.println(e);
}

mdtr is a mediaTracker fileName is a name of a gif file I print the Image on the screen like that:
target.drawImage(frames[currentFrame],xPosition,yPosition,bgColor,null);

target is declared "Graphics target", but it actualt of the type Graphics2D. target is my buffer frames[currentFrame] is the image I loaded before You can guess what xPosition and yPosition are bgColor is the background color Now, I made some pictures with white backgrounds, and tried to print the with
bgColor=new Color(255,255,255);

But the pictures background is still not transparent. What have I been doing wrong?

Share this post


Link to post
Share on other sites
Advertisement
Do you really have to use an AWT image? If you use BufferedImage you could do like this:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
Offscreen = gc.createCompatibleImage(300,300, Transparency.TRANSLUCENT);

Share this post


Link to post
Share on other sites
Well, I don't realy use Graphics and Image Objects. Those classes are abstract. The actual Objects are of the types Graphics2D and BufferedImage.

gcsaba2, thanks for replying, but your code didn't solved the problem. It only made the entire background black.

I tried to use the setXORMode(java.awt.Color) function of the Graphics class with the parameter java.awt.Color.white. It solved that problem, but it made other probelm with images lying on each other.

Any other ideas?

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy
gcsaba2, thanks for replying, but your code didn't solved the problem. It only made the entire background black.

Yes I know. There is a way to fix this though I haven't looked it up (too lazy). I solved the problem by using only GIF images, and you can draw them to have a transparent background. I downloaded IrfanView which is very useful for conversion between image types, and when you save an image as a GIF it shows you your image zoomed and you can select a color, and then that color will be shown as transparent if you load it from Java.

Share this post


Link to post
Share on other sites
Quote:
java.awt.image.BufferedImage#getAlphaRaster()
getAlphaRaster

public WritableRaster getAlphaRaster()

Returns a WritableRaster representing the alpha channel for BufferedImage objects with ColorModel objects that support a separate spatial alpha channel, such as ComponentColorModel and DirectColorModel. Returns null if there is no alpha channel associated with the ColorModel in this image. This method assumes that for all ColorModel objects other than IndexColorModel, if the ColorModel supports alpha, there is a separate alpha channel which is stored as the last band of image data. If the image uses an IndexColorModel that has alpha in the lookup table, this method returns null since there is no spatially discrete alpha channel. This method creates a new WritableRaster, but shares the data array.

Returns:
a WritableRaster or null if this BufferedImage has no alpha channel associated with its ColorModel.


java.awt.image.BufferedImage@getTransparency()
getTransparency

public int getTransparency()

Returns the transparency. Returns either OPAQUE, BITMASK, or TRANSLUCENT.

Specified by:
getTransparency in interface Transparency

Returns:
the transparency of this BufferedImage.
Since:
1.5
See Also:
Transparency.OPAQUE, Transparency.BITMASK, Transparency.TRANSLUCENT


Share this post


Link to post
Share on other sites
Well, IrfanView didn't solved my problem.

capn_midnight, can you explain or link to a toturial which explains how to use Rasters and Alfa?

Share this post


Link to post
Share on other sites
Will it slow my game seriuesly if I will paint the images manualy, using getRGB and setRGB?

Share this post


Link to post
Share on other sites
One idea to use transparency is to draw a loaded image to a BufferedImage and then filter out a color that you want to be transparent.


//Filters a color out of an image (replaces with transparency)
public static BufferedImage filterImage(Image i, Color c)
{
final int WIDTH = i.getWidth(null);
final int HEIGHT = i.getHeight(null);
final int COLOR = c.getRGB();
final Color CLEAR = new Color(0,0,0,0);

GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();

//The new image with the color filtered out
BufferedImage temp;
temp = gc.createCompatibleImage(WIDTH,HEIGHT,Transparency.BITMASK);

//Gets the graphics of the temporary image
Graphics2D g = temp.createGraphics();

//Copies the old image to this one
g.drawImage(i,0,0,null);

//Gets rid of extra resources used on the graphics obj.
g.dispose();

//Find all COLOR pixels and make them transparent
for(int x=0; x<WIDTH; x++){
for(int y=0; y<HEIGHT; y++)
if(temp.getRGB(x,y) == COLOR)
temp.setRGB(x,y,CLEAR.getRGB());
}

return temp;
}



Now you have the image just display it with
target.drawImage(img,positionX,positionY,null);


Also, another way to load images (from Brackeen's "Developing Games in Java") is to use
Image img = (new ImageIcon(file)).getImage();
It handles waiting for the image to finish loading and supports (as far as i can tell) .png and .gif.
(ImageIcon is in javax.swing.*)

Share this post


Link to post
Share on other sites
Thank you mako_5. I will stay in your debt forever. Now my game looks better.

Share this post


Link to post
Share on other sites
That's great mako_5, somebody should put that code in the FAQ

Share this post


Link to post
Share on other sites
Hoy.

If you use BufferedImage, you really should consider using the raster data instead. (It's much faster than setting and getting single RGB values).


DataBufferInt dbuffer = (DataBufferInt)(((WritableRaster)image.getRaster()).getDataBuffer());

int[] imageData = dbuffer.getData();


This gives you the int array imageData which is imageWidth*imageHeight in length. For bitmask images, the alpha value is either 0 or 1 (translucency is inbetween). 1 is opaque, 0 is transparent. Now, color mapping is I won't go into here, but to make a pixel transparent in imageData, simply imageData=0;
does the trick.

The big advantage with image.getRaster() is that the int array is directly mapped to the image (actual array, no copy). So any changes to the array, is reflected on the image itself. if you want an array like imageData, but not changes to it to reflect the image directly, use image.getData() (the same as getRaster() except this is a copy).

If you do not plan to mix and mess with colors at all, you can substitute the image.getRaster() with image.getAlphaRaster(). Note that not all ColorModel's support the alpha raster, so it will sometimes return null (the API is really self-explanatory).

It's just as well to learn how to use the raster right now, and learn it well. Once you understand it, it will make alot of stuff easiar for you.




Share this post


Link to post
Share on other sites
Well I guess it is only needed once to make an image transparent, and that is during the process of reading it from a file, which I guess happens during game initialization, when players are ready to wait for awhile. So it doesn't really matter if you use one way or another, but Addictman's method is certainly useful for effects I guess. But how do you know which color does imageData contains?

Share this post


Link to post
Share on other sites
Well, it depends on your color model if you want to do it directly. But for a DirectColorModel (standard RGB with alpha),



From API:

Number of bits: 32
Red mask: 0x00ff0000
Green mask: 0x0000ff00
Blue mask: 0x000000ff
Alpha mask: 0xff000000
Color space: sRGB
isAlphaPremultiplied: False
Transparency: Transparency.TRANSLUCENT
transferType: DataBuffer.TYPE_INT



You can do the following:



int alpha = (pixels&0xff000000)>>24;
int red = (pixels&0x00ff0000)>>16;
int green = (pixels&0x0000ff00)>>8;
int blue = pixels&0x000000ff;

to convert back to packed color, do something like

public static int ARGB(int r, int g, int b, int a)
{
return ( a << 24 ) | ( r << 16) | ( g << 8 ) | b;
}
for pixels that should be translucent or transparent,
or simply

public static int RGB(int r, int g, int b)
{
return ( 255 << 24 ) | ( r << 16) | ( g << 8 ) | b;
}

for opaque pixels.



Hope this helps.

[Edited by - Addictman on May 5, 2005 4:38:10 AM]

Share this post


Link to post
Share on other sites
As a sidenote, does anyone know if the following alpha scaling works always for DirectColorModels (default with GraphicsConfiguration.createCompatibleImage(..))



int alpha = ((c & 0xff000000)>>>24);



It *seems* (in my experiments) that this works. However, I am not sure if it can be trusted or not.

Share this post


Link to post
Share on other sites
Quote:
Original post by Addictman
Hoy.

If you use BufferedImage, you really should consider using the raster data instead. (It's much faster than setting and getting single RGB values).


DataBufferInt dbuffer = (DataBufferInt)(((WritableRaster)image.getRaster()).getDataBuffer());

int[] imageData = dbuffer.getData();


This gives you the int array imageData which is imageWidth*imageHeight in length. For bitmask images, the alpha value is either 0 or 1 (translucency is inbetween). 1 is opaque, 0 is transparent. Now, color mapping is I won't go into here, but to make a pixel transparent in imageData, simply imageData=0;
does the trick.

The big advantage with image.getRaster() is that the int array is directly mapped to the image (actual array, no copy). So any changes to the array, is reflected on the image itself. if you want an array like imageData, but not changes to it to reflect the image directly, use image.getData() (the same as getRaster() except this is a copy).

If you do not plan to mix and mess with colors at all, you can substitute the image.getRaster() with image.getAlphaRaster(). Note that not all ColorModel's support the alpha raster, so it will sometimes return null (the API is really self-explanatory).

It's just as well to learn how to use the raster right now, and learn it well. Once you understand it, it will make alot of stuff easiar for you.


Be aware that you don't always get DataBufferInt and if you don't check it's type, you'll end up with a ClassCastException. I've seen this on Images loaded with ImageIO on macs. So only get the raster when you know it's got the correct color model.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement