获取Java打印机图形设备
JavaDocs表明GraphicsEnvironment支持“屏幕和打印机设备” 我能看到如何获取有关屏幕设备的信息,但似乎无法找到有关如何获取打印机设备信息的信息 基本上,在打印时,我希望能够使用devices GraphicsConfiguration创建兼容的缓冲图像 希望这样做的主要原因是:获取Java打印机图形设备,java,graphics,printing,Java,Graphics,Printing,JavaDocs表明GraphicsEnvironment支持“屏幕和打印机设备” 我能看到如何获取有关屏幕设备的信息,但似乎无法找到有关如何获取打印机设备信息的信息 基本上,在打印时,我希望能够使用devices GraphicsConfiguration创建兼容的缓冲图像 希望这样做的主要原因是: 我们希望在页面的第一个请求上缓冲页面请求,并在页面的后续请求上简单地绘制回缓冲区(因为页面包含大量图像和一些复杂的呈现-而不是浪费时间绘制每个页面请求,我们希望使用缓冲区) 保持打印机的高分辨率输
GraphicsConfiguration conf = ((Graphics2D) graphics).getDeviceConfiguration();
assert conf.getDevice().getType() == GraphicsDevice.TYPE_PRINTER;
System.out.println("Device: " + conf.getDevice().getIDstring());
final AffineTransform trans = conf.getDefaultTransform();
double dpi = trans.transform(new Point2D.Float(72, 0), null).getX();
System.out.println(dpi + " DPI");
Rectangle bounds = conf.getBounds();
System.out.println("page size: " + bounds.width + "x" + bounds.height);
// now you could do
buffer = conf.createCompatibleImage(bounds.width, bounds.height);
// verify values, you wouldn’t do this in production code:
g2d.drawImage(buffer, 0, 0, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableWidth(), null);
double scale = dpi / 72d;
AffineTransform scaleAT = AffineTransform.getScaleInstance(scale, scale);
g2d.setTransform(scaleAT);
print(g2d, pageFormat.getImageableWidth(), pageFormat.getImageableWidth());
它实际上会生成一个缓冲图像
,该图像将被转换为打印机DPI
为了简化测试,我编写了一个简单的print
方法
public void print(Graphics2D g2d, double width, double height) {
Font font = g2d.getFont();
font = font.deriveFont(64f);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String text = "Hello World!";
double x = (width - fm.stringWidth(text)) / 2;
double y = (height - fm.getHeight()) / 2;
g2d.drawString(text, (float) x, (float) y);
}
我可以使用打印机图形
上下文或其他图形
上下文
现在很明显,当以72dpi打印到A4页面时,生成的图像大小为595x841,为600dpi(上面的示例已报告),这将生成4970x7029的图像。好的,这很好,我只需要在绘制到目标打印机Graphics
context时缩小图像的比例,例如
GraphicsConfiguration conf = ((Graphics2D) graphics).getDeviceConfiguration();
assert conf.getDevice().getType() == GraphicsDevice.TYPE_PRINTER;
System.out.println("Device: " + conf.getDevice().getIDstring());
final AffineTransform trans = conf.getDefaultTransform();
double dpi = trans.transform(new Point2D.Float(72, 0), null).getX();
System.out.println(dpi + " DPI");
Rectangle bounds = conf.getBounds();
System.out.println("page size: " + bounds.width + "x" + bounds.height);
// now you could do
buffer = conf.createCompatibleImage(bounds.width, bounds.height);
// verify values, you wouldn’t do this in production code:
g2d.drawImage(buffer, 0, 0, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableWidth(), null);
double scale = dpi / 72d;
AffineTransform scaleAT = AffineTransform.getScaleInstance(scale, scale);
g2d.setTransform(scaleAT);
print(g2d, pageFormat.getImageableWidth(), pageFormat.getImageableWidth());
(这是测试,所以现在还不要就质量相关的问题向我发火)
(左侧为正常,buffereImage
右侧为正常)…好的,这样不行
因此,我当时想,我可以对缓冲区Graphics
上下文应用AffineTransform
缩放,使用类似于
GraphicsConfiguration conf = ((Graphics2D) graphics).getDeviceConfiguration();
assert conf.getDevice().getType() == GraphicsDevice.TYPE_PRINTER;
System.out.println("Device: " + conf.getDevice().getIDstring());
final AffineTransform trans = conf.getDefaultTransform();
double dpi = trans.transform(new Point2D.Float(72, 0), null).getX();
System.out.println(dpi + " DPI");
Rectangle bounds = conf.getBounds();
System.out.println("page size: " + bounds.width + "x" + bounds.height);
// now you could do
buffer = conf.createCompatibleImage(bounds.width, bounds.height);
// verify values, you wouldn’t do this in production code:
g2d.drawImage(buffer, 0, 0, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableWidth(), null);
double scale = dpi / 72d;
AffineTransform scaleAT = AffineTransform.getScaleInstance(scale, scale);
g2d.setTransform(scaleAT);
print(g2d, pageFormat.getImageableWidth(), pageFormat.getImageableWidth());
这意味着我不需要在我们现有的底层绘制例程中应用任何“打印模式”类型转换
这导致
但是等一下,这里出了什么问题
所以我回去看了所有的测量结果
GraphicsConfiguration conf = ((Graphics2D) graphics).getDeviceConfiguration();
//...
Rectangle bounds = conf.getBounds();
buffer = conf.createCompatibleImage(bounds.width, bounds.height);
我们报告的图像大小是4960x7015,但它应该是4970x7029…但是等等,想象中的区域呢…应该是600dpi,3768x5827…所以这是不可靠的
即使纠正了这一点,结果仍然没有让图像在位置和质量上与预期相符
Graphics2D
提供了一种获取链接到图形设备的图形配置的方法。缺少的是信息,您可以放心地假设在打印上下文中,图形
是图形2d
例如,以下程序在我的设置中起作用:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.awt.print.*;
import javax.print.*;
public class PrintDev implements Printable {
public static void main(String[] args) throws PrintException {
final DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintService ps=PrintServiceLookup.lookupDefaultPrintService();
System.out.println(ps.getName());
ps.createPrintJob().print(new SimpleDoc(new PrintDev(), flavor, null), null);
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
GraphicsConfiguration conf = ((Graphics2D)graphics).getDeviceConfiguration();
assert conf.getDevice().getType()==GraphicsDevice.TYPE_PRINTER;
System.out.println("Device: "+conf.getDevice().getIDstring());
final AffineTransform trans = conf.getDefaultTransform();
System.out.println(trans.transform(new Point2D.Float(72,0),null).getX()+" DPI");
Rectangle bounds = conf.getBounds();
System.out.println("page size: "+bounds.width+"x"+bounds.height);
// now you could do
BufferedImage bi=conf.createCompatibleImage(bounds.width, bounds.height);
// verify values, you wouldn’t do this in production code:
try { trans.invert(); }
catch(NoninvertibleTransformException ex){ return NO_SUCH_PAGE; }
Point2D p=trans.transform(new Point2D.Float(bounds.width, bounds.height),null);
System.out.printf("page in inches: %.2fx%.2f%n", p.getX()/72, p.getY()/72);
return NO_SUCH_PAGE;
}
}
这个问题是关于Java Graphics2D或输出到HW打印机的大小的???@mKorbel两者都不是。就像您可以创建一个兼容的图像来渲染到屏幕上一样,我想用打印机也这样做。一般来说,如果创建缓冲图像并将其绘制到打印机的图形上下文中,它的渲染速度(我认为)为72dpi。如果你直接画图形,你就得到了印刷者的dpi。现在我的问题很清楚了:-)这可能会有帮助:真的吗?为什么这个问题会引起反对票?是否有人想进一步说明原因,以便我有机会纠正这个问题…?我按喇叭,我尝试了这个,但没有成功。我会重新测试以确定事实上,几个月前我尝试过类似的方法,但没有成功。仍然在测试所以为了完整性,它在Windows7 32位
,jdk 1.7.0(40
…Windows7 x64,Java6,7和8上工作-仍然在测试;)这是否意味着它正在这些系统上工作?