[Cin] Writing 16-bit per component png?

Andrew Randrianasulu randrianasulu at gmail.com
Mon Mar 16 18:52:27 CET 2020


Probably stupid misuse of libpng api on my side ...

I tried to add support for writing 16 bit per component PNGs into Cin.

int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
{
 PNGUnit *png_unit = (PNGUnit*)unit;
 png_structp png_ptr = 0;
 png_infop info_ptr = 0;
 VFrame *output_frame;
 int result = 1;
 int is_float = (frame->get_color_model() == BC_RGBA_FLOAT || frame->get_color_model() == BC_RGB_FLOAT);

==== here I try to get idea if project's colormodel actually *-FLOAT or not ====
 
 data->set_compressed_size(0);
//printf("FilePNG::write_frame 1\n");
 native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888;
 if (is_float)
 native_cmodel = asset->png_use_alpha ? BC_RGBA16161616 : BC_RGB161616;

=== here I try to set native_colormodel to wide-channel integer format, if input was FP ====
 
 if(frame->get_color_model() != native_cmodel)
 {
  if(!png_unit->temp_frame) png_unit->temp_frame =
   new VFrame(asset->width, asset->height, native_cmodel, 0);

  png_unit->temp_frame->transfer_from(frame);
  output_frame = png_unit->temp_frame;
 }
 else
  output_frame = frame;

//printf("FilePNG::write_frame 1\n");
 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
 if( png_ptr ) {
  if( !setjmp(png_jmpbuf(png_ptr)) ) {
   info_ptr = png_create_info_struct(png_ptr);
   png_set_write_fn(png_ptr, data,
    (png_rw_ptr)write_function, (png_flush_ptr)flush_function);
   png_set_compression_level(png_ptr, asset->png_compression);

   png_set_IHDR(png_ptr, info_ptr, asset->width, asset->height, is_float ? 16 : 8,
    asset->png_use_alpha ?  PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
    PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

==== here I try to call libpng with different bit depth depending on is_float ======

   png_write_info(png_ptr, info_ptr);
   png_write_image(png_ptr, output_frame->get_rows());
   png_write_end(png_ptr, info_ptr);
   result = 0;
  }
  png_destroy_write_struct(&png_ptr, &info_ptr);
 }
 if( result ) {
  char error[256];  png_error(png_ptr, error);
  fprintf(stderr, "FilePNG::write_frame failed: %s\n", error);
 }
//printf("FilePNG::write_frame 3 %d\n", data->get_compressed_size());
 return result;
}

I also modified 


int FilePNG::get_best_colormodel(Asset *asset, int driver)
{
 if(asset->png_use_alpha)
  //return BC_RGBA8888;
  return BC_RGBA16161616;
 else
  //return BC_RGB888;
  return BC_RGB161616;
}

but probably those changes alone not enough, I get wrong colors or 
completely transparent picture in resulted png ?


More information about the Cin mailing list