views:

232

answers:

1

I have a BufferedImage that I get that has an IndexColorModel. I then wish to apply an AffineTransform with AffineTransformOP in order to create a transformed version of displayImage.

Here's a code snippet:

int type = isRGB() ? AffineTransformOp.TYPE_BILINEAR : AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
AffineTransformOp op = new AffineTransformOp(atx, type);
displayImage = op.filter(displayImage, null);

I'm running this with many images, and from an earlier post I discovered that if I set the transform type to bilinear, then I was running out of memory because I was getting an image back with a DirectColorModel. However, this DirectColorModel had a correct alpha channel (when I drew the image an a green background after translating it, I could see green around the whole image). When I set the interpolation type to nearest neighbor, pixels above and to the left of the image appear black no matter what the background is. I'm assuming this means that the alpha is not getting set.

Can anyone tell me how to correctly set the alpha channel with an IndexColorModel, or change the AffineTransformOP parameters such that I get an IndexColorModel with the correct alpha?

Thanks!!

EDIT: Here is the desired effect, with AffineTransformOp.TYPE_BINLINEAR: alt text

Here is the effect that I'm seeing with AffineTransformOp.TYPE_NEAREST_NEIGHBOR: alt text

The whole background is initially painted green for effect and in both cases the image is drawn at position (0, 0).

+1  A: 

I'm not sure what effect you're trying to achieve, but I get expected results when I adjust the alpha before and/or after transforming. Typically, I start with setComposite(AlphaComposite.Clear) followed by fillRect(). If all else fails, you can filter() to a WritableRaster, and brute-force the result you want. Also, you might look at RenderingHints related to KEY_ALPHA_INTERPOLATION. Here's a toy I use to experiment with various combinations of alpha, mode and color.

I seem to recall seeing the effect your images show. Recalling that the AffineTransformOp may return an image with different co-ordinates, especially with rotation, I'm guessing the added "empty" space isn't getting initialized correctly. You can get a transparent border with the code below, which also makes rotation around the center somewhat more symmetric:

private BufferedImage getSquareImage(BufferedImage image) {
    int w = image.getWidth();
    int h = image.getHeight();
    int max = Math.max(w, h);
    BufferedImage square = new BufferedImage(
            max, max, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = square.createGraphics();
    g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setComposite(AlphaComposite.Clear);
    g2d.fillRect(0, 0, max, max);
    g2d.setComposite(AlphaComposite.Src);
    g2d.drawImage(image, (max - w) / 2, (max - h) / 2, null);
    g2d.dispose();
    return square;
}
trashgod
I'm a little confused. Do you do this when you're painting the image, or do you do this on the displayImage.createGraphics() graphics? I read the API on AlphaComposite, and I'm a little confused on what is the src and what is the dst.
Jon
The terms src and dst are pixels, named A and B in Porter and Duff's paper <http://keithp.com/~keithp/porterduff/p253-porter.pdf>.
trashgod
I tried running displayImage through this method after filtering it and it returned a DirectColorModel which will cause my initial out of memory errors.
Jon