GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Posted
2003-05-08 15:47:18 » |
|
I previously wrote a Macromedia Fireworks script to do this, but due to some requirements for tools I need to automate this as a Java process. I've figured out everything except the critical step and can't seem to understand how to do it. I have an image, which is 64x64 pixels. It is an RGB image, no Alpha channel. I have a second image, which is also 64x64 pixels. This one is black and white. What I need to do is to take the full color image and mask it. Specifically, black areas of the second image should retain color information from the first one, while white areas of the second image should be transparent (therefore, the destination image is RGBA). I can't seem to composite them properly and the articles I read at Sun about Advanced Imaging and other articles don't help much. Any thoughts? I tried using clipping regions, but can't seem to get an irregular clip region based on color. Thanks. Edit: 
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
Abuse
|
 |
«
Reply #1 - Posted
2003-05-08 18:54:08 » |
|
Is it speed critical? if not, you can simply subclass RGBImageFilter and add the appropriate behaviour. something like... (i've expanded it from a 1 liner, so u can understand it  ) 1 2 3 4 5 6 7 8 9
| int imgPixel = image.getRGB(x,y); int maskPixel = mask.getRGB(x,y); maskPixel = (maskPixel &0xFF)<<24 image.setRGB(x,y,imgPixel|maskPixel); |
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #2 - Posted
2003-05-08 19:02:06 » |
|
I got it now. Thanks. This should do the trick JUST fine. 
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
Games published by our own members! Check 'em out!
|
|
jbanes
|
 |
«
Reply #3 - Posted
2003-05-08 19:37:52 » |
|
Seems Abuse beat me to it. Here's my solution: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| import java.awt.*; import java.awt.image.*; import java.io.*; import java.util.*;
import javax.imageio.*; import javax.swing.*;
public class ImageMasker { public static BufferedImage createTileMask(BufferedImage tile, BufferedImage mask) { GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); BufferedImage result = gc.createCompatibleImage(tile.getWidth(null), tile.getHeight(null), Transparency.BITMASK); BufferedImage temp = gc.createCompatibleImage(tile.getWidth(null), tile.getHeight(null), Transparency.BITMASK); WritableRaster raster = result.getRaster(); Raster maskData = mask.getRaster(); Raster tileData = tile.getRaster(); Graphics g; int[] pixel = new int[4]; int width = tile.getWidth(null); int height = tile.getHeight(null); for(int y=0; y<height; y++) { for(int x=0; x<width; x++) { pixel = maskData.getPixel(x, y, pixel); if(pixel[0] == 0) { tileData.getPixel(x, y, pixel); pixel[3] = 255; raster.setPixel(x, y, pixel); pixel = tileData.getPixel(x, y, pixel); } } } result.setData(raster); g = temp.createGraphics(); g.drawImage(result, 0, 0, null); g.dispose(); return temp; } public static void main(String[] args) { try { BufferedImage tile = ImageIO.read(new File("color.jpg")); BufferedImage mask = ImageIO.read(new File("bw.jpg")); BufferedImage masked = createTileMask(tile, mask); JFrame frame = new JFrame(); ImageIcon icon = new ImageIcon(masked); JLabel label = new JLabel(icon); frame.getContentPane().add(label); frame.pack(); frame.setVisible(true); } catch(Exception e) { e.printStackTrace(); } } } |
It's inefficient, but it works. BTW, I highly recommend not using JPGs for game images unless you are dealing with photographs. You'll cause all kinds of unpredictable artifacts. P.S. Anyone know how to get this forum to actually preserve spacing? It keeps mucking with my code.
|
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #4 - Posted
2003-05-08 19:41:29 » |
|
Thanks to the both of you. For some reason I just could NOT get the idea of having to manipulate the image on the pixel level; I was hung up on some crazy idea that I could just call this magical method that would composite the two images. Now that I'm past that, it's working to my satisfaction.
JPEGs suck when it comes to any image that isn't continuous tone. I exclusively use PNGs lately (since that's what Fireworks supports, and since I like PNG anyway).
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
Orangy Tang
|
 |
