Как преобразовать изображение в прозрачное изображение в Java

Как превратить белый фон изображения в прозрачный фон? Кто-нибудь может сказать мне, как это сделать?


person SWDeveloper    schedule 23.06.2010    source источник


Ответы (4)


Первый результат от Google таков:

Сделайте цвет прозрачным http://www.rgagnon.com/javadetails/java-0265.html

Это делает синюю часть изображения прозрачной, но я уверен, что вы можете адаптировать это, чтобы использовать вместо нее белый.

(подсказка: передать Color.WHITE функции makeColorTransparent вместо Color.BLUE)

Здесь нашел более полный и современный ответ: png">Как сделать цвет прозрачным в BufferedImage и сохранить как PNG

person tim_yates    schedule 23.06.2010
comment
Привет, Тим, спасибо за твой ответ, я попробовал этот код с белым вместо синего, но я не получаю прозрачного изображения, цвет фона изображения заполнен черным цветом. К вашему сведению, я не использовал апплет, вместо этого я использовал ImageIO.write и записал его как image.png, пробовал и с gif. - person SWDeveloper; 23.06.2010
comment
Нашел это также stackoverflow.com/questions/665406/ - person tim_yates; 23.06.2010
comment
Я думаю, что ваша проблема с «черным фоном» заключается не в создании нового BufferedImage с TYPE_INT_ARGB для копирования отфильтрованного изображения (т.е. вы копируете изображение в BufferedImage, не поддерживающее прозрачность) - person tim_yates; 23.06.2010
comment
Вау, ты прав, все работает... Но есть одна маленькая проблема, оно не совсем прозрачное, некоторые пиксели возле контура изображения все еще белые. - person SWDeveloper; 23.06.2010
comment
Они не на 100% белые... :-/ - person tim_yates; 23.06.2010
comment
Вместо того, чтобы делать if ( ( rgb | 0xFF000000 ) == markerRGB ) {, вам нужно проверить, находится ли цвет в определенном диапазоне - person tim_yates; 23.06.2010
comment
@tim_yates ваш ответ не сработал в первый раз, поэтому вы должны ПРИНОСИТЬ ИЗВИНЕНИЯ от SWDeveloper за то, что написали. Первый результат от Google таков: ! ;) Ваш рабочий ответ: stackoverflow.com/questions/665406/ - person Bahadir Tasdemir; 15.06.2016

Этот метод сделает фон прозрачным. Вам нужно передать изображение, которое вы хотите изменить, цвет и допуск.

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);
}
person Ruchi    schedule 05.06.2014

Вот мое решение. Этот фильтр удалит фон с любого изображения, если цвет фонового изображения находится в верхнем левом углу.

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);
person Bob    schedule 13.08.2010

Я знаю, что этому вопросу более десяти лет и что некоторые ответы уже даны. Однако ни один из них не является удовлетворительным, если пиксели внутри изображения имеют тот же цвет, что и фон. Возьмем практический пример. Учитывая эти изображения:

введите здесь описание изображения введите здесь описание изображения

оба имеют белый фон, но белый цвет также находится внутри вырезаемого изображения. Другими словами, белые пиксели снаружи двух вымпелов должны стать прозрачными, а те, что внутри, должны остаться такими, какие они есть. Добавьте к этому осложнение, заключающееся в том, что белый цвет фона не идеально белый (из-за сжатия jpeg), поэтому необходим допуск. Усложнить задачу можно фигурами не только выпуклыми, но и вогнутыми.

Я создал алгоритм на Java, который очень хорошо решает проблему, я протестировал его с помощью двух рисунков, показанных здесь. Следующий код относится к Java API Codename One (https://www.codenameone.com/javadoc/), но его можно перепрофилировать в 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);
    }
person Francesco Galgani    schedule 04.06.2021