【问题标题】:Why does Java ImageIO generate different images on different machines (linux vs Windows)?为什么 Java ImageIO 在不同的机器(linux vs Windows)上生成不同的图像?
【发布时间】:2012-03-22 05:36:16
【问题描述】:

我在 Windows 和 Linux 上使用 javax.imageio 从文本字符串生成图像,我发现图像的质量非常不同(Linux = 质量差,物理尺寸小,尽管尺寸相同)。

Linux (Ubunutu),443 字节

Windows 7,1,242 字节

我使用相同的字体文件(从 Windows 上传到 linux),并使用此代码生成图像。知道如何提高 linux 生成的图像的质量吗?首先为什么生成的图像不同?

我已尝试设置 explicit compression(通过 iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);),但尝试设置时出现 UnsupportedOperationException。

更新:

这是一个 SSCCE。我已经更新了我的示例并删除了字体,结果是一致的。如果您在两个系统上都设置了字体,它们也会发生。

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Example {
    /**
     * <p>Create an image from text. <p/>
     * <p/>
     * http://stackoverflow.com/a/4437998/11236
     */
    public static void createFromText(String text, Path outputFile, int width, int height, Color color, int fontSize) {
        JLabel label = new JLabel(text, SwingConstants.CENTER);
        label.setSize(width, height);
        label.setForeground(color);

        BufferedImage image = new BufferedImage(
                label.getWidth(), label.getHeight(),
                BufferedImage.TYPE_INT_ARGB);

        Graphics g = null;
        try {
            // paint the html to an image
            g = image.getGraphics();
            g.setColor(Color.BLACK);
            label.paint(g);
        } finally {
            if (g != null) {
                g.dispose();
            }
        }

        // get the byte array of the image (as jpeg)
        try {
            ImageIO.write(image, "png", outputFile.toFile());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        Path output = Paths.get("/tmp/foo.png");
        createFromText("Custom Text", output, 200, 40, Color.blue, 30);
    }
}

【问题讨论】:

  • “我试过了..” 尝试发布SSCCE。但我建议您排除JLabel,而是使用RenderingHints 映射直接将字符串绘制到图形实例,您可以在其中指定..可以指定的所有内容。后者将绕过一些可能使用的不同默认值。
  • 另外,您似乎认为不同之处在于图像的保存方式。我(和其他人,显然)怀疑是这种情况。在渲染之前将JLabel 本身弹出到JOptionPane 中是值得的。抓取屏幕截图并将其与其他系统的屏幕截图进行比较。最初的 JLabel 实例看起来是否相同?
  • @AndrewThompson - 我可能确实需要制作一个 sccee。我会检查 RenderingHints。我无法在 linux 系统上轻松预览图像,我认为它没有安装 UI……它是一个 EC2 ubuntu 服务器。
  • @AndrewThompson - 更新为真正的 SSCCE。
  • 好吧,我设置了我能找到的所有渲染提示(更新了 SSCCE gist.github.com/1973391),图像更接近了,但仍然不完全相同。我还注意到我使用的字体没有 BOLD 版本,只有 PLAIN 版本。当我修改代码以输出 PLAIN 版本时,图像现在看起来几乎完全相同......仍然不是二进制相同。

标签: java image javax.imageio


【解决方案1】:

只是一个猜测,但您的图像看起来像这样也可能来自将文本渲染到图像时的不同抗锯齿行为。这意味着差异不是在图像的压缩或 png 编码期间造成的,而是在将文本渲染到图像时已经造成的。如果没有文字抗锯齿,图像可以被压缩到更小的尺寸,因为它包含的不同颜色更少,所以这也可以解释文件大小的差异。

尝试明确指定抗锯齿设置,而不是依赖系统默认设置,看看这是否会有所不同。您可以通过将 RenderingHints 添加到 Graphics2D 对象来做到这一点,例如渲染提示 text_antialising:

http://docs.oracle.com/javase/6/docs/api/java/awt/RenderingHints.html#KEY_TEXT_ANTIALIASING

有关字体渲染行为的讨论,请参见此处:

Java Font Rendering

【讨论】:

  • 这和@AndrewThompson 的 cmets 很有帮助。仍然(请参阅我对问题的评论回复),我想了解为什么两个平台之间有任何区别?即使我设置了相同的渲染提示,一些差异仍然存在。为什么这不是确定性的?
【解决方案2】:

有一次你说你只想制作字符串图像,然后在代码中你说你从 html 制作图像...... 请注明

仅适用于字符串: 也许在linux上label本身为图形设置了其他属性,所以自己做,不要使用labels绘制方法...可以与linux的Window-UI链接

html: 尝试使用 JTextPane,它应该具有高级 html 设置...也许这会提高质量

【讨论】:

  • JLabel 是否呈现为 HTML 取决于 text 参数的值。如果有什么东西暗示了那个属性的内容,我错过了。
  • 它可能是 HTML,在我的情况下它只是一个字符串。
猜你喜欢
  • 2019-09-05
  • 2014-07-16
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
  • 2015-07-18
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
相关资源
最近更新 更多