прозрачный фон java - PullRequest
       58

прозрачный фон java

4 голосов
/ 03 марта 2011

У меня есть изображение GIF, которое содержит только цветную фигуру и прозрачный фон

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

Я создал фильтр, который правильно заменяет белый на красный (это тест)

Однако у меня возникла проблема с моим методом imageToBufferedImage, он удаляет прозрачность и заменяет ее на черный (не знаю почему).

Итак, что я сделал до сих пор:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import javax.imageio.ImageIO;

public class TestPNG {

    public static void main(String[] args) throws Exception {

        File in = new File("bg.gif");
        BufferedImage source = ImageIO.read(in);
        int color = source.getRGB(0, 0);

        Image image = makeColorTransparent(source, new Color(color), new Color(255, 0, 0));

        BufferedImage transparent = imageToBufferedImage(image);

        File out = new File("bg2.gif");
        ImageIO.write(transparent, "gif", out);

    }

    private static BufferedImage imageToBufferedImage(Image image) {
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        //g2.setBackground(Color.blue);
        g2.clearRect(0, 0, 200, 40);
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
        return bufferedImage;
    }

    public static Image makeColorTransparent(BufferedImage im, final Color search, final Color replace) {
        ImageFilter filter = new RGBImageFilter() {
                public final int filterRGB(int x, int y, int rgb) {
                        if (rgb == search.getRGB()) {
                            return replace.getRGB();
                        } else {
                            return rgb;
                        }
                }
        };
        ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
        return Toolkit.getDefaultToolkit().createImage(ip);
    }

}

Ответы [ 5 ]

2 голосов
/ 28 октября 2012

В вашем коде есть 3 проблемы:

1) Замените

Image image = makeColorTransparent(source, new Color(color), new Color(255, 0, 0));

на

Image image = makeColorTransparent(source, color, new Color(255, 0, 0));

и

public static Image makeColorTransparent(BufferedImage im, final Color search, final Color replace) {
...
if (rgb == search.getRGB()) {
...
}

на

public static Image makeColorTransparent(BufferedImage im, final int search, final Color replace) {
...
if (rgb == search) {
...
}

ПОСКОЛЬКУ по какой-то причине source.getRGB(0, 0) игнорирует альфа-значение и становится белым ((255, 255, 255, 0) становится (255, 255, 255, 255))

2) Вы не можете использовать int color = source.getRGB(0, 0), потому что он использует цвет первого пикселя (прозрачный).Вы должны использовать какой-то другой код (например, запросить цвет в консоли), чтобы узнать, какой цвет пикселя хранить в int color

3) Вы очищаете цвет BufferedImage bufferedImage в imageToBufferedImage(...) с помощью Color.BLACK (по умолчанию).Замените //g2.setBackground(Color.blue); на g2.setBackground(new Color(0, 0, 0, 0)); или удалите g2.clearRect(...);

0 голосов
/ 26 апреля 2014

Вы очищаете пиксели с помощью композита. Вы не можете просто закрасить прозрачные пиксели поверх других пикселей или любого другого мусора. Правила Портера-Даффа ясны, делая все это, пиксели будут смешиваться в соответствии с составным правилом. Так что просто поменяй, правило очисти пиксели.

Проблема в том, что большинство решений пытаются уговорить изображение получить пиксели, которые вы хотите получить в конце, используя правило. Измените правило на секунду, и все станет намного проще.

Composite composite = g.getComposite();

g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g.fillRect(0, 0, bufferedimage.getWidth(), bufferedimage.getHeight());

g.setComposite(composite);

Это очистит графический объект от текущих пикселей. Тогда просто нарисуйте то, что вы хотите. Мой пример восстановил предыдущую композицию, так как вы будете удивлены, как часто эта штука выглядит странно, поэтому вы просто получаете очищенные пиксели и можете начинать все заново, ничего не изменяя в графическом контексте.

0 голосов
/ 03 марта 2011

Просто угадать:

a) Возможно, вам не нужен метод clearRect(...).

b) Может быть, вы можете использовать что-то вроде:

g2.setColor(new Color(0, 0, 0, 0));
g2.fillRect(...);
0 голосов
/ 03 марта 2011

У вас есть это:

    g2.drawImage(image, 0, 0, null);

Из Javadoc для этого метода:

Прозрачные пиксели на изображении не влияют на то, какие пиксели уже есть.

Так как вы очистили свое изображение, заполнив его цветом фона, пиксели уже черные, поэтому они остаются черными.

Попробуйте

g2.setBackground(new Color(0, 0, 0, 0) );
g2.clearRect(0, 0, 200, 40);

перед покраской вашего изображения.

0 голосов
/ 03 марта 2011

Вы уверены, что ваше изображение поддерживает альфа-канал? Попытка сначала нарисовать не черный полноразмерный прямоугольник в bufferedImage?

...