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