Fix PNG encoding on Linux: bundled libpng headers must win over GTK3's system libpng16 - #114
Merged
slajerek merged 1 commit intoAug 4, 2026
Conversation
The binary statically links the bundled libpng 1.5.2 from MTEngineSDL, but pkg_check_modules(GTK3) adds -I/usr/include/libpng16 to the include path before the bundled directory, so png.h resolves to the system 1.6.x header. That makes png_create_write_struct() receive PNG_LIBPNG_VER_STRING "1.6.48", fail its version handshake against the 1.5.2 implementation and return NULL. Effect on Linux: c64/screen/snapshot and c64/screen/save always answered HTTP 500, and the same dead call sits in vice/gfxoutputdrv/pngdrv.c. macOS and Windows are unaffected -- they have no GTK3 in the include path. Also split the single 'Screen image not available or PNG encoding failed' string, which merged five distinct failures into one message with no log entry, into per-cause messages with LOGError. Verified on Debian 13: screen/snapshot now returns a 384x272 PNG.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Linux,
c64/screen/snapshotandc64/screen/savealways answer HTTP 500 with{"error":"Screen image not available or PNG encoding failed"}, in every machine state.The same applies to the
atari800/*andnes/*variants.Cause
It is not the screen image -- that part works. It is a libpng version handshake failure.
src/Remote/CDebuggerServerApi.cppincludespng.h, and on Linux that resolves to thesystem header, because
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)puts-I/usr/include/libpng16into the include path before the bundled libpng directory(
CMakeLists.txt:32-33vs:92; in the generatedflags.makethey land at position 8 and 72).The binary, however, links the bundled libpng 1.5.2 from MTEngineSDL statically:
So the call site passes
PNG_LIBPNG_VER_STRING="1.6.48"into an implementation thatidentifies itself as
"1.5.2".png_create_write_struct()compares the version(
pngwrite.c:523-525), refuses and returns NULL, and the lambda exits atif (!png_ptr) return {};-- which the endpoints translate into HTTP 500.Measured on the running process:
The only difference is the version string. Breakpoints confirmed the exit point: line 1102
is hit, none of the later PNG calls are.
This is Linux-only -- macOS and Windows have no GTK3 in the include path, so the bundled
header wins there and everything works. That is likely why it went unnoticed.
Fix
One line in
CMakeLists.txt: add the bundled libpng directory withBEFORE, so the headermatches the implementation that is actually linked. That also revives
src/Emulators/vice/gfxoutputdrv/pngdrv.c, which has the same dead call today.I checked the PNG API used across the repo (
png_create_write_struct,png_set_IHDR,png_set_PLTE,png_write_*,png_jmpbuf) -- all of it exists in 1.5.2, so compiling againstthe older header is safe.
The second commit part splits the error message. One
ifchain merged five distinct causes(no image, no pixel data, zero width, zero height, encoder init failure, libpng longjmp) into a
single string, and no branch logged anything -- with
GLOBAL_DEBUG_OFFthe log stays empty, sodiagnosing this needed a debugger. Each cause now has its own message and a
LOGError.Verification
Debian 13, GCC 14, same binary before/after:
c64/screen/snapshotc64/screen/save\x89PNG\r\n\x1a\nNote on MTEngineSDL
CImageData::Save()has the same defect for the same reason (its own build has the sameinclude order), so the GUI's "Save screenshot as PNG" is dead on Linux too -- silently, since
it only calls
LOGError. I have not touched MTEngineSDL, as AGENTS.md asks. It needs the sameone-line change; happy to send it if you want.