pngtest.c 11.2 KB
Newer Older
A
Andreas Dilger 已提交
1

G
Guy Schalnat 已提交
2
/* pngtest.c - a simple test program to test libpng
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * libpng 1.00.97
 * For conditions of distribution and use, see copyright notice in png.h
 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
 * Copyright (c) 1996, 1997 Andreas Dilger
 * May 28, 1997
 *
 * This program reads in a PNG image, writes it out again, and then
 * compares the two files.  If the files are identical, this shows that
 * the basic chunk handling, filtering, and (de)compression code is working
 * properly.  It does not currently test all of the transforms, although
 * it probably should.
 *
 * The program will fail in certain legitimate cases:
 * 1) when the compression level or filter selection method is changed.
 * 2) when the chunk size is smaller than 8K.
 * 3) unknown ancillary chunks exist in the input file.
 * 4) others not listed here...
 * In these cases, it is best to check with another tool such as "pngcheck"
 * to see what the differences between the two images are.
 *
 * If a filename is given on the command-line, then this file is used
 * for the input, rather than the default "pngtest.png".  This allows
 * testing a wide variety of files easily.
 */
G
Guy Schalnat 已提交
28 29 30

#include <stdio.h>
#include <stdlib.h>
A
Andreas Dilger 已提交
31 32 33 34 35 36

/* Makes pngtest verbose so we can find problems (needs to be before png.h) */
#ifndef PNG_DEBUG
#define PNG_DEBUG 0
#endif

G
Guy Schalnat 已提交
37 38 39 40 41 42 43
#include "png.h"

#ifdef __TURBOC__
#include <mem.h>
#endif

/* defined so I can write to a file on gui/windowing platforms */
G
Guy Schalnat 已提交
44
/*  #define STDERR stderr  */
G
Guy Schalnat 已提交
45
#define STDERR stdout   /* for DOS */
G
Guy Schalnat 已提交
46 47

/* input and output filenames */
G
Guy Schalnat 已提交
48
#ifdef RISCOS
49 50
PNG_CONST char *inname = "pngtest_png";
PNG_CONST char *outname = "pngout_png";
G
Guy Schalnat 已提交
51
#else
52 53
PNG_CONST char *inname = "pngtest.png";
PNG_CONST char *outname = "pngout.png";
G
Guy Schalnat 已提交
54
#endif
G
Guy Schalnat 已提交
55 56 57

char inbuf[256], outbuf[256];

A
Andreas Dilger 已提交
58 59
int
main(int argc, char *argv[])
G
Guy Schalnat 已提交
60
{
G
Guy Schalnat 已提交
61
   FILE *fpin, *fpout;
A
Andreas Dilger 已提交
62 63
   png_structp read_ptr, write_ptr;
   png_infop read_info_ptr, write_info_ptr, end_info_ptr;
G
Guy Schalnat 已提交
64
   png_bytep row_buf;
G
Guy Schalnat 已提交
65
   png_uint_32 y;
A
Andreas Dilger 已提交
66 67 68
   png_uint_32 width, height;
   int num_pass, pass;
   int bit_depth, color_type;
A
Andreas Dilger 已提交
69 70 71
#ifdef USE_FAR_KEYWORD
   jmp_buf jmpbuf;
#endif   
G
Guy Schalnat 已提交
72
   row_buf = (png_bytep)NULL;
G
Guy Schalnat 已提交
73

G
Guy Schalnat 已提交
74 75 76 77 78 79 80 81 82 83
   fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);

   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
   {
      fprintf(STDERR,
         "Warning: versions are different between png.h and png.c\n");
      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
   }

G
Guy Schalnat 已提交
84 85 86 87 88 89 90 91 92 93 94 95
   if (argc > 1)
     inname = argv[1];

   if (argc > 2)
     outname = argv[2];

   if (argc > 3)
   {
     fprintf(stderr, "usage: %s [infile.png] [outfile.png]\n", argv[0]);
     exit(1);
   }

A
Andreas Dilger 已提交
96
   if ((fpin = fopen(inname, "rb")) == NULL)
