writing 48/64 bit PNGs?

Andrew Randrianasulu <[email protected]> Fri, 27 Mar 2020 05:58:29 +0300
Newsgroups gmane.comp.graphics.png.devel
Message-ID <[email protected]>
Hello!

I'm trying to implement 16 bits per channel PNG writing.

I use this software (video editor/compositor)
https://git.cinelerra-gg.org/git/?p=goodguy/cinelerra.git;a=blob;f=cinelerra-5.1/cinelerra/filepng.C;h=3b28e0eac5fa145ee8c99b7adc21cf4c9b688d6f;hb=HEAD

well, actually in this form 64 bit PNGs are broken.

If I add small patch adding png_set_swap - it works!

Still, there is something strange:
depend on OS I tested  my changes with, place where I must put this call 
for fixing broken PNG was different!

On 64-bit Ubuntu 18.04.4:

diff --git a/cinelerra-5.1/cinelerra/filepng.C b/cinelerra-5.1/cinelerra/filepng.C
index 3b28e0ea..2d1f3fbd 100644
--- a/cinelerra-5.1/cinelerra/filepng.C
+++ b/cinelerra-5.1/cinelerra/filepng.C
@@ -228,6 +228,8 @@ int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
                        png_set_IHDR(png_ptr, info_ptr, asset->width, asset->height, asset->png_depth,
                                asset->png_use_alpha ?  PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
                                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+                       if( asset->png_depth == 16 && BC_Resources::little_endian )
+                       png_set_swap(png_ptr);
                        png_write_info(png_ptr, info_ptr);
                        png_write_image(png_ptr, output_frame->get_rows());
                        png_write_end(png_ptr, info_ptr);

in other words png_set_swap BEFORE png_write_info/png_write_image 

On my 32-bit Slackware system I must place this call AFTER png_write_info:

diff --git a/cinelerra-5.1/cinelerra/filepng.C b/cinelerra-5.1/cinelerra/filepng.C
index 3b28e0ea..1e380e61 100644
--- a/cinelerra-5.1/cinelerra/filepng.C
+++ b/cinelerra-5.1/cinelerra/filepng.C
@@ -228,7 +228,11 @@ int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
                        png_set_IHDR(png_ptr, info_ptr, asset->width, asset->height, asset->png_depth,
                                asset->png_use_alpha ?  PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
                                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+                       if( asset->png_depth == 16 && BC_Resources::little_endian )
+                       png_set_swap(png_ptr);
                        png_write_info(png_ptr, info_ptr);
+                       if( asset->png_depth == 16 && BC_Resources::little_endian )
+                       png_set_swap(png_ptr);
                        png_write_image(png_ptr, output_frame->get_rows());
                        png_write_end(png_ptr, info_ptr);
                        result = 0;

I found this ..strange. On Slackware I have libpng 1.6.37. (but also 1.4.15)

On Ubuntu ....
1.6.34

Ubuntu version I tested, under qemu:
http://mirror.yandex.ru/ubuntu-cdimage/xubuntu/releases/18.04/release/
xubuntu-18.04.4-desktop-amd64.iso

As far as I can see this call is required, yet depend  on system/libpng version  exact
place to put it may wary, or this is a bug?

I used GIMP source as my reference:
https://github.com/GNOME/gimp/blob/mainline/plug-ins/common/file-png.c