我的printerjob当前存在问题,它对于肖像图像非常有效,但对于风景图像,它将剪切图像的一部分并填充空白。

这是我的代码

编辑

PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
BufferedImage bufferedImage = ImageIO.read(new File("house.jpg"));

boolean isLandscape = bufferedImage.getWidth() > bufferedImage.getHeight();
PrinterJob printerJob = PrinterJob.getPrinterJob();
printerJob.setPrintService(printService);
printerJob.setCopies(copies);

PageFormat pageFormat = printerJob.defaultPage();
pageFormat.setOrientation(isLandscape ? PageFormat.LANDSCAPE : PageFormat.PORTRAIT);

Paper paper = new Paper();
paper.setSize(pageFormat.getWidth(), pageFormat.getHeight());
paper.setImageableArea(0.0, 0.0, paper.getWidth(), paper.getHeight());

pageFormat.setPaper(paper);

printerJob.setPrintable(new Printable(){
   @Override
   public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException{
       if (pageIndex == 0) {
          Graphics2D g2 = (Graphics2D)graphics;
          double xScale = 1;
          double xTranslate = 0;
          double yScale = 1;
          double yTranslate = 0;
          double widthScale = (pageFormat.getImageableWidth() / bufferedImage.getWidth()) * xScale;
          double heightScale = (pageFormat.getImageableHeight() / bufferedImage.getHeight()) * yScale;

          AffineTransform affineTransform = AffineTransform.getScaleInstance(widthScale, heightScale);
          affineTransform.translate(xTranslate, yTranslate);

          g2.drawRenderedImage(bufferedImage, affineTransform);
          g2.translate((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY());

          return PAGE_EXISTS;
       }else return NO_SUCH_PAGE;
   }
}, pageFormat);

printerJob.print();


这使我可以打印肖像图片以适合给定的纸张,并且没有边框(适合纸张),我需要它对风景图片进行相同的处理。

这是当我尝试纵向和横向图像时发生的情况的示例,以便您了解我的意思。图片应始终适合纸张尺寸且无边距,在这种情况下为10x15cm,

人像图片:
java - Java Printerjob横向空白-LMLPHP

风景图片:
java - Java Printerjob横向空白-LMLPHP

最佳答案

不要使用PageFormat#getWidthPageFormat#getHeight,而是使用PageFormat#getImageableWidthPageFormat#getImageableHeight

JavaDocs


  返回页面可成像区域的高度/宽度,以1/72英寸为单位。此方法考虑了页面的方向。


您还应该通过Graphics翻译打印机ImageableX/Y ...

g2.translate((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY());


可运行的例子

这是一个简单的可运行示例。这段代码能够拍摄原始照片(左图)并以纵向和横向打印,没有任何问题。



import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PrintTest100 {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                try {
                    PrinterJob pj = PrinterJob.getPrinterJob();
                    pj.setJobName(" Print Component ");

                    PageFormat pf = pj.defaultPage();
//                  pf.setOrientation(PageFormat.LANDSCAPE);
//                  pf = pj.validatePage(pf);

                    pj.setPrintable(new ImagePrintable(ImageIO.read(new File("..."))), pf);

                    if (!pj.printDialog()) {
                        return;
                    }
                    try {
                        pj.print();
                    } catch (PrinterException ex) {
                        ex.printStackTrace();
                    }
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public static class ImagePrintable implements Printable {

        private int currentPage = -1;
        private Image cachedScaledImage = null;

        private BufferedImage master;

        public ImagePrintable(BufferedImage master) {
            this.master = master;
        }

        public double getScaleFactor(int iMasterSize, int iTargetSize) {
            double dScale = 1;
            if (iMasterSize > iTargetSize) {
                dScale = (double) iTargetSize / (double) iMasterSize;
            } else {
                dScale = (double) iTargetSize / (double) iMasterSize;
            }
            return dScale;
        }

        public double getScaleFactorToFit(BufferedImage img, Dimension size) {
            double dScale = 1;
            if (img != null) {
                int imageWidth = img.getWidth();
                int imageHeight = img.getHeight();
                dScale = getScaleFactorToFit(new Dimension(imageWidth, imageHeight), size);
            }
            return dScale;
        }

        public double getScaleFactorToFit(Dimension original, Dimension toFit) {
            double dScale = 1d;
            if (original != null && toFit != null) {
                double dScaleWidth = getScaleFactor(original.width, toFit.width);
                double dScaleHeight = getScaleFactor(original.height, toFit.height);

                dScale = Math.min(dScaleHeight, dScaleWidth);
            }
            return dScale;
        }

        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {

            int result = Printable.NO_SUCH_PAGE;

            if (pageIndex == 0) {

                result = Printable.PAGE_EXISTS;

                Graphics2D graphics2D = (Graphics2D) graphics;
                graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

                int width = (int) Math.round(pageFormat.getImageableWidth());
                int height = (int) Math.round(pageFormat.getImageableHeight());

                if (currentPage != pageIndex || cachedScaledImage == null) {
                    currentPage = pageIndex;

                    double scaleFactor = getScaleFactorToFit(new Dimension(master.getWidth(), master.getHeight()), new Dimension(width, height));

                    int imageWidth = (int) Math.round(master.getWidth() * scaleFactor);
                    int imageHeight = (int) Math.round(master.getHeight() * scaleFactor);

                    cachedScaledImage = master.getScaledInstance(imageWidth, imageHeight, Image.SCALE_SMOOTH);

                }

                double x = ((pageFormat.getImageableWidth() - cachedScaledImage.getWidth(null)) / 2);
                double y = ((pageFormat.getImageableHeight() - cachedScaledImage.getHeight(null)) / 2);

                graphics2D.drawImage(cachedScaledImage, (int) x, (int) y, null);
                graphics2D.setColor(Color.RED);
                graphics2D.drawRect(0, 0, width - 1, height - 1);
            }

            return result;
        }
    }

}


nb:优胜美地遇到了一个问题,试图找出如何从对话框中更改打印方向,最后,我放弃了,并通过从PageFormat更改PrintJob强制了它。我曾经在无数的应用程序中使用过这种类型的代码,但是之前没有问题...

更新

原始图片:1920x1200

08-05 07:13