Segfault in RGBGFX given a transparent+3-color PNG
Rangi42 opened this issue · comments
As reported by @rondnelson99:
It seems like if I use alpha, it [GIMP] seems to work fine but then once exported, it adds an additional color to the colormap at index 0, which is used for transparent pixels, shifting all other colormap entries over by one
I tried to compensate for this behaviour by only putting three colors in the colormap (so GIMP would add the fourth on export) but the resulting image makes RGBGFX segfault
That was the image, and I was running the tool with
rgbgfx --columns -o res/cursor.spritetiles src/res/cursor.png
tbh I wouldn't even be too suprised if the png is malformed though. The color assignments in the final image doesn't match what GIMP showed before exporting. The interior or the arrow is supposed to be white, not transparent
Testing confirms this to occur on master:
$ ./rgbgfx -V
rgbgfx v0.6.1-119-g528a4c0b
$ file cursor.png
cursor.png: PNG image data, 48 x 48, 2-bit colormap, non-interlaced
$ sha1sum cursor.png
391537423e8c404ad715aa91fd96f0ca366e6a1e cursor.png
$ ./rgbgfx -Z -o cursor.2bpp cursor.png
Segmentation fault (core dumped)
Being more verbose is more informative:
$ ./rgbgfx -vvvvv -Z -o cursor.2bpp cursor.png
rgbgfx v0.6.1-119-g528a4c0b
Options:
Visit image in column-major order
Bit depth: 2bpp
Maximum 8 palettes
Palettes contain 4 colors
No palette spec
Input image slice: 0x0 pixels starting at (0, 0)
Base tile IDs: [0, 0]
Maximum 65535 tiles in bank 0, 0 in bank 1
Input image: cursor.png
Output tile data: cursor.2bpp
Ready.
Using libpng 1.6.37
Reading tiles...
Opened input file
PNG header signature is OK
Input image: 48x48 pixels, 2bpp palette, not interlaced
rgbgfx: src/gfx/process.cpp:262: Png: Assertion `nbTransparentEntries == nbColors' failed.
Aborted (core dumped)
This is the assertion being violated:
if (png_get_PLTE(png, info, &embeddedPal, &nbColors) != 0) {
int nbTransparentEntries;
if (png_get_tRNS(png, info, &transparencyPal, &nbTransparentEntries, nullptr)) {
assert(nbTransparentEntries == nbColors);
}
https://www.nayuki.io/page/png-file-chunk-inspector reports this from the chunk data:
- The
IHDR
chunk defines color type 3, an indexed palette - The
PLTE
chunk defines 4 colors:#000000
,#346856
,#88C070
, and#E0F8D0
. - The
tRNS
chunk defines 1 alpha value:$00
This is valid:
For colour type 3 (indexed-colour), the
tRNS
chunk contains a series of one-byte alpha values, corresponding to entries in thePLTE
chunk. Each entry indicates that pixels of the corresponding palette index shall be treated as having the specified alpha value. Alpha values have the same interpretation as in an 8-bit full alpha channel: 0 is fully transparent, 255 is fully opaque, regardless of image bit depth. ThetRNS
chunk shall not contain more alpha values than there are palette entries, but atRNS
chunk may contain fewer values than there are palette entries. In this case, the alpha value for all remaining palette entries is assumed to be 255. In the common case in which only palette index 0 need be made transparent, only a one-bytetRNS
chunk is needed, and when all palette indices are opaque, thetRNS
chunk may be omitted.