Transparency, Programmatically - Question

I’ve searched the forums, and even the web extensively in search for an answer to this question, so I’m sorry if this topic has already been discussed. In any event could you please refer me to the article or thread if this happens to have already been asked.

I’m new to Java, having recently finished my first semester with it at the university level. So I do know the basics but Java’s 2D graphics abilities are still a bit hazy to me. Anyway, I’m trying to figure out how to create transparent images programmatically after loading them from file in an opaque state. I’m familiar with blitting transparent images with Win32 and I’m trying for a similar but simple approach to this in java. I am terrible with graphics and do not understand alpha channels very well so that is why I’m not making the images transparent with a graphics editor; I simply do not know how.

In any event, how would I go about loading a 24 bit PNG from file and then modifying the image to allow any white pixels in the image to be transparent? Would I load the image from file as an image and then copy the image into a bufferedImage? Could I then use setRGB to iterate through the white pixels and change them to be transparent? If so, how would I do this? Also is there a way to iterate through a single PNG that holds all the frames for an animation, and then select the pixels for that particular frame and store them in a bufferedImage?

I seek to do all this for the purpose of game programming, so the fastest way to do this would be ideal. If there is a better way to do the procedures I listed above please let me know. Basically I do not know how to add transparency to images I create or edit in a graphics editor so if there is a way to do it in code for PNG or BITMAP your knowledge on the subject would be most appreciated. Thanks guys, and I’m sorry if I was a bit wordy. Like I said I might be looking at this the wrong way, so correct me if I am.

Ok, just some quick code…I need to hurry to university:


      private BufferedImage buffi;
      private Graphics2D buffigraph;

      
      public Map(File name){
            try {
                  // create temporary bufferedImage of unknown Type
                  BufferedImage buff = ImageIO.read(name);
                  
                  // create BufferedImage of Bitmask Type
                  buffi = new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.BITMASK);
                  
                  // copy the map onto the bitmask bufferedImage
                  buffigraph = (Graphics2D) buffi.getGraphics();
                  buffigraph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                  buffigraph.drawImage(buff, 0, 0, null);
                                    
            } catch (IOException e) {
                  e.printStackTrace();
            }
            removeMagicPink();
      }
      
      private void removeMagicPink(){
            
            int r, g, b, alpha;
            
            int[] colorBuffer =  
                    ((DataBufferInt) buffi.getRaster().getDataBuffer()).getData();
            
            for(int i=0; i < colorBuffer.length; i++)
            {
                   alpha = (colorBuffer[i] >> 24) & 0x00000FF;
                   r = (colorBuffer[i] & 0x00FF0000) >> 16;
                   g = (colorBuffer[i] & 0x0000FF00) >> 8;
                   b = (colorBuffer[i] & 0x000000FF);
                  
                  if( (r==255) && (g==0) && (b==255) ) {
                        colorBuffer[i] = (0 << 24) & (r << 16) & (g << 8) & b;
                        
                  }
            }
      }

this code works with a GIF image (32 bit, format: alpha, R, G, B) and sets the 255,0,255 pink to transparent.

Well, now I feel like a fool because I found out how easy it is to create a transparent image with Photoshop.

However, is there any advantage in creating a mask for an image with Java? I’m use to having to do this when writing games using Win32 API, so that explains why I tried such an approach in the first place. Does loading a transparent image from file still blit to the screen just as fast as one done in code? I also assume by creating masks in code the game would actually have a longer load time in order to process all the images. So really there is no point to create transparency in code if one can do it in a graphics editor, right?

[quote]Well, now I feel like a fool because I found out how easy it is to create a transparent image with Photoshop.
[/quote]
Not to fear, you’re in good company. I think all of us have done something boneheadly stupid at some point or another. Not knowing how to do transparencies rates pretty low on that scale. :slight_smile:

[quote]However, is there any advantage in creating a mask for an image with Java?
[/quote]
Not unless you’re a masochist.

