使用Java的4 x 6纸上打印1800 x 1200的图像 [英] Printing a 1800 x 1200 image on 4 x 6 paper using Java

查看:337
本文介绍了使用Java的4 x 6纸上打印1800 x 1200的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在4×6的论文(也称为4R)

I need to print a 1800 x 1200 pixels, 300 dpi image on 4" x 6" paper (also known as 4r)

我曾尝试

我创建了一个的PrintRequestAttributeSet 这需要我的 PrintableArea (4×6),<$ C $的护理C>打印机的打印DPI ,方向。我已经在底部附有MCVE。

I have created a PrintRequestAttributeSet which takes care of my PrintableArea(4 x 6), Printer print DPI, Orientation. I have attached a MCVE at the bottom.

问题

虽然code工作,我也得到一个的PageFormat 具有以下属性(我的打印机):

While the code works, and I get a PageFormat with the following attributes(for my printer) :

x= 12.0
y= 12.32
w= 276.0
h= 419.67

的宽度和高度都少一点,因为我的打印机不支持零保证金。 (这是我所考虑的。如果有人知道的比这通过它我可以强制零保证金等办法,请让我知道的)

我供给利润率为0 ,因为这些图像将通过支持零保证金(即影打印机)的打印机进行打印。

I am supplying the margin as 0, because these images will be printed via printers which support zero margin(Photobooth Printers).

aset.add(new MediaPrintableArea(0, 0, 4, 6, MediaPrintableArea.INCH));

包括保证金可打印区域大致是4×6的要求。当我缩放图像的可打印区域内打印时出现问题。

The printable area including the margin is roughly 4 x 6 as required. The problem occurs when I scale the image to print inside the printable area.

由于图象为1800 * 1200,它支持的纵横比为3:2,这意味着在创建图像(后得到旋转和缩放)获得印在一个4×6的纸张。 以供参考。

Since image is 1800 x 1200, it supports an aspect ratio of 3:2, which means the image is created to get printed on a 4 x 6 paper(after getting rotated and scaled). For Reference.

现在,因为页宽和pageHeight的的PageFormat 是由ImageWidth和ImageHeight不能整除。我得到的缩放问题。

Now, since the pageWidth and pageHeight of the PageFormat are not exactly divisible by the ImageWidth and ImageHeight. I am getting scaling issues.

注意:我旋转图像,因为它有4×6要打印,而不是6×4

Note : I rotate the image because it has to be printed on 4 x 6 and not 6 x 4.

这是应该的图像取4×6的空间正在某处接近4×5的图像尺寸也大幅降低。

The image which is supposed to take 4 x 6 space is taking somewhere close to 4 x 5. The image size is also reduced drastically.

我要如何解决这个问题?

How do I overcome this issue?

code

请在这里找到MCVE:

Please find the MCVE here :

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图像路径主程序,它会打印到默认打印机。

推荐答案

东西,我担心......

Things that worry me...


  1. 挂在图形规模/旋转的语境,不任必先复制或在事后将其复位。这实际上可能影响后续效果,因为打印可多次调用...

  2. 使用的Graphics2D#比例。这确实不是最好的质量,也不是一般的快。请参见的Image.getScaledInstance的危险中()。我也preFER使用的AffineTransform ,不过这只是我...

  3. 不缓存结果。好了,这涉及到previous评论,但你的打印方法可称为多次打印单页,缩放图像每次都是昂贵的,相反,你应该一旦它的规模,并重新使用经过换算的结果。

  4. 除非你将身体旋转图像,你可能要绕页面的中心,而不是图像本身,这会影响到的位置,其中为0x0 变。

  5. 现在,请记住,当你旋转图形的背景下,原点的变化,所以不是一直在顶部/左上角,在这种情况下,它将成为顶部/右下角。现在你知道为什么我会在隔离已旋转的图像,而不是试图与图形背景插科打诨:P

  1. Hanging the scale/rotation of the Graphics context without either first making a copy of it or resetting it after the fact. This could actually affect subsequent renderings, as the printable may be called multiple times...
  2. Using Graphics2D#scale. This really isn't the best quality nor is it generally that fast. See The Perils of Image.getScaledInstance(). I also prefer to use AffineTransform, but that's just me...
  3. Not buffering the result. Okay, this relates to the previous comment, but your print method may be called multiple times to print a single page, scaling the image each time is costly, instead, you should scale it once and re-use the scaled result.
  4. Unless you're going to physically rotate the image, you probably want to rotate about the center of the page, not the image itself, this will affect the location where 0x0 becomes.
  5. Now remember, when you rotate the Graphics context, the origin point changes, so instead of been in the top/left corner, in this case, it will become the top/right corner. And now you know why I would have rotated the image in isolation and not tried messing around with the Graphics context :P

我想的情况是,比例之间,旋转和坐标(交换高度和宽度)的操作,事情越来越拧......但坦率地说,我是不是用它去浪费时间当我有更好的解决方案...

What I "think" is happening is that between the scaling, rotating and manipulations of the coordinates (swapping the height and width), things are getting screwed...but frankly, I wasn't going to mess around with it when I have better solutions...

下面的示例使用了一堆个人图书馆code的,所以一些可能是一个有点令人费解,但我用其他的东西单独的功能,所以它结合得很好...

The following example makes use of a bunch of personal library code, so some of might be a little convoluted, but I use the separate functionality for other things, so it binds well together...

所以,开始的7680x4800的图像,这会产生的423x26​​4缩放图像

So, starting with an image of 7680x4800, this generates a scaled image of 423x264

(红色边境倾销的结果时,PDF,以节省纸张可视向导只,使用;))

(the red border are visual guides only, used when dumping the result to PDF to save paper ;))

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

您知道什么会容易得多,在横向模式下打印的页面入手:P

You know what would MUCH easier, printing the page in landscape mode to start with :P

这篇关于使用Java的4 x 6纸上打印1800 x 1200的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