G
Guy Schalnat 已提交
97 98 99 100 101
   {
      fprintf(STDERR, "Could not find input file %s\n", inname);
      return 1;
   }

A
Andreas Dilger 已提交
102
   if ((fpout = fopen(outname, "wb")) == NULL)
G
Guy Schalnat 已提交
103
   {
G
Guy Schalnat 已提交
104
      fprintf(STDERR, "Could not open output file %s\n", outname);
G
Guy Schalnat 已提交
105 106 107 108
      fclose(fpin);
      return 1;
   }

A
Andreas Dilger 已提交
109
   png_debug(0, "Allocating read and write structures\n");
A
Andreas Dilger 已提交
110
   read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
A
Andreas Dilger 已提交
111
      (png_error_ptr)NULL, (png_error_ptr)NULL);
A
Andreas Dilger 已提交
112
   write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
G
Guy Schalnat 已提交
113
      (png_error_ptr)NULL, (png_error_ptr)NULL);
A
Andreas Dilger 已提交
114 115 116 117
   png_debug(0, "Allocating read_info, write_info and end_info structures\n");
   read_info_ptr = png_create_info_struct(read_ptr);
   write_info_ptr = png_create_info_struct(read_ptr);
   end_info_ptr = png_create_info_struct(read_ptr);
G
Guy Schalnat 已提交
118

A
Andreas Dilger 已提交
119
   png_debug(0, "Setting jmpbuf for read struct\n");
A
Andreas Dilger 已提交
120 121 122
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
#else
G
Guy Schalnat 已提交
123
   if (setjmp(read_ptr->jmpbuf))
A
Andreas Dilger 已提交
124
#endif
G
Guy Schalnat 已提交
125 126
   {
      fprintf(STDERR, "libpng read error\n");
A
Andreas Dilger 已提交
127 128
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
G
Guy Schalnat 已提交
129 130 131 132
      fclose(fpin);
      fclose(fpout);
      return 1;
   }
A
Andreas Dilger 已提交
133 134

   png_debug(0, "Setting jmpbuf for write struct\n");
A
Andreas Dilger 已提交
135 136 137 138
#ifdef USE_FAR_KEYWORD
   png_memcpy(read_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
   if (setjmp(jmpbuf))
#else
G
Guy Schalnat 已提交
139
   if (setjmp(write_ptr->jmpbuf))
A
Andreas Dilger 已提交
140
#endif
G
Guy Schalnat 已提交
141
   {
G
Guy Schalnat 已提交
142
      fprintf(STDERR, "libpng write error\n");
A
Andreas Dilger 已提交
143 144
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
G
Guy Schalnat 已提交
145 146 147 148
      fclose(fpin);
      fclose(fpout);
      return 1;
   }
A
Andreas Dilger 已提交
149

A
Andreas Dilger 已提交
150 151 152
#ifdef USE_FAR_KEYWORD
   png_memcpy(write_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
#endif
A
Andreas Dilger 已提交
153
   png_debug(0, "Initializing input and output streams\n");
G
Guy Schalnat 已提交
154 155
   png_init_io(read_ptr, fpin);
   png_init_io(write_ptr, fpout);
G
Guy Schalnat 已提交
156

A
Andreas Dilger 已提交
157 158
   png_debug(0, "Reading info struct\n");
   png_read_info(read_ptr, read_info_ptr);
G
Guy Schalnat 已提交
159

A
Andreas Dilger 已提交
160 161 162
   png_debug(0, "Transferring info struct\n");
   {
      int interlace_type, compression_type, filter_type;
G
Guy Schalnat 已提交
163

A
Andreas Dilger 已提交
164 165 166 167 168 169 170 171
      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
          &color_type, &interlace_type, &compression_type, &filter_type))
      {
         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
            color_type, interlace_type, compression_type, filter_type);
      }
   }
#if defined(PNG_READ_bKGD_SUPPORTED) && defined(PNG_WRITE_bKGD_SUPPORTED)
G
Guy Schalnat 已提交
172
   {
A
Andreas Dilger 已提交
173 174 175 176 177 178
      png_color_16p background;

      if (png_get_bKGD(read_ptr, read_info_ptr, &background))
      {
         png_set_bKGD(write_ptr, write_info_ptr, background);
      }
G
Guy Schalnat 已提交
179
   }
