Graphics2D не поддерживает альфу?

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

BufferedImage background, foreground;
public GraphicsTest() {
    background = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB);
    foreground = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB);  // Fully capable of alpha.
    Random r = new Random();
    int white = Color.white.getRGB();
            // Draw random white dots
    for (int i=0; i<500; i++) {
        int
        x = r.nextInt(500),
        y = r.nextInt(500);
        background.setRGB(x, y, white);
    }
}

@Override
protected void paintComponent(Graphics g) {
    BufferedImage output = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB); // Fully capable of alpha.
    Graphics2D canvas = output.createGraphics();
    Graphics2D overlay = foreground.createGraphics();

    canvas.drawImage(background, 0, 0, null);

    overlay.setColor(Color.white);
    overlay.fillRect(0, 0, 500, 500);
            // Start drawing with alpha
    overlay.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
    overlay.setColor(new Color(0xFF000000)); // Overwrite/draw full alpha, colour doesn't matter when alpha is 100%
    overlay.fillRect(100, 100, 125, 87);

    //canvas.setColor(Color.red);
    //canvas.fillRect(0, 0, 500, 500);
    canvas.drawImage(foreground, 0, 0, null);
    overlay.dispose();
    canvas.dispose();
    g.drawImage(output, 0, 0, null);
            // Also write to a file for manual raw pixel checking
    try {
                    // Does output a 32-bit depth image
        ImageIO.write(output, "PNG", new File("c:/output.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Это самый простой тест, который я мог придумать, у меня есть два изображения, одно для фона и одно для переднего плана, мне нужно увидеть фон через передний план в поле 127x87 (произвольного размера). В настоящее время это приводит к белому экрану с черным полем, заднее поле должно быть той частью фона.

Я пробовал здесь всевозможные методы, устанавливая композит и рисуя черный с полной альфой, но в сочетании я никогда не вижу фона, setColor (0xFF000000), похоже, ничего не делает, кроме рисования черным, а композит является виновником это «подделка», вместо перезаписи FF000000 (черный) на фоне 00FFFFFF (белый без альфы), что дает FF000000 (то, что я установил), вместо этого 007F7F7F (серый без альфы).

Единственная причина, по которой я вижу это, заключается в том, что все проходит через объект Graphics2D, я не могу использовать output.setRGB, так как он медленный, и я не знаю, как рисовать с его помощью пользовательские фигуры.


person Lee Fogg    schedule 02.11.2013    source источник
comment
Не уверен насчет альфа-проблемы, но НЕ используйте ImageIO (или любой другой IO) в методе рисования.   -  person camickr    schedule 03.11.2013
comment
Вам нужно установить композит через setComposite() см. класс AlphaComposite для различных режимов смешивания   -  person vandale    schedule 03.11.2013
comment
@camickr Почему? Это не цикл, поэтому файл записывается только один раз.   -  person Lee Fogg    schedule 03.11.2013
comment
@vandale Я делаю это со своим оверлейным изображением, не могли бы вы объяснить, если я делаю это неправильно?   -  person Lee Fogg    schedule 03.11.2013
comment
если вы используете непрозрачный цвет, вам нужно использовать конструктор Color(int rgba, boolean hasalpha)   -  person vandale    schedule 03.11.2013
comment
Все методы рисования вызываются всякий раз, когда Swing определяет, что компонент необходимо перерисовать, поэтому да, его можно вызывать несколько раз.   -  person camickr    schedule 03.11.2013


Ответы (1)


Вам нужно изменить 3 вещи, чтобы ваш код работал правильно.

Как сказал @vandale, вам нужно использовать цвет с фактической альфой с логическим конструктором. Во-вторых, альфа — это непрозрачность (поэтому она должна быть равна 0 для прозрачного цвета). Ты получаешь:

 overlay.setColor(new Color(0x0000000, true));

В-третьих, вам нужно сказать, что ваша операция рисования фактически заменит все, что уже было (вы не хотите рисовать поверх (ATOP) существующего, а скорее заменяете прозрачным цветом (IN) то, что там было). Ты получаешь:

 overlay.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1f));
person Rémi    schedule 02.11.2013
comment
Фантастический. Интересно, что альфа перевернута. Приятно знать, что это не вина Graphics2D. - person Lee Fogg; 03.11.2013