我有两个从pngs加载的BufferedImages.第一个包含图像,第二个包含图像的alpha蒙版.
我想通过应用alpha蒙版来创建两者的组合图像.我的google-fu让我失望了.
我知道如何加载/保存图像,我只需要从两个BufferedImages到一个带有正确alpha通道的BufferedImage.
我对这个答案来说太迟了,但无论如何它可能对某人有用.这是Michael Myers方法的更简单,更有效的版本:
public void applyGrayscaleMaskToAlpha(BufferedImage image, BufferedImage mask) { int width = image.getWidth(); int height = image.getHeight(); int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width); int[] maskPixels = mask.getRGB(0, 0, width, height, null, 0, width); for (int i = 0; i < imagePixels.length; i++) { int color = imagePixels[i] & 0x00ffffff; // Mask preexisting alpha int alpha = maskPixels[i] << 24; // Shift blue to alpha imagePixels[i] = color | alpha; } image.setRGB(0, 0, width, height, imagePixels, 0, width); }
它在开始时将所有像素读入数组,因此只需要一个for循环.此外,它直接将蓝色字节移动到alpha(掩码颜色),而不是首先屏蔽红色字节然后移动它.
与其他方法一样,它假设两个图像具有相同的尺寸.
我最近玩这个东西,在另一个上显示图像,并将图像淡化为灰色.
还使用具有透明度的蒙版(我之前版本的此消息!)来屏蔽图像.
我拿了我的小测试程序并调整了一下以获得想要的结果.
以下是相关位:
TestMask() throws IOException { m_images = new BufferedImage[3]; m_images[0] = ImageIO.read(new File("E:/Documents/images/map.png")); m_images[1] = ImageIO.read(new File("E:/Documents/images/mapMask3.png")); Image transpImg = TransformGrayToTransparency(m_images[1]); m_images[2] = ApplyTransparency(m_images[0], transpImg); } private Image TransformGrayToTransparency(BufferedImage image) { ImageFilter filter = new RGBImageFilter() { public final int filterRGB(int x, int y, int rgb) { return (rgb << 8) & 0xFF000000; } }; ImageProducer ip = new FilteredImageSource(image.getSource(), filter); return Toolkit.getDefaultToolkit().createImage(ip); } private BufferedImage ApplyTransparency(BufferedImage image, Image mask) { BufferedImage dest = new BufferedImage( image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = dest.createGraphics(); g2.drawImage(image, 0, 0, null); AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0F); g2.setComposite(ac); g2.drawImage(mask, 0, 0, null); g2.dispose(); return dest; }
其余部分只是在一个小Swing面板中显示图像.
请注意,蒙版图像是灰度级,黑色变为完全透明,白色变为完全不透明.
虽然你已经解决了你的问题,但我可以分享我对它的看法.它使用稍微多一点的Java-ish方法,使用标准类来处理/过滤图像.
实际上,我的方法使用了更多的内存(制作一个额外的图像),我不确定它是否更快(测量相应的性能可能很有趣),但它稍微更抽象.
至少,你有选择!:-)
您可以通过一次获取多个像素的RGB数据来改进您的解决方案(请参阅http://java.sun.com/javase/6/docs/api/java/awt/image/BufferedImage.html),并通过在内循环的每次迭代中都不创建三个Color对象.
final int width = image.getWidth(); int[] imgData = new int[width]; int[] maskData = new int[width]; for (int y = 0; y < image.getHeight(); y++) { // fetch a line of data from each image image.getRGB(0, y, width, 1, imgData, 0, 1); mask.getRGB(0, y, width, 1, maskData, 0, 1); // apply the mask for (int x = 0; x < width; x++) { int color = imgData[x] & 0x00FFFFFF; // mask away any alpha present int maskColor = (maskData[x] & 0x00FF0000) << 8; // shift red into alpha bits color |= maskColor; imgData[x] = color; } // replace the data image.setRGB(0, y, width, 1, imgData, 0, 1); }