【问题标题】:Java Printing at anything above 72 DPI doesn't fill page任何高于 72 DPI 的 Java 打印都不会填满页面
【发布时间】:2011-12-19 23:45:32
【问题描述】:

我正在编写一个 jOGL 应用程序,它允许用户打印当前渲染的屏幕截图。为了打印出渲染,我将 OpenGL 上下文的大小设置为纸张的可打印区域,然后将前端缓冲区保存到绘制到可打印画布的图像中。

应用程序还必须以尽可能高的质量打印出这些屏幕截图,因此我一直在尝试将 DPI 从默认的 72 提高到 300。但是,图像的分辨率并没有增加,而是保持不变,并且现在只占页面的大约 1/4。知道为什么会这样吗?

这是打印代码:

    // Set up for printing
    PrinterJob job = PrinterJob.getPrinterJob();

    PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
    PrinterResolution pr =
      new PrinterResolution(300, 300, PrinterResolution.DPI);

    aset.add(pr);

    aset.add(PrintQuality.HIGH);

    boolean ok = job.printDialog(aset);
    if (ok) {
        try {
            Book book = new Book();

            PageFormat pf = job.getPageFormat(aset);
            Paper paper = pf.getPaper();

            // Halve margins
            paper.setImageableArea(pf.getImageableX()/2, pf.getImageableY()/2, pf.getImageableWidth() + pf.getImageableX(), pf.getImageableHeight() + pf.getImageableY());
            pf.setOrientation(PageFormat.LANDSCAPE);

            pf.setPaper(paper);

            book.append(glcanvas, pf, 2);

            job.setPageable(book);
            job.print(aset);
        }
    }

然后,在我的可打印对象中,调整 OpenGL 上下文的大小:

    glcanvas.reshape(0, 0, (int)pf.getImageableWidth(), (int) pf.getImageableHeight() - StaticViewerUtility.HEADER_HEIGHT);

但是,PageFormat 的可成像大小永远不会改变。它保持在 72、72、468、648(即 72 DPI,在 8.5"x11" 纸上具有 1" 边距)。即使将 DPI 设置为 300,成像区域也不会改变。将其强制更高只会让打印机看到页面为任意大小(例如:22.87232“x11.8892”)并且图像仍然只打印到页面的一角。我也尝试过手动更改 OpenGL 上下文的大小,但打印输出仍然以原来的精确尺寸切割。

问题截图示例: http://img32.imageshack.us/img32/2708/capturedodg.jpg

我有什么遗漏吗?

【问题讨论】:

  • 您的glViewport() 电话在哪里?它被这个“jOGL”的东西照顾了吗?
  • 是的,当我调用 glcanvas.reshape() 时,jOGL 会重新初始化具有视口调用 (glViewport(0, 0, windowWidth, windowHeight);) 的 OpenGL 上下文。问题是打印的可分页区域永远不会改变,因此即使在调整 OpenGL 上下文大小之前也是一个问题。

标签: java opengl printing dpi


【解决方案1】:

所以我一直在尝试将 DPI 从默认的 72 提高到 300

OpenGL 创建一个光栅图像,这意味着您拥有固定数量的像素。分辨率 (DPI) 告诉打印机一英寸有多少像素。如果您增加 DPI,固定数量的像素将仅覆盖较短的长度。为了弥补这一点,您需要使用 OpenGL 以相应的更高分辨率进行渲染。

从窗口拍照有它的问题。我强烈建议使用屏幕外缓冲区,例如 PBuffer 或帧缓冲区对象。


OpenGL 是一个针对实时图形的光栅化器,无论如何都不太适合为打印机提供数据(打印机喜欢矢量图形作为数据输入,但 OpenGL 的输出是光栅图像)。

使用OpenGL进行高质量打印的常用方法如下:

  • 确定图像的目标大小和分辨率。例如。 300DPI 时为 10 英寸 × 20 英寸。因此所需的分辨率为 3000×6000 像素。

  • 帧缓冲区有一个最大大小; OpenGL 要求至少支持 4096×4096。借助 EyeFinity 等功能,您可以获得数万像素。但是假设您的实现只能处理 4096×4096 max。所以你不能把 3000×6000 放进去。解决方案是平铺渲染。你把你的图片分成2×3000×3000

    for t in tiles:
        glViewport(0, 0, t.width, t.height)
        glMatrixMode(GL_PROJECTION)
        glScalef(total_width / t.width, total_height / t.height, 1)
        glTranslatef(-1 + 2*total_width / t.off_x, -1 + 2*total_height / t.off_y, 0)
        your_projection()
        render_scene()
    

    然后将图块合并成一张大图。

另一个不错的方法是将 OpenGL 转换为矢量输出:http://geuz.org/gl2ps/(不幸的是,这个库似乎只支持即时模式)。如果您仍想使用 GPU 并拥有可用的现代功能,您也可以使用转换反馈。

【讨论】:

  • 我们的许多客户将在带有集成显卡的笔记本电脑上运行此应用程序(这意味着其中许多将运行 OpenGL 2.0 或更低版本),因此 PBuffer 或 FBO 不是一个可行的选择。出于调试目的,我的代码还在打印前将前端缓冲区保存为 JPG。 JPG 是正确的大小,并且没有问题,即使将视口大小调整 300/72 倍(从 72 放大到 300 DPI)。问题是我的分页大小没有改变,所以即使 OpenGL 渲染出正确的大小,它也会被打印操作裁剪回来。
  • 前端缓冲区的内容,已保存:img864.imageshack.us/img864/4925/saved.png 发送到打印机的内容:img831.imageshack.us/img831/4/capturesmj.jpg
  • @Nicholas'Snobaste'Fetcko:PBuffers 早在 1990 年代末就已经存在(我记得在 1999 年编写了我的第一个基于 PBuffer 的程序),所以这绝对不是什么大事。此外,如果您先渲染为 JPG 然后打印,您将无法获得分辨率,而只是放大。应该注意的是,您不能(不应该)在打印机 DC 上使用 OpenGL(请参阅我在答案中的编辑)。
  • 我知道保存前端缓冲区显然不是进行打印的最佳方式,但这不是问题。即使在打印出矢量图形(使用 Java 图形库绘制)时,我也被锁定在页面的左上角。
  • @Nicholas'Snobaste'Fetcko:DPI 设置不会神奇地缩放您的图像。假设您要打印 10" 宽且设置为 300DPI 的图片,则图像尺寸必须在 0...3000 范围内。因此,保持图像尺寸不变,改变分辨率 (DPI) 将改变结果的物理尺寸.
猜你喜欢
  • 2020-04-24
  • 1970-01-01
  • 2014-04-21
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 2017-04-13
相关资源
最近更新 更多