all repos — mgba @ 9de8f084ba55460b02d300c1dd8b8e6c56f691d5

mGBA Game Boy Advance Emulator

src/third-party/libpng/contrib/libtests/pngstest.c (view raw)

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