使用Java在4 x 6纸张上打印1800 x 1200图像

使用Java在4 x 6纸张上打印1800 x 1200图像,java,printing,awt,Java,Printing,Awt,我需要在4英寸x 6英寸的纸张(也称为4r)上打印1800 x 1200像素、300 dpi的图像 我尝试过的 我已经创建了一个PrintRequestAttributeSet,它负责我的PrintableArea(4 x 6),打印机打印DPI,方向。我在底部附上了一个MCVE 问题 代码运行时,我会得到一个带有以下属性的PageFormat(适用于我的打印机): 宽度和高度稍小,因为我的打印机不支持零边距。(这就是我所考虑的。如果有人知道除此之外我可以强制零保证金的其他方法,请告诉我) 我提

我需要在4英寸x 6英寸的纸张(也称为4r)上打印1800 x 1200像素、300 dpi的图像

我尝试过的

我已经创建了一个
PrintRequestAttributeSet
,它负责我的
PrintableArea
(4 x 6),
打印机打印DPI
方向
。我在底部附上了一个MCVE

问题

代码运行时,我会得到一个带有以下属性的
PageFormat
(适用于我的打印机):

宽度和高度稍小,因为我的打印机不支持
零边距
。(这就是我所考虑的。如果有人知道除此之外我可以强制零保证金的其他方法,请告诉我)

我提供的
页边距为0
,因为这些图像将通过支持零页边距的打印机(Photobooth打印机)打印

包括页边距在内的可打印面积约为4 x 6(根据需要)。当我缩放图像以在可打印区域内打印时,会出现问题

由于图像是1800 x 1200,它支持3:2的纵横比,这意味着创建图像是为了在4 x 6纸张上打印(旋转和缩放后)

现在,由于
PageFormat
的pageWidth和pageHeight不能完全被ImageWidth和ImageHeight整除。我遇到了缩放问题

注意:我旋转图像,因为它必须在4 x 6而不是6 x 4上打印

这张本应占4x6空间的图像,拍摄的位置接近4x5。图像大小也大大减小

我如何克服这个问题

代码

请在此处找到MCVE:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
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.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterResolution;

public class ImgPrinter implements Printable {

    Image img;

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

