1b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*- 2b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pngstest.c 3b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Copyright (c) 2013 John Cunningham Bowler 5b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 6b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Last changed in libpng 1.6.8 [December 19, 2013] 7b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This code is released under the libpng license. 9b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * For conditions of distribution and use, see the disclaimer 10b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and license in png.h 11b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 12b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Test for the PNG 'simplified' APIs. 13b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 14b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define _ISOC90_SOURCE 1 15b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define MALLOC_CHECK_ 2/*glibc facility: turn on debugging*/ 16b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 17b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <stddef.h> 18b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <stdlib.h> 19b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <string.h> 20b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <stdio.h> 21b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <errno.h> 22b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <ctype.h> 23b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include <math.h> 24b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 25b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) 26b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# include <config.h> 27b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 28b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 29b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Define the following to use this test against your installed libpng, rather 30b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * than the one being built here: 31b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 32b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FREESTANDING_TESTS 33b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# include <png.h> 34b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 35b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# include "../../png.h" 36b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 37b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 38b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SIMPLIFIED_READ_SUPPORTED /* Else nothing can be done */ 39b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include "../tools/sRGB.h" 40b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 41b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* KNOWN ISSUES 42b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 43b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * These defines switch on alternate algorithms for format conversions to match 44b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the current libpng implementation; they are set to allow pngstest to pass 45b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * even though libpng is producing answers that are not as correct as they 46b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * should be. 47b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 48b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define ALLOW_UNUSED_GPC 0 49b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If true include unused static GPC functions and declare an external array 50b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * of them to hide the fact that they are unused. This is for development 51b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * use while testing the correct function to use to take into account libpng 52b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * misbehavior, such as using a simple power law to correct sRGB to linear. 53b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 54b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 55b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following is to support direct compilation of this file as C++ */ 56b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef __cplusplus 57b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define voidcast(type, value) static_cast<type>(value) 58b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define aligncastconst(type, value) \ 59b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static_cast<type>(static_cast<const void*>(value)) 60b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 61b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define voidcast(type, value) (value) 62b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define aligncastconst(type, value) ((const void*)(value)) 63b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* __cplusplus */ 64b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 65b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* During parallel runs of pngstest each temporary file needs a unique name, 66b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this is used to permit uniqueness using a command line argument which can be 67b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * up to 22 characters long. 68b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 69b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic char tmpf[23] = "TMP"; 70b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 71b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Generate random bytes. This uses a boring repeatable algorithm and it 72b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is implemented here so that it gives the same set of numbers on every 73b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * architecture. It's a linear congruential generator (Knuth or Sedgewick 74b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and 75b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Hill, "The Art of Electronics". 76b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 77b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 78b50c217251b086440efcdb273c22f86a06c80cbaChris Craikmake_random_bytes(png_uint_32* seed, void* pv, size_t size) 79b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 80b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 u0 = seed[0], u1 = seed[1]; 81b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep bytes = voidcast(png_bytep, pv); 82b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 83b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* There are thirty three bits, the next bit in the sequence is bit-33 XOR 84b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. 85b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 86b50c217251b086440efcdb273c22f86a06c80cbaChris Craik size_t i; 87b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<size; ++i) 88b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 89b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First generate 8 new bits then shift them in at the end. */ 90b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; 91b50c217251b086440efcdb273c22f86a06c80cbaChris Craik u1 <<= 8; 92b50c217251b086440efcdb273c22f86a06c80cbaChris Craik u1 |= u0 >> 24; 93b50c217251b086440efcdb273c22f86a06c80cbaChris Craik u0 <<= 8; 94b50c217251b086440efcdb273c22f86a06c80cbaChris Craik u0 |= u; 95b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *bytes++ = (png_byte)u; 96b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 97b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 98b50c217251b086440efcdb273c22f86a06c80cbaChris Craik seed[0] = u0; 99b50c217251b086440efcdb273c22f86a06c80cbaChris Craik seed[1] = u1; 100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 102b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 103b50c217251b086440efcdb273c22f86a06c80cbaChris Craikrandom_color(png_colorp color) 104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static png_uint_32 color_seed[2] = { 0x12345678, 0x9abcdef }; 106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik make_random_bytes(color_seed, color, sizeof *color); 107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Math support - neither Cygwin nor Visual Studio have C99 support and we need 110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * a predictable rounding function, so make one here: 111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 112b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic double 113b50c217251b086440efcdb273c22f86a06c80cbaChris Craikclosestinteger(double x) 114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return floor(x + .5); 116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Cast support: remove GCC whines. */ 119b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 120b50c217251b086440efcdb273c22f86a06c80cbaChris Craiku8d(double d) 121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = closestinteger(d); 123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_byte)d; 124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 126b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 127b50c217251b086440efcdb273c22f86a06c80cbaChris Craiku16d(double d) 128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = closestinteger(d); 130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_uint_16)d; 131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sRGB support: use exact calculations rounded to the nearest int, see the 134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * fesetround() call in main(). sRGB_to_d optimizes the 8 to 16-bit conversion. 135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 136b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic double sRGB_to_d[256]; 137b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic double g22_to_d[256]; 138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 139b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 140b50c217251b086440efcdb273c22f86a06c80cbaChris Craikinit_sRGB_to_d(void) 141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sRGB_to_d[0] = 0; 145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=1; i<255; ++i) 146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sRGB_to_d[i] = linear_from_sRGB(i/255.); 147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sRGB_to_d[255] = 1; 148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g22_to_d[0] = 0; 150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=1; i<255; ++i) 151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g22_to_d[i] = pow(i/255., 1/.45455); 152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g22_to_d[255] = 1; 153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 155b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 156b50c217251b086440efcdb273c22f86a06c80cbaChris CraiksRGB(double linear /*range 0.0 .. 1.0*/) 157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return u8d(255 * sRGB_from_linear(linear)); 159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 161b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 162b50c217251b086440efcdb273c22f86a06c80cbaChris CraikisRGB(int fixed_linear) 163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return sRGB(fixed_linear / 65535.); 165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 /* not used */ 168b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 169b50c217251b086440efcdb273c22f86a06c80cbaChris Craikunpremultiply(int component, int alpha) 170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha <= component) 172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 255; /* Arbitrary, but consistent with the libpng code */ 173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (alpha >= 65535) 175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return isRGB(component); 176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return sRGB((double)component / alpha); 179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 182b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 183b50c217251b086440efcdb273c22f86a06c80cbaChris Craikilinear(int fixed_srgb) 184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return u16d(65535 * sRGB_to_d[fixed_srgb]); 186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 188b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 189b50c217251b086440efcdb273c22f86a06c80cbaChris Craikilineara(int fixed_srgb, int alpha) 190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return u16d((257 * alpha) * sRGB_to_d[fixed_srgb]); 192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 194b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 195b50c217251b086440efcdb273c22f86a06c80cbaChris Craikilinear_g22(int fixed_srgb) 196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return u16d(65535 * g22_to_d[fixed_srgb]); 198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 201b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 202b50c217251b086440efcdb273c22f86a06c80cbaChris Craikilineara_g22(int fixed_srgb, int alpha) 203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return u16d((257 * alpha) * g22_to_d[fixed_srgb]); 205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 208b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic double 209b50c217251b086440efcdb273c22f86a06c80cbaChris CraikYfromRGBint(int ir, int ig, int ib) 210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double r = ir; 212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double g = ig; 213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double b = ib; 214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return YfromRGB(r, g, b); 215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 /* unused */ 218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The error that results from using a 2.2 power law in place of the correct 219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sRGB transform, given an 8-bit value which might be either sRGB or power-law. 220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 221b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 222b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpower_law_error8(int value) 223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (value > 0 && value < 255) 225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double vd = value / 255.; 227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double e = fabs( 228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pow(sRGB_to_d[value], 1/2.2) - sRGB_from_linear(pow(vd, 2.2))); 229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Always allow an extra 1 here for rounding errors */ 231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e = 1+floor(255 * e); 232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (int)e; 233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 238b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_in_sRGB_roundtrip = 56; /* by experiment */ 239b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 240b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpower_law_error16(int value) 241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (value > 0 && value < 65535) 243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Round trip the value through an 8-bit representation but using 245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * non-matching to/from conversions. 246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double vd = value / 65535.; 248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double e = fabs( 249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pow(sRGB_from_linear(vd), 2.2) - linear_from_sRGB(pow(vd, 1/2.2))); 250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Always allow an extra 1 here for rounding errors */ 252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e = error_in_sRGB_roundtrip+floor(65535 * e); 253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (int)e; 254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 259b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 260b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcompare_8bit(int v1, int v2, int error_limit, int multiple_algorithms) 261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int e = abs(v1-v2); 263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ev1, ev2; 264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (e <= error_limit) 266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!multiple_algorithms) 269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ev1 = power_law_error8(v1); 272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (e <= ev1) 273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ev2 = power_law_error8(v2); 276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (e <= ev2) 277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 282b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 283b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcompare_16bit(int v1, int v2, int error_limit, int multiple_algorithms) 284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int e = abs(v1-v2); 286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ev1, ev2; 287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (e <= error_limit) 289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* "multiple_algorithms" in this case means that a color-map has been 292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * involved somewhere, so we can deduce that the values were forced to 8-bit 293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (like the via_linear case for 8-bit.) 294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!multiple_algorithms) 296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ev1 = power_law_error16(v1); 299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (e <= ev1) 300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ev2 = power_law_error16(v2); 303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (e <= ev2) 304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* unused */ 309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define READ_FILE 1 /* else memory */ 311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define USE_STDIO 2 /* else use file name */ 312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define STRICT 4 /* fail on warnings too */ 313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define VERBOSE 8 314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define KEEP_TMPFILES 16 /* else delete temporary files */ 315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define KEEP_GOING 32 316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define ACCUMULATE 64 317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define FAST_WRITE 128 318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define sRGB_16BIT 256 319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 320b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 321b50c217251b086440efcdb273c22f86a06c80cbaChris Craikprint_opts(png_uint_32 opts) 322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & READ_FILE) 324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --file"); 325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & USE_STDIO) 326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --stdio"); 327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & STRICT) 328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --strict"); 329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & VERBOSE) 330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --verbose"); 331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & KEEP_TMPFILES) 332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --preserve"); 333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & KEEP_GOING) 334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --keep-going"); 335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & ACCUMULATE) 336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --accumulate"); 337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(opts & FAST_WRITE)) /* --fast is currently the default */ 338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --slow"); 339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & sRGB_16BIT) 340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" --sRGB-16bit"); 341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define FORMAT_NO_CHANGE 0x80000000 /* additional flag */ 344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* A name table for all the formats - defines the format of the '+' arguments to 346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pngstest. 347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define FORMAT_COUNT 64 349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define FORMAT_MASK 0x3f 350b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic PNG_CONST char * PNG_CONST format_names[FORMAT_COUNT] = 351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-gray", 353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-gray+alpha", 354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-rgb", 355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-rgb+alpha", 356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-gray", 357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-gray+alpha", 358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-rgb", 359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-rgb+alpha", 360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-gray", 362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-gray+alpha", 363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-rgb", 364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-rgb+alpha", 365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-gray", 366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-gray+alpha", 367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-rgb", 368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-rgb+alpha", 369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-gray", 371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-gray+alpha", 372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-bgr", 373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-bgr+alpha", 374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-gray", 375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-gray+alpha", 376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-bgr", 377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-bgr+alpha", 378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-gray", 380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-gray+alpha", 381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-bgr", 382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-bgr+alpha", 383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-gray", 384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-gray+alpha", 385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-bgr", 386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-bgr+alpha", 387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-gray", 389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+sRGB-gray", 390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-rgb", 391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+sRGB-rgb", 392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-gray", 393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+linear-gray", 394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-rgb", 395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+linear-rgb", 396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-gray", 398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+sRGB-gray", 399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-rgb", 400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+sRGB-rgb", 401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-gray", 402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+linear-gray", 403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-rgb", 404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+linear-rgb", 405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-gray", 407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+sRGB-gray", 408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "sRGB-bgr", 409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+sRGB-bgr", 410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-gray", 411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+linear-gray", 412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "linear-bgr", 413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "alpha+linear-bgr", 414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-gray", 416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+sRGB-gray", 417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-sRGB-bgr", 418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+sRGB-bgr", 419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-gray", 420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+linear-gray", 421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-linear-bgr", 422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "color-mapped-alpha+linear-bgr", 423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Decode an argument to a format number. */ 426b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_32 427b50c217251b086440efcdb273c22f86a06c80cbaChris Craikformatof(const char *arg) 428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char *ep; 430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned long format = strtoul(arg, &ep, 0); 431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ep > arg && *ep == 0 && format < FORMAT_COUNT) 433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_uint_32)format; 434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else for (format=0; format < FORMAT_COUNT; ++format) 436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (strcmp(format_names[format], arg) == 0) 438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_uint_32)format; 439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "pngstest: format name '%s' invalid\n", arg); 442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return FORMAT_COUNT; 443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Bitset/test functions for formats */ 446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define FORMAT_SET_COUNT (FORMAT_COUNT / 32) 447b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 bits[FORMAT_SET_COUNT]; 450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 451b50c217251b086440efcdb273c22f86a06c80cbaChris Craikformat_list; 452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 453b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void format_init(format_list *pf) 454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<FORMAT_SET_COUNT; ++i) 457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pf->bits[i] = 0; /* All off */ 458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 /* currently unused */ 461b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void format_clear(format_list *pf) 462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<FORMAT_SET_COUNT; ++i) 465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pf->bits[i] = 0; 466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 469b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int format_is_initial(format_list *pf) 470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<FORMAT_SET_COUNT; ++i) 473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pf->bits[i] != 0) 474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 479b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int format_set(format_list *pf, png_uint_32 format) 480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format < FORMAT_COUNT) 482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return pf->bits[format >> 5] |= ((png_uint_32)1) << (format & 31); 483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 /* currently unused */ 488b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int format_unset(format_list *pf, png_uint_32 format) 489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format < FORMAT_COUNT) 491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return pf->bits[format >> 5] &= ~((png_uint_32)1) << (format & 31); 492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 497b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int format_isset(format_list *pf, png_uint_32 format) 498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return format < FORMAT_COUNT && 500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (pf->bits[format >> 5] & (((png_uint_32)1) << (format & 31))) != 0; 501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 503b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void format_default(format_list *pf, int redundant) 504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (redundant) 506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* set everything, including flags that are pointless */ 510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<FORMAT_SET_COUNT; ++i) 511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pf->bits[i] = ~(png_uint_32)0; 512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 f; 517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (f=0; f<FORMAT_COUNT; ++f) 519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 520b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Eliminate redundant and unsupported settings. */ 521b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_BGR_SUPPORTED 522b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* BGR is meaningless if no color: */ 523b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((f & PNG_FORMAT_FLAG_COLOR) == 0 && 524b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (f & PNG_FORMAT_FLAG_BGR) != 0) 525b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# else 526b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((f & 0x10U/*HACK: fixed value*/) != 0) 527b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* AFIRST is meaningless if no alpha: */ 531b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 532b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((f & PNG_FORMAT_FLAG_ALPHA) == 0 && 533b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (f & PNG_FORMAT_FLAG_AFIRST) != 0) 534b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# else 535b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((f & 0x20U/*HACK: fixed value*/) != 0) 536b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format_set(pf, f); 540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* THE Image STRUCTURE */ 545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The super-class of a png_image, contains the decoded image plus the input 546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * data necessary to re-read the file with a different format. 547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 548b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image image; 551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 opts; 552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const char *file_name; 553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int stride_extra; 554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *input_file; 555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp input_memory; 556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t input_memory_size; 557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep buffer; 558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t stride; 559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t bufsize; 560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t allocsize; 561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char tmpfile_name[32]; 562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 colormap[256*4]; 563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 564b50c217251b086440efcdb273c22f86a06c80cbaChris CraikImage; 565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Initializer: also sets the permitted error limit for 16-bit operations. */ 567b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 568b50c217251b086440efcdb273c22f86a06c80cbaChris Craiknewimage(Image *image) 569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(image, 0, sizeof *image); 571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Reset the image to be read again - only needs to rewind the FILE* at present. 574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 575b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 576b50c217251b086440efcdb273c22f86a06c80cbaChris Craikresetimage(Image *image) 577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->input_file != NULL) 579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik rewind(image->input_file); 580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Free the image buffer; the buffer is re-used on a re-read, this is just for 583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * cleanup. 584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 585b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 586b50c217251b086440efcdb273c22f86a06c80cbaChris Craikfreebuffer(Image *image) 587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->buffer) free(image->buffer); 589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->buffer = NULL; 590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->bufsize = 0; 591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->allocsize = 0; 592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Delete function; cleans out all the allocated data and the temporary file in 595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the image. 596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 597b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 598b50c217251b086440efcdb273c22f86a06c80cbaChris Craikfreeimage(Image *image) 599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik freebuffer(image); 601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_free(&image->image); 602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->input_file != NULL) 604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fclose(image->input_file); 606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_file = NULL; 607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->input_memory != NULL) 610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik free(image->input_memory); 612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory = NULL; 613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory_size = 0; 614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->tmpfile_name[0] != 0 && (image->opts & KEEP_TMPFILES) == 0) 617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik remove(image->tmpfile_name); 619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->tmpfile_name[0] = 0; 620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This is actually a re-initializer; allows an image structure to be re-used by 624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * freeing everything that relates to an old image. 625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 626b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void initimage(Image *image, png_uint_32 opts, const char *file_name, 627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int stride_extra) 628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik freeimage(image); 630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(&image->image, 0, sizeof image->image); 631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opts = opts; 632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->file_name = file_name; 633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->stride_extra = stride_extra; 634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Make sure the image buffer is big enough; allows re-use of the buffer if the 637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * image is re-read. 638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define BUFFER_INIT8 73 640b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 641b50c217251b086440efcdb273c22f86a06c80cbaChris Craikallocbuffer(Image *image) 642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t size = PNG_IMAGE_BUFFER_SIZE(image->image, image->stride); 644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (size+32 > image->bufsize) 646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik freebuffer(image); 648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->buffer = voidcast(png_bytep, malloc(size+32)); 649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->buffer == NULL) 650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, 653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "simpletest: out of memory allocating %lu(+32) byte buffer\n", 654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)size); 655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(1); 656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->bufsize = size+32; 658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(image->buffer, 95, image->bufsize); 661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(image->buffer+16, BUFFER_INIT8, size); 662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->allocsize = size; 663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Make sure 16 bytes match the given byte. */ 666b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 667b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcheck16(png_const_bytep bp, int b) 668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i = 16; 670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (*bp != b) return 1; 673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (--i); 674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Check for overwrite in the image buffer. */ 679b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 680b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcheckbuffer(Image *image, const char *arg) 681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (check16(image->buffer, 95)) 683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: overwrite at start of image buffer\n", arg); 686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(1); 687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (check16(image->buffer+16+image->allocsize, 95)) 690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: overwrite at end of image buffer\n", arg); 693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(1); 694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* ERROR HANDLING */ 698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Log a terminal error, also frees the libpng part of the image if necessary. 699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 700b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 701b50c217251b086440efcdb273c22f86a06c80cbaChris Craiklogerror(Image *image, const char *a1, const char *a2, const char *a3) 702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->image.warning_or_error) 705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s%s%s: %s\n", a1, a2, a3, image->image.message); 706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s%s%s\n", a1, a2, a3); 709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->image.opaque != NULL) 711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: image opaque pointer non-NULL on error\n", 713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->file_name); 714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_free(&image->image); 715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Log an error and close a file (just a utility to do both things in one 721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * function call.) 722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 723b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 724b50c217251b086440efcdb273c22f86a06c80cbaChris Craiklogclose(Image *image, FILE *f, const char *name, const char *operation) 725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int e = errno; 727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fclose(f); 729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, name, operation, strerror(e)); 730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Make sure the png_image has been freed - validates that libpng is doing what 733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the spec says and freeing the image. 734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 735b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 736b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcheckopaque(Image *image) 737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->image.opaque != NULL) 739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_free(&image->image); 741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, image->file_name, ": opaque not NULL", ""); 742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image->image.warning_or_error != 0 && (image->opts & STRICT) != 0) 745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, image->file_name, " --strict", ""); 746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* IMAGE COMPARISON/CHECKING */ 752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Compare the pixels of two images, which should be the same but aren't. The 753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * images must have been checked for a size match. 754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 755b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The components, for grayscale images the gray value is in 'g' and if alpha 758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is not present 'a' is set to 255 or 65535 according to format. 759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int r, g, b, a; 761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} Pixel; 762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 763b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The background as the original sRGB 8-bit value converted to the final 766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * integer format and as a double precision linear value in the range 0..1 767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for with partially transparent pixels. 768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ir, ig, ib; 770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double dr, dg, db; /* linear r,g,b scaled to 0..1 */ 771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} Background; 772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Basic image formats; control the data but not the layout thereof. */ 774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define BASE_FORMATS\ 775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_LINEAR) 776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Read a Pixel from a buffer. The code below stores the correct routine for 778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the format in a function pointer, these are the routines: 779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 780b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 781b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_g8(Pixel *p, png_const_voidp pb) 782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = p->g = p->b = pp[0]; 786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = 255; 787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 789b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 790b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_ga8(Pixel *p, png_const_voidp pb) 791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = p->g = p->b = pp[0]; 795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[1]; 796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 798b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_AFIRST_SUPPORTED 799b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 800b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_ag8(Pixel *p, png_const_voidp pb) 801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = p->g = p->b = pp[1]; 805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[0]; 806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 807b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 809b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 810b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_rgb8(Pixel *p, png_const_voidp pb) 811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[0]; 815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[2]; 817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = 255; 818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 820b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_BGR_SUPPORTED 821b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 822b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_bgr8(Pixel *p, png_const_voidp pb) 823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[2]; 827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[0]; 829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = 255; 830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 831b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 833b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 834b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_rgba8(Pixel *p, png_const_voidp pb) 835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[0]; 839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[2]; 841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[3]; 842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 844b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_BGR_SUPPORTED 845b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 846b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_bgra8(Pixel *p, png_const_voidp pb) 847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[2]; 851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[0]; 853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[3]; 854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 855b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 857b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_AFIRST_SUPPORTED 858b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 859b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_argb8(Pixel *p, png_const_voidp pb) 860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[1]; 864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[2]; 865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[3]; 866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[0]; 867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 868b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 870b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED) 871b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 872b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_abgr8(Pixel *p, png_const_voidp pb) 873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep pp = voidcast(png_const_bytep, pb); 875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[3]; 877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[2]; 878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[1]; 879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[0]; 880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 881b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 883b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 884b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_g16(Pixel *p, png_const_voidp pb) 885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = p->g = p->b = pp[0]; 889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = 65535; 890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 892b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 893b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_ga16(Pixel *p, png_const_voidp pb) 894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = p->g = p->b = pp[0]; 898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[1]; 899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_AFIRST_SUPPORTED 902b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 903b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_ag16(Pixel *p, png_const_voidp pb) 904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = p->g = p->b = pp[1]; 908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[0]; 909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 910b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 912b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 913b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_rgb16(Pixel *p, png_const_voidp pb) 914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[0]; 918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[2]; 920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = 65535; 921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 923b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_BGR_SUPPORTED 924b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 925b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_bgr16(Pixel *p, png_const_voidp pb) 926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[2]; 930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[0]; 932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = 65535; 933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 934b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 936b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 937b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_rgba16(Pixel *p, png_const_voidp pb) 938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[0]; 942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[2]; 944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[3]; 945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_BGR_SUPPORTED 948b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 949b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_bgra16(Pixel *p, png_const_voidp pb) 950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[2]; 954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[1]; 955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[0]; 956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[3]; 957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 958b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 960b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FORMAT_AFIRST_SUPPORTED 961b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 962b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_argb16(Pixel *p, png_const_voidp pb) 963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[1]; 967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[2]; 968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[3]; 969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[0]; 970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 971b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 973b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED) 974b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 975b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgp_abgr16(Pixel *p, png_const_voidp pb) 976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->r = pp[3]; 980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->g = pp[2]; 981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->b = pp[1]; 982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p->a = pp[0]; 983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 984b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Given a format, return the correct one of the above functions. */ 987b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void (* 988b50c217251b086440efcdb273c22f86a06c80cbaChris Craikget_pixel(png_uint_32 format))(Pixel *p, png_const_voidp pb) 989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The color-map flag is irrelevant here - the caller of the function 991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * returned must either pass the buffer or, for a color-mapped image, the 992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correct entry in the color-map. 993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_LINEAR) 995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_COLOR) 997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 998b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_BGR_SUPPORTED 999b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_BGR) 1000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1001b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_ALPHA) 1002b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1003b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1004b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 1005b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_abgr16; 1006b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1007b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1008b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1009b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_bgra16; 1010b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1013b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_bgr16; 1014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1017b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_ALPHA) 1020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1021b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1022b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 1023b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_argb16; 1024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1025b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1026b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_rgba16; 1028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_rgb16; 1032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_ALPHA) 1038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1039b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1040b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 1041b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_ag16; 1042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1043b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1044b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_ga16; 1046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_g16; 1050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_COLOR) 1056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1057b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_BGR_SUPPORTED 1058b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_BGR) 1059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1060b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_ALPHA) 1061b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1062b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1063b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 1064b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_abgr8; 1065b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1066b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1067b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1068b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_bgra8; 1069b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1072b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_bgr8; 1073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1076b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_ALPHA) 1079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1080b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1081b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 1082b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_argb8; 1083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1084b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1085b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_rgba8; 1087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_rgb8; 1091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_ALPHA) 1097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1098b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1099b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 1100b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return gp_ag8; 1101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1102b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1103b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_ga8; 1105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gp_g8; 1109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Convertion between pixel formats. The code above effectively eliminates the 1114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * component ordering changes leaving three basic changes: 1115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1) Remove an alpha channel by pre-multiplication or compositing on a 1117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background color. (Adding an alpha channel is a no-op.) 1118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2) Remove color by mapping to grayscale. (Grayscale to color is a no-op.) 1120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3) Convert between 8-bit and 16-bit components. (Both directtions are 1122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * relevant.) 1123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This gives the following base format conversion matrix: 1125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * OUT: ----- 8-bit ----- ----- 16-bit ----- 1127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IN G GA RGB RGBA G GA RGB RGBA 1128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 G . . . . lin lin lin lin 1129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 GA bckg . bckc . pre' pre pre' pre 1130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 RGB g8 g8 . . glin glin lin lin 1131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre 1132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 G sRGB sRGB sRGB sRGB . . . . 1133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 GA b16g unpg b16c unpc A . A . 1134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 RGB sG sG sRGB sRGB g16 g16 . . 1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 RGBA gb16 sGp cb16 sCp g16 g16' A . 1136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit to 8-bit: 1138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bckg: composite on gray background 1139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bckc: composite on color background 1140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * g8: convert sRGB components to sRGB grayscale 1141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * g8b: convert sRGB components to grayscale and composite on gray background 1142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit to 16-bit: 1144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * lin: make sRGB components linear, alpha := 65535 1145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pre: make sRGB components linear and premultiply by alpha (scale alpha) 1146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pre': as 'pre' but alpha := 65535 1147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * glin: make sRGB components linear, convert to grayscale, alpha := 65535 1148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gpre: make sRGB components grayscale and linear and premultiply by alpha 1149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gpr': as 'gpre' but alpha := 65535 1150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16-bit to 8-bit: 1152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sRGB: convert linear components to sRGB, alpha := 255 1153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * unpg: unpremultiply gray component and convert to sRGB (scale alpha) 1154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * unpc: unpremultiply color components and convert to sRGB (scale alpha) 1155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * b16g: composite linear onto gray background and convert the result to sRGB 1156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * b16c: composite linear onto color background and convert the result to sRGB 1157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sG: convert linear RGB to sRGB grayscale 1158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sGp: unpremultiply RGB then convert to sRGB grayscale 1159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sCp: unpremultiply RGB then convert to sRGB 1160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gb16: composite linear onto background and convert to sRGB grayscale 1161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (order doesn't matter, the composite and grayscale operations permute) 1162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * cb16: composite linear onto background and convert to sRGB 1163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16-bit to 16-bit: 1165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * A: set alpha to 65535 1166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * g16: convert linear RGB to linear grayscale (alpha := 65535) 1167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * g16': as 'g16' but alpha is unchanged 1168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Simple copy: */ 1170b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1171b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_noop(Pixel *out, const Pixel *in, const Background *back) 1172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = in->r; 1175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = in->g; 1176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = in->b; 1177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a; 1178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1181b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1182b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_nop8(Pixel *out, const Pixel *in, const Background *back) 1183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a == 0) 1186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 255; 1187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = in->r; 1191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = in->g; 1192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = in->b; 1193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a; 1196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1200b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1201b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_nop6(Pixel *out, const Pixel *in, const Background *back) 1202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a == 0) 1205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 65535; 1206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = in->r; 1210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = in->g; 1211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = in->b; 1212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a; 1215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* 8-bit to 8-bit conversions */ 1219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* bckg: composite on gray background */ 1220b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1221b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_bckg(Pixel *out, const Pixel *in, const Background *back) 1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = back->ig; 1225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->a >= 255) 1227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = in->g; 1228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a / 255.; 1232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a)); 1234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* bckc: composite on color background */ 1240b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1241b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_bckc(Pixel *out, const Pixel *in, const Background *back) 1242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = back->ir; 1246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = back->ig; 1247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = back->ib; 1248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->a >= 255) 1251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = in->r; 1253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = in->g; 1254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = in->b; 1255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a / 255.; 1260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = sRGB(sRGB_to_d[in->r] * a + back->dr * (1-a)); 1262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a)); 1263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = sRGB(sRGB_to_d[in->b] * a + back->db * (1-a)); 1264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* g8: convert sRGB components to sRGB grayscale */ 1270b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1271b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_g8(Pixel *out, const Pixel *in, const Background *back) 1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = in->g; 1277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 1280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sRGB(YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a; 1283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* g8b: convert sRGB components to grayscale and composite on gray background */ 1286b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1287b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_g8b(Pixel *out, const Pixel *in, const Background *back) 1288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = back->ig; 1291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->a >= 255) 1293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = in->g; 1296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(YfromRGB( 1299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a/255.; 1305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(a * YfromRGB(sRGB_to_d[in->r], 1307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sRGB_to_d[in->g], sRGB_to_d[in->b]) + back->dg * (1-a)); 1308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* 8-bit to 16-bit conversions */ 1314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* lin: make sRGB components linear, alpha := 65535 */ 1315b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1316b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_lin(Pixel *out, const Pixel *in, const Background *back) 1317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = ilinear(in->r); 1321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilinear(in->b); 1331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = ilinear(in->g); 1336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilinear(in->b); 1345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* pre: make sRGB components linear and premultiply by alpha (scale alpha) */ 1351b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1352b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_pre(Pixel *out, const Pixel *in, const Background *back) 1353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = ilineara(in->r, in->a); 1357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara(in->b, in->a); 1367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = ilineara(in->g, in->a); 1372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara(in->b, in->a); 1381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a * 257; 1384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* pre': as 'pre' but alpha := 65535 */ 1387b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1388b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_preq(Pixel *out, const Pixel *in, const Background *back) 1389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = ilineara(in->r, in->a); 1393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara(in->b, in->a); 1403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = ilineara(in->g, in->a); 1408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara(in->b, in->a); 1417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* glin: make sRGB components linear, convert to grayscale, alpha := 65535 */ 1423b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1424b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_glin(Pixel *out, const Pixel *in, const Background *back) 1425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = ilinear(in->g); 1430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(65535 * 1433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* gpre: make sRGB components grayscale and linear and premultiply by alpha */ 1439b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1440b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_gpre(Pixel *out, const Pixel *in, const Background *back) 1441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = ilineara(in->g, in->a); 1446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(in->a * 257 * 1449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 257 * in->a; 1452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* gpr': as 'gpre' but alpha := 65535 */ 1455b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1456b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_gprq(Pixel *out, const Pixel *in, const Background *back) 1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = ilineara(in->g, in->a); 1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(in->a * 257 * 1465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* 8-bit to 16-bit conversions for gAMA 45455 encoded values */ 1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Lin: make gAMA 45455 components linear, alpha := 65535 */ 1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_Lin(Pixel *out, const Pixel *in, const Background *back) 1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = ilinear_g22(in->r); 1478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilinear_g22(in->b); 1488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = ilinear_g22(in->g); 1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilinear_g22(in->b); 1502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Pre: make gAMA 45455 components linear and premultiply by alpha (scale alpha) 1509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1510b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_Pre(Pixel *out, const Pixel *in, const Background *back) 1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = ilineara_g22(in->r, in->a); 1516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara_g22(in->b, in->a); 1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = ilineara_g22(in->g, in->a); 1531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara_g22(in->b, in->a); 1540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a * 257; 1543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Pre': as 'Pre' but alpha := 65535 */ 1548b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_Preq(Pixel *out, const Pixel *in, const Background *back) 1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = ilineara_g22(in->r, in->a); 1554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara_g22(in->b, in->a); 1564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = ilineara_g22(in->g, in->a); 1569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = ilineara_g22(in->b, in->a); 1578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Glin: make gAMA 45455 components linear, convert to grayscale, alpha := 65535 1586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1587b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1588b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_Glin(Pixel *out, const Pixel *in, const Background *back) 1589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = ilinear_g22(in->g); 1594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(65535 * 1597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); 1598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Gpre: make gAMA 45455 components grayscale and linear and premultiply by 1605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * alpha. 1606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1607b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1608b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_Gpre(Pixel *out, const Pixel *in, const Background *back) 1609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = ilineara_g22(in->g, in->a); 1614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(in->a * 257 * 1617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); 1618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 257 * in->a; 1620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Gpr': as 'Gpre' but alpha := 65535 */ 1625b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1626b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_Gprq(Pixel *out, const Pixel *in, const Background *back) 1627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->r == in->g && in->g == in->b) 1631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = ilineara_g22(in->g, in->a); 1632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(in->a * 257 * 1635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); 1636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* 16-bit to 8-bit conversions */ 1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sRGB: convert linear components to sRGB, alpha := 255 */ 1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_sRGB(Pixel *out, const Pixel *in, const Background *back) 1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = isRGB(in->r); 1649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->g == in->r) 1651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = out->r; 1653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = isRGB(in->b); 1659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = isRGB(in->g); 1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->b == in->r) 1666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->r; 1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->b == in->g) 1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = out->g; 1670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = isRGB(in->b); 1673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* unpg: unpremultiply gray component and convert to sRGB (scale alpha) */ 1679b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1680b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_unpg(Pixel *out, const Pixel *in, const Background *back) 1681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 128) 1685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 255; 1687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 0; 1688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB((double)in->g / in->a); 1693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = u8d(in->a / 257.); 1694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* unpc: unpremultiply color components and convert to sRGB (scale alpha) */ 1698b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1699b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_unpc(Pixel *out, const Pixel *in, const Background *back) 1700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 128) 1704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 255; 1706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 0; 1707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = sRGB((double)in->r / in->a); 1712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = sRGB((double)in->g / in->a); 1713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = sRGB((double)in->b / in->a); 1714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = u8d(in->a / 257.); 1715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* b16g: composite linear onto gray background and convert the result to sRGB */ 1719b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1720b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_b16g(Pixel *out, const Pixel *in, const Background *back) 1721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = back->ig; 1724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a/65535.; 1728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a1 = 1-a; 1729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik a /= 65535; 1731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1); 1732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* b16c: composite linear onto color background and convert the result to sRGB*/ 1738b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1739b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_b16c(Pixel *out, const Pixel *in, const Background *back) 1740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = back->ir; 1744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = back->ig; 1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = back->ib; 1746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a/65535.; 1751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a1 = 1-a; 1752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik a /= 65535; 1754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = sRGB(in->r * a + back->dr * a1); 1755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = sRGB(in->g * a + back->dg * a1); 1756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = sRGB(in->b * a + back->db * a1); 1757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sG: convert linear RGB to sRGB grayscale */ 1763b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1764b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_sG(Pixel *out, const Pixel *in, const Background *back) 1765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/65535); 1769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sGp: unpremultiply RGB then convert to sRGB grayscale */ 1773b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1774b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_sGp(Pixel *out, const Pixel *in, const Background *back) 1775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 128) 1779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 255; 1781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 0; 1782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/in->a); 1787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = u8d(in->a / 257.); 1788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sCp: unpremultiply RGB then convert to sRGB */ 1792b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_sCp(Pixel *out, const Pixel *in, const Background *back) 1794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 128) 1798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = 255; 1800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 0; 1801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = sRGB((double)in->r / in->a); 1806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = sRGB((double)in->g / in->a); 1807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = sRGB((double)in->b / in->a); 1808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = u8d(in->a / 257.); 1809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* gb16: composite linear onto background and convert to sRGB grayscale */ 1813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* (order doesn't matter, the composite and grayscale operations permute) */ 1814b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1815b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_gb16(Pixel *out, const Pixel *in, const Background *back) 1816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = back->ig; 1819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->a >= 65535) 1821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = isRGB(in->g); 1822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a / 65535.; 1826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a1 = 1-a; 1827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik a /= 65535; 1829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1); 1830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* cb16: composite linear onto background and convert to sRGB */ 1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1837b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_cb16(Pixel *out, const Pixel *in, const Background *back) 1838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in->a <= 0) 1840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = back->ir; 1842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = back->ig; 1843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = back->ib; 1844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (in->a >= 65535) 1847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = isRGB(in->r); 1849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = isRGB(in->g); 1850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = isRGB(in->b); 1851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a = in->a / 65535.; 1856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double a1 = 1-a; 1857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik a /= 65535; 1859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = sRGB(in->r * a + back->dr * a1); 1860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = sRGB(in->g * a + back->dg * a1); 1861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = sRGB(in->b * a + back->db * a1); 1862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 255; 1865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* 16-bit to 16-bit conversions */ 1868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* A: set alpha to 65535 */ 1869b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1870b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_A(Pixel *out, const Pixel *in, const Background *back) 1871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = in->r; 1874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->g = in->g; 1875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->b = in->b; 1876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* g16: convert linear RGB to linear grayscale (alpha := 65535) */ 1880b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1881b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_g16(Pixel *out, const Pixel *in, const Background *back) 1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b)); 1885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = 65535; 1886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* g16': as 'g16' but alpha is unchanged */ 1889b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1890b50c217251b086440efcdb273c22f86a06c80cbaChris Craikgpc_g16q(Pixel *out, const Pixel *in, const Background *back) 1891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)back; 1893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b)); 1894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out->a = in->a; 1895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if ALLOW_UNUSED_GPC 1898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Unused functions (to hide them from GCC unused function warnings) */ 1899b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid (* const gpc_unused[]) 1900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (Pixel *out, const Pixel *in, const Background *back) = 1901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik gpc_Pre, gpc_Preq, gpc_Glin, gpc_Gpre, gpc_Gprq, gpc_nop8, gpc_nop6 1903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 1904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* OUT: ----- 8-bit ----- ----- 16-bit ----- 1907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IN G GA RGB RGBA G GA RGB RGBA 1908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 G . . . . lin lin lin lin 1909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 GA bckg . bckc . pre' pre pre' pre 1910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 RGB g8 g8 . . glin glin lin lin 1911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre 1912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 G sRGB sRGB sRGB sRGB . . . . 1913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 GA b16g unpg b16c unpc A . A . 1914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 RGB sG sG sRGB sRGB g16 g16 . . 1915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 RGBA gb16 sGp cb16 sCp g16 g16' A . 1916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The matrix is held in an array indexed thus: 1918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gpc_fn[out_format & BASE_FORMATS][in_format & BASE_FORMATS]; 1920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This will produce a compile time error if the FORMAT_FLAG values don't 1922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * match the above matrix! 1923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if PNG_FORMAT_FLAG_ALPHA == 1 && PNG_FORMAT_FLAG_COLOR == 2 &&\ 1925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_FORMAT_FLAG_LINEAR == 4 1926b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void (* const gpc_fn[8/*in*/][8/*out*/]) 1927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (Pixel *out, const Pixel *in, const Background *back) = 1928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */ 1930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_Lin, gpc_Lin, gpc_Lin, gpc_Lin }, 1931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre }, 1932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin }, 1933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre }, 1934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop}, 1935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop}, 1936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop}, 1937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop} 1938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 1939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The array is repeated for the cases where both the input and output are color 1941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * mapped because then different algorithms are used. 1942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1943b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void (* const gpc_fn_colormapped[8/*in*/][8/*out*/]) 1944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (Pixel *out, const Pixel *in, const Background *back) = 1945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */ 1947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_lin, gpc_lin, gpc_lin, gpc_lin }, 1948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre }, 1949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin }, 1950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre }, 1951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop}, 1952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop}, 1953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop}, 1954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop} 1955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 1956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The error arrays record the error in the same matrix; 64 entries, however 1958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the different algorithms used in libpng for colormap and direct conversions 1959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * mean that four separate matrices are used (for each combination of 1960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * colormapped and direct.) 1961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * In some cases the conversion between sRGB formats goes via a linear 1963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * intermediate; an sRGB to linear conversion (as above) is followed by a simple 1964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear to sRGB step with no other conversions. This is done by a separate 1965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * error array from an arbitrary 'in' format to one of the four basic outputs 1966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (since final output is always sRGB not colormapped). 1967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * These arrays may be modified if the --accumulate flag is set during the run; 1969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * then instead of logging errors they are simply added in. 1970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The three entries are currently for transparent, partially transparent and 1972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * opaque input pixel values. Notice that alpha should be exact in each case. 1973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Errors in alpha should only occur when converting from a direct format 1975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to a colormapped format, when alpha is effectively smashed (so large 1976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * errors can occur.) There should be no error in the '0' and 'opaque' 1977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values. The fourth entry in the array is used for the alpha error (and it 1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * should always be zero for the 'via linear' case since this is never color 1979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * mapped.) 1980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Mapping to a colormap smashes the colors, it is necessary to have separate 1982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values for these cases because they are much larger; it is very much 1983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * impossible to obtain a reasonable result, these are held in 1984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gpc_error_to_colormap. 1985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if PNG_FORMAT_FLAG_COLORMAP == 8 /* extra check also required */ 1987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* START MACHINE GENERATED */ 1988b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] = 1989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { /* input: sRGB-gray */ 1991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 1992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 372, 0 }, { 0, 0, 372, 0 }, { 0, 0, 372, 0 }, { 0, 0, 372, 0 }, 1993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 1994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 1995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-gray+alpha */ 1996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 18, 0, 0 }, { 0, 0, 0, 0 }, { 0, 20, 0, 0 }, { 0, 0, 0, 0 }, 1997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, 1998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 1999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-rgb */ 2001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 893, 0 }, { 0, 0, 893, 0 }, { 0, 0, 811, 0 }, { 0, 0, 811, 0 }, 2003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-rgb+alpha */ 2006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 4, 13, 0 }, { 0, 14, 13, 0 }, { 0, 19, 0, 0 }, { 0, 0, 0, 0 }, 2007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 832, 764, 0 }, { 0, 832, 764, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, 2008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-gray */ 2011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, 2012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-gray+alpha */ 2016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 74, 9, 0 }, { 0, 20, 9, 0 }, { 0, 74, 9, 0 }, { 0, 20, 9, 0 }, 2017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, 2018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-rgb */ 2021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, 2022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 4, 0 }, { 0, 0, 4, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-rgb+alpha */ 2026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 126, 143, 0 }, { 0, 9, 7, 0 }, { 0, 74, 9, 0 }, { 0, 16, 9, 0 }, 2027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 4, 4, 0 }, { 0, 5, 4, 0 }, { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, 2028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-gray */ 2031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-gray+alpha */ 2036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-rgb */ 2041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 13, 0 }, { 0, 0, 13, 0 }, { 0, 0, 8, 0 }, { 0, 0, 8, 0 }, 2042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 673, 0 }, { 0, 0, 673, 0 }, { 0, 0, 674, 0 }, { 0, 0, 674, 0 }, 2043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 460, 0 }, { 0, 0, 460, 0 }, { 0, 0, 263, 0 }, { 0, 0, 263, 0 } 2045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-rgb+alpha */ 2046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 6, 8, 0 }, { 0, 7, 8, 0 }, { 0, 75, 8, 0 }, { 0, 9, 8, 0 }, 2047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 585, 427, 0 }, { 0, 585, 427, 0 }, { 0, 717, 409, 0 }, { 0, 717, 409, 0 }, 2048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, 2049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 13323, 460, 0 }, { 0, 334, 460, 0 }, { 0, 16480, 263, 0 }, { 0, 243, 263, 0 } 2050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-gray */ 2051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 282, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-gray+alpha */ 2056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 253, 282, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-rgb */ 2061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 265, 0 }, { 0, 0, 0, 0 } 2065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-rgb+alpha */ 2066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 2069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 243, 265, 0 } 2070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 2072b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 gpc_error_via_linear[16][4/*out*/][4] = 2073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { /* input: sRGB-gray */ 2075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 7, 0 }, { 0, 0, 7, 0 }, { 0, 0, 7, 0 }, { 0, 0, 7, 0 } 2076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-gray+alpha */ 2077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 15, 15, 0 }, { 0, 186, 15, 0 }, { 0, 15, 15, 0 }, { 0, 186, 15, 0 } 2078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-rgb */ 2079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 15, 0 }, { 0, 0, 15, 0 } 2080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-rgb+alpha */ 2081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 12, 14, 0 }, { 0, 180, 14, 0 }, { 0, 14, 15, 0 }, { 0, 186, 15, 0 } 2082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-gray */ 2083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 } 2084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-gray+alpha */ 2085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 } 2086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-rgb */ 2087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 } 2088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-rgb+alpha */ 2089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 1, 1, 0 }, { 0, 8, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 } 2090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-gray */ 2091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-gray+alpha */ 2093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-rgb */ 2095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 13, 0 }, { 0, 0, 13, 0 }, { 0, 0, 14, 0 }, { 0, 0, 14, 0 } 2096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-sRGB-rgb+alpha */ 2097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 4, 8, 0 }, { 0, 9, 8, 0 }, { 0, 8, 3, 0 }, { 0, 32, 3, 0 } 2098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-gray */ 2099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-gray+alpha */ 2101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-rgb */ 2103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: color-mapped-linear-rgb+alpha */ 2105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } 2106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 2108b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] = 2109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { /* input: sRGB-gray */ 2111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, 2112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 560, 0 }, { 0, 0, 560, 0 }, { 0, 0, 560, 0 }, { 0, 0, 560, 0 } 2113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-gray+alpha */ 2114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 19, 2, 0 }, { 0, 255, 2, 25 }, { 0, 88, 2, 0 }, { 0, 255, 2, 25 }, 2115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 1012, 745, 0 }, { 0, 16026, 745, 6425 }, { 0, 1012, 745, 0 }, { 0, 16026, 745, 6425 } 2116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-rgb */ 2117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 25, 0 }, { 0, 0, 25, 0 }, 2118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 937, 0 }, { 0, 0, 937, 0 }, { 0, 0, 13677, 0 }, { 0, 0, 13677, 0 } 2119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: sRGB-rgb+alpha */ 2120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 63, 77, 0 }, { 0, 255, 19, 25 }, { 0, 220, 25, 0 }, { 0, 255, 25, 67 }, 2121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 17534, 18491, 0 }, { 0, 15614, 2824, 6425 }, { 0, 14019, 13677, 0 }, { 0, 48573, 13677, 17219 } 2122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-gray */ 2123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, 2124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 } 2125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-gray+alpha */ 2126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 74, 74, 0 }, { 0, 255, 74, 25 }, { 0, 97, 74, 0 }, { 0, 255, 74, 25 }, 2127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 18919, 18907, 0 }, { 0, 24549, 18907, 6552 }, { 0, 18919, 18907, 0 }, { 0, 24549, 18907, 6552 } 2128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-rgb */ 2129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 98, 0 }, { 0, 0, 98, 0 }, 2130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 0, 18664, 0 }, { 0, 0, 18664, 0 }, { 0, 0, 24998, 0 }, { 0, 0, 24998, 0 } 2131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }, { /* input: linear-rgb+alpha */ 2132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 181, 196, 0 }, { 0, 255, 61, 25 }, { 206, 187, 98, 0 }, { 0, 255, 98, 67 }, 2133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0, 18141, 18137, 0 }, { 0, 17494, 17504, 6553 }, { 0, 24979, 24992, 0 }, { 0, 46509, 24992, 17347 } 2134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 2136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* END MACHINE GENERATED */ 2137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* COLORMAP flag check */ 2138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* flag checks */ 2139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2140b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 2141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Basic pixel information: */ 2143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Image* in_image; /* Input image */ 2144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const Image* out_image; /* Output image */ 2145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'background' is the value passed to the gpc_ routines, it may be NULL if 2147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it should not be used (*this* program has an error if it crashes as a 2148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * result!) 2149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Background background_color; 2151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const Background* background; 2152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Precalculated values: */ 2154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int in_opaque; /* Value of input alpha that is opaque */ 2155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int is_palette; /* Sample values come from the palette */ 2156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int accumulate; /* Accumlate component errors (don't log) */ 2157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int output_8bit; /* Output is 8 bit (else 16 bit) */ 2158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik void (*in_gp)(Pixel*, png_const_voidp); 2160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik void (*out_gp)(Pixel*, png_const_voidp); 2161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik void (*transform)(Pixel *out, const Pixel *in, const Background *back); 2163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* A function to perform the required transform */ 2164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik void (*from_linear)(Pixel *out, const Pixel *in, const Background *back); 2166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* For 'via_linear' transforms the final, from linear, step, else NULL */ 2167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 error[4]; 2169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Three error values for transparent, partially transparent and opaque 2170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * input pixels (in turn). 2171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 *error_ptr; 2174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Where these are stored in the static array (for 'accumulate') */ 2175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2176b50c217251b086440efcdb273c22f86a06c80cbaChris CraikTransform; 2177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Return a 'transform' as above for the given format conversion. */ 2179b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 2180b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktransform_from_formats(Transform *result, Image *in_image, 2181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const Image *out_image, png_const_colorp background, int via_linear) 2182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 in_format, out_format; 2184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 in_base, out_base; 2185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(result, 0, sizeof *result); 2187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Store the original images for error messages */ 2189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->in_image = in_image; 2190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->out_image = out_image; 2191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik in_format = in_image->image.format; 2193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out_format = out_image->image.format; 2194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in_format & PNG_FORMAT_FLAG_LINEAR) 2196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->in_opaque = 65535; 2197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->in_opaque = 255; 2199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->output_8bit = (out_format & PNG_FORMAT_FLAG_LINEAR) == 0; 2201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->is_palette = 0; /* set by caller if required */ 2203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->accumulate = (in_image->opts & ACCUMULATE) != 0; 2204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The loaders (which need the ordering information) */ 2206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->in_gp = get_pixel(in_format); 2207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->out_gp = get_pixel(out_format); 2208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Remove the ordering information: */ 2210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik in_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP; 2211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik in_base = in_format & BASE_FORMATS; 2212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP; 2213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out_base = out_format & BASE_FORMATS; 2214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (via_linear) 2216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for an error in this program: */ 2218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out_format & (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLORMAP)) 2219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "internal transform via linear error 0x%x->0x%x\n", 2221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik in_format, out_format); 2222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(1); 2223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->transform = gpc_fn[in_base][out_base | PNG_FORMAT_FLAG_LINEAR]; 2226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->from_linear = gpc_fn[out_base | PNG_FORMAT_FLAG_LINEAR][out_base]; 2227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error_ptr = gpc_error_via_linear[in_format][out_format]; 2228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (~in_format & out_format & PNG_FORMAT_FLAG_COLORMAP) 2231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The input is not colormapped but the output is, the errors will 2233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * typically be large (only the grayscale-no-alpha case permits preserving 2234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * even 8-bit values.) 2235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->transform = gpc_fn[in_base][out_base]; 2237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->from_linear = NULL; 2238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error_ptr = gpc_error_to_colormap[in_base][out_base]; 2239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The caller handles the colormap->pixel value conversion, so the 2244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * transform function just gets a pixel value, however because libpng 2245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * currently contains a different implementation for mapping a colormap if 2246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * both input and output are colormapped we need different conversion 2247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * functions to deal with errors in the libpng implementation. 2248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in_format & out_format & PNG_FORMAT_FLAG_COLORMAP) 2250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->transform = gpc_fn_colormapped[in_base][out_base]; 2251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->transform = gpc_fn[in_base][out_base]; 2253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->from_linear = NULL; 2254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error_ptr = gpc_error[in_format][out_format]; 2255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Follow the libpng simplified API rules to work out what to pass to the gpc 2258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * routines as a background value, if one is not required pass NULL so that 2259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this program crashes in the even of a programming error. 2260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background = NULL; /* default: not required */ 2262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Rule 1: background only need be supplied if alpha is to be removed */ 2264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in_format & ~out_format & PNG_FORMAT_FLAG_ALPHA) 2265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The input value is 'NULL' to use the background and (otherwise) an sRGB 2267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background color (to use a solid color). The code above uses a fixed 2268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * byte value, BUFFER_INIT8, for buffer even for 16-bit output. For 2269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear (16-bit) output the sRGB background color is ignored; the 2270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * composition is always on the background (so BUFFER_INIT8 * 257), except 2271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that for the colormap (i.e. linear colormapped output) black is used. 2272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background = &result->background_color; 2274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out_format & PNG_FORMAT_FLAG_LINEAR || via_linear) 2276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out_format & PNG_FORMAT_FLAG_COLORMAP) 2278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ir = 2280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ig = 2281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ib = 0; 2282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dr = 2283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dg = 2284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.db = 0; 2285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ir = 2290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ig = 2291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ib = BUFFER_INIT8 * 257; 2292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dr = 2293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dg = 2294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.db = 0; 2295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* sRGB output */ 2299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background != NULL) 2301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out_format & PNG_FORMAT_FLAG_COLOR) 2303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ir = background->red; 2305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ig = background->green; 2306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ib = background->blue; 2307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* TODO: sometimes libpng uses the power law conversion here, how 2308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to handle this? 2309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dr = sRGB_to_d[background->red]; 2311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dg = sRGB_to_d[background->green]; 2312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.db = sRGB_to_d[background->blue]; 2313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* grayscale: libpng only looks at 'g' */ 2316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ir = 2318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ig = 2319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ib = background->green; 2320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* TODO: sometimes libpng uses the power law conversion here, how 2321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to handle this? 2322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dr = 2324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dg = 2325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.db = sRGB_to_d[background->green]; 2326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if ((out_format & PNG_FORMAT_FLAG_COLORMAP) == 0) 2330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ir = 2332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ig = 2333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ib = BUFFER_INIT8; 2334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* TODO: sometimes libpng uses the power law conversion here, how 2335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to handle this? 2336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dr = 2338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dg = 2339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.db = sRGB_to_d[BUFFER_INIT8]; 2340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Else the output is colormapped and a background color must be 2343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * provided; if pngstest crashes then that is a bug in this program 2344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (though libpng should png_error as well.) 2345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background = NULL; 2348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (result->background == NULL) 2352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ir = 2354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ig = 2355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.ib = -1; /* not used */ 2356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dr = 2357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.dg = 2358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->background_color.db = 1E30; /* not used */ 2359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Copy the error values into the Transform: */ 2363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error[0] = result->error_ptr[0]; 2364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error[1] = result->error_ptr[1]; 2365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error[2] = result->error_ptr[2]; 2366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result->error[3] = result->error_ptr[3]; 2367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Compare two pixels. 2371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * OLD error values: 2373b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_to_linear = 811; * by experiment * 2374b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_to_linear_grayscale = 424; * by experiment * 2375b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_to_sRGB = 6; * by experiment * 2376b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_to_sRGB_grayscale = 17; * libpng error by calculation + 2377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2 by experiment * 2378b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_in_compose = 2; * by experiment * 2379b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_in_premultiply = 1; 2380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The following is *just* the result of a round trip from 8-bit sRGB to linear 2382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * then back to 8-bit sRGB when it is done by libpng. There are two problems: 2383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1) libpng currently uses a 2.2 power law with no linear segment, this results 2385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * in instability in the low values and even with 16-bit precision sRGB(1) ends 2386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * up mapping to sRGB(0) as a result of rounding in the 16-bit representation. 2387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This gives an error of 1 in the handling of value 1 only. 2388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2) libpng currently uses an intermediate 8-bit linear value in gamma 2390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correction of 8-bit values. This results in many more errors, the worse of 2391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * which is mapping sRGB(14) to sRGB(0). 2392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The general 'error_via_linear' is more complex because of pre-multiplication, 2394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this compounds the 8-bit errors according to the alpha value of the pixel. 2395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * As a result 256 values are pre-calculated for error_via_linear. 2396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 2398b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_in_libpng_gamma; 2399b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int error_via_linear[256]; /* Indexed by 8-bit alpha */ 2400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2401b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 2402b50c217251b086440efcdb273c22f86a06c80cbaChris Craikinit_error_via_linear(void) 2403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int alpha; 2405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_via_linear[0] = 255; /* transparent pixel */ 2407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (alpha=1; alpha<=255; ++alpha) 2409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 16-bit values less than 128.5 get rounded to 8-bit 0 and so the worst 2411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * case error arises with 16-bit 128.5, work out what sRGB 2412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (non-associated) value generates 128.5; any value less than this is 2413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * going to map to 0, so the worst error is floor(value). 2414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Note that errors are considerably higher (more than a factor of 2) 2416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * because libpng uses a simple power law for sRGB data at present. 2417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Add .1 for arithmetic errors inside libpng. 2419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double v = floor(255*pow(.5/*(128.5 * 255 / 65535)*/ / alpha, 1/2.2)+.1); 2421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_via_linear[alpha] = (int)v; 2423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is actually 14.99, but, despite the closeness to 15, 14 seems to work 2426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ok in this case. 2427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_in_libpng_gamma = 14; 2429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 2431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2432b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 2433b50c217251b086440efcdb273c22f86a06c80cbaChris Craikprint_pixel(char string[64], const Pixel *pixel, png_uint_32 format) 2434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (format & (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR)) 2436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0: 2438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(string, "%s(%d)", format_names[format], pixel->g); 2439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FORMAT_FLAG_ALPHA: 2442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(string, "%s(%d,%d)", format_names[format], pixel->g, 2443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel->a); 2444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FORMAT_FLAG_COLOR: 2447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(string, "%s(%d,%d,%d)", format_names[format], 2448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel->r, pixel->g, pixel->b); 2449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA: 2452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(string, "%s(%d,%d,%d,%d)", format_names[format], 2453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel->r, pixel->g, pixel->b, pixel->a); 2454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(string, "invalid-format"); 2458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2462b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2463b50c217251b086440efcdb273c22f86a06c80cbaChris Craiklogpixel(const Transform *transform, png_uint_32 x, png_uint_32 y, 2464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const Pixel *in, const Pixel *calc, const Pixel *out, const char *reason) 2465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 in_format = transform->in_image->image.format; 2467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 out_format = transform->out_image->image.format; 2468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 back_format = out_format & ~PNG_FORMAT_FLAG_ALPHA; 2470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const char *via_linear = ""; 2471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char pixel_in[64], pixel_calc[64], pixel_out[64], pixel_loc[64]; 2473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char background_info[100]; 2474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik print_pixel(pixel_in, in, in_format); 2476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik print_pixel(pixel_calc, calc, out_format); 2477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik print_pixel(pixel_out, out, out_format); 2478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->is_palette) 2480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(pixel_loc, "palette: %lu", (unsigned long)y); 2481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(pixel_loc, "%lu,%lu", (unsigned long)x, (unsigned long)y); 2483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->from_linear != NULL) 2485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik via_linear = " (via linear)"; 2487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And as a result the *read* format which did any background processing 2488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * was itself linear, so the background color information is also 2489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear. 2490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_format |= PNG_FORMAT_FLAG_LINEAR; 2492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->background != NULL) 2495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Pixel back; 2497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char pixel_back[64]; 2498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back.r = transform->background->ir; 2500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back.g = transform->background->ig; 2501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back.b = transform->background->ib; 2502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back.a = -1; /* not used */ 2503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik print_pixel(pixel_back, &back, back_format); 2505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(background_info, " on background %s", pixel_back); 2506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_info[0] = 0; 2510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->in_image->file_name != transform->out_image->file_name) 2512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char error_buffer[512]; 2514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(error_buffer, 2515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n" 2516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Use --preserve and examine: ", pixel_loc, reason, via_linear, 2517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel_in, background_info, pixel_out, pixel_calc); 2518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(transform->in_image, transform->in_image->file_name, 2519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_buffer, transform->out_image->file_name); 2520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char error_buffer[512]; 2525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(error_buffer, 2526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n" 2527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik " The error happened when reading the original file with this format.", 2528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel_loc, reason, via_linear, pixel_in, background_info, pixel_out, 2529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel_calc); 2530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(transform->in_image, transform->in_image->file_name, 2531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_buffer, ""); 2532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2535b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2536b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcmppixel(Transform *transform, png_const_voidp in, png_const_voidp out, 2537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 x, png_uint_32 y/*or palette index*/) 2538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int maxerr; 2540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_charp errmsg; 2541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Pixel pixel_in, pixel_calc, pixel_out; 2542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->in_gp(&pixel_in, in); 2544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->from_linear == NULL) 2546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->transform(&pixel_calc, &pixel_in, transform->background); 2547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->transform(&pixel_out, &pixel_in, transform->background); 2551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->from_linear(&pixel_calc, &pixel_out, NULL); 2552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->out_gp(&pixel_out, out); 2555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Eliminate the case where the input and output values match exactly. */ 2557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pixel_calc.a == pixel_out.a && pixel_calc.r == pixel_out.r && 2558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pixel_calc.g == pixel_out.g && pixel_calc.b == pixel_out.b) 2559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Eliminate the case where the output pixel is transparent and the output 2562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is 8-bit - any component values are valid. Don't check the input alpha 2563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * here to also skip the 16-bit small alpha cases. 2564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->output_8bit && pixel_calc.a == 0 && pixel_out.a == 0) 2566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for alpha errors first; an alpha error can damage the components too 2569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * so avoid spurious checks on components if one is found. 2570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik errmsg = NULL; 2572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int err_a = abs(pixel_calc.a-pixel_out.a); 2574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (err_a > transform->error[3]) 2576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If accumulating check the components too */ 2578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->accumulate) 2579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->error[3] = (png_uint_16)err_a; 2580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik errmsg = "alpha"; 2583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now if *either* of the output alphas are 0 but alpha is within tolerance 2587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * eliminate the 8-bit component comparison. 2588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (errmsg == NULL && transform->output_8bit && 2590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (pixel_calc.a == 0 || pixel_out.a == 0)) 2591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (errmsg == NULL) /* else just signal an alpha error */ 2594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int err_r = abs(pixel_calc.r - pixel_out.r); 2596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int err_g = abs(pixel_calc.g - pixel_out.g); 2597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int err_b = abs(pixel_calc.b - pixel_out.b); 2598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int limit; 2599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((err_r | err_g | err_b) == 0) 2601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; /* exact match */ 2602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Mismatch on a component, check the input alpha */ 2604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pixel_in.a >= transform->in_opaque) 2605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik errmsg = "opaque component"; 2607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik limit = 2; /* opaque */ 2608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (pixel_in.a > 0) 2611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik errmsg = "alpha component"; 2613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik limit = 1; /* partially transparent */ 2614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik errmsg = "transparent component (background)"; 2619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik limit = 0; /* transparent */ 2620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik maxerr = err_r; 2623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (maxerr < err_g) maxerr = err_g; 2624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (maxerr < err_b) maxerr = err_b; 2625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (maxerr <= transform->error[limit]) 2627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; /* within the error limits */ 2628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Handle a component mis-match; log it, just return an error code, or 2630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * accumulate it. 2631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transform->accumulate) 2633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform->error[limit] = (png_uint_16)maxerr; 2635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; /* to cause the caller to keep going */ 2636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Failure to match and not accumulating, so the error must be logged. */ 2640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logpixel(transform, x, y, &pixel_in, &pixel_calc, &pixel_out, errmsg); 2641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2643b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 2644b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcomponent_loc(png_byte loc[4], png_uint_32 format) 2645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Given a format return the number of channels and the location of 2647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * each channel. 2648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The mask 'loc' contains the component offset of the channels in the 2650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * following order. Note that if 'format' is grayscale the entries 1-3 must 2651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * all contain the location of the gray channel. 2652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0: alpha 2654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1: red or gray 2655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2: green or gray 2656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3: blue or gray 2657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte channels; 2659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_COLOR) 2661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik channels = 3; 2663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik loc[2] = 1; 2665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2666b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_BGR_SUPPORTED 2667b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_BGR) 2668b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 2669b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari loc[1] = 2; 2670b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari loc[3] = 0; 2671b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 2672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2673b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 2674b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 2675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik loc[1] = 0; 2677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik loc[3] = 2; 2678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik channels = 1; 2684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik loc[1] = loc[2] = loc[3] = 0; 2685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_ALPHA) 2688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2689b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 2690b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (format & PNG_FORMAT_FLAG_AFIRST) 2691b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 2692b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari loc[0] = 0; 2693b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ++loc[1]; 2694b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ++loc[2]; 2695b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ++loc[3]; 2696b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 2697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2698b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 2699b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 2700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik loc[0] = channels; 2701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++channels; 2703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik loc[0] = 4; /* not present */ 2707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return channels; 2709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Compare two images, the original 'a', which was written out then read back in 2712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to * give image 'b'. The formats may have been changed. 2713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2714b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2715b50c217251b086440efcdb273c22f86a06c80cbaChris Craikcompare_two_images(Image *a, Image *b, int via_linear, 2716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_colorp background) 2717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t stridea = a->stride; 2719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t strideb = b->stride; 2720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep rowa = a->buffer+16; 2721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep rowb = b->buffer+16; 2722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 width = a->image.width; 2723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 height = a->image.height; 2724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 formata = a->image.format; 2725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 formatb = b->image.format; 2726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const unsigned int a_sample = PNG_IMAGE_SAMPLE_SIZE(formata); 2727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const unsigned int b_sample = PNG_IMAGE_SAMPLE_SIZE(formatb); 2728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int alpha_added, alpha_removed; 2729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int bchannels; 2730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int btoa[4]; 2731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y; 2732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Transform tr; 2733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This should never happen: */ 2735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (width != b->image.width || height != b->image.height) 2736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(a, a->file_name, ": width x height changed: ", 2737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik b->file_name); 2738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set up the background and the transform */ 2740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik transform_from_formats(&tr, a, b, background, via_linear); 2741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Find the first row and inter-row space. */ 2743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(formata & PNG_FORMAT_FLAG_COLORMAP) && 2744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (formata & PNG_FORMAT_FLAG_LINEAR)) 2745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stridea *= 2; 2746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(formatb & PNG_FORMAT_FLAG_COLORMAP) && 2748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (formatb & PNG_FORMAT_FLAG_LINEAR)) 2749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strideb *= 2; 2750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (stridea < 0) rowa += (height-1) * (-stridea); 2752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (strideb < 0) rowb += (height-1) * (-strideb); 2753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First shortcut the two colormap case by comparing the image data; if it 2755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * matches then we expect the colormaps to match, although this is not 2756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * absolutely necessary for an image match. If the colormaps fail to match 2757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * then there is a problem in libpng. 2758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (formata & formatb & PNG_FORMAT_FLAG_COLORMAP) 2760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Only check colormap entries that actually exist; */ 2762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep ppa, ppb; 2763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int match; 2764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte in_use[256], amax = 0, bmax = 0; 2765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(in_use, 0, sizeof in_use); 2767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ppa = rowa; 2769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ppb = rowb; 2770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do this the slow way to accumulate the 'in_use' flags, don't break out 2772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * of the loop until the end; this validates the color-mapped data to 2773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ensure all pixels are valid color-map indexes. 2774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (y=0, match=1; y<height && match; ++y, ppa += stridea, ppb += strideb) 2776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 x; 2778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (x=0; x<width; ++x) 2780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte bval = ppb[x]; 2782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte aval = ppa[x]; 2783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bval > bmax) 2785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bmax = bval; 2786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bval != aval) 2788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik match = 0; 2789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik in_use[aval] = 1; 2791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (aval > amax) 2792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik amax = aval; 2793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If the buffers match then the colormaps must too. */ 2797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (match) 2798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do the color-maps match, entry by entry? Only check the 'in_use' 2800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entries. An error here should be logged as a color-map error. 2801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep a_cmap = (png_const_bytep)a->colormap; 2803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep b_cmap = (png_const_bytep)b->colormap; 2804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result = 1; /* match by default */ 2805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is used in logpixel to get the error message correct. */ 2807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.is_palette = 1; 2808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (y=0; y<256; ++y, a_cmap += a_sample, b_cmap += b_sample) 2810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in_use[y]) 2811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The colormap entries should be valid, but because libpng doesn't 2813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * do any checking at present the original image may contain invalid 2814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pixel values. These cause an error here (at present) unless 2815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * accumulating errors in which case the program just ignores them. 2816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (y >= a->image.colormap_entries) 2818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((a->opts & ACCUMULATE) == 0) 2820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char pindex[9]; 2822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(pindex, "%lu[%lu]", (unsigned long)y, 2823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)a->image.colormap_entries); 2824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik logerror(a, a->file_name, ": bad pixel index: ", pindex); 2825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 0; 2827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (y >= b->image.colormap_entries) 2830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((a->opts & ACCUMULATE) == 0) 2832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char pindex[9]; 2834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(pindex, "%lu[%lu]", (unsigned long)y, 2835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)b->image.colormap_entries); 2836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik logerror(b, b->file_name, ": bad pixel index: ", pindex); 2837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 0; 2839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* All the mismatches are logged here; there can only be 256! */ 2842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (!cmppixel(&tr, a_cmap, b_cmap, 0, y)) 2843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 0; 2844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If reqested copy the error values back from the Transform. */ 2847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (a->opts & ACCUMULATE) 2848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[0] = tr.error[0]; 2850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[1] = tr.error[1]; 2851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[2] = tr.error[2]; 2852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[3] = tr.error[3]; 2853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 1; /* force a continue */ 2854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 2857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* else the image buffers don't match pixel-wise so compare sample values 2860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * instead, but first validate that the pixel indexes are in range (but 2861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * only if not accumulating, when the error is ignored.) 2862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if ((a->opts & ACCUMULATE) == 0) 2864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check the original image first, 2866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: deal with input images with bad pixel values? 2867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (amax >= a->image.colormap_entries) 2869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char pindex[9]; 2871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(pindex, "%d[%lu]", amax, 2872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)a->image.colormap_entries); 2873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(a, a->file_name, ": bad pixel index: ", pindex); 2874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (bmax >= b->image.colormap_entries) 2877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char pindex[9]; 2879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(pindex, "%d[%lu]", bmax, 2880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)b->image.colormap_entries); 2881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(b, b->file_name, ": bad pixel index: ", pindex); 2882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We can directly compare pixel values without the need to use the read 2887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * or transform support (i.e. a memory compare) if: 2888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1) The bit depth has not changed. 2890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2) RGB to grayscale has not been done (the reverse is ok; we just compare 2891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the three RGB values to the original grayscale.) 2892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3) An alpha channel has not been removed from an 8-bit format, or the 2893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit alpha value of the pixel was 255 (opaque). 2894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * If an alpha channel has been *added* then it must have the relevant opaque 2896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value (255 or 65535). 2897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The fist two the tests (in the order given above) (using the boolean 2899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * equivalence !a && !b == !(a || b)) 2900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(((formata ^ formatb) & PNG_FORMAT_FLAG_LINEAR) | 2902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (formata & (formatb ^ PNG_FORMAT_FLAG_COLOR) & PNG_FORMAT_FLAG_COLOR))) 2903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Was an alpha channel changed? */ 2905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 alpha_changed = (formata ^ formatb) & 2906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_FORMAT_FLAG_ALPHA; 2907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Was an alpha channel removed? (The third test.) If so the direct 2909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * comparison is only possible if the input alpha is opaque. 2910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_removed = (formata & alpha_changed) != 0; 2912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Was an alpha channel added? */ 2914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_added = (formatb & alpha_changed) != 0; 2915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The channels may have been moved between input and output, this finds 2917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * out how, recording the result in the btoa array, which says where in 2918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'a' to find each channel of 'b'. If alpha was added then btoa[alpha] 2919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ends up as 4 (and is not used.) 2920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 2923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte aloc[4]; 2924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte bloc[4]; 2925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following are used only if the formats match, except that 2927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'bchannels' is a flag for matching formats. btoa[x] says, for each 2928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * channel in b, where to find the corresponding value in a, for the 2929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bchannels. achannels may be different for a gray to rgb transform 2930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (a will be 1 or 2, b will be 3 or 4 channels.) 2931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)component_loc(aloc, formata); 2933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bchannels = component_loc(bloc, formatb); 2934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Hence the btoa array. */ 2936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<4; ++i) if (bloc[i] < 4) 2937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik btoa[bloc[i]] = aloc[i]; /* may be '4' for alpha */ 2938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha_added) 2940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_added = bloc[0]; /* location of alpha channel in image b */ 2941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_added = 4; /* Won't match an image b channel */ 2944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha_removed) 2946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_removed = aloc[0]; /* location of alpha channel in image a */ 2947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_removed = 4; 2950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Direct compare is not possible, cancel out all the corresponding local 2956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * variables. 2957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bchannels = 0; 2959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha_removed = alpha_added = 4; 2960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik btoa[3] = btoa[2] = btoa[1] = btoa[0] = 4; /* 4 == not present */ 2961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (y=0; y<height; ++y, rowa += stridea, rowb += strideb) 2964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep ppa, ppb; 2966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 x; 2967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (x=0, ppa=rowa, ppb=rowb; x<width; ++x) 2969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep psa, psb; 2971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (formata & PNG_FORMAT_FLAG_COLORMAP) 2973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik psa = (png_const_bytep)a->colormap + a_sample * *ppa++; 2974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik psa = ppa, ppa += a_sample; 2976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (formatb & PNG_FORMAT_FLAG_COLORMAP) 2978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik psb = (png_const_bytep)b->colormap + b_sample * *ppb++; 2979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik psb = ppb, ppb += b_sample; 2981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do the fast test if possible. */ 2983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bchannels) 2984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check each 'b' channel against either the corresponding 'a' 2986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * channel or the opaque alpha value, as appropriate. If 2987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * alpha_removed value is set (not 4) then also do this only if the 2988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'a' alpha channel (alpha_removed) is opaque; only relevant for 2989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the 8-bit case. 2990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (formatb & PNG_FORMAT_FLAG_LINEAR) /* 16-bit checks */ 2992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pua = aligncastconst(png_const_uint_16p, psa); 2994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p pub = aligncastconst(png_const_uint_16p, psb); 2995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (bchannels) 2997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 4: 2999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pua[btoa[3]] != pub[3]) break; 3000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 3: 3001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pua[btoa[2]] != pub[2]) break; 3002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 2: 3003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pua[btoa[1]] != pub[1]) break; 3004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 3005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pua[btoa[0]] != pub[0]) break; 3006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha_added != 4 && pub[alpha_added] != 65535) break; 3007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; /* x loop */ 3008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; /* impossible */ 3010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (alpha_removed == 4 || psa[alpha_removed] == 255) 3014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (bchannels) 3016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 4: 3018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (psa[btoa[3]] != psb[3]) break; 3019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 3: 3020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (psa[btoa[2]] != psb[2]) break; 3021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 2: 3022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (psa[btoa[1]] != psb[1]) break; 3023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 3024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (psa[btoa[0]] != psb[0]) break; 3025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha_added != 4 && psb[alpha_added] != 255) break; 3026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; /* x loop */ 3027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; /* impossible */ 3029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If we get to here the fast match failed; do the slow match for this 3034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pixel. 3035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!cmppixel(&tr, psa, psb, x, y) && (a->opts & KEEP_GOING) == 0) 3037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* error case */ 3038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If reqested copy the error values back from the Transform. */ 3042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (a->opts & ACCUMULATE) 3043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[0] = tr.error[0]; 3045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[1] = tr.error[1]; 3046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[2] = tr.error[2]; 3047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tr.error_ptr[3] = tr.error[3]; 3048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Read the file; how the read gets done depends on which of input_file and 3054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * input_memory have been set. 3055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3056b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3057b50c217251b086440efcdb273c22f86a06c80cbaChris Craikread_file(Image *image, png_uint_32 format, png_const_colorp background) 3058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(&image->image, 0, sizeof image->image); 3060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->image.version = PNG_IMAGE_VERSION; 3061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->input_memory != NULL) 3063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!png_image_begin_read_from_memory(&image->image, image->input_memory, 3065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory_size)) 3066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, "memory init: ", image->file_name, ""); 3067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3069b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_STDIO_SUPPORTED 3070b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (image->input_file != NULL) 3071b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 3072b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!png_image_begin_read_from_stdio(&image->image, image->input_file)) 3073b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return logerror(image, "stdio init: ", image->file_name, ""); 3074b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 3075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3076b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 3077b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 3078b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!png_image_begin_read_from_file(&image->image, image->file_name)) 3079b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return logerror(image, "file init: ", image->file_name, ""); 3080b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 3081b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# else 3082b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 3083b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 3084b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return logerror(image, "unsupported file/stdio init: ", 3085b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari image->file_name, ""); 3086b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 3087b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 3088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This must be set after the begin_read call: */ 3090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opts & sRGB_16BIT) 3091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->image.flags |= PNG_IMAGE_FLAG_16BIT_sRGB; 3092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Have an initialized image with all the data we need plus, maybe, an 3094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * allocated file (myfile) or buffer (mybuffer) that need to be freed. 3095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 3098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 image_format; 3099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Print both original and output formats. */ 3101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image_format = image->image.format; 3102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opts & VERBOSE) 3104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("%s %lu x %lu %s -> %s", image->file_name, 3106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)image->image.width, 3107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)image->image.height, 3108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format_names[image_format & FORMAT_MASK], 3109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (format & FORMAT_NO_CHANGE) != 0 || image->image.format == format 3110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ? "no change" : format_names[format & FORMAT_MASK]); 3111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background != NULL) 3113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" background(%d,%d,%d)\n", background->red, 3114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background->green, background->blue); 3115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("\n"); 3117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'NO_CHANGE' combined with the color-map flag forces the base format 3122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * flags to be set on read to ensure that the original representation is 3123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * not lost in the pass through a colormap format. 3124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & FORMAT_NO_CHANGE) != 0) 3126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 && 3128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image_format & PNG_FORMAT_FLAG_COLORMAP) != 0) 3129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format = (image_format & ~BASE_FORMATS) | (format & BASE_FORMATS); 3130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format = image_format; 3133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->image.format = format; 3136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->stride = PNG_IMAGE_ROW_STRIDE(image->image) + image->stride_extra; 3138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik allocbuffer(image); 3139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_image_finish_read(&image->image, background, 3141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->buffer+16, (png_int_32)image->stride, image->colormap); 3142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik checkbuffer(image, image->file_name); 3144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (result) 3146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return checkopaque(image); 3147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, image->file_name, ": image read failed", ""); 3150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Reads from a filename, which must be in image->file_name, but uses 3154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * image->opts to choose the method. The file is always read in its native 3155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * format (the one the simplified API suggests). 3156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3157b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3158b50c217251b086440efcdb273c22f86a06c80cbaChris Craikread_one_file(Image *image) 3159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(image->opts & READ_FILE) || (image->opts & USE_STDIO)) 3161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* memory or stdio. */ 3163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *f = fopen(image->file_name, "rb"); 3164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (f != NULL) 3166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opts & READ_FILE) 3168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_file = f; 3169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* memory */ 3171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fseek(f, 0, SEEK_END) == 0) 3173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik long int cb = ftell(f); 3175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cb > 0 && (unsigned long int)cb < (size_t)~(size_t)0) 3177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep b = voidcast(png_bytep, malloc((size_t)cb)); 3179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (b != NULL) 3181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik rewind(f); 3183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fread(b, (size_t)cb, 1, f) == 1) 3185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fclose(f); 3187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory_size = cb; 3188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory = b; 3189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik free(b); 3194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logclose(image, f, image->file_name, 3195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ": read failed: "); 3196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logclose(image, f, image->file_name, 3201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ": out of memory: "); 3202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (cb == 0) 3205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logclose(image, f, image->file_name, 3206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ": zero length: "); 3207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logclose(image, f, image->file_name, 3210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ": tell failed: "); 3211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logclose(image, f, image->file_name, ": seek failed: "); 3215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, image->file_name, ": open failed: ", 3220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strerror(errno)); 3221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return read_file(image, FORMAT_NO_CHANGE, NULL); 3224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 3227b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3228b50c217251b086440efcdb273c22f86a06c80cbaChris Craikwrite_one_file(Image *output, Image *image, int convert_to_8bit) 3229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opts & FAST_WRITE) 3231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->image.flags |= PNG_IMAGE_FLAG_FAST; 3232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opts & USE_STDIO) 3234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *f = tmpfile(); 3236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (f != NULL) 3238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_image_write_to_stdio(&image->image, f, convert_to_8bit, 3240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->buffer+16, (png_int_32)image->stride, image->colormap)) 3241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fflush(f) == 0) 3243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik rewind(f); 3245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik initimage(output, image->opts, "tmpfile", image->stride_extra); 3246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output->input_file = f; 3247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!checkopaque(image)) 3248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 3249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logclose(image, f, "tmpfile", ": flush: "); 3253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fclose(f); 3258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, "tmpfile", ": write failed", ""); 3259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, "tmpfile", ": open: ", strerror(errno)); 3264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static int counter = 0; 3269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char name[32]; 3270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sprintf(name, "%s%d.png", tmpf, ++counter); 3272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_image_write_to_file(&image->image, name, convert_to_8bit, 3274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->buffer+16, (png_int_32)image->stride, image->colormap)) 3275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik initimage(output, image->opts, output->tmpfile_name, 3277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->stride_extra); 3278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Afterwards, or freeimage will delete it! */ 3279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strcpy(output->tmpfile_name, name); 3280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!checkopaque(image)) 3282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 3283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, name, ": write failed", ""); 3287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'output' has an initialized temporary image, read this back in and compare 3290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this against the original: there should be no change since the original 3291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * format was written unmodified unless 'convert_to_8bit' was specified. 3292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * However, if the original image was color-mapped, a simple read will zap 3293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the linear, color and maybe alpha flags, this will cause spurious failures 3294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * under some circumstances. 3295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (read_file(output, image->image.format | FORMAT_NO_CHANGE, NULL)) 3297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 original_format = image->image.format; 3299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (convert_to_8bit) 3301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik original_format &= ~PNG_FORMAT_FLAG_LINEAR; 3302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((output->image.format & BASE_FORMATS) != 3304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (original_format & BASE_FORMATS)) 3305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(image, image->file_name, ": format changed on read: ", 3306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output->file_name); 3307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return compare_two_images(image, output, 0/*via linear*/, NULL); 3309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return logerror(output, output->tmpfile_name, 3313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ": read of new file failed", ""); 3314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3317b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3318b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktestimage(Image *image, png_uint_32 opts, format_list *pf) 3319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 3321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Image copy; 3322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Copy the original data, stealing it from 'image' */ 3324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik checkopaque(image); 3325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik copy = *image; 3326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik copy.opts = opts; 3328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik copy.buffer = NULL; 3329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik copy.bufsize = 0; 3330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik copy.allocsize = 0; 3331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_file = NULL; 3333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory = NULL; 3334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->input_memory_size = 0; 3335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->tmpfile_name[0] = 0; 3336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 counter; 3339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Image output; 3340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik newimage(&output); 3342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 1; 3344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Use the low bit of 'counter' to indicate whether or not to do alpha 3346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * removal with a background color or by composting onto the image; this 3347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * step gets skipped if it isn't relevant 3348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (counter=0; counter<2*FORMAT_COUNT; ++counter) 3350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format_isset(pf, counter >> 1)) 3351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 format = counter >> 1; 3353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color background_color; 3355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_colorp background = NULL; 3356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If there is a format change that removes the alpha channel then 3358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the background is relevant. If the output is 8-bit color-mapped 3359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * then a background color *must* be provided, otherwise there are 3360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * two tests to do - one with a color, the other with NULL. The 3361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * NULL test happens second. 3362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((counter & 1) == 0) 3364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & PNG_FORMAT_FLAG_ALPHA) == 0 && 3366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image->image.format & PNG_FORMAT_FLAG_ALPHA) != 0) 3367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Alpha/transparency will be removed, the background is 3369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * relevant: make it a color the first time 3370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik random_color(&background_color); 3372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background = &background_color; 3373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* BUT if the output is to a color-mapped 8-bit format then 3375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the background must always be a color, so increment 'counter' 3376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to skip the NULL test. 3377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 && 3379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (format & PNG_FORMAT_FLAG_LINEAR) == 0) 3380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++counter; 3381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Otherwise an alpha channel is not being eliminated, just leave 3384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background NULL and skip the (counter & 1) NULL test. 3385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++counter; 3388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* else just use NULL for background */ 3390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik resetimage(©); 3392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik copy.opts = opts; /* in case read_file needs to change it */ 3393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = read_file(©, format, background); 3395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!result) 3396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Make sure the file just read matches the original file. */ 3399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = compare_two_images(image, ©, 0/*via linear*/, background); 3400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!result) 3401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 3404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Write the *copy* just made to a new file to make sure the write 3405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * side works ok. Check the conversion to sRGB if the copy is 3406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear. 3407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output.opts = opts; 3409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = write_one_file(&output, ©, 0/*convert to 8bit*/); 3410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!result) 3411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Validate against the original too; the background is needed here 3414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * as well so that compare_two_images knows what color was used. 3415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = compare_two_images(image, &output, 0, background); 3417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!result) 3418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & PNG_FORMAT_FLAG_LINEAR) != 0 && 3421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (format & PNG_FORMAT_FLAG_COLORMAP) == 0) 3422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'output' is linear, convert to the corresponding sRGB format. 3424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output.opts = opts; 3426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = write_one_file(&output, ©, 1/*convert to 8bit*/); 3427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!result) 3428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This may involve a conversion via linear; in the ideal world 3431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this would round-trip correctly, but libpng 1.5.7 is not the 3432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ideal world so allow a drift (error_via_linear). 3433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'image' has an alpha channel but 'output' does not then there 3435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * will a strip-alpha-channel operation (because 'output' is 3436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear), handle this by composing on black when doing the 3437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * comparison. 3438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = compare_two_images(image, &output, 1/*via_linear*/, 3440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background); 3441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!result) 3442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ 3445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik freeimage(&output); 3448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik freeimage(©); 3451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 3453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3455b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3456b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktest_one_file(const char *file_name, format_list *formats, png_uint_32 opts, 3457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int stride_extra, int log_pass) 3458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 3460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Image image; 3461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik newimage(&image); 3463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik initimage(&image, opts, file_name, stride_extra); 3464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = read_one_file(&image); 3465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (result) 3466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = testimage(&image, opts, formats); 3467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik freeimage(&image); 3468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Ensure that stderr is flushed into any log file */ 3470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stderr); 3471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (log_pass) 3473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (result) 3475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("PASS:"); 3476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("FAIL:"); 3479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifndef PNG_SIMPLIFIED_WRITE_SUPPORTED 3481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" (no write)"); 3482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 3483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik print_opts(opts); 3485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" %s\n", file_name); 3486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* stdout may not be line-buffered if it is piped to a file, so: */ 3487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (!result) 3491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(1); 3492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 3494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3496b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint 3497b50c217251b086440efcdb273c22f86a06c80cbaChris Craikmain(int argc, char **argv) 3498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 opts = FAST_WRITE; 3500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format_list formats; 3501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const char *touch = NULL; 3502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int log_pass = 0; 3503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int redundant = 0; 3504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int stride_extra = 0; 3505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int retval = 0; 3506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int c; 3507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik init_sRGB_to_d(); 3509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 3510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik init_error_via_linear(); 3511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format_init(&formats); 3513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (c=1; c<argc; ++c) 3515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const char *arg = argv[c]; 3517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (strcmp(arg, "--log") == 0) 3519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik log_pass = 1; 3520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--fresh") == 0) 3521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(gpc_error, 0, sizeof gpc_error); 3523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(gpc_error_via_linear, 0, sizeof gpc_error_via_linear); 3524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--file") == 0) 3526b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_STDIO_SUPPORTED 3527b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari opts |= READ_FILE; 3528b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# else 3529b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 77; /* skipped: no support */ 3530b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 3531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--memory") == 0) 3532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~READ_FILE; 3533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--stdio") == 0) 3534b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_STDIO_SUPPORTED 3535b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari opts |= USE_STDIO; 3536b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# else 3537b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 77; /* skipped: no support */ 3538b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 3539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--name") == 0) 3540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~USE_STDIO; 3541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--verbose") == 0) 3542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= VERBOSE; 3543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--quiet") == 0) 3544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~VERBOSE; 3545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--preserve") == 0) 3546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= KEEP_TMPFILES; 3547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--nopreserve") == 0) 3548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~KEEP_TMPFILES; 3549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--keep-going") == 0) 3550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= KEEP_GOING; 3551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--fast") == 0) 3552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= FAST_WRITE; 3553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--slow") == 0) 3554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~FAST_WRITE; 3555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--accumulate") == 0) 3556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= ACCUMULATE; 3557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--redundant") == 0) 3558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik redundant = 1; 3559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--stop") == 0) 3560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~KEEP_GOING; 3561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--strict") == 0) 3562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= STRICT; 3563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--sRGB-16bit") == 0) 3564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts |= sRGB_16BIT; 3565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--linear-16bit") == 0) 3566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik opts &= ~sRGB_16BIT; 3567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--tmpfile") == 0) 3568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (c+1 < argc) 3570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (strlen(argv[++c]) >= sizeof tmpf) 3572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: %s is too long for a temp file prefix\n", 3575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argv[0], argv[c]); 3576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Safe: checked above */ 3580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strcpy(tmpf, argv[c]); 3581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: %s requires a temporary file prefix\n", 3587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argv[0], arg); 3588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (strcmp(arg, "--touch") == 0) 3592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (c+1 < argc) 3594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik touch = argv[++c]; 3595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: %s requires a file name argument\n", 3600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argv[0], arg); 3601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (arg[0] == '+') 3605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 format = formatof(arg+1); 3607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format > FORMAT_COUNT) 3609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format_set(&formats, format); 3612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (arg[0] == '-' && arg[1] != 0 && (arg[1] != '0' || arg[2] != 0)) 3614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: unknown option: %s\n", argv[0], arg); 3617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format_is_initial(&formats)) 3622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format_default(&formats, redundant); 3623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (arg[0] == '-') 3625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int term = (arg[1] == '0' ? 0 : '\n'); 3627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int ich = 0; 3628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Loop reading files, use a static buffer to simplify this and just 3630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * stop if the name gets to long. 3631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static char buffer[4096]; 3633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 3635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ch = getchar(); 3637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Don't allow '\0' in file names, and terminate with '\n' or, 3639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for -0, just '\0' (use -print0 to find to make this work!) 3640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ch == EOF || ch == term || ch == 0) 3642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buffer[ich] = 0; 3644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ich > 0 && !test_one_file(buffer, &formats, opts, 3646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stride_extra, log_pass)) 3647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik retval = 1; 3648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ch == EOF) 3650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ich = 0; 3653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --ich; /* so that the increment below sets it to 0 again */ 3654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buffer[ich] = (char)ch; 3658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } while (++ich < sizeof buffer); 3659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ich) 3661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buffer[32] = 0; 3663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buffer[4095] = 0; 3664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s...%s: file name too long\n", buffer, 3665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buffer+(4096-32)); 3666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (!test_one_file(arg, &formats, opts, stride_extra, log_pass)) 3671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik retval = 1; 3672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (opts & ACCUMULATE) 3676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int in; 3678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("static png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] =\n"); 3680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("{\n"); 3681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (in=0; in<16; ++in) 3682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int out; 3684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" { /* input: %s */\n ", format_names[in]); 3685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (out=0; out<16; ++out) 3686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int alpha; 3688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" {"); 3689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (alpha=0; alpha<4; ++alpha) 3690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" %d", gpc_error[in][out][alpha]); 3692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 3) putchar(','); 3693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" }"); 3695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out < 15) 3696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar(','); 3698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out % 4 == 3) printf("\n "); 3699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("\n }"); 3702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in < 15) 3704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar(','); 3705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar('\n'); 3707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("};\n"); 3709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("static png_uint_16 gpc_error_via_linear[16][4/*out*/][4] =\n"); 3711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("{\n"); 3712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (in=0; in<16; ++in) 3713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int out; 3715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" { /* input: %s */\n ", format_names[in]); 3716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (out=0; out<4; ++out) 3717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int alpha; 3719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" {"); 3720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (alpha=0; alpha<4; ++alpha) 3721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" %d", gpc_error_via_linear[in][out][alpha]); 3723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 3) putchar(','); 3724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" }"); 3726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out < 3) 3727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar(','); 3728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("\n }"); 3730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in < 15) 3732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar(','); 3733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar('\n'); 3735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("};\n"); 3737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("static png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] =\n"); 3739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("{\n"); 3740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (in=0; in<8; ++in) 3741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int out; 3743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" { /* input: %s */\n ", format_names[in]); 3744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (out=0; out<8; ++out) 3745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int alpha; 3747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" {"); 3748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (alpha=0; alpha<4; ++alpha) 3749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" %d", gpc_error_to_colormap[in][out][alpha]); 3751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 3) putchar(','); 3752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf(" }"); 3754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out < 7) 3755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar(','); 3757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out % 4 == 3) printf("\n "); 3758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("\n }"); 3761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (in < 7) 3763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar(','); 3764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik putchar('\n'); 3766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik printf("};\n"); 3768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (retval == 0 && touch != NULL) 3771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *fsuccess = fopen(touch, "wt"); 3773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fsuccess != NULL) 3775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int error = 0; 3777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(fsuccess, "PNG simple API tests succeeded\n"); 3778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(fsuccess); 3779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = ferror(fsuccess); 3780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fclose(fsuccess) || error) 3782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: write failed\n", touch); 3785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fflush(stdout); 3792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "%s: open failed\n", touch); 3793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exit(99); 3794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return retval; 3798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else /* !PNG_SIMPLIFIED_READ_SUPPORTED */ 3801b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint main(void) 3802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fprintf(stderr, "pngstest: no read support in libpng, test skipped\n"); 3804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* So the test is skipped: */ 3805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 77; 3806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ 3808