pnggroup / libpng

LIBPNG: Portable Network Graphics support, official libpng repository
http://libpng.sf.net
Other
1.26k stars 613 forks source link

Preserve Pixels that RGB != 0 but Alpha = 0 #425

Open zhoub opened 2 years ago

zhoub commented 2 years ago

Hi,

we're counting an issue about how to preserve the RGB isn't black but its alpha=0.

Here is the example C code

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

int width = 128, height = 128;
png_byte color_type = PNG_COLOR_TYPE_RGBA;
png_byte bit_depth = 8;
png_byte *pixels = NULL;

void write_png_file(char *filename) {
  int y;

  FILE *fp = fopen(filename, "wb");
  if(!fp) abort();

  png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png) abort();

  png_infop info = png_create_info_struct(png);
  if (!info) abort();

  if (setjmp(png_jmpbuf(png))) abort();

  png_init_io(png, fp);

  // Output is 8bit depth, RGBA format.
  png_set_IHDR(
    png,
    info,
    width, height,
    8,
    PNG_COLOR_TYPE_RGBA,
    PNG_INTERLACE_NONE,
    PNG_COMPRESSION_TYPE_DEFAULT,
    PNG_FILTER_TYPE_DEFAULT
  );
  png_write_info(png, info);

  // To remove the alpha channel for PNG_COLOR_TYPE_RGB format,
  // Use png_set_filler().
  //png_set_filler(png, 0, PNG_FILLER_AFTER);

  for (int y = 0; y < height; y++)
    png_write_row(png, pixels + y * width * 4);
  png_write_end(png, NULL);

  png_write_end(png, info);

  fclose(fp);
}

int main(int argc, char *argv[]) {
  pixels = malloc(4 * width * height);
  for (int y = 0; y < height; y++)
  {
    for (int x = 0; x < width; x++)
    {
      size_t offset = (y * width + x) * 4;
      pixels[offset] = (float)x / (float)width * 255;
      pixels[offset + 1] = (float)y / (float)height * 255;
      pixels[offset + 2] = (float)y / (float)height * 255;
      pixels[offset + 3] = (y < 64 ? 0 : 255);  // <<<<<<<<<<<<<<<<<<<<<<< THIS LINE SETS ALPHA <<<<<<<<<<<<<<<<
    }
  }
  write_png_file("test.png");
  free(pixels);

  return 0;
}

The example code to generate a gradient .png file, the problem is the alpha data, if that's 0, the RGB color was removed. Is there any API to keep the raw data as it should be ? We wants to generate a PNG file with pixels that RGB != 0 but Alpha = 0.

Thanks a lot.

landfillbaby commented 2 years ago

what libpng version are you using? 1.6.37 doesn't change pixels at all for me

zhoub commented 2 years ago

Interesting, I'm using 1.6.37 too on OSX.

clang -I/usr/local/Cellar/libpng/1.6.37/include -L/usr/local/Cellar/libpng/1.6.37/lib -lpng16 test.c

test

As you can see the up part is blank, which isn't what I want, it should be colorful, but alpha=0.

landfillbaby commented 2 years ago

i downloaded it and inspected it. the colour info is there. are you maybe confused about what alpha is? alpha 0 means it's 100% transparent.

zhoub commented 2 years ago
image

By Krita, the up part color is gone.

But TIFF format supports RGB has color but Alpha = 0, so background color was preserved(alpha = 0) by EXTRASAMPLE_UNASSALPHA.

What I would like to is if PNG support the unassociated alpha mode as TIFF EXTRASAMPLE_UNASSALPHA ?

https://www.awaresystems.be/imaging/tiff/tifftags/extrasamples.html

Thanks a lot.