gbdev / rgbds

Rednex Game Boy Development System - An assembly toolchain for the Nintendo Game Boy and Game Boy Color

Home Page:https://rgbds.gbdev.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

cursor.png

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 the PLTE 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. The tRNS chunk shall not contain more alpha values than there are palette entries, but a tRNS 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-byte tRNS chunk is needed, and when all palette indices are opaque, the tRNS chunk may be omitted.