«
Reply #5 - Posted
2003-05-08 23:02:08 » |
|
JPEGs suck when it comes to any image that isn't continuous tone. I exclusively use PNGs lately (since that's what Fireworks supports, and since I like PNG anyway).
.png is great, now if only IE would support them properly (full alpha channel instead of single bit) then we'd all be happy. Unfortunatly it looks like the next major version of IE will be with longhorn and so quite a while off (yes its probably on Opera and others, but theres no point in making a site that looks substandard on 80% of peoples machines  ).
|
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #6 - Posted
2003-05-08 23:24:41 » |
|
Good to see you around, Orangy Tang.
I agree with you on the PNG in IE thing, however, I've only been using it for 1-bit alpha. I don't do anything that really requires multi-channel alpha though I know it can be done. (Though you have just given me a REALLY neat idea for transition tiles).
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
Abuse
|
 |
«
Reply #7 - Posted
2003-05-08 23:39:05 » |
|
I was hung up on some crazy idea that I could just call this magical method that would composite the two images
if the AND and OR composition operations were supported, it would be exactly that ez. 1) Blit the mask with a bitwise AND onto the target. 2) Then using a bitwise OR, blit the image over the top. I still don't understand why the AND and OR drawing operations arn't supported  Infact, back when I only knew VB, and wrote stuff using the win32 api, those were the only composition operations I knew of!! any1 know why java doesn't support them?
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
swpalmer
|
 |
«
Reply #8 - Posted
2003-05-09 03:55:23 » |
|
Is there REALLY no way to do this with the supported compositing rules? Perhaps we should file a RFE? Seems dumb to have that fancy compositing stuff in there and yet we have to resort to manipulating things at the pixel data level. The compositing stuff could even be accelerated with SIMD instructions under the hood (do the JAI performance packs use SIMD instructions?)
|
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #9 - Posted
2003-05-09 04:46:31 » |
|
This took me a while to find, but I think you are right, there is a way to do this in the current rules. It lies in the java.awt.AlphaComposite class, and so far the BEST explanation I have seen of what it can do is here: http://www.redbrick.dcu.ie/help/reference/java/2d/display/compositing.htmlI have no idea how to use the AlphaComposite class, but it's not a big deal. I can figure it out later. Now it's almost 1AM here and time for sleep, while dreaming of data structures. 
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
Games published by our own members! Check 'em out!
|
|
Abuse
|
 |
«
Reply #10 - Posted
2003-05-09 11:25:22 » |
|
all the AlphaCompositing rules deal with compositing the Alpha channel (hence the name  ) What we need for this particular problem is a ColorCompositing class (and yeah, you don't need to check, it doesn't exist  )
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
mattocks
Senior Newbie 
Java games rock!
|
 |
«
Reply #11 - Posted
2003-05-11 06:16:44 » |
|
See example 11-12 CompositeEffects.java from the O'Reilly "Java Examples in a Nutshell" book: http://examples.oreilly.com/jenut2/2nd_edition/The last effect uses a complex shape for a clipping region. - Craig
|
|
|
|
|
Abuse
|
 |
«
Reply #12 - Posted
2003-05-11 12:17:26 » |
|
Hmm, spose you could do it like that... make your own class that implements the Shape interface, and implement the contains(x,y) method as a simple collision map (using the b&w bitmask as the collision map) It would then be a simple case of using your BitMaskShape object as the clip shape for your Graphics context. Thats actually quite a neat solution, and very reusable. Though its pretty slow. (even slower than the suggestions earier  )
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
zingbat
|
 |
«
Reply #13 - Posted
2003-05-11 14:41:39 » |
|
Have you checked the demos in the jfc/java2d. Click the composition tab and see how it works.
I think the mode you need is SrcAtop or DstAtop.
|
|
|
|
|
Abuse
|
 |
