Java - 设置DPI以打印图像

3

我有一堆.jpg图片,想要将它们打印出来(使用墨水打印在纸上),并且指定固定的尺寸(以厘米为单位)。 假设image1.png是400x600像素,我希望将其以300 dpi的分辨率打印出来。 我尝试使用PrinterJob和Printable实现进行打印,但似乎无法指定dpi。 以下是代码片段:

PrinterJob job = PrinterJob.getPrinterJob();

job.setPrintable(new PrintableDeck(cardDB));

PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
attr.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
attr.add(new MediaPrintableArea(8,21,210-16,296-42,MediaPrintableArea.MM));
attr.add(MediaSizeName.ISO_A4);
attr.add(new Copies(1));
attr.add(OrientationRequested.PORTRAIT);
attr.add(PrintQuality.HIGH);
//attr.add(Fidelity.FIDELITY_TRUE);

job.print(attr);

并且

public class PrintableDeck implements Printable {

    BufferedImage image;

    public PrintableDeck(DB cardDB){
        // This load an image into 'image'            
        BufferedImage image = cardDB.getCard(5462).getBufferedImage();
    }

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

        if(page>0){
            return NO_SUCH_PAGE;
        }

        Graphics2D g2 = (Graphics2D) graphics;
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

        double pageHeight = pf.getImageableHeight();
        double pageWidth = pf.getImageableWidth();

        // This print ONLY ~596x842, as if page is 72 DPI
        System.out.println("Imageable WH: "+pageWidth+" x "+pageHeight);

        // This print correctly 400x600
        System.out.println("Image: "+images.get(0).getWidth(null)+" x "+images.get(0).getHeight(null));

        g2.drawImage(image, 0, 0, null);
        g2.dispose();


        return PAGE_EXISTS;
    }
}

如上所示,我使用了PageFormat.getImageableHeight() ~ 842和PageFormat.getImageableWidth() ~ 595。如果页面是300 DPI,我期望这些值会更高,大约是3000 x 2500。

我错过了什么吗?

非常感谢。

2个回答

1
Java将图像的DPI设置为默认的java 72dpi,如果图像的元数据中没有先前定义的DPI,则比在java 72dpi默认分辨率下缩放图像到其尺寸要好,最好将您的300dpi分辨率添加到图像元数据中,因此,它将根据正确的可打印区域尺寸调整到更好的分辨率,除此之外还要设置打印机分辨率、介质大小和介质可打印区域属性。您可以使用http://www.javased.com/?post=321736中的方法将dpi设置为已保存的图像。
private void saveGridImage(File output,BufferedImage gridImage) throws IOException {
    output.delete();

    final String formatName = "png";

    for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName(formatName); iw.hasNext();) {
       ImageWriter writer = iw.next();
       ImageWriteParam writeParam = writer.getDefaultWriteParam();
       ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
       IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
       if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
          continue;
       }

       setDPI(metadata);

       final ImageOutputStream stream = ImageIO.createImageOutputStream(output);
       try {
            writer.setOutput(stream);
            writer.write(metadata, new IIOImage(gridImage, null, metadata), writeParam);
         } finally {
           stream.close();
         }
         break;
    }
}

private void setDPI(IIOMetadata metadata) throws IIOInvalidTreeException {

    double INCH_2_CM = 2.54;

       // for PMG, it's dots per millimeter
    double dotsPerMilli = 1.0 * DPI / 10 / INCH_2_CM;

    IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
    horiz.setAttribute("value", Double.toString(dotsPerMilli));

    IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
    vert.setAttribute("value", Double.toString(dotsPerMilli));

    IIOMetadataNode dim = new IIOMetadataNode("Dimension");
    dim.appendChild(horiz);
    dim.appendChild(vert);

    IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
    root.appendChild(dim);

    metadata.mergeTree("javax_imageio_1.0", root);
}

然后添加打印属性,如下所示:

   attr.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
   attr.add(new MediaPrintableArea(8,21,210-16,296-42,MediaPrintableArea.MM));
   attr.add(MediaSizeName.ISO_A4);

为了获得更好的图像视觉质量和分辨率。

0

这是我的代码,请注意我正在使用Scalr。

    private String autoResizeImage(String image, int width, int dpi, String prefix) throws IllegalArgumentException, ImagingOpException, IOException {

    File file = new File(image);

    BufferedImage img = ImageIO.read(file);


    BufferedImage result = Scalr.resize(img, Scalr.Method.SPEED, Scalr.Mode.FIT_TO_WIDTH, width, Scalr.OP_ANTIALIAS);


    File outputfile = new File(prefix);
    PNGEncodeParam penc = PNGEncodeParam.getDefaultEncodeParam(result);

    double meter2inchRatio = 1d / 0.0254d;
    int dim = (int) (dpi * meter2inchRatio) + 1;
    penc.setPhysicalDimension(dim, dim, 1);

    // resize orginal image
    JAI.create("filestore", result, outputfile.getAbsolutePath(), "PNG", penc);

    return outputfile.getAbsolutePath();

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接