Как нарисовать прозрачную фигуру с помощью объекта Graphics g?

Я хочу создать «кольцо» в BufferedImage с прозрачным фоном. Я могу нарисовать круг с прозрачным фоном вот так:

BufferedImage bi = new BufferedImage(d, d, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) bi.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(c);
g.fillOval(0, 0, d, d);

Но теперь я хочу нарисовать в середине прозрачный круг меньшего размера, чтобы получилось кольцо (поэтому, когда я рисую это изображение поверх другого изображения, пиксели вокруг и внутри кольца не отображаются). Я хочу использовать для этого объект Graphics, чтобы можно было использовать сглаживание.

Это возможно? Если нет, как лучше всего решить эту проблему?


person Alan    schedule 01.06.2012    source источник


Ответы (2)


Создайте круглую форму, затем вычтите из нее еще одну круглую форму, установите ее как зажим, и вы можете получить что-то по нужным линиям. Чтобы скрыть острые края клипа, нарисуйте обводку формы шириной 2 пикселя.

Одно кольцо

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

public class OneRing {

    OneRing(BufferedImage imageBG, BufferedImage imageFG) {
        // presumes the images are identical in size BNI
        int w = imageBG.getWidth();
        int h = imageBG.getHeight();
        Ellipse2D.Double ellipse1 = new Ellipse2D.Double(
                w/16,h/16,7*w/8,7*h/8); 
        Ellipse2D.Double ellipse2 = new Ellipse2D.Double(
                w/4,h/4,w/2,h/2);
        Area circle = new Area(ellipse1);
        circle.subtract(new Area(ellipse2));

        Graphics2D g = imageBG.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g.setClip(circle);
        g.drawImage(imageFG, 0, 0, null);
        g.setClip(null);
        Stroke s = new BasicStroke(2);
        g.setStroke(s);
        g.setColor(Color.BLACK);
        g.draw(circle);
        g.dispose();

        JLabel l = new JLabel(new ImageIcon(imageBG));
        JOptionPane.showMessageDialog(null, l);
    }

    public static void main(String[] args) throws Exception {
        URL urlFG = new URL("http://i.stack.imgur.com/OVOg3.jpg");
        URL urlBG = new URL("http://i.stack.imgur.com/lxthA.jpg");
        final BufferedImage biFG = ImageIO.read(urlFG);
        final BufferedImage biBG = ImageIO.read(urlBG);
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                new OneRing(biBG, biFG);
            }
        });
    }
}
person Andrew Thompson    schedule 01.06.2012

Нельзя рисовать прозрачные фигуры. В большинстве графических API, включая Java 2D, когда вы рисуете поверх чего-либо, графический контекст «смешивает» существующие пиксели с новыми. Вы должны найти режим наложения, который достигнет того, что вы ищете. Смешивание в java выполняется с помощью Composite.

Вы должны использовать / реализовать композит, выполнив следующую операцию:

result color = destination color
result alpha = destination alpha - source alpha

Затем каждый пиксель, который вы рисуете с альфа = 1, будет смешан как альфа = 0, а пиксели с альфа = 1 останутся такими же.

person Butaca    schedule 01.06.2012