blob: e2c1ca556ffbf154842f1b275c7707eebb3a2eb6 [file]
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
# include <config.h>
#endif
#ifdef PNG_FREESTANDING_TESTS
# include <png.h>
#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;
}