Подтвердить что ты не робот

Java: заполнение BufferedImage прозрачными пикселями

У меня есть off-screen BufferedImage, построенный с типом BufferedImage.TYPE_INT_ARGB. Он может содержать что угодно, и я ищу способ (достаточно эффективно) полностью перезаписать изображение с прозрачными пикселями, что приведет к "невидимому" изображению.

Используя что-то вроде этого:

    (bufimg.getGraphics()).setColor(new Color(10, 10, 100, 0));   
    (bufimg.getGraphics()).fillRect (0, 0, x, y);

Не действует. Одним из возможных методов может быть просто написать каждый пиксель в BufferedImage, но я не уверен, что это лучшее решение. Как вы это сделаете?

[править]
В документации Graphics не рекомендуется использовать clearRect для изображений вне экрана, но я пробовал его с теми же результатами, что и выше.

[edit2]
После экспериментирования с кодом MeBigFatGuy (спасибо!) Он очищает изображение. Но он также останавливает дальнейшее рисование этого образа (или появляется). Этот код, например:

    BufferedImage img = new BufferedImage (600, 600, BufferedImage.TYPE_INT_ARGB);
    Graphics g = img.createGraphics ()    
    g.drawLine (100, 100, 500, 500);
    AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
    g.setComposite(composite);
    g.setColor(new Color(0, 0, 0, 0));
    g.fillRect(0, 0, 600, 600);
    graphicsAI.setColor(new Color (10, 10, 10, 255));
    graphicsAI.drawLine (100, 100, 500, 500);

Результаты не отображаются на изображении (я рисую изображение в JPanel). Это связано с добавлением альфа-значений?

4b9b3361

Ответ 1

Вы можете получить базовый массив int[] вашего BufferedImage (обязательно используйте совместимый формат: то есть тот, который поддерживается int[]).

Затем заполните int[] с помощью int, чье альфа-значение равно 0 (0 будет делать;)

A System.arraycopy будет очень быстрым.

Вы должны знать, что непосредственно запись в int[] выполняется намного быстрее, чем использование setRGB.

Теперь BufferedImage - это немного черное искусство на Java: в зависимости от того, что вы делаете, и на какой платформе /JVM вы это делаете, вы можете потерять аппаратное ускорение (которого, возможно, никогда не было в первое место в любом случае). В дополнение к этому, вы, возможно, совсем не заботитесь об аппаратном ускорении, потому что вы, возможно, не работаете, скажем, с игрой, требующей воспроизведения более 60 FPS и т.д.

Это сложная тема очень, и есть более чем один способ обмануть кошку BufferedImage. Насколько мне известно, я работаю непосредственно в int[], когда мне приходится сталкиваться с пиксельным уровнем, потому что я думаю, что это имеет гораздо больше смысла, чем пытаться использовать примитивы рисования более высокого уровня, и я действительно не заботятся о потенциальной утрате аппаратного ускорения.

Ответ 2

После того, как вы очистите фон композитом CLEAR, вам нужно вернуть его обратно в SRC_OVER, чтобы снова рисовать. например:

//clear
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2.fillRect(0,0,256,256);

//reset composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//draw
g2.setPaint(Color.RED);
g2.fillOval(50,50,100,100);

Ответ 3

Если вы передаете объект Graphics объекту Graphics2D, вы можете установить объект Composite через

AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setComposite(composite);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.fillRect(0, 0, 10, 10);

Ответ 4

Несмотря на то, что вы говорите, что это не сработало, я использовал clearRect довольно хорошо.

Очищает указанный прямоугольник, заполняя его цветом фона текущей поверхности чертежа. Эта операция не использует текущий режим окраски.

Начиная с Java 1.1, цвет фона заставных изображений может быть зависящим от системы. Приложения должны использовать setColor, за которым следует fillRect, чтобы убедиться, что очищенное изображение очищено до определенного цвет.


Заполняет указанный прямоугольник. Левый и правый края прямоугольник имеет x и x + ширину - 1. Верхний и нижний края находятся на y и y + height - 1. Полученный прямоугольник охватывает ширину области пикселей в ширину по высоте. Прямоугольник заполняется с помощью текущий контекст графического контекста.

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

Это чисто спекуляция, но я думаю, что примечание о заставке изображения относится к объектам Graphics, полученным из внеэкранных компонентов AWT, поскольку они являются родными. Я не могу себе представить, как фоновый цвет BufferedImage может быть зависимым от системы. Поскольку документ API для Graphics, это может быть обобщение, не относящееся к случаю BufferedImage.

Мой тестовый код:

JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

BufferedImage img = new BufferedImage(200, 300, BufferedImage.TYPE_INT_ARGB);

Graphics2D g = img.createGraphics();

//fill right half with opaque white
g.setColor(Color.WHITE);
g.fillRect(100, 0, 100, 300);

//leave top third as it is

//fill middle third with transparent color
g.setColor(new Color(0, true));
g.fillRect(0, 100, 200, 100);

//clear bottom third with transparent color
g.setBackground(new Color(0, true));
g.clearRect(0, 200, 200, 100);

g.dispose();

jf.add(new JLabel(new ImageIcon(img)));

jf.pack();
jf.setVisible(true);

результат - два белых квадрата, верхний правый. Там, где белый цвет не был окрашен, или clearRect используется для перезаписи белого, результат - светло-серый, цвет фона по умолчанию для фона.

Производительность - это регулярный рисунок. arraycopy может быть быстрее, я не знаю, но, по крайней мере, это, скорее всего, аппаратное ускорение, как и любая другая операция рисования.

A плюс точка против решения массива: a) отсутствие дополнительной памяти и b) независимость от цветовой модели; это должно работать независимо от того, как было настроено изображение.

Минус-точка против решения Composite заключается в том, что он разрешает очищать прямоугольники; настройка композита позволяет вам очистить любую форму.

Ответ 5

Настройка фона графического объекта, похоже, выполняет задание:

g.setBackground(new Color(0, 0, 0, 0));

(по крайней мере, при рисовании изображений для масштабирования)

Ответ 6

Несмотря на то, что он хочет сделать пиксель переднего плана прозрачным, ваш ответ, безусловно, является правильным.

private Color transparent = new Color(0, true);

((Graphics2D) g).setBackground(transparent);

g.clearRect(0, 0, w, h);

устанавливает прозрачный фон

Кстати: другие ответы в основном мусор или просто FUD. Пожалуйста, не принимайте ответы, которые говорят о "буферизованном изображении, являющемся черным искусством" на техническом форуме.