【问题标题】:How to convert an image into a transparent image in java如何在java中将图像转换为透明图像
【发布时间】:2011-03-07 07:09:42
【问题描述】:

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

【问题讨论】:

    标签: java image transparent gif


    【解决方案1】:

    Google 的第一个结果是这样的:

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

    它使图像的蓝色部分透明,但我相信您可以调整它以使用白色代替

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

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

    【讨论】:

    • 嗨蒂姆,谢谢你的回复,我试过用白色代替蓝色的代码,但我没有得到透明的图像,图像背景颜色填充了黑色。仅供参考 - 我没有使用小程序,而是使用“ImageIO.write”并将其写为 image.png,也尝试使用 gif。
    • 我认为您的“黑色背景”问题不是使用 TYPE_INT_ARGB 创建新的 BufferedImage 以将过滤后的图像复制到其中(即:您将图像复制到不支持透明度的 BufferedImage 中)
    • 哇,你说得对,它的工作原理......但是有一个小问题,它不是完全透明的,图像轮廓附近的一些像素仍然是白色的。
    • 他们不是 100% 白人... :-/
    【解决方案2】:

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

    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);
    }
    

    【讨论】:

      【解决方案3】:

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

      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);
      

      【讨论】:

        【解决方案4】:

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

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

        我用 Java 创建了一个算法,可以很好地解决这个问题,我用这里显示的两个图对其进行了测试。以下代码引用代号一 (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);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-02-12
          • 1970-01-01
          • 2021-06-01
          • 2012-11-23
          • 1970-01-01
          • 1970-01-01
          • 2011-04-23
          相关资源
          最近更新 更多