Java-将缓冲的图像绘制为可打印的图像与直接绘制为可打印的图像会产生模糊结果

时间:2019-07-05 13:18:51

标签: java printing

我正在设计一个Java程序,用于在A4纸上打印一些标签。我想在一个单独的类中创建标签,该类返回BufferedImage,然后将BufferedImages的集合传递给实现Printable接口的另一个类,该类将在页面上安排它们并进行打印。

我可以做所有这一切,但是在将BufferedImage绘制到可打印对象时发现,较精细的元素(尤其是文本)有点模糊。如果我直接绘制到Printable提供的图形对象中,则效果会好得多,但这对于程序的结构是不方便的。

我尝试设置文本和图形的抗锯齿提示,还尝试绘制两倍大小的图像,然后在绘制到Printable中时将其按比例缩小,但这会产生更差的结果。

下面是我编写的用于说明差异的测试程序。在输出上,当我使用与绘制到Printable中的正方形相同大小的BufferedImage时,以及在使用较大的BufferedImage并按比例缩小时,文本显然更加模糊。

    package printerresolutiontest;

    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;
    import java.awt.print.PageFormat;
    import java.awt.print.Paper;
    import java.awt.print.Printable;
    import java.awt.print.PrinterException;
    import java.awt.print.PrinterJob;

    public class PrinterResolutionTest implements Printable {

        public static void main(String[] args) throws PrinterException {

            PrinterResolutionTest printrestest = new PrinterResolutionTest();

            PrinterJob pj = PrinterJob.getPrinterJob();

            PageFormat pf = pj.defaultPage();
            Paper paper = pf.getPaper();
            paper.setImageableArea(0*72, 0*72, 8.3*72, 11.7*72);
            pf.setPaper(paper);
            pj.setPrintable(printrestest, pf);

            Boolean PRINT_DIALOG_OK = pj.printDialog();
            if (PRINT_DIALOG_OK) {
                pj.print();
            }

        }

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

            Graphics2D g2d = (Graphics2D) graphics;
            BufferedImage img1 = new BufferedImage(144, 144, BufferedImage.TYPE_INT_RGB);
            BufferedImage img2 = new BufferedImage(72, 72, BufferedImage.TYPE_INT_RGB);

            Graphics2D g2d_bigbuf = img1.createGraphics();
            Graphics2D g2d_buf = img2.createGraphics();            

            if (pageIndex > 0) {
                return NO_SUCH_PAGE;
            }

            /*************************
             * Draw directly into the Printable graphics object
             */

            g2d.setColor(Color.RED);
            g2d.fillRect(200, 200, 72, 72);
            g2d.setColor(Color.black);
            g2d.drawString("test", 202, (72/2)+202);

            /*************************
             * Draw the same features
             * into a BufferedImage
             */

            g2d_buf.setColor(Color.RED);
            g2d_buf.fillRect(0, 0, 72, 72);
            g2d_buf.setColor(Color.black);
            g2d_buf.drawString("test", 0, 72/2);

            /*************************
             * Draw a double sized square and 
             * increase font size accordingly
             */

            g2d_bigbuf.setColor(Color.RED);
            g2d_bigbuf.fillRect(0, 0, 144, 144);
            g2d_bigbuf.setColor(Color.black);
            Font currentfont = g2d_bigbuf.getFont();
            Font newfont = currentfont.deriveFont(currentfont.getSize() * 2F);
            g2d_bigbuf.setFont(newfont);
            g2d_bigbuf.drawString("test", 0, 144/2);

            // Draw the regular sided BufferedImage
            g2d.drawImage(img2, 300, 200, null);
            // Draw the larger BufferedImage and scale down by half
            g2d.drawImage(img1.getScaledInstance(72, 72, Image.SCALE_AREA_AVERAGING), 400, 200, null);

            return PAGE_EXISTS;
        }

    }

BufferedImage test PNG 这是我打印到PDF的文件的测试屏幕截图,以作为区别的示例。理想情况下,我希望使用BufferedImage获得与直接绘制到Printable中时相同的图像质量。

1 个答案:

答案 0 :(得分:0)

屏幕和打印机是非常不同的介质。在屏幕上,您通常具有大约72到92 dpi(每英寸像素)的低分辨率。每个像素可以具有大量的颜色(24m或更多)。在打印机上,您通常具有高分辨率(最高2540 dpi),但只有2(b / w)至6色之间。为了创建中间颜色,打印机将使用光栅化技术,例如halftone

您创建 BufferedImage 的方式非常偏向于屏幕输出:分辨率低,使用中间颜色进行抗锯齿等。结果会很差。此外,您的输出意图也消失了。打印机驱动程序只能看到一个像素图。它不知道文本是否存在以及在哪里,也无法为其优化输出。

为了提高质量,主要有两种选择:

  • 如果仅打印行和文本,并且仅使用打印机可以创建的颜色而没有混合颜色,则可以创建与打印机分辨率和颜色完全匹配的 BufferedImage 。那应该给你不错的素质。

  • 否则,直接绘制到 Printable 。这样就可以保留输出操作的意图,并且打印驱动程序可以产生最佳质量。我确信您可以重构代码,以使您仍然具有非常可维护的结构。