Вопрос

I need to do the following : I have a standard JPEG image as input.What I need to do is to convert it to PNG 32bit(alpha transparency) and set a transparent border of some amount of pixels.

I tried to use ImageMagic these commands:

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 

And that's the result after I am using this image in OpenGL program which premultiplies it on the output as there is a need for alpha blending.

enter image description here

The black edge is where the part of original JPEG image ends(there is also 10 pixels transparent border around the visible edge) and it means that the image resulting from the ImageMagic is probably premultiplied which is not what I want.I need it to be unremultiplied just like Photoshop exports PNG images in unpremultiplied state.This way I can get rid from the black border artifacts.

The bleeding happens if I use linear interpolation like GL_LINEAR or GL_LINEAR_MIPMAP_LINEAR.It is also stated in many sources that this bleeding is the result of linear interpolation of neighbor pixels.

Strangely.If I do such a setup in Photoshop,that's,dropping JPG into transparent canvas and then saving it to PNG24 with transparency channel then the bleeding is gone.Also,if I drop the resulting PNG from the above mentioned ImageMagic process and re-save it with Photoshop then it gets fixed as well.I can't use Photoshop as I need a command line tool like ImageMagic to create those images.I could also use something customized via C++ code,but I currently have no idea how to get rid of that black edge.

Это было полезно?

Решение

You can try to use this C++ command-line tool. There is a precompiled windows binary and an example of a modified image. It does not do anything with the image, it just sets zero alpha border around it (no premultiplication). To build this you need libjpeg and libpng (you can get x86 / x64 prebuilt windws libs here).

A couple of notes about OpenGL. The bleeding of the edges can be only up to 1 pixel wide and is caused by repetitive texture application. You can remove it even if using GL_LINEAR or GL_LINEAR_MIPMAP_LINEAR mode by setting clamp mode to 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);

In case you are not using GL_TEXTURE_2D, you need to replace that with whatever you are using. The bleeding is kind of suspicious, and may be also related to the RGB color that is in the regions that have zero alpha. The correct way to set up the blending mode is:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This way anything that is with zero alpha does not have any influence on the pixels under it. However, the interpolation may cause bleeding of the black pixels with zero alpha to the first pixel of the image with 100% alpha, yielding a thin black border. To get rid of that, it is necessary to replicate the color of the edge of the original image to the border and set zero alpha.

To do that, define __BLEED_EDGE when compiling, or use the precompiled AddTransparentBorder_BleedEdge version. There is also an example of an image with the edges duplicated. You can try to use those examples first and see if the black edge occurs.

Другие советы

For me, this produces an out.png that contains only 0 and 100% alphas, using the current ImageMagick (which is version 6.8.9-0):

convert in.jpg -alpha set -bordercolor none -border 25x25 png32:out.png
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top