«
Reply #14 - Posted
2003-05-11 17:25:33 » |
|
Have you checked the demos in the jfc/java2d. Click the composition tab and see how it works.
I think the mode you need is SrcAtop or DstAtop.
that is AlphaCompositing only, it deals with the src and dst Alpha channel, not the pixel color.
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #15 - Posted
2003-05-11 17:54:24 » |
|
See reply below: it wasn't showing up well on the white contrast, so I'm double posting just to get it on blue.
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #16 - Posted
2003-05-11 17:57:15 » |
|
I think I need to clarify one thing.  +  =  Does tht modify any of the suggestions made so far? I'm somewhat liking the RGBImageFilter solution myself, but I wanted to post this to see if that might change the AlphaComposite attempted solutions. Thanks.
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
Abuse
|
 |
«
Reply #17 - Posted
2003-05-11 19:26:54 » |
|
Hmm, spose you could do it like that... make your own class that implements the Shape interface, and implement the contains(x,y) method as a simple collision map (using the b&w bitmask as the collision map) It would then be a simple case of using your BitMaskShape object as the clip shape for your Graphics context. Thats actually quite a neat solution, and very reusable. Though its pretty slow. (even slower than the suggestions earier  ) I tried my earlier idea, and it doesn't work. setClip uses the PathIterator of the shape for determining 'insideness' of a point, and because the shape described by a bitmask image cannot be represented as a Path, there is no way this idea will work. It could be done using the the Composite interface , however the Composite interface is fairly complicated, so I aint gonna bother trying  As you mentioned, its prolly eziest to stick with the RGBFilter. Perhaps an RFE is in order. (Something like a ColorComposite or PixelComposite class)
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
swpalmer
|
 |
«
Reply #18 - Posted
2003-05-11 21:09:34 » |
|
I think the key here is that we need to get an image that is either 1-bit or 8-bit greyscale to be interpreted as an Alpha channel instead of the image colour content. This might be possible with existing image and compositing classes.
Isn't there a way to make a custom image format where you can say which bits are part of which ARGB component?
The existing AlphaComposite class is fine, as long as we can tell it that the binary or greyscale image is nothing but alpha data.
GK - It looks like you figured this out already, but I will mention it in this thread just for completness. A white (FF) alpha channel indicates 100% opaque, a black (0) alpha channel indicates 100% transparent. The images used in this thread are backwards from that standard
|
|
|
|
swpalmer
|
 |
«
Reply #19 - Posted
2003-05-12 01:23:08 » |
|
I looked into this a bit more.
It looks like the main thing to do is to change the SampleModel of the BufferedImage's Raster so that there is a band for Alpha. The BufferedImage's ColorModel would need to change too. The question is. Can you make these changes on a BufferedImage and the related classes to remap the data in the Raster? It would be great if you could do this without needing to copy image data around. Incidentally, that would be the next step I would try.. copy that mask to the alpha channel of another image when you first load it, then use the built-in AlpahComposite stuff as needed.
|
|
|
|
Abuse
|
 |
«
Reply #20 - Posted
2003-05-12 02:09:49 » |
|
I looked into this a bit more.
It looks like the main thing to do is to change the SampleModel of the BufferedImage's Raster so that there is a band for Alpha. The BufferedImage's ColorModel would need to change too. The question is. Can you make these changes on a BufferedImage and the related classes to remap the data in the Raster? It would be great if you could do this without needing to copy image data around. Incidentally, that would be the next step I would try.. copy that mask to the alpha channel of another image when you first load it, then use the built-in AlpahComposite stuff as needed. thats pretty much what was suggested right at the start of this Thread 
|
Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! 
|
|
|
swpalmer
|
 |
«
Reply #21 - Posted
2003-05-12 04:17:15 » |
|
Well not directly... The earlier talk was about manipulating the pixels manually to put the alpha channel into the foreground image. I was suggesting that, if there is a reason, it could be kept separate as the alpha channel of some different image. But when I look closer it seems that it won't work that way either.. since there is no way to give a third image as the alpha channel for the AlphaComposite stuff. So nevermind 
|
|
|
|
|