开发者

How to convert an image into a transparent image in java

开发者 https://www.devze.com 2023-01-04 06:36 出处:网络
How to convert a white background of an image into a transparent back开发者_如何学运维ground? Can anyone tel me how to do this?The first result from Google is this:

How to convert a white background of an image into a transparent back开发者_如何学运维ground? Can anyone tel me how to do this?


The first result from Google is this:

Make a color transparent http://www.rgagnon.com/javadetails/java-0265.html

It makes the Blue part of an image transparent, but I'm sure you can adapt that to use White intstead

(hint: Pass Color.WHITE to the makeColorTransparent function, instead of Color.BLUE)

Found a more complete and modern answer here: How to make a color transparent in a BufferedImage and save as PNG


This method will make background transparent. You need to pass the image you want to modify, colour, and tolerance.

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


Here is my solution. This filter will remove the background from any image as long as the background image color is in the top left corner.

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

Elsewhere...

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


I am aware that this question is over a decade old and that some answers have already been given. However, none of them is satisfactory if the pixels inside the image are the same color as the background. Let's take a practical example. Given these images:

How to convert an image into a transparent image in java

How to convert an image into a transparent image in java

both have a white background, but the white color is also inside the image to be cutout. In other words, the white pixels on the outside of the two pennants must become transparent, the ones on the inside must remain as they are. Add to this the complication that the white of the background is not perfectly white (due to jpeg compression), so a tolerance is needed. The issue can be made more complex by figures that are not only convex, but also concave.

I created an algorithm in Java that solves the problem very well, I tested it with the two figures shown here. The following code refers to the Java API of Codename One (https://www.codenameone.com/javadoc/), but can be repurposed to the Java SE API or implemented in other languages. The important thing is to understand the rationale.

    /**
     * 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);
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号