Libpng, Palette Png with Alpha or Not

Libpng, Palette png with alpha or not?

PNG supports transparency in two (or three) quite different ways:

  1. Truecolor or grayscale images with a separated alpha channel (RGBA or GA)

  2. Transparency extra info in the (optional) tRNS chunk . Which has two different flavors:

    2a. For indexed images: the tRNS chunk specifies a transparency value ("alpha") for one, several or all the palette indexes.

    2b. For truecolor or grayscale images: the tRNS chunk specifies a single color value (RGB or Gray) that should be considered as fully transparent.

If you are interested in case 2a, and if you are using libpng, you should look at the function png_get_tRNS()

How to set libpng background transparency with palettes?

Hmm, my setup code to do this is pretty similar to yours. I write the image row at a time with png_write_row, but it should be much the same with png_write_image.

#include <stdio.h>
#include <stdlib.h>
#include <png.h>

int main(){
png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

if (!png_ptr) {
exit (EXIT_FAILURE);
}

png_infop info_ptr = png_create_info_struct(png_ptr);

if (!info_ptr) {
png_destroy_write_struct(&png_ptr, NULL);
exit (EXIT_FAILURE);
}

if(setjmp(png_jmpbuf(png_ptr))){
printf ("PNG error\n");
exit(EXIT_FAILURE);
}

FILE * fp = fopen("foo.png", "wb");
if(fp==NULL){
perror("opening output file");
exit (EXIT_FAILURE);
}
png_init_io(png_ptr, fp);

int width=100, height=100;

png_set_IHDR(png_ptr,
info_ptr,
width,
height,
8, // bit_depth,
PNG_COLOR_TYPE_PALETTE,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);

png_color palette[] = {
{0,0,0}, {100,0,0}
};

png_set_PLTE(png_ptr, info_ptr, palette, 2);

png_byte trans[] = {255, 128}; // entry 0 opaque, entry 1 half alpha
png_set_tRNS(png_ptr, info_ptr, trans, 2, NULL);

png_write_info(png_ptr, info_ptr);

// write the image data, row by row
for (int y=0; y<height; y++) {
png_byte row[width];

for (int x = 0; x < width; x++){
row[x] = ((50-x)*(50-x) + (50-y)*(50-y)) < (50*50); // circle
}

png_write_row(png_ptr, row);
}

png_write_end(png_ptr, NULL);

png_destroy_write_struct(&png_ptr, &info_ptr);

png_free(png_ptr, palette);
return 0;
}

Note that, just for my debugging, palette[1] (the non transparent entry), is set to red-ish. It sounds like you'd set it to black for your purpose.

How to set a pixel as transparent for 8-bit pngs when encoding with libpng?

To mark some palette index(es) as transparent, you must create a tRNS chunk.
In libpng, I guess you must use the function png_set_tRNS()

Alpha transparency in indexed-png images

I've finally found the actual answer: There is a metadata entry that allows you to define the alpha value of each colour in the colour table. Most graphics programs don't make use of this, but it does exist and can be used, in particular by GD.

Can a PNG image that is entirely opaque contain an alpha channel?

  1. Yes. Just like an RGB image may contain only data in the Red channel and not in Green and Blue; "unused" channels are not a problem. Alpha is a separate channel of its own, and in particular, its values should be independent of the associated pixel colors: "PNG does not use premultiplied alpha" (6.2 Alpha representation).

    Also see 12.4 Alpha channel creation in the official specifications for some additional details:

    The alpha channel can be regarded either as a mask that temporarily hides transparent parts of the image, or as a means for constructing a non-rectangular image. In the first case, the colour values of fully transparent pixels should be preserved for future use. In the second case, the transparent pixels carry no useful data and are simply there to fill out the rectangular image area required by PNG. In this case, fully transparent pixels should all be assigned the same colour value for best compression.

  2. Because they don't need to, per that same specification:

    ... PNG provides a patent-free replacement for GIF and can also replace many common uses of TIFF. Indexed-color, grayscale, and truecolor images are supported, plus an optional alpha channel. (my emphasis)

What are this properties in libjpeg and in libpng?

So first what are the possibilities of pixel size (info.output_components;) ?

From the doc

output_components is 1 (a colormap index) when quantizing colors; otherwise it
equals out_color_components. It is the number of JSAMPLE values that will be
emitted per pixel in the output arrays.

  int out_color_components;     /* # of color components in out_color_space */
int output_components; /* # of color components returned */
/* output_components is 1 (a colormap index) when quantizing colors;
* otherwise it equals out_color_components.

What are the possibilities of color space (info.out_color_space;) ?

From the source

  JCS_UNKNOWN,            /* error/unspecified */
JCS_GRAYSCALE, /* monochrome */
JCS_RGB, /* red/green/blue as specified by the RGB_RED,
RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */
JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
JCS_CMYK, /* C/M/Y/K */
JCS_YCCK, /* Y/Cb/Cr/K */
JCS_EXT_RGB, /* red/green/blue */
JCS_EXT_RGBX, /* red/green/blue/x */
JCS_EXT_BGR, /* blue/green/red */
JCS_EXT_BGRX, /* blue/green/red/x */
JCS_EXT_XBGR, /* x/blue/green/red */
JCS_EXT_XRGB, /* x/red/green/blue */
/* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR,
or JCS_EXT_XRGB during decompression, the X byte is undefined, and in
order to ensure the best performance, libjpeg-turbo can set that byte to
whatever value it wishes. Use the following colorspace constants to
ensure that the X byte is set to 0xFF, so that it can be interpreted as an
opaque alpha channel. */
JCS_EXT_RGBA, /* red/green/blue/alpha */
JCS_EXT_BGRA, /* blue/green/red/alpha */
JCS_EXT_ABGR, /* alpha/blue/green/red */
JCS_EXT_ARGB, /* alpha/red/green/blue */
JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue */

And can a JPEG image have an alpha channel ?

As you can see from the source code above, libjpeg-turbo does support alpha channel for jpegs.



So first what is the bit depth (png_get_bit_depth(png, info);) ?

Simply put, number of bits used to represent each pixel in an image. The higher the bit depth, the more colors each pixel can contain.

From the PNG Spec:

Color type is a single-byte integer that describes the interpretation of the image data. Color type codes represent sums of the following values: 1 (palette used), 2 (color used), and 4 (alpha channel used). Valid values are 0, 2, 3, 4, and 6.

  Color    Allowed    Interpretation
Type Bit Depths

0 1,2,4,8,16 Each pixel is a grayscale sample.

2 8,16 Each pixel is an R,G,B triple.

3 1,2,4,8 Each pixel is a palette index;
a PLTE chunk must appear.

4 8,16 Each pixel is a grayscale sample,
followed by an alpha sample.

6 8,16 Each pixel is an R,G,B triple,
followed by an alpha sample.


Related Topics



Leave a reply



Submit