A
Andreas Dilger 已提交
180 181 182 183
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) && defined(PNG_WRITE_cHRM_SUPPORTED)
   {
      double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
G
Guy Schalnat 已提交
184

A
Andreas Dilger 已提交
185 186 187 188 189 190 191 192 193
      if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
         &red_y, &green_x, &green_y, &blue_x, &blue_y))
      {
         png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
            red_y, green_x, green_y, blue_x, blue_y);
      }
   }
#endif
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_WRITE_gAMA_SUPPORTED)
G
Guy Schalnat 已提交
194
   {
A
Andreas Dilger 已提交
195 196 197 198 199 200
      double gamma;

      if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
      {
         png_set_gAMA(write_ptr, write_info_ptr, gamma);
      }
G
Guy Schalnat 已提交
201
   }
202 203 204 205 206 207 208 209 210 211
#endif
#if defined(PNG_READ_sRGB_SUPPORTED) && defined(PNG_WRITE_sRGB_SUPPORTED)
   {
      png_byte intent;

      if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
      {
         png_set_sRGB(write_ptr, write_info_ptr, intent);
      }
   }
A
Andreas Dilger 已提交
212 213
#endif
#if defined(PNG_READ_hIST_SUPPORTED) && defined(PNG_WRITE_hIST_SUPPORTED)
G
Guy Schalnat 已提交
214
   {
A
Andreas Dilger 已提交
215 216 217 218 219 220
      png_uint_16p hist;

      if (png_get_hIST(read_ptr, read_info_ptr, &hist))
      {
         png_set_hIST(write_ptr, write_info_ptr, hist);
      }
G
Guy Schalnat 已提交
221
   }
A
Andreas Dilger 已提交
222 223 224 225 226
#endif
#if defined(PNG_READ_oFFs_SUPPORTED) && defined(PNG_WRITE_oFFs_SUPPORTED)
   {
      png_uint_32 offset_x, offset_y;
      int unit_type;
G
Guy Schalnat 已提交
227

A
Andreas Dilger 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
      if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
      {
         png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
      }
   }
#endif
#if defined(PNG_READ_pCAL_SUPPORTED) && defined(PNG_WRITE_pCAL_SUPPORTED)
   {
      png_charp purpose, units;
      png_charpp params;
      png_int_32 X0, X1;
      int type, nparams;

      if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
         &nparams, &units, &params))
      {
         png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
            nparams, units, params);
      }
   }
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) && defined(PNG_WRITE_pHYs_SUPPORTED)
   {
      png_uint_32 res_x, res_y;
      int unit_type;

      if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
      {
         png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
      }
   }
#endif
   {
      png_colorp palette;
      int num_palette;

      if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
      {
         png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
      }
   }
#if defined(PNG_READ_sBIT_SUPPORTED) && defined(PNG_WRITE_sBIT_SUPPORTED)
G
Guy Schalnat 已提交
270
   {
A
Andreas Dilger 已提交
271 272 273
      png_color_8p sig_bit;

      if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
G
Guy Schalnat 已提交
274
      {
A
Andreas Dilger 已提交
275 276 277
         png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
      }
   }
G
Guy Schalnat 已提交
278
#endif
A
Andreas Dilger 已提交
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
#if (defined(PNG_READ_tEXt_SUPPORTED) && defined(PNG_WRITE_tEXt_SUPPORTED)) || \
    (defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED))
   {
      png_textp text_ptr;
      int num_text;

      if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
      {
         png_debug1(0, "Handling %d tEXt/zTXt chunks\n", num_text);
         png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
      }
   }
#endif
#if defined(PNG_READ_tIME_SUPPORTED) && defined(PNG_WRITE_tIME_SUPPORTED)
   {
      png_timep mod_time;

      if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
      {
         png_set_tIME(write_ptr, write_info_ptr, mod_time);
      }
   }
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) && defined(PNG_WRITE_tRNS_SUPPORTED)
   {
      png_bytep trans;
      int num_trans;
      png_color_16p trans_values;

      if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
         &trans_values))
      {
         png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
            trans_values);
      }
   }
