/* pnggetset.c * * Copyright (c) 2026 Cosmin Truta * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h * * Test getter and setter correctness. */ #include #include #include #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) # include #endif #ifdef PNG_FREESTANDING_TESTS # include #else # include "../../png.h" #endif /* Test: get the PLTE, pass it straight back to set, verify roundtrip. */ static int test_plte_roundtrip(void) { png_structp png_ptr; png_infop info_ptr; png_color palette[4]; png_colorp got_palette = NULL; int num_palette = 0; int i; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_plte_roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* Set up a palette-color image header. */ png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Populate with recognizable values. */ for (i = 0; i < 4; i++) { palette[i].red = (png_byte)(i * 10); palette[i].green = (png_byte)(i * 20); palette[i].blue = (png_byte)(i * 30); } png_set_PLTE(png_ptr, info_ptr, palette, 4); /* Get the internal pointer and feed it straight back. */ png_get_PLTE(png_ptr, info_ptr, &got_palette, &num_palette); if (got_palette == NULL || num_palette != 4) { fprintf(stderr, "pnggetset: png_get_PLTE returned unexpected values\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* This is the critical call: the pointer aliases info_ptr->palette. */ png_set_PLTE(png_ptr, info_ptr, got_palette, num_palette); /* Verify the data survived the roundtrip. */ got_palette = NULL; num_palette = 0; png_get_PLTE(png_ptr, info_ptr, &got_palette, &num_palette); if (got_palette == NULL || num_palette != 4) { fprintf(stderr, "pnggetset: PLTE lost after roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } for (i = 0; i < 4; i++) { if ((got_palette[i].red != (png_byte)(i * 10)) || (got_palette[i].green != (png_byte)(i * 20)) || (got_palette[i].blue != (png_byte)(i * 30))) { fprintf(stderr, "pnggetset: PLTE entry %d corrupted after roundtrip\n", i); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } } png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } #ifdef PNG_hIST_SUPPORTED /* Test: get the hIST, pass it straight back to set, verify roundtrip. */ static int test_hist_roundtrip(void) { png_structp png_ptr; png_infop info_ptr; png_color palette[4]; png_uint_16 hist[4]; png_uint_16p got_hist = NULL; int i; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_hist_roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* Set up a palette-color image header. */ memset(palette, 0, sizeof palette); png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_PLTE(png_ptr, info_ptr, palette, 4); /* Populate with recognizable values. */ for (i = 0; i < 4; i++) hist[i] = (png_uint_16)(i * 100 + 42); png_set_hIST(png_ptr, info_ptr, hist); /* Get the internal pointer and feed it straight back. */ if (png_get_hIST(png_ptr, info_ptr, &got_hist) == 0 || got_hist == NULL) { fprintf(stderr, "pnggetset: png_get_hIST returned unexpected values\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* This is the critical call: the pointer aliases info_ptr->hist. */ png_set_hIST(png_ptr, info_ptr, got_hist); /* Verify the data survived the roundtrip. */ got_hist = NULL; if (png_get_hIST(png_ptr, info_ptr, &got_hist) == 0 || got_hist == NULL) { fprintf(stderr, "pnggetset: hIST lost after roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } for (i = 0; i < 4; i++) { if (got_hist[i] != (png_uint_16)(i * 100 + 42)) { fprintf(stderr, "pnggetset: hIST entry %d corrupted after roundtrip\n", i); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } } png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } #endif /* PNG_hIST_SUPPORTED */ #ifdef PNG_tRNS_SUPPORTED /* Test: get the tRNS, pass it straight back to set, verify roundtrip. */ static int test_trns_roundtrip(void) { png_structp png_ptr; png_infop info_ptr; png_color palette[4]; png_byte trans_alpha[4]; png_color_16 trans_color; png_bytep got_alpha = NULL; png_color_16p got_color = NULL; int num_trans = 0; int i; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_trns_roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* Set up a palette-color image. */ memset(palette, 0, sizeof palette); png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_PLTE(png_ptr, info_ptr, palette, 4); /* Populate tRNS with recognizable values. */ for (i = 0; i < 4; i++) trans_alpha[i] = (png_byte)(0xff - i * 0x11); memset(&trans_color, 0, sizeof trans_color); png_set_tRNS(png_ptr, info_ptr, trans_alpha, 4, &trans_color); /* Get the internal pointer and feed it straight back. */ png_get_tRNS(png_ptr, info_ptr, &got_alpha, &num_trans, &got_color); if (got_alpha == NULL || num_trans != 4) { fprintf(stderr, "pnggetset: png_get_tRNS returned unexpected values\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* This is the critical call: the pointer aliases info_ptr->trans_alpha. */ png_set_tRNS(png_ptr, info_ptr, got_alpha, num_trans, got_color); /* Verify the data survived the roundtrip. */ got_alpha = NULL; num_trans = 0; png_get_tRNS(png_ptr, info_ptr, &got_alpha, &num_trans, &got_color); if (got_alpha == NULL || num_trans != 4) { fprintf(stderr, "pnggetset: tRNS lost after roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } for (i = 0; i < 4; i++) { if (got_alpha[i] != (png_byte)(0xff - i * 0x11)) { fprintf(stderr, "pnggetset: tRNS entry %d corrupted after roundtrip\n", i); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } } png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } #endif /* PNG_tRNS_SUPPORTED */ #ifdef PNG_TEXT_SUPPORTED /* Test: get the text array, pass it straight back to set, verify data. */ #define TEXT_COUNT 6 /* enough to trigger reallocation on the second set */ static int test_text_roundtrip(void) { png_structp png_ptr; png_infop info_ptr; png_text text_entries[TEXT_COUNT]; png_textp got_text = NULL; int got_num_text = 0; int i; /* Recognizable keys and values. */ static const char *keys[TEXT_COUNT] = { "Title", "Author", "Desc", "Copyright", "Source", "Comment" }; static const char *vals[TEXT_COUNT] = { "t0", "t1", "t2", "t3", "t4", "t5" }; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_text_roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* Populate the text entries. */ memset(text_entries, 0, sizeof text_entries); for (i = 0; i < TEXT_COUNT; i++) { text_entries[i].compression = PNG_TEXT_COMPRESSION_NONE; text_entries[i].key = (png_charp)keys[i]; text_entries[i].text = (png_charp)vals[i]; } png_set_text(png_ptr, info_ptr, text_entries, TEXT_COUNT); /* Get the internal pointer and feed it straight back (append). */ png_get_text(png_ptr, info_ptr, &got_text, &got_num_text); if (got_text == NULL || got_num_text != TEXT_COUNT) { fprintf(stderr, "pnggetset: png_get_text returned unexpected values\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* This is the critical call: got_text aliases info_ptr->text. */ png_set_text(png_ptr, info_ptr, got_text, got_num_text); /* Verify the original entries survived. */ got_text = NULL; got_num_text = 0; png_get_text(png_ptr, info_ptr, &got_text, &got_num_text); if (got_text == NULL || got_num_text != TEXT_COUNT * 2) { fprintf(stderr, "pnggetset: text count %d, expected %d after roundtrip\n", got_num_text, TEXT_COUNT * 2); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } for (i = 0; i < TEXT_COUNT; i++) { if (got_text[i].key == NULL || strcmp(got_text[i].key, keys[i]) != 0 || got_text[i].text == NULL || strcmp(got_text[i].text, vals[i]) != 0) { fprintf(stderr, "pnggetset: text entry %d corrupted after roundtrip\n", i); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } } png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } #undef TEXT_COUNT #endif /* PNG_TEXT_SUPPORTED */ #ifdef PNG_sPLT_SUPPORTED /* Test: get the sPLT array, pass it straight back to set, verify data. */ static int test_splt_roundtrip(void) { png_structp png_ptr; png_infop info_ptr; png_sPLT_t splt; png_sPLT_entry splt_entries[4]; png_sPLT_tp got_spalettes = NULL; int got_num, i; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_splt_roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* Populate with recognizable values. */ memset(splt_entries, 0, sizeof splt_entries); for (i = 0; i < 4; i++) { splt_entries[i].red = (png_uint_16)(i * 1000); splt_entries[i].green = (png_uint_16)(i * 2000); splt_entries[i].blue = (png_uint_16)(i * 3000); splt_entries[i].alpha = 0xffffU; splt_entries[i].frequency = (png_uint_16)(i + 1); } memset(&splt, 0, sizeof splt); splt.name = (png_charp)"test_sPLT"; splt.depth = 16; splt.entries = splt_entries; splt.nentries = 4; png_set_sPLT(png_ptr, info_ptr, &splt, 1); /* Get the internal pointer and feed it straight back (append). */ got_num = png_get_sPLT(png_ptr, info_ptr, &got_spalettes); if (got_spalettes == NULL || got_num != 1) { fprintf(stderr, "pnggetset: png_get_sPLT returned unexpected values\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* This is the critical call: got_spalettes aliases internal storage. */ png_set_sPLT(png_ptr, info_ptr, got_spalettes, got_num); /* Verify the original entry survived. */ got_spalettes = NULL; got_num = png_get_sPLT(png_ptr, info_ptr, &got_spalettes); if (got_spalettes == NULL || got_num != 2) { fprintf(stderr, "pnggetset: sPLT count %d, expected 2 after roundtrip\n", got_num); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } if (strcmp(got_spalettes[0].name, "test_sPLT") != 0 || got_spalettes[0].nentries != 4 || got_spalettes[0].depth != 16) { fprintf(stderr, "pnggetset: sPLT entry 0 corrupted after roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } for (i = 0; i < 4; i++) { if (got_spalettes[0].entries[i].red != (png_uint_16)(i * 1000) || got_spalettes[0].entries[i].green != (png_uint_16)(i * 2000) || got_spalettes[0].entries[i].blue != (png_uint_16)(i * 3000)) { fprintf(stderr, "pnggetset: sPLT[0] entry %d corrupted after roundtrip\n", i); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } } png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } #endif /* PNG_sPLT_SUPPORTED */ #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED /* Test: get unknown chunks, pass them straight back to set, verify data. */ static int test_unknown_roundtrip(void) { png_structp png_ptr; png_infop info_ptr; png_unknown_chunk unk; png_unknown_chunkp got_unknowns = NULL; int got_num; static const png_byte test_data[] = {0xde, 0xad, 0xbe, 0xef}; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_unknown_roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* Set up an unknown chunk with recognizable data. */ memset(&unk, 0, sizeof unk); memcpy(unk.name, "teSt", 5); unk.data = (png_bytep)test_data; unk.size = sizeof test_data; unk.location = PNG_HAVE_IHDR; png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0); png_set_unknown_chunks(png_ptr, info_ptr, &unk, 1); /* Get the internal pointer and feed it straight back (append). */ got_num = png_get_unknown_chunks(png_ptr, info_ptr, &got_unknowns); if (got_unknowns == NULL || got_num != 1) { fprintf(stderr, "pnggetset: png_get_unknown_chunks returned unexpected values\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } /* This is the critical call: got_unknowns aliases internal storage. */ png_set_unknown_chunks(png_ptr, info_ptr, got_unknowns, got_num); /* Verify the original entry survived. */ got_unknowns = NULL; got_num = png_get_unknown_chunks(png_ptr, info_ptr, &got_unknowns); if (got_unknowns == NULL || got_num != 2) { fprintf(stderr, "pnggetset: unknown_chunks count %d, expected 2 after roundtrip\n", got_num); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } if (memcmp(got_unknowns[0].name, "teSt", 4) != 0 || got_unknowns[0].size != sizeof test_data || memcmp(got_unknowns[0].data, test_data, sizeof test_data) != 0) { fprintf(stderr, "pnggetset: unknown chunk 0 corrupted after roundtrip\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } #endif /* PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED */ /* Memory buffer for PNG I/O without temp files. */ #define MEM_BUF_SIZE 4096 typedef struct { png_byte data[MEM_BUF_SIZE]; size_t len; size_t pos; } mem_buf; static void PNGCBAPI mem_write(png_structp png_ptr, png_bytep buf, png_size_t length) { mem_buf *mb = (mem_buf *)png_get_io_ptr(png_ptr); if (mb->len + length > MEM_BUF_SIZE) png_error(png_ptr, "pnggetset: write overflow"); memcpy(mb->data + mb->len, buf, length); mb->len += length; } static void PNGCBAPI mem_flush(png_structp png_ptr) { (void)png_ptr; } static void PNGCBAPI mem_read(png_structp png_ptr, png_bytep buf, png_size_t length) { mem_buf *mb = (mem_buf *)png_get_io_ptr(png_ptr); if (mb->pos + length > mb->len) png_error(png_ptr, "pnggetset: read overflow"); memcpy(buf, mb->data + mb->pos, length); mb->pos += length; } /* Palette sync after gamma correction. * * When info_ptr->palette and png_ptr->palette are separate buffers, * in-place gamma correction of png_ptr->palette must be synced back * to info_ptr->palette so that png_get_PLTE returns the corrected * values. */ #define PLTE_SYNC_NPALETTE 4 static const png_color plte_sync_original[PLTE_SYNC_NPALETTE] = { { 64, 96, 128 }, { 128, 160, 192 }, { 192, 224, 240 }, { 32, 48, 64 } }; static int test_plte_palette_sync(void) { mem_buf buf; png_structp png_ptr; png_infop info_ptr; png_colorp got_palette; int num_palette; double file_gamma; png_byte row[1]; int i; int changed; /* Write a 1x1 palette PNG with gAMA = 1.0 (linear). */ buf.len = 0; buf.pos = 0; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_write_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_write_struct(&png_ptr, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_plte_palette_sync" " (write)\n"); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; } png_set_write_fn(png_ptr, &buf, mem_write, mem_flush); png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_PLTE(png_ptr, info_ptr, (png_colorp)plte_sync_original, PLTE_SYNC_NPALETTE); png_set_gAMA(png_ptr, info_ptr, 1.0); png_write_info(png_ptr, info_ptr); row[0] = 0; png_write_row(png_ptr, row); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); /* Read back with gamma correction as the sole transform. */ buf.pos = 0; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_read_struct failed\n"); return 1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "pnggetset: png_create_info_struct failed\n"); png_destroy_read_struct(&png_ptr, NULL, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pnggetset: libpng error in test_plte_palette_sync" " (read)\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 1; } png_set_read_fn(png_ptr, &buf, mem_read); png_read_info(png_ptr, info_ptr); if (png_get_gAMA(png_ptr, info_ptr, &file_gamma) == 0) { fprintf(stderr, "pnggetset: gAMA chunk not found\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 1; } png_set_gamma(png_ptr, 2.2, file_gamma); png_read_update_info(png_ptr, info_ptr); if (png_get_PLTE(png_ptr, info_ptr, &got_palette, &num_palette) == 0) { fprintf(stderr, "pnggetset: png_get_PLTE failed after update\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 1; } if (num_palette != PLTE_SYNC_NPALETTE) { fprintf(stderr, "pnggetset: palette size %d, expected %d\n", num_palette, PLTE_SYNC_NPALETTE); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 1; } /* Every entry must differ from the original after gamma correction * (file_gamma=1.0, screen_gamma=2.2). If the sync was skipped, * info_ptr->palette still holds the stale pre-correction values. */ changed = 0; for (i = 0; i < PLTE_SYNC_NPALETTE; i++) { if ((got_palette[i].red != plte_sync_original[i].red) || (got_palette[i].green != plte_sync_original[i].green) || (got_palette[i].blue != plte_sync_original[i].blue)) { changed++; } else { fprintf(stderr, "pnggetset: palette entry %d NOT gamma-corrected: " "got {%u, %u, %u}, same as original\n", i, (unsigned)got_palette[i].red, (unsigned)got_palette[i].green, (unsigned)got_palette[i].blue); } } png_read_row(png_ptr, row, NULL); png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (changed != PLTE_SYNC_NPALETTE) { fprintf(stderr, "pnggetset: only %d of %d palette entries were " "gamma-corrected (palette sync failed)\n", changed, PLTE_SYNC_NPALETTE); return 1; } return 0; } int main(void) { int result = 0; printf("Testing PLTE get-then-set roundtrip... "); fflush(stdout); if (test_plte_roundtrip() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); #ifdef PNG_hIST_SUPPORTED printf("Testing hIST get-then-set roundtrip... "); fflush(stdout); if (test_hist_roundtrip() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); #endif #ifdef PNG_tRNS_SUPPORTED printf("Testing tRNS get-then-set roundtrip... "); fflush(stdout); if (test_trns_roundtrip() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); #endif #ifdef PNG_TEXT_SUPPORTED printf("Testing tEXt get-then-set roundtrip... "); fflush(stdout); if (test_text_roundtrip() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); #endif #ifdef PNG_sPLT_SUPPORTED printf("Testing sPLT get-then-set roundtrip... "); fflush(stdout); if (test_splt_roundtrip() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); #endif #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED printf("Testing unknown chunks get-then-set roundtrip... "); fflush(stdout); if (test_unknown_roundtrip() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); #endif printf("Testing PLTE sync after gamma correction... "); fflush(stdout); if (test_plte_palette_sync() != 0) { printf("FAIL\n"); result = 1; } else printf("PASS\n"); return result; }