【问题标题】:JPEG to transparent PNG causes black bleedingJPEG 到透明 PNG 会导致黑色渗色
【发布时间】:2014-06-17 18:01:48
【问题描述】:

我需要做以下事情:我有一个标准的 JPEG 图像作为输入。我需要做的是将其转换为 PNG 32 位(alpha 透明度)并设置一些像素的透明边框。

我尝试使用 ImageMagic 这些命令:

convert  xxx.jpg xxx.png 

convert xxx.png -channel RGBA -separate -resize 500x500 -combine xxx.png 

convert xxx.png -alpha set -channel RGBA -separate \
        -background "RGBA(0,0,0,0)" -gravity center \
        -extent 550x550 -composite xxx1.png 

这就是我在 OpenGL 程序中使用此图像后的结果,它在输出上预乘它,因为需要 alpha 混合。

黑色边缘是原始 JPEG 图像部分结束的位置(可见边缘周围还有 10 像素透明边框),这意味着从 ImageMagic 生成的图像可能是预乘的,这不是我想要的。我需要就像 Photoshop 以未预乘状态导出 PNG 图像一样,它不会被重乘。这样我可以摆脱黑色边框伪影。

如果我使用像 GL_LINEAR 或 GL_LINEAR_MIPMAP_LINEAR 这样的线性插值,就会发生出血。许多资料中还指出,这种出血是相邻像素线性插值的结果。

奇怪。如果我在 Photoshop 中进行这样的设置,即,将 JPG 放入透明画布,然后使用透明通道将其保存到 PNG24,那么出血就消失了。此外,如果我从上述 ImageMagic 过程中删除生成的 PNG并用 Photoshop 重新保存它,然后它也得到修复。我不能使用 Photoshop,因为我需要像 ImageMagic 这样的命令行工具来创建这些图像。我也可以使用通过 C++ 代码自定义的东西,但我目前不知道如何摆脱那个黑边。

【问题讨论】:

  • 也许尝试来自imagemagick.org/Usage/thumbnails/#pad的所有其他命令?
  • 已经检查过了。不起作用。ImageMagic 导出 JPG 的方式与 Photoshop 不同。
  • 你的意思是如果你从photoshop保存xxx.png并运行命令2和3,没有出血?
  • 不,我的意思是,如果我使用 1,2,3 命令拍摄已经通过 ImageMagic 传递的图片并将其重新保存为 PNG,然后它就会得到修复。
  • 您能否发布指向使用 Photoshop 生成的图像(一个很好的结果)和使用 ImageMagick 生成的图像(导致出血的图像)的链接。从描述中我不确定它应该是什么样子,但如果你发布图片,我会调查一下。

标签: opengl image-processing imagemagick png jpeg


【解决方案1】:

您可以尝试使用this C++ command-line tool。有一个预编译的 windows 二进制文件和一个修改后的图像示例。它不对图像做任何事情,它只是在它周围设置零 alpha 边框(没有预乘)。要构建它,您需要 libjpeg 和 libpng(您可以获得 x86 / x64 预构建的windws libs here)。

关于 OpenGL 的几点说明。边缘的渗色最多只能达到 1 个像素宽,并且是由重复的纹理应用引起的。即使使用GL_LINEARGL_LINEAR_MIPMAP_LINEAR 模式,您也可以通过将钳位模式设置为GL_CLAMP_TO_EDGE 来删除它:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

如果您不使用GL_TEXTURE_2D,则需要将其替换为您正在使用的任何内容。出血有点可疑,也可能与 Alpha 为零的区域中的 RGB 颜色有关。设置混合模式的正确方法是:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

这样,任何 alpha 为零的东西都不会对其下方的像素产生任何影响。但是,插值可能会导致 alpha 为零的黑色像素渗入到 alpha 为 100% 的图像的第一个像素,从而产生细黑色边框。为了摆脱这种情况,需要将原始图像边缘的颜色复制到边框,并将 alpha 设置为零。

为此,请在编译时定义__BLEED_EDGE,或使用预编译的AddTransparentBorder_BleedEdge 版本。还有一个边缘重复的图像示例。您可以先尝试使用这些示例,看看是否出现黑边。

【讨论】:

  • Nope.CLAMP 不会解决它。我正在使用这种模式。slove 是 GL_NEAREST 插值。因为 LINEAR 对最近的像素和边缘进行采样,其中一些是黑色的,alpha 为零。这就是出血来自。但我不能留在 NEAREST,因为我使用平滑的 mipmapping
  • 好吧,我可能应该更加强调答案。有两种情况会发生出血。一个在纹理的边缘(由夹具固定),另一个靠近像素,alpha 为零。该工具的出血边缘模式解决了后一个问题。
  • @MichaelIV 效果如何?你试过了吗?
  • @MichaelIV 好吧,我有时会忘记有这样的事情(当你坐在电脑旁时,你似乎也是如此)。周末愉快。
【解决方案2】:

对我来说,这会生成一个仅包含 0 和 100% alpha 的 out.png,使用 当前的 ImageMagick(版本 6.8.9-0):

convert in.jpg -alpha set -bordercolor none -border 25x25 png32:out.png

【讨论】:

  • 正是,这就是问题所在。当这些 (o,o,o,o) 像素用可见像素进行插值时,它们会添加到最终颜色黑色。
  • 如果您之后要重新缩放 PNG,那将无济于事。它是最后一个零(alpha 值),它使用来自相邻像素的 alpha 值 (1) 进行插值,这发生在 OPENGL 中。要使用 ImageMagick“修复”PNG,您需要知道您计划合成它的颜色并使用该颜色,但要透明(例如,#ffff0000 表示透明黄色)。
猜你喜欢
  • 2012-06-25
  • 2020-04-14
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 2013-03-20
相关资源
最近更新 更多