JPEG到透明PNG会导致黑色出血

时间:2014-05-01 08:49:10

标签: opengl image-processing imagemagick png jpeg

我需要执行以下操作:我有一个标准的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混合。

enter image description here

黑色边缘是原始JPEG图像的一部分结束的地方(可见边缘周围还有10个像素的透明边框),这意味着ImageMagic产生的图像可能是预乘的,这不是我想要的。我需要它就像Photoshop一样以非预期的方式导出PNG图像。这样我就可以摆脱黑色边框的神器。

如果我使用GL_LINEAR或GL_LINEAR_MIPMAP_LINEAR等线性插值,就会出现流血现象。许多消息来源也说明这种出血是相邻像素线性插值的结果。

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

2 个答案:

答案 0 :(得分:1)

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

关于OpenGL的几点说明。边缘的出血可能只有1个像素宽,并且是由重复纹理应用引起的。您可以通过将钳制模式设置为GL_LINEAR来使用GL_LINEAR_MIPMAP_LINEARGL_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的任何内容都不会对其下的像素产生任何影响。然而,插值可能导致具有零α的黑色像素出血到具有100%α的图像的第一像素,从而产生薄的黑色边界。要摆脱这种情况,有必要将原始图像边缘的颜色复制到边框并设置为零alpha。

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

答案 1 :(得分:0)

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

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