#endif

   png_debug(0, "\nWriting info struct\n");
   png_write_info(write_ptr, write_info_ptr);

   row_buf = (png_bytep)png_malloc(read_ptr, 
      png_get_rowbytes(read_ptr, read_info_ptr));
   if (row_buf == NULL)
   {
      fprintf(STDERR, "No memory to allocate row buffer\n");
      png_destroy_read_struct(&read_ptr, &read_info_ptr, (png_infopp)NULL);
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
      fclose(fpin);
      fclose(fpout);
      return 1;
   }

   num_pass = png_set_interlace_handling(read_ptr);
   png_set_interlace_handling(write_ptr);

   for (pass = 0; pass < num_pass; pass++)
   {
      for (y = 0; y < height; y++)
      {
         png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)NULL, 1);
G
Guy Schalnat 已提交
340
         png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
G
Guy Schalnat 已提交
341 342 343
      }
   }

A
Andreas Dilger 已提交
344 345 346
   png_debug(0, "Reading and writing end_info data\n");
   png_read_end(read_ptr, end_info_ptr);
   png_write_end(write_ptr, end_info_ptr);
G
Guy Schalnat 已提交
347

A
Andreas Dilger 已提交
348 349 350
   png_debug(0, "Destroying data structs\n");
   png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
   png_destroy_write_struct(&write_ptr, &write_info_ptr);
G
Guy Schalnat 已提交
351 352 353 354

   fclose(fpin);
   fclose(fpout);

A
Andreas Dilger 已提交
355
   png_free(read_ptr, row_buf);
G
Guy Schalnat 已提交
356

A
Andreas Dilger 已提交
357 358
   png_debug(0, "Opening files for comparison\n");
   if ((fpin = fopen(inname, "rb")) == NULL)
G
Guy Schalnat 已提交
359
   {
G
Guy Schalnat 已提交
360
      fprintf(STDERR, "Could not find file %s\n", inname);
G
Guy Schalnat 已提交
361 362 363
      return 1;
   }

A
Andreas Dilger 已提交
364
   if ((fpout = fopen(outname, "rb")) == NULL)
G
Guy Schalnat 已提交
365
   {
G
Guy Schalnat 已提交
366
      fprintf(STDERR, "Could not find file %s\n", outname);
G
Guy Schalnat 已提交
367 368 369
      fclose(fpin);
      return 1;
   }
A
Andreas Dilger 已提交
370

G
Guy Schalnat 已提交
371 372
   while (1)
   {
A
Andreas Dilger 已提交
373
      png_size_t num_in, num_out;
G
Guy Schalnat 已提交
374

A
Andreas Dilger 已提交
375 376
      num_in = fread(inbuf, 1, 1, fpin);
      num_out = fread(outbuf, 1, 1, fpout);
G
Guy Schalnat 已提交
377 378 379

      if (num_in != num_out)
      {
G
Guy Schalnat 已提交
380 381
         fprintf(STDERR, "Files %s and %s are of a different size\n",
                 inname, outname);
G
Guy Schalnat 已提交
382 383 384 385 386 387 388 389
         fclose(fpin);
         fclose(fpout);
         return 1;
      }

      if (!num_in)
         break;

A
Andreas Dilger 已提交
390
      if (png_memcmp(inbuf, outbuf, num_in))
G
Guy Schalnat 已提交
391
      {
G
Guy Schalnat 已提交
392
         fprintf(STDERR, "Files %s and %s are different\n", inname, outname);
G
Guy Schalnat 已提交
393 394 395 396 397 398 399 400
         fclose(fpin);
         fclose(fpout);
         return 1;
      }
   }

   fclose(fpin);
   fclose(fpout);
G
Guy Schalnat 已提交
401 402 403 404
   fprintf(STDERR, "libpng passes test\n");

   return 0;
}
G
Guy Schalnat 已提交
405