Binary Suggested Palette Decoding for PNGs

Started by blue-j, April 07, 2024, 03:32:26 PM

Previous topic - Next topic

blue-j

this config:

        sPLT => {
            Name => 'SuggestedPalette',
            ValueConv => q{
                my @values = unpack('C*',$val);

                # Identify the position of the null character that separates the palette name from the data.
                my $null_pos = 0;
                ++$null_pos until $values[$null_pos] == 0 || $null_pos > $#values;

                # Extract the palette name using the bytes up to the null position.
                my $palette_name = pack('C*', @values[0..$null_pos-1]);
                $palette_name = unpack("A*", $palette_name);

                # Sample depth is the byte immediately following the null separator.
                my $sample_depth = $values[$null_pos + 1];

                # Determine the size of each entry based on the sample depth.
                my $entry_size = $sample_depth == 8 ? 6 : 10;
                my @entries;

                # Process each palette entry based on the determined entry size.
                for (my $i = $null_pos + 2; $i <= $#values; $i += $entry_size) {
                    my ($r, $g, $b, $a, $frequency);
                    if ($sample_depth == 8) {
                        # For 8-bit sample depth, directly assign the values.
                        ($r, $g, $b, $a, $frequency) = @values[$i..$i+5];
                        $frequency = ($frequency << 8) | $values[$i+5]; # Correcting frequency assignment for 8-bit depth
                    } else {
                        # For 16-bit sample depth, combine each pair of bytes to form 16-bit values.
                        $r = ($values[$i] << 8) | $values[$i+1];
                        $g = ($values[$i+2] << 8) | $values[$i+3];
                        $b = ($values[$i+4] << 8) | $values[$i+5];
                        $a = ($values[$i+6] << 8) | $values[$i+7];
                        $frequency = ($values[$i+8] << 8) | $values[$i+9];
                    }

                    # Add the processed entry to the list of entries.
                    push @entries, { R => $r, G => $g, B => $b, A => $a, Frequency => $frequency };
                }

                # Convert the collected data to JSON.
                my $json = JSON->new->utf8->pretty(0)->encode({
                    PaletteName => $palette_name,
                    SampleDepth => $sample_depth,
                    Entries => \@entries,
                });

                return $json;
            },
        },

simply will not emit 16 bit values, no matter what i do?  anyone see my gaffe?  test file attached (official PNG test file)

- J

blue-j

I checked the output against pngcheck 3.0.3's, and it reconciles.  the PNG spec does permit 16 bit values, but apparently when print converting the convention is to emit 8 bit values...

- J