写入图像时出现问题,然后用Java打印到SVG

时间:2013-01-27 12:53:24

标签: java printing svg bufferedimage

作为我正在编写的程序的一部分,我希望将图像打印为SVG格式。我需要它是SVG格式,以便我可以稍后使用Adobe Illustrator对其进行修改。虽然我可以直接在print方法中绘制一个矩形并成功导出为SVG格式。

当我在getTagCloud方法中绘制相同的矩形时,结果(当打印到SVG时)是一个由大量小矩形组成的矩形。我不知道为什么会出现这种情况,但希望对于读这篇文章的人来说,答案显而易见!

最终,我需要打印的不仅仅是一个矩形,但Illustrator中导出的“Group”是如此之大(包含所有这些不同大小的小矩形),我无法找到我拥有的其他对象绘制(因为一切,无论我最初使用什么颜色,都是黑色渲染)。任何帮助将不胜感激。 以下是相关代码。我没有包含import语句,因为编译代码没有任何问题。

public class TagCloud {

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI(); 
        }
    });
}

public static void createAndShowGUI() {
    System.out.println("Created GUI on EDT? "+
    SwingUtilities.isEventDispatchThread());
    JFrame f = new JFrame("Tag Cloud Generator");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    MyPanel myPanel = new MyPanel();

    Toolkit tk = f.getToolkit();       
    Dimension wndSize = tk.getScreenSize();  


    f.setBounds(0, 0,   
                      wndSize.width, wndSize.height); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.addWindowListener(new WindowAdapter() {
           public void windowClosing(WindowEvent e) {System.exit(0);}
        });

    f.add("Center",myPanel);
    f.pack();
    f.setVisible(true);
    myPanel.printTagCloud();

}


}

class MyPanel extends JPanel implements Printable{

private int squareX = 50;
private int squareY = 50;
private int squareW = 20;
private int squareH = 20;
private int x_offset = 30;
private int y_offset = 30;
private BufferedImage img = null;
private int defaultFontSize = 16;




public int print(Graphics g, PageFormat pf, int page) throws
                                                    PrinterException {

    if (page > 0) { /* We have only one page, and 'page' is zero-based */
        return NO_SUCH_PAGE;
    }

    Graphics2D g2d = (Graphics2D)g;
    g2d.translate(pf.getImageableX(), pf.getImageableY());

    if (img == null){
        getTagCloudImage();

    } 
    g.setColor(Color.red);
    g.fillRect(0, 0, 250, 400);
    //g.drawImage(img, 0, 0, null);
    g.dispose();

    return PAGE_EXISTS;
}

public void printTagCloud(){

    PrinterJob job = PrinterJob.getPrinterJob();
    PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
    PageFormat pf = job.pageDialog(aset);
    job.setPrintable(this);
    boolean ok = job.printDialog(aset);
    if (ok) {
        try {
             job.print(aset);
        } catch (PrinterException ex) {

        }
    }
}

public MyPanel() {
    setBorder(BorderFactory.createLineBorder(Color.black));


    addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            moveSquare(e.getX(),e.getY());
        }
    });

    addMouseMotionListener(new MouseAdapter() {
        public void mouseDragged(MouseEvent e) {
            moveSquare(e.getX(),e.getY());
        }
    });
}

private void moveSquare(int x, int y) {

    int OFFSET = 1;
    if ((squareX!=x) || (squareY!=y)) {
        repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
        squareX=x;
        squareY=y;
        repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    } 
}

public Dimension getPreferredSize() {
    return new Dimension(1000,800);
}

public void paintComponent(Graphics g) {
    super.paintComponent(g); 
if (img == null){
    getTagCloudImage();
    } 
else{

    g.drawImage(img, x_offset, y_offset, null);
}

}


public void getTagCloudImage(){

img = new BufferedImage(250, 250, BufferedImage.TYPE_INT_RGB); 


Graphics g = img.getGraphics();
Graphics2D g2 = (Graphics2D)g;

Rectangle r = new Rectangle (0,0,250,250);
g2.draw(r);
g2.setColor(Color.black);
g2.fill(r);
g2.dispose();
}

1 个答案:

答案 0 :(得分:1)

如果没有关于Java BufferedImageGraphicsPrinterJob以及其他相关类实现的知识,我无能为力。 (你可以为这个问题开始一个赏金,以吸引那些对java awt图形内容有更多内在知识的人的注意力。)

正如您显然必须注意到使用BufferedImage(或不使用它)是SVG输出的不同之处。在可用的版本中,您直接在Graphic上下文中绘制矩形作为print()方法参数提供给您,我相信它是如何设计为由Printable接口和打印的作者使用的框架。

在第二种方法(无法正常工作)中,首先将矩形绘制到新的BufferedImage对象上,然后在提供的Graphic上下文中绘制此图像。所以你做的事情要比直接在上下文中绘制更简单。开发人员众所周知的事实或直觉是,你使用某种API的方式越简单,你做作意外的机会就越大:(。

我的注意事项如下:BufferedImage是(因为你可以从它的Javadocs中推断出来)只是一个光栅图像,即。像素网格。这就是为什么svg文件填充了许多小矩形(试图模仿像素)。 Graphics方法提供的draw()对象可能更抽象,对形状而不是像素进行操作,这更适合写入SVG等矢量图形格式。但这只是一种幻想。

问题是,你真的需要使用BufferedImage吗?如果我理解正确,您希望用户能够在屏幕上编辑矩形,并在准备好时将其导出到SVG。您不能记住例如左上角和用户编辑的矩形尺寸,然后使用此数据直接在Graphics提供的print()对象上重新创建此矩形,如:

public int print(Graphics g, PageFormat pf, int page)
  throws PrinterException {
...
  g.fillRect(userRect.x,userRect.y,userRect.width,userRect.height);
...
}

userRect是您自己的自定义类的对象,它只存储有关用户编辑的图像的数据)