当前位置: 首页 > 知识库问答 >
问题:

Java-将缓冲图像绘制到可打印文件中与直接绘制到可打印文件中相比会产生模糊结果

姬正文
2023-03-14

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

我可以做到这一切,但我发现在将BuffereImage绘制到可打印文件中时,更精细的元素,尤其是文本,有点模糊。如果我直接绘制到可打印的图形对象中,那么结果会更好,但这对程序的结构来说很不方便。

我尝试过为文本和图形设置抗锯齿提示,也尝试过绘制两倍大小的图像,然后在绘制到可打印文件时将其缩小,但这会产生更糟糕的结果。

下面是我编写的一个测试程序,以说明这些差异。在输出上,当我使用与绘制到可打印文件中的正方形大小相同的BuffereImage时,文本明显更模糊,再次使用更大的BuffereImage并缩小时。

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

    }

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

共有1个答案

子车芷阳
2023-03-14

屏幕和打印机是非常不同的媒体。在屏幕上,通常分辨率约为72到92 dpi(每英寸像素)。每个像素可以有大量的颜色(24m或更多)。在打印机上,分辨率通常很高(高达2540 dpi),但仅在2(黑白)到6色之间。为了创建中间颜色,打印机将使用光栅化技术,例如半色调。

创建BuffereImage的方式严重偏向屏幕输出:低分辨率、使用中间颜色进行消除混叠等。结果会很差。此外,输出的意图也丢失了。打印机驱动程序只能看到像素图。它不知道文本是否在哪里,也无法优化文本的输出。

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

>

  • 如果只打印行和文本,并且只使用打印机可以创建的颜色而不混合颜色,则可以创建与打印机分辨率和颜色完全匹配的BuffereImage。这应该给你一个体面的质量。

    否则,直接绘制到可打印文件。然后,输出操作的意图将被保留,打印驱动程序可以产生最佳质量。我相信,只要稍微想一想,您就可以重构代码,这样您仍然有一个非常可维护的结构。

  •  类似资料:
    • 我目前正在尝试制作一个画布,我可以绘制的东西,并使它出现在一个JFrame。 为此,我打算在一个JPanel组件中有一个BufferedImage,paintComponent方法可以从中进行绘制。 理想情况下,我希望能够从给定的JFrame中引用这个缓冲图像,然后使用其Graphics2D向其绘制素材,paintComponent方法可以在使用缓冲图像绘制时显示这些素材。 我这样做是为了避免直接

    • 我真的被困在作业的这一特定部分,它要求我将简单文本打印到控制台中,然后创建一个文件(无论主文件中的std::string文件名是什么),并将控制台的内容打印到该文件中。 我真的很困惑,因为该函数需要ostream,而且它还需要该函数使用任何文件名(在本例中是statistics.txt,只是为了测试该函数是否工作)。 函数是PrintStatistics。 我知道我可以使用cout在控制台上打印,

    • 问题内容: 如何将Java输出同时输出到Shell控制台和某个文件中?那可能吗? 问题答案: 您可以在程序的开头包含以下几行:

    • 问题内容: 我有一个文本文件,需要将其打印到特定的网络打印机。我知道打印机的名称。 到目前为止,我已经创建了Printable类来打印文件(票证)。 我这样称呼TicketPrintPage: 它的工作原理还不错,但是: -我的文本不多于一页(找到了一些算法,但是很好) -我不知道打印机何时完成打印,如果我尝试打印两页如果打印机连续打印了多张票证,则会返回“打印机未就绪”消息。 所以问题又来了:没

    • 问题内容: 我已经搜索过,但我只能找到有关另一种方式的问题:将stdin写入文件:) 有没有一种快速简便的方法将文件内容转储到stdout? 问题答案: 当然。假设您有一个字符串,文件名为,下面的技巧就可以了。

    • 问题内容: 我想将数组打印到文件中。 我希望文件看起来像这样的代码完全相似。 假设$ abc是一个数组。 是否有任何一种解决方案,而不是每次外观都是常规的。 PS-我目前使用序列化,但是我想使文件可读,因为使用序列化数组很难读取。 问题答案: 无论是或将返回输出,而不是打印出来的。 PHP手册中的示例 然后,您可以使用保存。或在写入文件时直接将其返回: