在Java中将笔划应用于图像

时间:2012-08-21 07:12:47

标签: java image image-processing java-2d stroke

我想在Java中对图像应用笔画(轮廓)。阅读thisthis之后,看起来Java2D API仅将笔划应用于形状?当然我可以进行位图填充,然后对该形状应用笔划,但我想知道是否可以直接在给定的位图上应用它。

更新: 我设法应用笔划位,它勾勒出整个图像。我的图像具有PNG透明度。如何仅在图像的可见像素周围应用笔划?

 public static void main(String[] args) {
    try {
        // TODO code application logic here
        URL u = GraphicsDemo.class.getResource("Capture222.png");
        BufferedImage img = ImageIO.read(new File(u.getPath()));
        System.out.print("loaded");
        Graphics2D g = img.createGraphics();
        Rectangle2D tr = new Rectangle2D.Double(0, 0,
                img.getWidth(), img.getHeight());
        // Create the TexturePaint.
        TexturePaint tp = new TexturePaint(img, tr);
        g.setStroke(new BasicStroke(20));
        g.setPaint(Color.ORANGE);
        //   g.fill(tr);
        g.draw(tr);


        ImageIO.write(img, "PNG", new File("myeditedimage.png"));
        g.dispose();
    } catch (IOException ex) {
        Logger.getLogger(GraphicsDemo.class.getName()).log(Level.SEVERE, null, ex);
    }
 } 

更新1: 我不确定我想要做的是使用Java Graphics API。再次。我需要根据可见像素轮廓而不是它的边界框来勾画图像。 这就是我想要实现的目标: enter image description here

5 个答案:

答案 0 :(得分:2)

是的,Java2D API仅将笔划应用于形状。你可以做两件事:

bitmap图像的透明度信息中创建一个Shape,以便您只能描边非透明部分。这在任何语言中都很难,因为这意味着将位图信息转换为vector-based information

请检查:Image/Graphic into a Shape

而且:Smoothing a jagged path

但基本上我会尝试避免转换问题,并以仅位图的方式解决它 - 例如,将这些像素着色(使用"笔触颜色"),透明像素可以是在给定的像素距离处找到("笔划宽度")。

答案 1 :(得分:0)

要获取绘制位图的Graphics2D对象,您应该使用BufferedImage。

BufferedImage img = ImageIO.read(new File("myimage.png"));
Graphics2D g = img.createGraphics();

// Paint on it like you want here...


g.dispose();
ImageIO.write(img, "PNG", new File("myeditedimage.png"));

答案 2 :(得分:0)

  • 首先,通过调用Graphics2D告诉setStroke()您希望如何绘制轮廓。此方法接受实现java.awt.Stroke interface的任何对象。 2D API附带了一个类java.awt.BasicStroke,它实现了常见的描边选项。
  • 使用setPaint()告诉Graphics2D应如何绘制轮廓本身。可以使用颜色,渐变,纹理或实现Paint界面的任何其他内容来绘制轮廓,例如形状的内部。
  • 使用Graphics2D的draw()方法绘制形状轮廓。 Graphics2D使用步骤1中的Stroke来确定轮廓的外观。步骤2中的Paint用于实际渲染轮廓。

Graphics2D使用笔划来确定特定形状的轮廓是什么样的。当你问Graphics2D draw()一个形状时,它会询问它的描边形状轮廓应该是什么样子。有趣的是,Stroke将描边轮廓作为另一种形状返回:

public abstract Shape createStrokedShape(Shape p)

此方法返回一个Shape,表示所提供形状的描边轮廓。 这是Stroke中唯一的方法。通常情况下,您不会自己调用,Graphics2D会在draw()形状时代表您调用它。

draw()上拨打Graphics2D等同于以下代码:

public void longwindedDraw(Graphics2D g2, Shape s) 
{
    Stroke stroke = g2.getStroke();
    Shape strokedOutline = stroke.createStrokedShape(s);
    g2.fill(strokedOutline);
}

答案 3 :(得分:0)

试试这个:

final static BasicStroke dash_stroke =new BasicStroke(1.0f,
                        BasicStroke.CAP_BUTT,
                        BasicStroke.JOIN_MITER,
                        10.0f, dash1, 0.0f);

然后设置笔划:

g2.getStroke()

答案 4 :(得分:-1)

喜欢这个?如果没有,请附上显示所需结果的图像。

StrokedImage

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

public class StrokedImage {

    public BufferedImage getStrokedImage(
            BufferedImage bi, Shape shape, int strokeWidth) {
        int w = bi.getWidth();
        int h = bi.getHeight();
        BufferedImage bib = new BufferedImage(w,h,bi.getType());
        Graphics2D g = bib.createGraphics();

        BasicStroke bs = new BasicStroke(strokeWidth);
        g.setStroke(bs);
        Rectangle rect = new Rectangle(0,0,w,h); 
        TexturePaint tp = new TexturePaint(bi, rect); 
        g.setPaint(tp);
        g.draw(shape);

        g.dispose();
        return bib;
    }

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://pscode.org/media/stromlo1.jpg");
        final BufferedImage bi = ImageIO.read(url);
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                StrokedImage si = new StrokedImage();

                int strokeWidth = 12;
                int pad = 50;
                Shape shape = new Rectangle(
                        pad,pad,
                        bi.getWidth()-(2*pad),bi.getHeight()-(2*pad)); 
                Image i = si.getStrokedImage(bi, shape, strokeWidth);

                JPanel p = new JPanel(new GridLayout(1,0,5,5));
                p.add(new JLabel(new ImageIcon(i)));
                p.add(new JLabel(new ImageIcon(bi)));
                JOptionPane.showMessageDialog(null, p);
            }
        });
    }
}

发布问题编辑 - 更新

看看this answer。它在绘制图像之前应用Shape的剪辑。然后它清除剪辑并将Shape本身作为边框绘制。