我想在Java中对图像应用笔画(轮廓)。阅读this和this之后,看起来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。再次。我需要根据可见像素轮廓而不是它的边界框来勾画图像。 这就是我想要实现的目标:
答案 0 :(得分:2)
是的,Java2D API仅将笔划应用于形状。你可以做两件事:
从bitmap图像的透明度信息中创建一个Shape,以便您只能描边非透明部分。这在任何语言中都很难,因为这意味着将位图信息转换为vector-based information。
请检查:Image/Graphic into a Shape
但基本上我会尝试避免转换问题,并以仅位图的方式解决它 - 例如,将这些像素着色(使用"笔触颜色"),透明像素可以是在给定的像素距离处找到("笔划宽度")。
答案 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界面的任何其他内容来绘制轮廓,例如形状的内部。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)
喜欢这个?如果没有,请附上显示所需结果的图像。
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
本身作为边框绘制。