【问题标题】:Fit image into the printing area使图像适合打印区域
【发布时间】:2012-08-29 08:15:06
【问题描述】:

我需要用 Java 打印图像。所以我实现了Printable接口的print()方法。但是打印机总是只打印一些原始图像。如何使图像适合打印区域(A4),以便打印机能够打印整个图像,而不是其中的一部分?现在我的代码如下所示:

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


    if (pageIndex >= images.size()) {
        return Printable.NO_SUCH_PAGE;
    }
    RenderedImage image;


    Graphics2D graphics2D = (Graphics2D) graphics;

    image = new NullOpImage((RenderedImage) images.get(pageIndex), null, null, OpImage.OP_IO_BOUND);


    double x = (pageFormat.getImageableWidth() - image.getWidth())/2 + pageFormat.getImageableX();
    double y = (pageFormat.getImageableHeight() - image.getHeight())/2 + pageFormat.getImageableY();


    graphics2D.drawRenderedImage(image, AffineTransform.getTranslateInstance(x, y));

    return PAGE_EXISTS;
}

【问题讨论】:

    标签: java printing jpanel


    【解决方案1】:

    您需要缩小图像以适应可用区域。

    private int currentPage = -1;
    private Image cachedScaledImage = null;
    
    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;
    }
    
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
    
        if (pageIndex >= images.size()) {
            return Printable.NO_SUCH_PAGE;
        }
        RenderedImage image;
    
    
        Graphics2D graphics2D = (Graphics2D) graphics;
    
        int width = (int)Math.round(pageFormat.getImageableWidth());
        int height = (int)Math.round(pageFormat.getImageableHeight());
    
        if (currentPage != pageIndex || cachedScaledImage == null) {
            currentPage = pageIndx;    
    
            image = new NullOpImage((RenderedImage) images.get(pageIndex), null, null, OpImage.OP_IO_BOUND);
    
            BufferedImage imageCopy = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = imageCopy.createGraphics();
            g2d.drawImage(imageCopy, 0, 0, null);
            g2d.dispose();
    
            double scaleFactor = getScaleFactorToFit(new Dimension(image.getWidth(), image.getHeight()), new Dimension(width, height));
    
            int imageWidth = (int)Math.round(image.getWidth() * scaleFactor);
            int imageHeight = (int)Math.round(image.getHeight() * scaleFactor);
    
            double x = ((pageFormat.getImageableWidth() - imageWidth) / 2) + pageFormat.getImageableX();
            double y = ((pageFormat.getImageableHeight() - imageHeight) / 2) + pageFormat.getImageableY();
    
            cachedScaledImage = imageCopy.getScaledInstance(imageWidth, imageHeight, Image.SCALE_SMOOTH);
    
        }
    
        graphics2D.drawRenderedImage(cachedScaledImage, AffineTransform.getTranslateInstance(x, y));
    
        return PAGE_EXISTS;
    }
    

    【讨论】:

    • 谢谢。但是我得到了: ClassCastExcepion 这里: graphics2D.drawRenderedImage(scaledImage, AffineTransform.getTranslateInstance(x, y)); 我将它(通过更改方法)修复为 drawImage(...)但现在我得到了 Java.lang.OutOfMemoryError: Java heap space
    • 这并不奇怪。系统多次请求一个特定的页面页面被渲染多次,这意味着每次,我们都在创建图像的新副本和每次缩放的实例。您应该考虑创建一个缓存,允许您缓存缩放的实例并引用该实例,直到页码更改
    • 我读到 JAI-ImageIO 工具可能会导致这样的错误。我需要NullOpImage吗?或者我可以换别的班?
    • 我更新了我的代码以演示如何使用缩放图像的缓存版本。我不确定你想从NullOpImage 中实现什么,所以我不能在那里提出任何建议
    • 我不需要使用NullOpImage,我从示例中得到它...当我将NullOpImage 更改为简单的java.awt.Image 时,我不再出现像OutOfMemoryError 这样的错误。所以我认为我不应该使用NullOpImage。但是如果我使用Image,像getWidthgetHeight 这样的方法需要额外的参数(ImageObserver),当我将null 作为参数传递时,打印的是空白页,而不是实际图像......
    猜你喜欢
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    相关资源
    最近更新 更多