【问题标题】:Java - set DPI to print imageJava - 设置 DPI 以打印图像
【发布时间】:2013-04-18 03:47:33
【问题描述】:

我有一堆 .jpg 图像,我想以固定尺寸(以厘米为单位)打印它们(用墨水在纸上)。 假设 image1.png 是 400x600 像素,我想以 300 dpi 打印它。 我尝试过使用 PrinterJob 和 Printable 实现,但似乎我无法指定 DPI。 这是sn-ps的代码:

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。 我错过了什么?

非常感谢。

【问题讨论】:

    标签: java image printing dpi


    【解决方案1】:

    如果图像的元数据中没有先前定义的 DPI,Java 会将图像的 DPI 设置为默认的 java 72dpi,因此它比在 java 72dpi 默认分辨率下将图像缩放到其尺寸更好,最好添加您的图像元数据的 300dpi 分辨率,因此,它将在正确的可打印区域尺寸中调整为更好的分辨率,除了设置打印机分辨率、介质尺寸和介质可打印区域属性之外,您可以将 dpi 设置为您的在http://www.javased.com/?post=321736 中用这种方法保存的图像:

    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);
    

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

    【讨论】:

      【解决方案2】:

      这是我的代码,注意我使用的是 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();
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        • 2018-05-02
        • 2013-04-11
        • 2016-10-23
        • 2018-09-17
        • 1970-01-01
        • 2011-03-04
        相关资源
        最近更新 更多