我正在设计一个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中时相同的图像质量。
答案 0 :(得分:0)
屏幕和打印机是非常不同的介质。在屏幕上,您通常具有大约72到92 dpi(每英寸像素)的低分辨率。每个像素可以具有大量的颜色(24m或更多)。在打印机上,您通常具有高分辨率(最高2540 dpi),但只有2(b / w)至6色之间。为了创建中间颜色,打印机将使用光栅化技术,例如halftone。
您创建 BufferedImage 的方式非常偏向于屏幕输出:分辨率低,使用中间颜色进行抗锯齿等。结果会很差。此外,您的输出意图也消失了。打印机驱动程序只能看到一个像素图。它不知道文本是否存在以及在哪里,也无法为其优化输出。
为了提高质量,主要有两种选择:
如果仅打印行和文本,并且仅使用打印机可以创建的颜色而没有混合颜色,则可以创建与打印机分辨率和颜色完全匹配的 BufferedImage 。那应该给你不错的素质。
否则,直接绘制到 Printable 。这样就可以保留输出操作的意图,并且打印驱动程序可以产生最佳质量。我确信您可以重构代码,以使您仍然具有非常可维护的结构。