如何在java中将图像转换为透明图像

时间:2010-06-23 12:12:19

标签: java image transparent gif

如何将图像的白色背景转换为透明背景?谁能告诉我怎么做?

4 个答案:

答案 0 :(得分:4)

Google的第一个结果是:

使颜色透明 http://www.rgagnon.com/javadetails/java-0265.html

它使图像的蓝色部分透明,但我相信你可以适应它使用白色intstead

(提示:将Color.WHITE传递给makeColorTransparent函数,而不是Color.BLUE

在此处找到更完整,更现代的答案:How to make a color transparent in a BufferedImage and save as PNG

答案 1 :(得分:1)

此方法将使背景透明。您需要传递要修改的图像,颜色和容差。

final int color = ret.getRGB(0, 0);
final Image imageWithTransparency = makeColorTransparent(ret, new Color(color), 10);
final BufferedImage transparentImage = imageToBufferedImage(imageWithTransparency);

private static BufferedImage imageToBufferedImage(final Image image) {
        final BufferedImage bufferedImage =
            new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        final Graphics2D g2 = bufferedImage.createGraphics();
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
        return bufferedImage;
}


private static Image makeColorTransparent(final BufferedImage im, final Color color, int tolerance) {
    int temp = 0;

    if (tolerance < 0 || tolerance > 100) {

        System.err.println("The tolerance is a percentage, so the value has to be between 0 and 100.");

        temp = 0;

    } else {

        temp = tolerance * (0xFF000000 | 0xFF000000) / 100;

    }

    final int toleranceRGB = Math.abs(temp);



    final ImageFilter filter = new RGBImageFilter() {

        // The color we are looking for (white)... Alpha bits are set to opaque

        public int markerRGBFrom = (color.getRGB() | 0xFF000000) - toleranceRGB;

        public int markerRGBTo = (color.getRGB() | 0xFF000000) + toleranceRGB;



        public final int filterRGB(final int x, final int y, final int rgb) {

            if ((rgb | 0xFF000000) >= markerRGBFrom && (rgb | 0xFF000000) <= markerRGBTo) {

                // Mark the alpha bits as zero - transparent

                return 0x00FFFFFF & rgb;

            } else {

                // Nothing to do

                return rgb;

            }

        }

    }; 

    final ImageProducer ip = new FilteredImageSource(im.getSource(), filter);

    return Toolkit.getDefaultToolkit().createImage(ip);
}

答案 2 :(得分:0)

这是我的解决方案。只要背景图像颜色位于左上角,此滤镜就会从任何图像中删除背景。

private static class BackgroundFilter extends RGBImageFilter{

    boolean setUp = false;
    int bgColor;

    @Override
    public int filterRGB(int x, int y, int rgb) {
        int colorWOAlpha = rgb & 0xFFFFFF;
        if( ! setUp && x == 0 && y == 0 ){
            bgColor = colorWOAlpha;
            setUp = true;
        }
        else if( colorWOAlpha == bgColor )
            return colorWOAlpha;
        return rgb;
    }
}

...别处

ImageFilter bgFilter = new BackgroundFilter();
ImageProducer ip = new FilteredImageSource(image.getSource(), bgFilter);
image = Toolkit.getDefaultToolkit().createImage(ip);

答案 3 :(得分:0)

我知道这个问题已经有十多年的历史了,并且已经给出了一些答案。但是,如果图像内的像素与背景颜色相同,则它们都不能令人满意。让我们举一个实际的例子。鉴于这些图片:

enter image description here enter image description here

两者都有白色背景,但白色也在要剪切的图像内。换句话说,两个三角旗外侧的白色像素必须变透明,内侧的白色像素必须保持原样。再加上背景的白色不是完全白色的复杂性(由于 jpeg 压缩),因此需要一个容差。不仅是凸的,而且是凹的,这个问题可以使问题变得更加复杂。

我用Java创建了一个很好地解决问题的算法,我用这里显示的两个图对其进行了测试。以下代码引用了 Codename One (https://www.codenameone.com/javadoc/) 的 Java API,但可以重新用于 Java SE API 或以其他语言实现。重要的是要了解其原理。

    /**
     * Given an image with no transparency, it makes the white background
     * transparent, provided that the entire image outline has a different color
     * from the background; the internal pixels of the image, even if they have
     * the same color as the background, are not changed.
     *
     * @param source image with a white background; the image must have an
     * outline of a different color from background.
     * @return a new image with a transparent background
     */
    public static Image makeBackgroundTransparent(Image source) {
        /*
         * Algorithm
         *
         * Pixels must be iterated in the four possible directions: (1) left to
         * right, for each row (top to bottom); (2) from right to left, for each
         * row (from top to bottom); (3) from top to bottom, for each column
         * (from left to right); (4) from bottom to top, for each column (from
         * left to right).
         *
         * In each iteration, each white pixel is replaced with a transparent
         * one. Each iteration ends when a pixel of color other than white (or
         * a transparent pixel) is encountered.
         */
        if (source == null) {
            throw new IllegalArgumentException("ImageUtilities.makeBackgroundTransparent -> null source image");
        }
        if (source instanceof FontImage) {
            source = ((FontImage) source).toImage();
        }
        int[] pixels = source.getRGB(); // array instance containing the ARGB data within this image
        int width = source.getWidth();
        int height = source.getHeight();
        int tolerance = 1000000; // value chosen through several attempts

        // check if the first pixel is transparent
        if ((pixels[0] >> 24) == 0x00) {
            return source; // nothing to do, the image already has a transparent background
        }
        
        Log.p("Converting white background to transparent...", Log.DEBUG);

        // 1. Left to right, for each row (top to bottom)
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int color = pixels[y * width + x];
                if ((color >> 24) != 0x00 && color >= ColorUtil.WHITE - tolerance && color <= ColorUtil.WHITE + tolerance) { // means white with tolerance and no transparency
                    pixels[y * width + x] = 0x00; // means full transparency
                } else {
                    break;
                }
            }
        }

        // 2. Right to left, for each row (top to bottom)
        for (int y = 0; y < height; y++) {
            for (int x = width - 1; x >= 0; x--) {
                int color = pixels[y * width + x];
                if ((color >> 24) != 0x00 && color >= ColorUtil.WHITE - tolerance && color <= ColorUtil.WHITE + tolerance) { // means white with tolerance and no transparency
                    pixels[y * width + x] = 0x00; // means full transparency
                } else {
                    break;
                }
            }
        }
        
        // 3. Top to bottom, for each column (from left to right)
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int color = pixels[y * width + x];
                if ((color >> 24) != 0x00 && color >= ColorUtil.WHITE - tolerance && color <= ColorUtil.WHITE + tolerance) { // means white with tolerance and no transparency
                    pixels[y * width + x] = 0x00; // means full transparency
                } else {
                    break;
                }
            }
        }
        
        // 4. Bottom to top, for each column (from left to right)
        for (int x = 0; x < width; x++) {
            for (int y = height - 1; y >= 0; y--) {
                int color = pixels[y * width + x];
                if ((color >> 24) != 0x00 && color >= ColorUtil.WHITE - tolerance && color <= ColorUtil.WHITE + tolerance) { // means white with tolerance and no transparency
                    pixels[y * width + x] = 0x00; // means full transparency
                } else {
                    break;
                }
            }
        }
        
        return EncodedImage.createFromRGB(pixels, width, height, false);
    }