[Cin] UPD: Writing 16-bit per component png?

Andrew Randrianasulu randrianasulu at gmail.com
Mon Mar 16 20:45:52 CET 2020


Oh, I was setting functions in wrong order:


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);
        
        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;
        
        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);
                        png_write_info(png_ptr, info_ptr);
                        if(is_float)
                        png_set_swap(png_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;
}
 
hint found via

https://github.com/GNOME/gimp/blob/mainline/plug-ins/common/file-png.c

png_set_swap  must come AFTER png_write_info!



----------  Пересланное сообщение  ----------

Тема: Writing 16-bit per component png?
Дата: Понедельник 16 марта 2020
Отправитель: Andrew Randrianasulu <randrianasulu at gmail.com>
Получатель:  "Cinelerra.GG" <cin at lists.cinelerra-gg.org>

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