[quote]I’m use to having to do this when writing games using Win32 API, so that explains why I tried such an approach in the first place.
[/quote]
That’s because Win32 sucks. :wink:

Actually it’s because Java was able to take advantage of technologies that simply didn’t exist when Win32 was developed.

[quote]Does loading a transparent image from file still blit to the screen just as fast as one done in code?
[/quote]
Indeedy, do. Java makes the hardware do it, so you’re writing less code and getting better performance! What could be better? ;D

[quote]I also assume by creating masks in code the game would actually have a longer load time in order to process all the images.
[/quote]
Correct.

[quote]So really there is no point to create transparency in code if one can do it in a graphics editor, right?
[/quote]
Pretty much. The only reason to do it in code is that you might do transformations to produce special effects.

Incidentally, KONI, that code you posted above grabs the DataBuffer of the BufferedImage - this makes the image ineligible for hardware acceleration.

If you are using that in any of your code, performance will be substandard.

Hey now, graphics are not my thing. I’m still learning here, cut me some slack. :slight_smile:

[quote] That’s because Win32 sucks. :wink:
[/quote]
Agreed.

Well thanks for the help jbanes; unfortunately I’ll probably have many more questions now that I’ve made the move to Java. See yah around. :slight_smile:

[quote]Incidentally, KONI, that code you posted above grabs the DataBuffer of the BufferedImage - this makes the image ineligible for hardware acceleration.

If you are using that in any of your code, performance will be substandard.
[/quote]
I got that code from:

http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=2D;action=display;num=1103281876;start=2#2

what would you suggest ? I need to get pixel access to an image to change a color to transparent.

I would suggest not doing it programmatically, as it is completely unnecessary, and slow.

[quote]I would suggest not doing it programmatically, as it is completely unnecessary, and slow.
[/quote]
k, I’ll change it into a transparent gif in my graphic program.

But what was the main reason to introduce the magic pink color, why didnt they immediatly use transparent gif images ?

Programmer pink was a hack from back in the days of bmp, pcx and other archaic image formats that had no support for transparency/translucency.

Has someone acctually tried the code provided by KONI?

I have and it didn’t change pink areas to transparent.

Anyone have any idea why?

I’d be suprised if it even compiled?

buffi = new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.BITMASK);

BITMASK is a member of the java.awt.Transparency interface.

As far as I can tell BufferedImage, or its superclasses, do not implement the Transparency interface.

[quote]I’d be suprised if it even compiled?

buffi = new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.BITMASK);

BITMASK is a member of the java.awt.Transparency interface.

As far as I can tell BufferedImage, or its superclasses, do not implement the Transparency interface.
[/quote]
Even changing that to Transparency.BITMASK won’t fix it. I think someone’s getting confused with the “gc.createCompatibleImage()” call. “Regular” BufferedImages constructors take an image type, not a transparency type. e.g.:

buffi = new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_ARGB);

Ok i manged to grab pixels and change smoe of them but how do i write it back to my gif file?

[quote]Ok i manged to grab pixels and change smoe of them but how do i write it back to my gif file?
[/quote]
For GIF files, you don’t. IIRC, GIF writing is unsupported due to the various patents surrounding it. However, writing to a PNG can be done with one of the various “write()” methods on ImageIO.

Would that be a

write(RenderedImage im, String formatName, File output) 

method? if so how do i convert a int[] of pixels into RenderedImage?

BufferedImage implements RenderedImage.

[quote]BufferedImage implements RenderedImage.
[/quote]
Thank you for your replay, but it doesn’t answer my question.

Create a new BufferedImage, and call the following method on it:

setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)  

I think Abuse’s point, however, is that you don’t need an INT[] array if you have a BufferedImage. You can just perform getRGB and setRGB on individual pixels instead of mucking around with rendering the image to an array, modifying it, then pushing it back into a BufferedImage.