打印在 Java 中旋转的图像会增加伪影

Posted

技术标签:

【中文标题】打印在 Java 中旋转的图像会增加伪影【英文标题】:Printing an image rotated in Java adds artifacts 【发布时间】:2018-07-06 01:20:59 【问题描述】:

我正在尝试用 Java 打印一个带有小旋转变换的简单图像。打印图像时,图像边界处存在原始图像中不存在的伪影,因此图像在边界处带有这些黑线。

有人见过吗?

要复制,请运行以下代码:

package test;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;

import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.Destination;

public class TestPrintBug implements Printable

    public static void main(String [] args)
    
        try
        
            PrintService[] services = PrinterJob.lookupPrintServices();
            for (int index = 0; index < services.length; index++) 
            
                if (services[index].getName().equalsIgnoreCase("Microsoft XPS Document Writer"))
                
                    PrinterJob pjob = PrinterJob.getPrinterJob();
                    HashPrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
                    attributes.add(new Destination(new File("c:/test.xps").toURI()));
                    pjob.setPrintable(new TestPrintBug(), new PageFormat());
                    pjob.setPrintService(services[index]);
                    pjob.print(attributes);
                
            
        
        catch(Throwable t)
        
            t.printStackTrace();
        
    

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException 
    
        if (pageIndex == 0)
        
            try
            
                int width = (int)(8.5 * 72);
                int height = 1 * 72;

                BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D biG = bi.createGraphics();
                biG.setColor(Color.yellow);
                biG.fillRect(0, 0, width, height);

                Graphics2D g2Print = (Graphics2D)graphics;
                g2Print.transform(AffineTransform.getRotateInstance(-0.02));
                g2Print.drawImage(bi, 0, 144, null);

                return Printable.PAGE_EXISTS;
            
            catch(Throwable t)
            
                t.printStackTrace();
            
        

        return Printable.NO_SUCH_PAGE;
    

【问题讨论】:

【参考方案1】:

打印图像时,图像边界处有伪影 不在原始图像中,因此图像带有这些 边框上有黑线。

我看到您正在旋转的图像只有 -0.02 弧度,大约为 -1.15 度。对于如此小的图像(612 X 72 像素)来说,这是一个非常小的角度。图像的最小单位是一个像素,它只能旋转 90 度或 90 度的倍数。这些库通过仅将一些像素旋转 90 度来解决此问题。但是,当旋转角度和图像像素尺寸都很小时 - 如您的情况一样,此算法变得不那么有效。这就是你看到那些黑色边框的原因。这显然不是AWT 库中的错误。如果允许,您可能希望增加旋转角度或使用高分辨率图像。此外,如果您将非方形图像旋转的角度不是 90 度的倍数,则需要确保旋转后的图像适合原始视口。如果没有,您必须编写额外的代码来绘制从视口中掉出的图像区域。

附: Graphics2DBufferedImage 等资源在使用后也应该处理掉,避免内存泄漏。例如。最后打电话给g2Print.dispose();

【讨论】:

没有理由使用旋转绘制图像会引入伪影。这样做本质上会破坏输出,因此会使旋转无法使用。这是图像处理中一个已解决的问题。我们已经使用其他应用程序和编程框架对此进行了测试,但从未见过这种情况发生。此外,这仅在 Java 中打印时发生:在屏幕或其他图像上绘制时,没有问题。 我们认为这绝对是 AWT / Swing 中的一个错误。我们已向 Java 报告了该错误,但同时我们希望有人遇到此问题并找到解决方法。

以上是关于打印在 Java 中旋转的图像会增加伪影的主要内容,如果未能解决你的问题,请参考以下文章

如何从我的 CATiledLayer 中移除这些旋转伪影?

在 OpenCV 图像拼接中混合伪影

检测图像中的噪声/伪影

从图像中删除字母伪影

使用TensorFlow对图像进行随机旋转的实现示例

使用TensorFlow对图像进行随机旋转的实现示例