        Graphics2D g2d = (Graphics2D) graphics;
        g2d.translate((int) (pageFormat.getImageableX()),
                (int) (pageFormat.getImageableY()));
        if (pageIndex == 0) {
            double pageWidth = pageFormat.getImageableWidth();
            double pageHeight = pageFormat.getImageableHeight();
            /**
             * Swapping width and height, coz the image is later rotated
             */
            double imageWidth = img.getHeight(null);
            double imageHeight = img.getWidth(null);
            double scaleX = pageWidth / imageWidth;
            double scaleY = pageHeight / imageHeight;
            g2d.scale(scaleX, scaleY);
            g2d.rotate(Math.toRadians(90), img.getWidth(null) / 2,
                    img.getHeight(null) / 2);
            g2d.drawImage(img, 0, 0, null);
            return Printable.PAGE_EXISTS;
        }
        return Printable.NO_SUCH_PAGE;

    }

    public void printPage(String file, String size) {
        try {
            Image img = ImageIO.read(new File(file));
            this.img = img;
            PrintRequestAttributeSet aset = createAsetForMedia(size);
            PrinterJob pj = PrinterJob.getPrinterJob();
            PageFormat pageFormat = pj.getPageFormat(aset);
            pj.setPrintable(this, pageFormat);
            pj.print();
        } catch (PrinterException ex) {
            ex.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private PrintRequestAttributeSet createAsetForMedia(String size) {
        PrintRequestAttributeSet aset = null;
        try {
            aset = new HashPrintRequestAttributeSet();
            aset.add(PrintQuality.NORMAL);
            aset.add(OrientationRequested.PORTRAIT);
            /**
             * Suggesting the print DPI as 300
             */
            aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
            /**
             * Setting the printable area and the margin as 0
             */
            if (size.equals("3r")) {
                aset.add(new MediaPrintableArea(0, 0, 3, 5,
                        MediaPrintableArea.INCH));
            } else if (size.equals("4r")) {
                aset.add(new MediaPrintableArea(0, 0, 4, 6,
                        MediaPrintableArea.INCH));
            } else if (size.equals("5r")) {
                aset.add(new MediaPrintableArea(0, 0, 5, 7,
                        MediaPrintableArea.INCH));
            } else if (size.equals("6r")) {
                aset.add(new MediaPrintableArea(0, 0, 6, 8,
                        MediaPrintableArea.INCH));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return aset;

    }

    public static void main(String[] args) {
        new ImgPrinter().printPage("/Some_URL/sam.jpg",
                "4r");
    }
}

要运行该程序,只需向主程序提供一个1800x1200图像路径,它将打印到默认打印机。

我认为您需要按比例缩放。像这样

double scaleX = pageWidth / imageWidth;
double scaleY = pageHeight / imageHeight;
double scale = Math.min(scaleX, scaleY); 
g2d.scale(scale, scale);
更新: mKorbel提到的另一个建议是单独缩放

尝试使用
public Image getScaledInstance(int-width、int-height、int-hints)
BufferedImage的方法
传递
图像。平滑缩放作为提示。

让我担心的事情

  • 更改
    图形
    上下文的缩放/旋转,无需先复制或事后重置。这实际上可能会影响后续渲染,因为可打印的
    可能会被多次调用
  • 使用
    图形2D#缩放
    。这真的不是最好的质量,一般来说也不是那么快。看见我也喜欢使用仿射翻译,但那只是我
  • 不缓冲结果。好的,这与前面的注释有关,但是您的
    print
    方法可能会被多次调用以打印一个页面,每次缩放图像都会带来成本,相反,您应该缩放一次并重新使用缩放结果
  • 除非要实际旋转图像,否则可能要围绕页面中心旋转,而不是图像本身,这将影响
    0x0
    的位置
  • 现在请记住,当您旋转
    图形
    上下文时,原点会发生变化,因此在本例中,原点将变为上/右角,而不是位于上/左角。现在你知道为什么我会孤立地旋转图像,而不是尝试与
    图形混为一谈了
  • 我“认为”正在发生的是,在坐标的缩放、旋转和操作(交换高度和宽度)之间,事情变得一团糟……但坦率地说,当我有更好的解决方案时,我不会再胡闹了

    下面的示例使用了一组个人库代码,因此其中一些代码可能有点复杂,但我对其他内容使用了单独的功能,因此它可以很好地结合在一起

    因此,从7680x4800的图像开始,这将生成423x264的缩放图像

    (红色边框仅为视觉指南,用于将结果转储到PDF以节省纸张;)

    导入java.awt.Color;
    导入java.awt.Dimension;
    导入java.awt.EventQueue;
    导入java.awt.Graphics;
    导入java.awt.Graphics2D;
    导入java.awt.RenderingHints;
    导入java.awt.Transparency;
    导入java.awt.geom.AffineTransform;
    导入java.awt.image.buffereImage;
    导入java.awt.print.PageFormat;
    导入java.awt.print.Printable;
    导入java.awt.print.PrinterException;
    导入java.awt.print.PrinterJob;
    导入java.io.File;
    导入java.io.IOException;
    导入javax.imageio.imageio;
    导入javax.print.attribute.HashPrintRequestAttributeSet;
    导入javax.print.attribute.PrintRequestAttributeSet;
    导入javax.print.attribute.standard.MediaPrintableArea;
    导入javax.print.attribute.standard.orientationrequired;
    导入javax.print.attribute.standard.PrintQuality;
    导入javax.print.attribute.standard.PrinterResolution;
    导入javax.swing.UIManager;
    导入javax.swing.UnsupportedLookAndFeelException;
    公共类ImgPrinter实现可打印{
    缓冲图像img;
    缓冲图像缩放;
    @凌驾
    公共整型打印(图形、页面格式、页面格式、整型页面索引)
    抛出PrinterException{
    int result=无此类页面;
    Graphics2D g2d=(Graphics2D)graphics.create();
    translate((int)(pageFormat.getImageableX()),(int)(pageFormat.getImageableY());
    如果(pageIndex==0){
    double pageWidth=pageFormat.getImageableWidth();
    double pageHeight=pageFormat.getImageableHeight();
    如果(缩放==null){
    //交换宽度和高度以允许旋转。。。
    系统输出打印项次(页面宽度+x+页面高度);
    scaled=getScaledInstanceToFit(
    img,
    新维度((int)pageHeight,(int)pageWidth));
    
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    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.print.attribute.HashPrintRequestAttributeSet;
    import javax.print.attribute.PrintRequestAttributeSet;
    import javax.print.attribute.standard.MediaPrintableArea;
    import javax.print.attribute.standard.OrientationRequested;
    import javax.print.attribute.standard.PrintQuality;
    import javax.print.attribute.standard.PrinterResolution;
    
    public class ImgPrinter implements Printable {
    
        Image img;
    
        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
                throws PrinterException {
    
            Graphics2D g2d = (Graphics2D) graphics;
            g2d.translate((int) (pageFormat.getImageableX()),
                    (int) (pageFormat.getImageableY()));
            if (pageIndex == 0) {
                double pageWidth = pageFormat.getImageableWidth();
                double pageHeight = pageFormat.getImageableHeight();
                /**
                 * Swapping width and height, coz the image is later rotated
                 */
                double imageWidth = img.getHeight(null);
                double imageHeight = img.getWidth(null);
                double scaleX = pageWidth / imageWidth;
                double scaleY = pageHeight / imageHeight;
                g2d.scale(scaleX, scaleY);
                g2d.rotate(Math.toRadians(90), img.getWidth(null) / 2,
                        img.getHeight(null) / 2);
                g2d.drawImage(img, 0, 0, null);
                return Printable.PAGE_EXISTS;
            }
            return Printable.NO_SUCH_PAGE;
    
        }
    
        public void printPage(String file, String size) {
            try {
                Image img = ImageIO.read(new File(file));
                this.img = img;
                PrintRequestAttributeSet aset = createAsetForMedia(size);
                PrinterJob pj = PrinterJob.getPrinterJob();
                PageFormat pageFormat = pj.getPageFormat(aset);
                pj.setPrintable(this, pageFormat);
                pj.print();
            } catch (PrinterException ex) {
                ex.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private PrintRequestAttributeSet createAsetForMedia(String size) {
            PrintRequestAttributeSet aset = null;
            try {
                aset = new HashPrintRequestAttributeSet();
                aset.add(PrintQuality.NORMAL);
                aset.add(OrientationRequested.PORTRAIT);
                /**
                 * Suggesting the print DPI as 300
                 */
                aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
                /**
                 * Setting the printable area and the margin as 0
                 */
                if (size.equals("3r")) {
                    aset.add(new MediaPrintableArea(0, 0, 3, 5,
                            MediaPrintableArea.INCH));
                } else if (size.equals("4r")) {
                    aset.add(new MediaPrintableArea(0, 0, 4, 6,
                            MediaPrintableArea.INCH));
                } else if (size.equals("5r")) {
                    aset.add(new MediaPrintableArea(0, 0, 5, 7,
                            MediaPrintableArea.INCH));
                } else if (size.equals("6r")) {
                    aset.add(new MediaPrintableArea(0, 0, 6, 8,
                            MediaPrintableArea.INCH));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return aset;
    
        }
    
        public static void main(String[] args) {
            new ImgPrinter().printPage("/Some_URL/sam.jpg",
                    "4r");
        }
    }
    
    double scaleX = pageWidth / imageWidth;
    double scaleY = pageHeight / imageHeight;
    double scale = Math.min(scaleX, scaleY); 
    g2d.scale(scale, scale);
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.Transparency;
    import java.awt.geom.AffineTransform;
    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.print.attribute.HashPrintRequestAttributeSet;
    import javax.print.attribute.PrintRequestAttributeSet;
    import javax.print.attribute.standard.MediaPrintableArea;
    import javax.print.attribute.standard.OrientationRequested;
    import javax.print.attribute.standard.PrintQuality;
    import javax.print.attribute.standard.PrinterResolution;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class ImgPrinter implements Printable {
    
        BufferedImage img;
        BufferedImage scaled;
    
        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
                throws PrinterException {
    
            int result = NO_SUCH_PAGE;
            Graphics2D g2d = (Graphics2D) graphics.create();
            g2d.translate((int) (pageFormat.getImageableX()), (int) (pageFormat.getImageableY()));
            if (pageIndex == 0) {
                double pageWidth = pageFormat.getImageableWidth();
                double pageHeight = pageFormat.getImageableHeight();
                if (scaled == null) {
                    // Swap the width and height to allow for the rotation...
                    System.out.println(pageWidth + "x" + pageHeight);
                    scaled = getScaledInstanceToFit(
                            img, 
                            new Dimension((int)pageHeight, (int)pageWidth));
                    System.out.println("In " + img.getWidth() + "x" + img.getHeight());
                    System.out.println("Out " + scaled.getWidth() + "x" + scaled.getHeight());
                }
                double imageWidth = scaled.getWidth();
                double imageHeight = scaled.getHeight();
    
                AffineTransform at = AffineTransform.getRotateInstance(
                        Math.toRadians(90), 
                        pageWidth / 2d, 
                        pageHeight / 2d
                );
    
                AffineTransform old = g2d.getTransform();
                g2d.setTransform(at);
                double x = (pageHeight - imageWidth) / 2d;
                double y = (pageWidth - imageHeight) / 2d;
                g2d.drawImage(
                        scaled, 
                        (int)x, 
                        (int)y, 
                        null);
    
                g2d.setTransform(old);
    
                // This is not affected by the previous changes, as those were made
                // to a different copy...
                g2d.setColor(Color.RED);
                g2d.drawRect(0, 0, (int)pageWidth - 1, (int)pageHeight - 1);
                result = PAGE_EXISTS;
            }
            g2d.dispose();
    
            return result;
        }
    
        public void printPage(String file, String size) {
            try {
                img = ImageIO.read(new File(file));
                PrintRequestAttributeSet aset = createAsetForMedia(size);
                PrinterJob pj = PrinterJob.getPrinterJob();
                PageFormat pageFormat = pj.getPageFormat(aset);
                pj.setPrintable(this, pageFormat);
                if (pj.printDialog()) {
                    pj.print();
                }
            } catch (PrinterException ex) {
                ex.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private PrintRequestAttributeSet createAsetForMedia(String size) {
            PrintRequestAttributeSet aset = null;
            try {
                aset = new HashPrintRequestAttributeSet();
                aset.add(PrintQuality.NORMAL);
                aset.add(OrientationRequested.PORTRAIT);
                /**
                 * Suggesting the print DPI as 300
                 */
                aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
                /**
                 * Setting the printable area and the margin as 0
                 */
                if (size.equals("3r")) {
                    aset.add(new MediaPrintableArea(1, 1, 3, 5,
                            MediaPrintableArea.INCH));
                } else if (size.equals("4r")) {
                    aset.add(new MediaPrintableArea(1, 1, 4, 6,
                            MediaPrintableArea.INCH));
                } else if (size.equals("5r")) {
                    aset.add(new MediaPrintableArea(1, 1, 5, 7,
                            MediaPrintableArea.INCH));
                } else if (size.equals("6r")) {
                    aset.add(new MediaPrintableArea(1, 1, 6, 8,
                            MediaPrintableArea.INCH));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return aset;
    
        }
    
        public static BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) {
    
            double scaleFactor = getScaleFactorToFit(img, size);
    
            return getScaledInstance(img, scaleFactor);
    
        }
    
        public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {
    
            return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    
        }
    
        public static 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 static 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;
    
        }
    
        public static double getScaleFactor(int iMasterSize, int iTargetSize) {
    
            return (double) iTargetSize / (double) iMasterSize;
    
        }
    
        protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint) {
    
            BufferedImage imgScale = img;
    
            int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
            int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);
    
            if (dScaleFactor <= 1.0d) {
    
                imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint);
    
            } else {
    
                imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint);
    
            }
    
            return imgScale;
    
        }
    
        protected static BufferedImage getScaledDownInstance(BufferedImage img,
                int targetWidth,
                int targetHeight,
                Object hint) {
    
    //      System.out.println("Scale down...");
            int type = (img.getTransparency() == Transparency.OPAQUE)
                    ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
    
            BufferedImage ret = (BufferedImage) img;
    
            if (targetHeight > 0 || targetWidth > 0) {
    
                int w = img.getWidth();
                int h = img.getHeight();
    
                do {
    
                    if (w > targetWidth) {
    
                        w /= 2;
                        if (w < targetWidth) {
    
                            w = targetWidth;
    
                        }
    
                    }
    
                    if (h > targetHeight) {
    
                        h /= 2;
                        if (h < targetHeight) {
    
                            h = targetHeight;
    
                        }
    
                    }
    
                    BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
                    Graphics2D g2 = tmp.createGraphics();
                    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
                    g2.drawImage(ret, 0, 0, w, h, null);
                    g2.dispose();
    
                    ret = tmp;
    
                } while (w != targetWidth || h != targetHeight);
    
            } else {
    
                ret = new BufferedImage(1, 1, type);
    
            }
    
            return ret;
    
        }
    
        protected static BufferedImage getScaledUpInstance(BufferedImage img,
                int targetWidth,
                int targetHeight,
                Object hint) {
    
            int type = BufferedImage.TYPE_INT_ARGB;
    
            BufferedImage ret = (BufferedImage) img;
            int w = img.getWidth();
            int h = img.getHeight();
    
            do {
    
                if (w < targetWidth) {
    
                    w *= 2;
                    if (w > targetWidth) {
    
                        w = targetWidth;
    
                    }
    
                }
    
                if (h < targetHeight) {
    
                    h *= 2;
                    if (h > targetHeight) {
    
                        h = targetHeight;
    
                    }
    
                }
    
                BufferedImage tmp = new BufferedImage(w, h, type);
                Graphics2D g2 = tmp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
                g2.drawImage(ret, 0, 0, w, h, null);
                g2.dispose();
    
                ret = tmp;
                tmp = null;
    
            } while (w != targetWidth || h != targetHeight);
    
            return ret;
    
        }
    
    
        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();
                    }
    
                    new ImgPrinter().printPage("/Volumes/Disk02/Dropbox/Wallpapers/animepaper.net_wallpaper_art_anime_aria_duanwu_festival_205050_wonderngo_7680x4800-a8aecc9c.jpg",
                            "4r");
                }
            });
        }
    }