1 |
|
2 |
/* pngtest.c - a simple test program to test libpng |
3 |
* |
4 |
* Last changed in libpng 1.2.37 [June 4, 2009] |
5 |
* Copyright (c) 1998-2009 Glenn Randers-Pehrson |
6 |
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 |
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 |
* |
9 |
* This code is released under the libpng license. |
10 |
* For conditions of distribution and use, see the disclaimer |
11 |
* and license in png.h |
12 |
* |
13 |
* This program reads in a PNG image, writes it out again, and then |
14 |
* compares the two files. If the files are identical, this shows that |
15 |
* the basic chunk handling, filtering, and (de)compression code is working |
16 |
* properly. It does not currently test all of the transforms, although |
17 |
* it probably should. |
18 |
* |
19 |
* The program will report "FAIL" in certain legitimate cases: |
20 |
* 1) when the compression level or filter selection method is changed. |
21 |
* 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. |
22 |
* 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks |
23 |
* exist in the input file. |
24 |
* 4) others not listed here... |
25 |
* In these cases, it is best to check with another tool such as "pngcheck" |
26 |
* to see what the differences between the two files are. |
27 |
* |
28 |
* If a filename is given on the command-line, then this file is used |
29 |
* for the input, rather than the default "pngtest.png". This allows |
30 |
* testing a wide variety of files easily. You can also test a number |
31 |
* of files at once by typing "pngtest -m file1.png file2.png ..." |
32 |
*/ |
33 |
|
34 |
#include "png.h" |
35 |
|
36 |
#if defined(_WIN32_WCE) |
37 |
# if _WIN32_WCE < 211 |
38 |
__error__ (f|w)printf functions are not supported on old WindowsCE.; |
39 |
# endif |
40 |
# include <windows.h> |
41 |
# include <stdlib.h> |
42 |
# define READFILE(file, data, length, check) \ |
43 |
if (ReadFile(file, data, length, &check, NULL)) check = 0 |
44 |
# define WRITEFILE(file, data, length, check)) \ |
45 |
if (WriteFile(file, data, length, &check, NULL)) check = 0 |
46 |
# define FCLOSE(file) CloseHandle(file) |
47 |
#else |
48 |
# include <stdio.h> |
49 |
# include <stdlib.h> |
50 |
# define READFILE(file, data, length, check) \ |
51 |
check=(png_size_t)fread(data, (png_size_t)1, length, file) |
52 |
# define WRITEFILE(file, data, length, check) \ |
53 |
check=(png_size_t)fwrite(data, (png_size_t)1, length, file) |
54 |
# define FCLOSE(file) fclose(file) |
55 |
#endif |
56 |
|
57 |
#if defined(PNG_NO_STDIO) |
58 |
# if defined(_WIN32_WCE) |
59 |
typedef HANDLE png_FILE_p; |
60 |
# else |
61 |
typedef FILE * png_FILE_p; |
62 |
# endif |
63 |
#endif |
64 |
|
65 |
/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ |
66 |
#ifndef PNG_DEBUG |
67 |
# define PNG_DEBUG 0 |
68 |
#endif |
69 |
|
70 |
#if !PNG_DEBUG |
71 |
# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ |
72 |
#endif |
73 |
|
74 |
/* Turn on CPU timing |
75 |
#define PNGTEST_TIMING |
76 |
*/ |
77 |
|
78 |
#ifdef PNG_NO_FLOATING_POINT_SUPPORTED |
79 |
#undef PNGTEST_TIMING |
80 |
#endif |
81 |
|
82 |
#ifdef PNGTEST_TIMING |
83 |
static float t_start, t_stop, t_decode, t_encode, t_misc; |
84 |
#include <time.h> |
85 |
#endif |
86 |
|
87 |
#if defined(PNG_TIME_RFC1123_SUPPORTED) |
88 |
#define PNG_tIME_STRING_LENGTH 29 |
89 |
static int tIME_chunk_present = 0; |
90 |
static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; |
91 |
#endif |
92 |
|
93 |
static int verbose = 0; |
94 |
|
95 |
int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); |
96 |
|
97 |
#ifdef __TURBOC__ |
98 |
#include <mem.h> |
99 |
#endif |
100 |
|
101 |
/* Defined so I can write to a file on gui/windowing platforms */ |
102 |
/* #define STDERR stderr */ |
103 |
#define STDERR stdout /* For DOS */ |
104 |
|
105 |
/* In case a system header (e.g., on AIX) defined jmpbuf */ |
106 |
#ifdef jmpbuf |
107 |
# undef jmpbuf |
108 |
#endif |
109 |
|
110 |
/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ |
111 |
#ifndef png_jmpbuf |
112 |
# define png_jmpbuf(png_ptr) png_ptr->jmpbuf |
113 |
#endif |
114 |
|
115 |
/* Example of using row callbacks to make a simple progress meter */ |
116 |
static int status_pass = 1; |
117 |
static int status_dots_requested = 0; |
118 |
static int status_dots = 1; |
119 |
|
120 |
void |
121 |
#ifdef PNG_1_0_X |
122 |
PNGAPI |
123 |
#endif |
124 |
read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); |
125 |
void |
126 |
#ifdef PNG_1_0_X |
127 |
PNGAPI |
128 |
#endif |
129 |
read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) |
130 |
{ |
131 |
if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) |
132 |
return; |
133 |
if (status_pass != pass) |
134 |
{ |
135 |
fprintf(stdout, "\n Pass %d: ", pass); |
136 |
status_pass = pass; |
137 |
status_dots = 31; |
138 |
} |
139 |
status_dots--; |
140 |
if (status_dots == 0) |
141 |
{ |
142 |
fprintf(stdout, "\n "); |
143 |
status_dots=30; |
144 |
} |
145 |
fprintf(stdout, "r"); |
146 |
} |
147 |
|
148 |
void |
149 |
#ifdef PNG_1_0_X |
150 |
PNGAPI |
151 |
#endif |
152 |
write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); |
153 |
void |
154 |
#ifdef PNG_1_0_X |
155 |
PNGAPI |
156 |
#endif |
157 |
write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) |
158 |
{ |
159 |
if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) |
160 |
return; |
161 |
fprintf(stdout, "w"); |
162 |
} |
163 |
|
164 |
|
165 |
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) |
166 |
/* Example of using user transform callback (we don't transform anything, |
167 |
* but merely examine the row filters. We set this to 256 rather than |
168 |
* 5 in case illegal filter values are present.) |
169 |
*/ |
170 |
static png_uint_32 filters_used[256]; |
171 |
void |
172 |
#ifdef PNG_1_0_X |
173 |
PNGAPI |
174 |
#endif |
175 |
count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); |
176 |
void |
177 |
#ifdef PNG_1_0_X |
178 |
PNGAPI |
179 |
#endif |
180 |
count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) |
181 |
{ |
182 |
if (png_ptr != NULL && row_info != NULL) |
183 |
++filters_used[*(data - 1)]; |
184 |
} |
185 |
#endif |
186 |
|
187 |
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) |
188 |
/* Example of using user transform callback (we don't transform anything, |
189 |
* but merely count the zero samples) |
190 |
*/ |
191 |
|
192 |
static png_uint_32 zero_samples; |
193 |
|
194 |
void |
195 |
#ifdef PNG_1_0_X |
196 |
PNGAPI |
197 |
#endif |
198 |
count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); |
199 |
void |
200 |
#ifdef PNG_1_0_X |
201 |
PNGAPI |
202 |
#endif |
203 |
count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) |
204 |
{ |
205 |
png_bytep dp = data; |
206 |
if (png_ptr == NULL)return; |
207 |
|
208 |
/* Contents of row_info: |
209 |
* png_uint_32 width width of row |
210 |
* png_uint_32 rowbytes number of bytes in row |
211 |
* png_byte color_type color type of pixels |
212 |
* png_byte bit_depth bit depth of samples |
213 |
* png_byte channels number of channels (1-4) |
214 |
* png_byte pixel_depth bits per pixel (depth*channels) |
215 |
*/ |
216 |
|
217 |
/* Counts the number of zero samples (or zero pixels if color_type is 3 */ |
218 |
|
219 |
if (row_info->color_type == 0 || row_info->color_type == 3) |
220 |
{ |
221 |
int pos = 0; |
222 |
png_uint_32 n, nstop; |
223 |
for (n = 0, nstop=row_info->width; n<nstop; n++) |
224 |
{ |
225 |
if (row_info->bit_depth == 1) |
226 |
{ |
227 |
if (((*dp << pos++ ) & 0x80) == 0) |
228 |
zero_samples++; |
229 |
if (pos == 8) |
230 |
{ |
231 |
pos = 0; |
232 |
dp++; |
233 |
} |
234 |
} |
235 |
if (row_info->bit_depth == 2) |
236 |
{ |
237 |
if (((*dp << (pos+=2)) & 0xc0) == 0) |
238 |
zero_samples++; |
239 |
if (pos == 8) |
240 |
{ |
241 |
pos = 0; |
242 |
dp++; |
243 |
} |
244 |
} |
245 |
if (row_info->bit_depth == 4) |
246 |
{ |
247 |
if (((*dp << (pos+=4)) & 0xf0) == 0) |
248 |
zero_samples++; |
249 |
if (pos == 8) |
250 |
{ |
251 |
pos = 0; |
252 |
dp++; |
253 |
} |
254 |
} |
255 |
if (row_info->bit_depth == 8) |
256 |
if (*dp++ == 0) |
257 |
zero_samples++; |
258 |
if (row_info->bit_depth == 16) |
259 |
{ |
260 |
if ((*dp | *(dp+1)) == 0) |
261 |
zero_samples++; |
262 |
dp+=2; |
263 |
} |
264 |
} |
265 |
} |
266 |
else /* Other color types */ |
267 |
{ |
268 |
png_uint_32 n, nstop; |
269 |
int channel; |
270 |
int color_channels = row_info->channels; |
271 |
if (row_info->color_type > 3)color_channels--; |
272 |
|
273 |
for (n = 0, nstop=row_info->width; n<nstop; n++) |
274 |
{ |
275 |
for (channel = 0; channel < color_channels; channel++) |
276 |
{ |
277 |
if (row_info->bit_depth == 8) |
278 |
if (*dp++ == 0) |
279 |
zero_samples++; |
280 |
if (row_info->bit_depth == 16) |
281 |
{ |
282 |
if ((*dp | *(dp+1)) == 0) |
283 |
zero_samples++; |
284 |
dp+=2; |
285 |
} |
286 |
} |
287 |
if (row_info->color_type > 3) |
288 |
{ |
289 |
dp++; |
290 |
if (row_info->bit_depth == 16) |
291 |
dp++; |
292 |
} |
293 |
} |
294 |
} |
295 |
} |
296 |
#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ |
297 |
|
298 |
static int wrote_question = 0; |
299 |
|
300 |
#if defined(PNG_NO_STDIO) |
301 |
/* START of code to validate stdio-free compilation */ |
302 |
/* These copies of the default read/write functions come from pngrio.c and |
303 |
* pngwio.c. They allow "don't include stdio" testing of the library. |
304 |
* This is the function that does the actual reading of data. If you are |
305 |
* not reading from a standard C stream, you should create a replacement |
306 |
* read_data function and use it at run time with png_set_read_fn(), rather |
307 |
* than changing the library. |
308 |
*/ |
309 |
|
310 |
#ifndef USE_FAR_KEYWORD |
311 |
static void |
312 |
pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) |
313 |
{ |
314 |
png_size_t check; |
315 |
|
316 |
/* fread() returns 0 on error, so it is OK to store this in a png_size_t |
317 |
* instead of an int, which is what fread() actually returns. |
318 |
*/ |
319 |
READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); |
320 |
|
321 |
if (check != length) |
322 |
{ |
323 |
png_error(png_ptr, "Read Error!"); |
324 |
} |
325 |
} |
326 |
#else |
327 |
/* This is the model-independent version. Since the standard I/O library |
328 |
can't handle far buffers in the medium and small models, we have to copy |
329 |
the data. |
330 |
*/ |
331 |
|
332 |
#define NEAR_BUF_SIZE 1024 |
333 |
#define MIN(a,b) (a <= b ? a : b) |
334 |
|
335 |
static void |
336 |
pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) |
337 |
{ |
338 |
int check; |
339 |
png_byte *n_data; |
340 |
png_FILE_p io_ptr; |
341 |
|
342 |
/* Check if data really is near. If so, use usual code. */ |
343 |
n_data = (png_byte *)CVT_PTR_NOCHECK(data); |
344 |
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); |
345 |
if ((png_bytep)n_data == data) |
346 |
{ |
347 |
READFILE(io_ptr, n_data, length, check); |
348 |
} |
349 |
else |
350 |
{ |
351 |
png_byte buf[NEAR_BUF_SIZE]; |
352 |
png_size_t read, remaining, err; |
353 |
check = 0; |
354 |
remaining = length; |
355 |
do |
356 |
{ |
357 |
read = MIN(NEAR_BUF_SIZE, remaining); |
358 |
READFILE(io_ptr, buf, 1, err); |
359 |
png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ |
360 |
if (err != read) |
361 |
break; |
362 |
else |
363 |
check += err; |
364 |
data += read; |
365 |
remaining -= read; |
366 |
} |
367 |
while (remaining != 0); |
368 |
} |
369 |
if (check != length) |
370 |
png_error(png_ptr, "read Error"); |
371 |
} |
372 |
#endif /* USE_FAR_KEYWORD */ |
373 |
|
374 |
#if defined(PNG_WRITE_FLUSH_SUPPORTED) |
375 |
static void |
376 |
pngtest_flush(png_structp png_ptr) |
377 |
{ |
378 |
/* Do nothing; fflush() is said to be just a waste of energy. */ |
379 |
png_ptr = png_ptr; /* Stifle compiler warning */ |
380 |
} |
381 |
#endif |
382 |
|
383 |
/* This is the function that does the actual writing of data. If you are |
384 |
* not writing to a standard C stream, you should create a replacement |
385 |
* write_data function and use it at run time with png_set_write_fn(), rather |
386 |
* than changing the library. |
387 |
*/ |
388 |
#ifndef USE_FAR_KEYWORD |
389 |
static void |
390 |
pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) |
391 |
{ |
392 |
png_uint_32 check; |
393 |
|
394 |
WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); |
395 |
if (check != length) |
396 |
{ |
397 |
png_error(png_ptr, "Write Error"); |
398 |
} |
399 |
} |
400 |
#else |
401 |
/* This is the model-independent version. Since the standard I/O library |
402 |
can't handle far buffers in the medium and small models, we have to copy |
403 |
the data. |
404 |
*/ |
405 |
|
406 |
#define NEAR_BUF_SIZE 1024 |
407 |
#define MIN(a,b) (a <= b ? a : b) |
408 |
|
409 |
static void |
410 |
pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) |
411 |
{ |
412 |
png_uint_32 check; |
413 |
png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ |
414 |
png_FILE_p io_ptr; |
415 |
|
416 |
/* Check if data really is near. If so, use usual code. */ |
417 |
near_data = (png_byte *)CVT_PTR_NOCHECK(data); |
418 |
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); |
419 |
if ((png_bytep)near_data == data) |
420 |
{ |
421 |
WRITEFILE(io_ptr, near_data, length, check); |
422 |
} |
423 |
else |
424 |
{ |
425 |
png_byte buf[NEAR_BUF_SIZE]; |
426 |
png_size_t written, remaining, err; |
427 |
check = 0; |
428 |
remaining = length; |
429 |
do |
430 |
{ |
431 |
written = MIN(NEAR_BUF_SIZE, remaining); |
432 |
png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ |
433 |
WRITEFILE(io_ptr, buf, written, err); |
434 |
if (err != written) |
435 |
break; |
436 |
else |
437 |
check += err; |
438 |
data += written; |
439 |
remaining -= written; |
440 |
} |
441 |
while (remaining != 0); |
442 |
} |
443 |
if (check != length) |
444 |
{ |
445 |
png_error(png_ptr, "Write Error"); |
446 |
} |
447 |
} |
448 |
#endif /* USE_FAR_KEYWORD */ |
449 |
|
450 |
/* This function is called when there is a warning, but the library thinks |
451 |
* it can continue anyway. Replacement functions don't have to do anything |
452 |
* here if you don't want to. In the default configuration, png_ptr is |
453 |
* not used, but it is passed in case it may be useful. |
454 |
*/ |
455 |
static void |
456 |
pngtest_warning(png_structp png_ptr, png_const_charp message) |
457 |
{ |
458 |
PNG_CONST char *name = "UNKNOWN (ERROR!)"; |
459 |
if (png_ptr != NULL && png_ptr->error_ptr != NULL) |
460 |
name = png_ptr->error_ptr; |
461 |
fprintf(STDERR, "%s: libpng warning: %s\n", name, message); |
462 |
} |
463 |
|
464 |
/* This is the default error handling function. Note that replacements for |
465 |
* this function MUST NOT RETURN, or the program will likely crash. This |
466 |
* function is used by default, or if the program supplies NULL for the |
467 |
* error function pointer in png_set_error_fn(). |
468 |
*/ |
469 |
static void |
470 |
pngtest_error(png_structp png_ptr, png_const_charp message) |
471 |
{ |
472 |
pngtest_warning(png_ptr, message); |
473 |
/* We can return because png_error calls the default handler, which is |
474 |
* actually OK in this case. |
475 |
*/ |
476 |
} |
477 |
#endif /* PNG_NO_STDIO */ |
478 |
/* END of code to validate stdio-free compilation */ |
479 |
|
480 |
/* START of code to validate memory allocation and deallocation */ |
481 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
482 |
|
483 |
/* Allocate memory. For reasonable files, size should never exceed |
484 |
* 64K. However, zlib may allocate more then 64K if you don't tell |
485 |
* it not to. See zconf.h and png.h for more information. zlib does |
486 |
* need to allocate exactly 64K, so whatever you call here must |
487 |
* have the ability to do that. |
488 |
* |
489 |
* This piece of code can be compiled to validate max 64K allocations |
490 |
* by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. |
491 |
*/ |
492 |
typedef struct memory_information |
493 |
{ |
494 |
png_uint_32 size; |
495 |
png_voidp pointer; |
496 |
struct memory_information FAR *next; |
497 |
} memory_information; |
498 |
typedef memory_information FAR *memory_infop; |
499 |
|
500 |
static memory_infop pinformation = NULL; |
501 |
static int current_allocation = 0; |
502 |
static int maximum_allocation = 0; |
503 |
static int total_allocation = 0; |
504 |
static int num_allocations = 0; |
505 |
|
506 |
png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size)); |
507 |
void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); |
508 |
|
509 |
png_voidp |
510 |
png_debug_malloc(png_structp png_ptr, png_uint_32 size) |
511 |
{ |
512 |
|
513 |
/* png_malloc has already tested for NULL; png_create_struct calls |
514 |
* png_debug_malloc directly, with png_ptr == NULL which is OK |
515 |
*/ |
516 |
|
517 |
if (size == 0) |
518 |
return (NULL); |
519 |
|
520 |
/* This calls the library allocator twice, once to get the requested |
521 |
buffer and once to get a new free list entry. */ |
522 |
{ |
523 |
/* Disable malloc_fn and free_fn */ |
524 |
memory_infop pinfo; |
525 |
png_set_mem_fn(png_ptr, NULL, NULL, NULL); |
526 |
pinfo = (memory_infop)png_malloc(png_ptr, |
527 |
(png_uint_32)png_sizeof(*pinfo)); |
528 |
pinfo->size = size; |
529 |
current_allocation += size; |
530 |
total_allocation += size; |
531 |
num_allocations ++; |
532 |
if (current_allocation > maximum_allocation) |
533 |
maximum_allocation = current_allocation; |
534 |
pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); |
535 |
/* Restore malloc_fn and free_fn */ |
536 |
png_set_mem_fn(png_ptr, |
537 |
png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, |
538 |
(png_free_ptr)png_debug_free); |
539 |
if (size != 0 && pinfo->pointer == NULL) |
540 |
{ |
541 |
current_allocation -= size; |
542 |
total_allocation -= size; |
543 |
png_error(png_ptr, |
544 |
"out of memory in pngtest->png_debug_malloc."); |
545 |
} |
546 |
pinfo->next = pinformation; |
547 |
pinformation = pinfo; |
548 |
/* Make sure the caller isn't assuming zeroed memory. */ |
549 |
png_memset(pinfo->pointer, 0xdd, pinfo->size); |
550 |
if (verbose) |
551 |
printf("png_malloc %lu bytes at %x\n", (unsigned long)size, |
552 |
pinfo->pointer); |
553 |
return (png_voidp)(pinfo->pointer); |
554 |
} |
555 |
} |
556 |
|
557 |
/* Free a pointer. It is removed from the list at the same time. */ |
558 |
void |
559 |
png_debug_free(png_structp png_ptr, png_voidp ptr) |
560 |
{ |
561 |
if (png_ptr == NULL) |
562 |
fprintf(STDERR, "NULL pointer to png_debug_free.\n"); |
563 |
if (ptr == 0) |
564 |
{ |
565 |
#if 0 /* This happens all the time. */ |
566 |
fprintf(STDERR, "WARNING: freeing NULL pointer\n"); |
567 |
#endif |
568 |
return; |
569 |
} |
570 |
|
571 |
/* Unlink the element from the list. */ |
572 |
{ |
573 |
memory_infop FAR *ppinfo = &pinformation; |
574 |
for (;;) |
575 |
{ |
576 |
memory_infop pinfo = *ppinfo; |
577 |
if (pinfo->pointer == ptr) |
578 |
{ |
579 |
*ppinfo = pinfo->next; |
580 |
current_allocation -= pinfo->size; |
581 |
if (current_allocation < 0) |
582 |
fprintf(STDERR, "Duplicate free of memory\n"); |
583 |
/* We must free the list element too, but first kill |
584 |
the memory that is to be freed. */ |
585 |
png_memset(ptr, 0x55, pinfo->size); |
586 |
png_free_default(png_ptr, pinfo); |
587 |
pinfo = NULL; |
588 |
break; |
589 |
} |
590 |
if (pinfo->next == NULL) |
591 |
{ |
592 |
fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); |
593 |
break; |
594 |
} |
595 |
ppinfo = &pinfo->next; |
596 |
} |
597 |
} |
598 |
|
599 |
/* Finally free the data. */ |
600 |
if (verbose) |
601 |
printf("Freeing %x\n", ptr); |
602 |
png_free_default(png_ptr, ptr); |
603 |
ptr = NULL; |
604 |
} |
605 |
#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ |
606 |
/* END of code to test memory allocation/deallocation */ |
607 |
|
608 |
|
609 |
/* Demonstration of user chunk support of the sTER and vpAg chunks */ |
610 |
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) |
611 |
|
612 |
/* (sTER is a public chunk not yet known by libpng. vpAg is a private |
613 |
chunk used in ImageMagick to store "virtual page" size). */ |
614 |
|
615 |
static png_uint_32 user_chunk_data[4]; |
616 |
|
617 |
/* 0: sTER mode + 1 |
618 |
* 1: vpAg width |
619 |
* 2: vpAg height |
620 |
* 3: vpAg units |
621 |
*/ |
622 |
|
623 |
static int read_user_chunk_callback(png_struct *png_ptr, |
624 |
png_unknown_chunkp chunk) |
625 |
{ |
626 |
png_uint_32 |
627 |
*my_user_chunk_data; |
628 |
|
629 |
/* Return one of the following: |
630 |
* return (-n); chunk had an error |
631 |
* return (0); did not recognize |
632 |
* return (n); success |
633 |
* |
634 |
* The unknown chunk structure contains the chunk data: |
635 |
* png_byte name[5]; |
636 |
* png_byte *data; |
637 |
* png_size_t size; |
638 |
* |
639 |
* Note that libpng has already taken care of the CRC handling. |
640 |
*/ |
641 |
|
642 |
if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ |
643 |
chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ |
644 |
{ |
645 |
/* Found sTER chunk */ |
646 |
if (chunk->size != 1) |
647 |
return (-1); /* Error return */ |
648 |
if (chunk->data[0] != 0 && chunk->data[0] != 1) |
649 |
return (-1); /* Invalid mode */ |
650 |
my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); |
651 |
my_user_chunk_data[0]=chunk->data[0]+1; |
652 |
return (1); |
653 |
} |
654 |
|
655 |
if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ |
656 |
chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ |
657 |
return (0); /* Did not recognize */ |
658 |
|
659 |
/* Found ImageMagick vpAg chunk */ |
660 |
|
661 |
if (chunk->size != 9) |
662 |
return (-1); /* Error return */ |
663 |
|
664 |
my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); |
665 |
|
666 |
my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); |
667 |
my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); |
668 |
my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; |
669 |
|
670 |
return (1); |
671 |
|
672 |
} |
673 |
#endif |
674 |
/* END of code to demonstrate user chunk support */ |
675 |
|
676 |
/* Test one file */ |
677 |
int |
678 |
test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) |
679 |
{ |
680 |
static png_FILE_p fpin; |
681 |
static png_FILE_p fpout; /* "static" prevents setjmp corruption */ |
682 |
png_structp read_ptr; |
683 |
png_infop read_info_ptr, end_info_ptr; |
684 |
#ifdef PNG_WRITE_SUPPORTED |
685 |
png_structp write_ptr; |
686 |
png_infop write_info_ptr; |
687 |
png_infop write_end_info_ptr; |
688 |
#else |
689 |
png_structp write_ptr = NULL; |
690 |
png_infop write_info_ptr = NULL; |
691 |
png_infop write_end_info_ptr = NULL; |
692 |
#endif |
693 |
png_bytep row_buf; |
694 |
png_uint_32 y; |
695 |
png_uint_32 width, height; |
696 |
int num_pass, pass; |
697 |
int bit_depth, color_type; |
698 |
#ifdef PNG_SETJMP_SUPPORTED |
699 |
#ifdef USE_FAR_KEYWORD |
700 |
jmp_buf jmpbuf; |
701 |
#endif |
702 |
#endif |
703 |
|
704 |
#if defined(_WIN32_WCE) |
705 |
TCHAR path[MAX_PATH]; |
706 |
#endif |
707 |
char inbuf[256], outbuf[256]; |
708 |
|
709 |
row_buf = NULL; |
710 |
|
711 |
#if defined(_WIN32_WCE) |
712 |
MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); |
713 |
if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) |
714 |
#else |
715 |
if ((fpin = fopen(inname, "rb")) == NULL) |
716 |
#endif |
717 |
{ |
718 |
fprintf(STDERR, "Could not find input file %s\n", inname); |
719 |
return (1); |
720 |
} |
721 |
|
722 |
#if defined(_WIN32_WCE) |
723 |
MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); |
724 |
if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) |
725 |
#else |
726 |
if ((fpout = fopen(outname, "wb")) == NULL) |
727 |
#endif |
728 |
{ |
729 |
fprintf(STDERR, "Could not open output file %s\n", outname); |
730 |
FCLOSE(fpin); |
731 |
return (1); |
732 |
} |
733 |
|
734 |
png_debug(0, "Allocating read and write structures"); |
735 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
736 |
read_ptr = |
737 |
png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, |
738 |
png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, |
739 |
(png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); |
740 |
#else |
741 |
read_ptr = |
742 |
png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, |
743 |
png_error_ptr_NULL, png_error_ptr_NULL); |
744 |
#endif |
745 |
#if defined(PNG_NO_STDIO) |
746 |
png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, |
747 |
pngtest_warning); |
748 |
#endif |
749 |
|
750 |
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) |
751 |
user_chunk_data[0] = 0; |
752 |
user_chunk_data[1] = 0; |
753 |
user_chunk_data[2] = 0; |
754 |
user_chunk_data[3] = 0; |
755 |
png_set_read_user_chunk_fn(read_ptr, user_chunk_data, |
756 |
read_user_chunk_callback); |
757 |
|
758 |
#endif |
759 |
#ifdef PNG_WRITE_SUPPORTED |
760 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
761 |
write_ptr = |
762 |
png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, |
763 |
png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, |
764 |
(png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); |
765 |
#else |
766 |
write_ptr = |
767 |
png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, |
768 |
png_error_ptr_NULL, png_error_ptr_NULL); |
769 |
#endif |
770 |
#if defined(PNG_NO_STDIO) |
771 |
png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, |
772 |
pngtest_warning); |
773 |
#endif |
774 |
#endif |
775 |
png_debug(0, "Allocating read_info, write_info and end_info structures"); |
776 |
read_info_ptr = png_create_info_struct(read_ptr); |
777 |
end_info_ptr = png_create_info_struct(read_ptr); |
778 |
#ifdef PNG_WRITE_SUPPORTED |
779 |
write_info_ptr = png_create_info_struct(write_ptr); |
780 |
write_end_info_ptr = png_create_info_struct(write_ptr); |
781 |
#endif |
782 |
|
783 |
#ifdef PNG_SETJMP_SUPPORTED |
784 |
png_debug(0, "Setting jmpbuf for read struct"); |
785 |
#ifdef USE_FAR_KEYWORD |
786 |
if (setjmp(jmpbuf)) |
787 |
#else |
788 |
if (setjmp(png_jmpbuf(read_ptr))) |
789 |
#endif |
790 |
{ |
791 |
fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); |
792 |
png_free(read_ptr, row_buf); |
793 |
row_buf = NULL; |
794 |
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); |
795 |
#ifdef PNG_WRITE_SUPPORTED |
796 |
png_destroy_info_struct(write_ptr, &write_end_info_ptr); |
797 |
png_destroy_write_struct(&write_ptr, &write_info_ptr); |
798 |
#endif |
799 |
FCLOSE(fpin); |
800 |
FCLOSE(fpout); |
801 |
return (1); |
802 |
} |
803 |
#ifdef USE_FAR_KEYWORD |
804 |
png_memcpy(png_jmpbuf(read_ptr), jmpbuf, png_sizeof(jmp_buf)); |
805 |
#endif |
806 |
|
807 |
#ifdef PNG_WRITE_SUPPORTED |
808 |
png_debug(0, "Setting jmpbuf for write struct"); |
809 |
#ifdef USE_FAR_KEYWORD |
810 |
if (setjmp(jmpbuf)) |
811 |
#else |
812 |
if (setjmp(png_jmpbuf(write_ptr))) |
813 |
#endif |
814 |
{ |
815 |
fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); |
816 |
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); |
817 |
png_destroy_info_struct(write_ptr, &write_end_info_ptr); |
818 |
#ifdef PNG_WRITE_SUPPORTED |
819 |
png_destroy_write_struct(&write_ptr, &write_info_ptr); |
820 |
#endif |
821 |
FCLOSE(fpin); |
822 |
FCLOSE(fpout); |
823 |
return (1); |
824 |
} |
825 |
#ifdef USE_FAR_KEYWORD |
826 |
png_memcpy(png_jmpbuf(write_ptr), jmpbuf, png_sizeof(jmp_buf)); |
827 |
#endif |
828 |
#endif |
829 |
#endif |
830 |
|
831 |
png_debug(0, "Initializing input and output streams"); |
832 |
#if !defined(PNG_NO_STDIO) |
833 |
png_init_io(read_ptr, fpin); |
834 |
# ifdef PNG_WRITE_SUPPORTED |
835 |
png_init_io(write_ptr, fpout); |
836 |
# endif |
837 |
#else |
838 |
png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); |
839 |
# ifdef PNG_WRITE_SUPPORTED |
840 |
png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, |
841 |
# if defined(PNG_WRITE_FLUSH_SUPPORTED) |
842 |
pngtest_flush); |
843 |
# else |
844 |
NULL); |
845 |
# endif |
846 |
# endif |
847 |
#endif |
848 |
if (status_dots_requested == 1) |
849 |
{ |
850 |
#ifdef PNG_WRITE_SUPPORTED |
851 |
png_set_write_status_fn(write_ptr, write_row_callback); |
852 |
#endif |
853 |
png_set_read_status_fn(read_ptr, read_row_callback); |
854 |
} |
855 |
else |
856 |
{ |
857 |
#ifdef PNG_WRITE_SUPPORTED |
858 |
png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); |
859 |
#endif |
860 |
png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); |
861 |
} |
862 |
|
863 |
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) |
864 |
{ |
865 |
int i; |
866 |
for (i = 0; i<256; i++) |
867 |
filters_used[i] = 0; |
868 |
png_set_read_user_transform_fn(read_ptr, count_filters); |
869 |
} |
870 |
#endif |
871 |
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) |
872 |
zero_samples = 0; |
873 |
png_set_write_user_transform_fn(write_ptr, count_zero_samples); |
874 |
#endif |
875 |
|
876 |
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) |
877 |
# ifndef PNG_HANDLE_CHUNK_ALWAYS |
878 |
# define PNG_HANDLE_CHUNK_ALWAYS 3 |
879 |
# endif |
880 |
png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, |
881 |
png_bytep_NULL, 0); |
882 |
#endif |
883 |
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) |
884 |
# ifndef PNG_HANDLE_CHUNK_IF_SAFE |
885 |
# define PNG_HANDLE_CHUNK_IF_SAFE 2 |
886 |
# endif |
887 |
png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, |
888 |
png_bytep_NULL, 0); |
889 |
#endif |
890 |
|
891 |
png_debug(0, "Reading info struct"); |
892 |
png_read_info(read_ptr, read_info_ptr); |
893 |
|
894 |
png_debug(0, "Transferring info struct"); |
895 |
{ |
896 |
int interlace_type, compression_type, filter_type; |
897 |
|
898 |
if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, |
899 |
&color_type, &interlace_type, &compression_type, &filter_type)) |
900 |
{ |
901 |
png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, |
902 |
#if defined(PNG_WRITE_INTERLACING_SUPPORTED) |
903 |
color_type, interlace_type, compression_type, filter_type); |
904 |
#else |
905 |
color_type, PNG_INTERLACE_NONE, compression_type, filter_type); |
906 |
#endif |
907 |
} |
908 |
} |
909 |
#if defined(PNG_FIXED_POINT_SUPPORTED) |
910 |
#if defined(PNG_cHRM_SUPPORTED) |
911 |
{ |
912 |
png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, |
913 |
blue_y; |
914 |
if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, |
915 |
&red_y, &green_x, &green_y, &blue_x, &blue_y)) |
916 |
{ |
917 |
png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, |
918 |
red_y, green_x, green_y, blue_x, blue_y); |
919 |
} |
920 |
} |
921 |
#endif |
922 |
#if defined(PNG_gAMA_SUPPORTED) |
923 |
{ |
924 |
png_fixed_point gamma; |
925 |
|
926 |
if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) |
927 |
png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); |
928 |
} |
929 |
#endif |
930 |
#else /* Use floating point versions */ |
931 |
#if defined(PNG_FLOATING_POINT_SUPPORTED) |
932 |
#if defined(PNG_cHRM_SUPPORTED) |
933 |
{ |
934 |
double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, |
935 |
blue_y; |
936 |
if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, |
937 |
&red_y, &green_x, &green_y, &blue_x, &blue_y)) |
938 |
{ |
939 |
png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, |
940 |
red_y, green_x, green_y, blue_x, blue_y); |
941 |
} |
942 |
} |
943 |
#endif |
944 |
#if defined(PNG_gAMA_SUPPORTED) |
945 |
{ |
946 |
double gamma; |
947 |
|
948 |
if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) |
949 |
png_set_gAMA(write_ptr, write_info_ptr, gamma); |
950 |
} |
951 |
#endif |
952 |
#endif /* Floating point */ |
953 |
#endif /* Fixed point */ |
954 |
#if defined(PNG_iCCP_SUPPORTED) |
955 |
{ |
956 |
png_charp name; |
957 |
png_charp profile; |
958 |
png_uint_32 proflen; |
959 |
int compression_type; |
960 |
|
961 |
if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, |
962 |
&profile, &proflen)) |
963 |
{ |
964 |
png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, |
965 |
profile, proflen); |
966 |
} |
967 |
} |
968 |
#endif |
969 |
#if defined(PNG_sRGB_SUPPORTED) |
970 |
{ |
971 |
int intent; |
972 |
|
973 |
if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) |
974 |
png_set_sRGB(write_ptr, write_info_ptr, intent); |
975 |
} |
976 |
#endif |
977 |
{ |
978 |
png_colorp palette; |
979 |
int num_palette; |
980 |
|
981 |
if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) |
982 |
png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); |
983 |
} |
984 |
#if defined(PNG_bKGD_SUPPORTED) |
985 |
{ |
986 |
png_color_16p background; |
987 |
|
988 |
if (png_get_bKGD(read_ptr, read_info_ptr, &background)) |
989 |
{ |
990 |
png_set_bKGD(write_ptr, write_info_ptr, background); |
991 |
} |
992 |
} |
993 |
#endif |
994 |
#if defined(PNG_hIST_SUPPORTED) |
995 |
{ |
996 |
png_uint_16p hist; |
997 |
|
998 |
if (png_get_hIST(read_ptr, read_info_ptr, &hist)) |
999 |
png_set_hIST(write_ptr, write_info_ptr, hist); |
1000 |
} |
1001 |
#endif |
1002 |
#if defined(PNG_oFFs_SUPPORTED) |
1003 |
{ |
1004 |
png_int_32 offset_x, offset_y; |
1005 |
int unit_type; |
1006 |
|
1007 |
if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, |
1008 |
&unit_type)) |
1009 |
{ |
1010 |
png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); |
1011 |
} |
1012 |
} |
1013 |
#endif |
1014 |
#if defined(PNG_pCAL_SUPPORTED) |
1015 |
{ |
1016 |
png_charp purpose, units; |
1017 |
png_charpp params; |
1018 |
png_int_32 X0, X1; |
1019 |
int type, nparams; |
1020 |
|
1021 |
if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, |
1022 |
&nparams, &units, ¶ms)) |
1023 |
{ |
1024 |
png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, |
1025 |
nparams, units, params); |
1026 |
} |
1027 |
} |
1028 |
#endif |
1029 |
#if defined(PNG_pHYs_SUPPORTED) |
1030 |
{ |
1031 |
png_uint_32 res_x, res_y; |
1032 |
int unit_type; |
1033 |
|
1034 |
if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) |
1035 |
png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); |
1036 |
} |
1037 |
#endif |
1038 |
#if defined(PNG_sBIT_SUPPORTED) |
1039 |
{ |
1040 |
png_color_8p sig_bit; |
1041 |
|
1042 |
if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) |
1043 |
png_set_sBIT(write_ptr, write_info_ptr, sig_bit); |
1044 |
} |
1045 |
#endif |
1046 |
#if defined(PNG_sCAL_SUPPORTED) |
1047 |
#ifdef PNG_FLOATING_POINT_SUPPORTED |
1048 |
{ |
1049 |
int unit; |
1050 |
double scal_width, scal_height; |
1051 |
|
1052 |
if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, |
1053 |
&scal_height)) |
1054 |
{ |
1055 |
png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); |
1056 |
} |
1057 |
} |
1058 |
#else |
1059 |
#ifdef PNG_FIXED_POINT_SUPPORTED |
1060 |
{ |
1061 |
int unit; |
1062 |
png_charp scal_width, scal_height; |
1063 |
|
1064 |
if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, |
1065 |
&scal_height)) |
1066 |
{ |
1067 |
png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height); |
1068 |
} |
1069 |
} |
1070 |
#endif |
1071 |
#endif |
1072 |
#endif |
1073 |
#if defined(PNG_TEXT_SUPPORTED) |
1074 |
{ |
1075 |
png_textp text_ptr; |
1076 |
int num_text; |
1077 |
|
1078 |
if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) |
1079 |
{ |
1080 |
png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); |
1081 |
png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); |
1082 |
} |
1083 |
} |
1084 |
#endif |
1085 |
#if defined(PNG_tIME_SUPPORTED) |
1086 |
{ |
1087 |
png_timep mod_time; |
1088 |
|
1089 |
if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) |
1090 |
{ |
1091 |
png_set_tIME(write_ptr, write_info_ptr, mod_time); |
1092 |
#if defined(PNG_TIME_RFC1123_SUPPORTED) |
1093 |
/* We have to use png_memcpy instead of "=" because the string |
1094 |
* pointed to by png_convert_to_rfc1123() gets free'ed before |
1095 |
* we use it. |
1096 |
*/ |
1097 |
png_memcpy(tIME_string, |
1098 |
png_convert_to_rfc1123(read_ptr, mod_time), |
1099 |
png_sizeof(tIME_string)); |
1100 |
tIME_string[png_sizeof(tIME_string) - 1] = '\0'; |
1101 |
tIME_chunk_present++; |
1102 |
#endif /* PNG_TIME_RFC1123_SUPPORTED */ |
1103 |
} |
1104 |
} |
1105 |
#endif |
1106 |
#if defined(PNG_tRNS_SUPPORTED) |
1107 |
{ |
1108 |
png_bytep trans; |
1109 |
int num_trans; |
1110 |
png_color_16p trans_values; |
1111 |
|
1112 |
if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, |
1113 |
&trans_values)) |
1114 |
{ |
1115 |
int sample_max = (1 << read_info_ptr->bit_depth); |
1116 |
/* libpng doesn't reject a tRNS chunk with out-of-range samples */ |
1117 |
if (!((read_info_ptr->color_type == PNG_COLOR_TYPE_GRAY && |
1118 |
(int)trans_values->gray > sample_max) || |
1119 |
(read_info_ptr->color_type == PNG_COLOR_TYPE_RGB && |
1120 |
((int)trans_values->red > sample_max || |
1121 |
(int)trans_values->green > sample_max || |
1122 |
(int)trans_values->blue > sample_max)))) |
1123 |
png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, |
1124 |
trans_values); |
1125 |
} |
1126 |
} |
1127 |
#endif |
1128 |
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) |
1129 |
{ |
1130 |
png_unknown_chunkp unknowns; |
1131 |
int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, |
1132 |
&unknowns); |
1133 |
if (num_unknowns) |
1134 |
{ |
1135 |
png_size_t i; |
1136 |
png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, |
1137 |
num_unknowns); |
1138 |
/* Copy the locations from the read_info_ptr. The automatically |
1139 |
* generated locations in write_info_ptr are wrong because we |
1140 |
* haven't written anything yet. |
1141 |
*/ |
1142 |
for (i = 0; i < (png_size_t)num_unknowns; i++) |
1143 |
png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, |
1144 |
unknowns[i].location); |
1145 |
} |
1146 |
} |
1147 |
#endif |
1148 |
|
1149 |
#ifdef PNG_WRITE_SUPPORTED |
1150 |
png_debug(0, "Writing info struct"); |
1151 |
|
1152 |
/* If we wanted, we could write info in two steps: |
1153 |
* png_write_info_before_PLTE(write_ptr, write_info_ptr); |
1154 |
*/ |
1155 |
png_write_info(write_ptr, write_info_ptr); |
1156 |
|
1157 |
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) |
1158 |
if (user_chunk_data[0] != 0) |
1159 |
{ |
1160 |
png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; |
1161 |
|
1162 |
unsigned char |
1163 |
ster_chunk_data[1]; |
1164 |
|
1165 |
if (verbose) |
1166 |
fprintf(STDERR, "\n stereo mode = %lu\n", |
1167 |
(unsigned long)(user_chunk_data[0] - 1)); |
1168 |
ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); |
1169 |
png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); |
1170 |
} |
1171 |
if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) |
1172 |
{ |
1173 |
png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; |
1174 |
|
1175 |
unsigned char |
1176 |
vpag_chunk_data[9]; |
1177 |
|
1178 |
if (verbose) |
1179 |
fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", |
1180 |
(unsigned long)user_chunk_data[1], |
1181 |
(unsigned long)user_chunk_data[2], |
1182 |
(unsigned long)user_chunk_data[3]); |
1183 |
png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); |
1184 |
png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); |
1185 |
vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); |
1186 |
png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); |
1187 |
} |
1188 |
|
1189 |
#endif |
1190 |
#endif |
1191 |
|
1192 |
#ifdef SINGLE_ROWBUF_ALLOC |
1193 |
png_debug(0, "Allocating row buffer..."); |
1194 |
row_buf = (png_bytep)png_malloc(read_ptr, |
1195 |
png_get_rowbytes(read_ptr, read_info_ptr)); |
1196 |
png_debug1(0, "0x%08lx", (unsigned long)row_buf); |
1197 |
#endif /* SINGLE_ROWBUF_ALLOC */ |
1198 |
png_debug(0, "Writing row data"); |
1199 |
|
1200 |
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ |
1201 |
defined(PNG_WRITE_INTERLACING_SUPPORTED) |
1202 |
num_pass = png_set_interlace_handling(read_ptr); |
1203 |
# ifdef PNG_WRITE_SUPPORTED |
1204 |
png_set_interlace_handling(write_ptr); |
1205 |
# endif |
1206 |
#else |
1207 |
num_pass = 1; |
1208 |
#endif |
1209 |
|
1210 |
#ifdef PNGTEST_TIMING |
1211 |
t_stop = (float)clock(); |
1212 |
t_misc += (t_stop - t_start); |
1213 |
t_start = t_stop; |
1214 |
#endif |
1215 |
for (pass = 0; pass < num_pass; pass++) |
1216 |
{ |
1217 |
png_debug1(0, "Writing row data for pass %d", pass); |
1218 |
for (y = 0; y < height; y++) |
1219 |
{ |
1220 |
#ifndef SINGLE_ROWBUF_ALLOC |
1221 |
png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); |
1222 |
row_buf = (png_bytep)png_malloc(read_ptr, |
1223 |
png_get_rowbytes(read_ptr, read_info_ptr)); |
1224 |
png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, |
1225 |
png_get_rowbytes(read_ptr, read_info_ptr)); |
1226 |
#endif /* !SINGLE_ROWBUF_ALLOC */ |
1227 |
png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); |
1228 |
|
1229 |
#ifdef PNG_WRITE_SUPPORTED |
1230 |
#ifdef PNGTEST_TIMING |
1231 |
t_stop = (float)clock(); |
1232 |
t_decode += (t_stop - t_start); |
1233 |
t_start = t_stop; |
1234 |
#endif |
1235 |
png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); |
1236 |
#ifdef PNGTEST_TIMING |
1237 |
t_stop = (float)clock(); |
1238 |
t_encode += (t_stop - t_start); |
1239 |
t_start = t_stop; |
1240 |
#endif |
1241 |
#endif /* PNG_WRITE_SUPPORTED */ |
1242 |
|
1243 |
#ifndef SINGLE_ROWBUF_ALLOC |
1244 |
png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); |
1245 |
png_free(read_ptr, row_buf); |
1246 |
row_buf = NULL; |
1247 |
#endif /* !SINGLE_ROWBUF_ALLOC */ |
1248 |
} |
1249 |
} |
1250 |
|
1251 |
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) |
1252 |
png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); |
1253 |
#endif |
1254 |
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) |
1255 |
png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); |
1256 |
#endif |
1257 |
|
1258 |
png_debug(0, "Reading and writing end_info data"); |
1259 |
|
1260 |
png_read_end(read_ptr, end_info_ptr); |
1261 |
#if defined(PNG_TEXT_SUPPORTED) |
1262 |
{ |
1263 |
png_textp text_ptr; |
1264 |
int num_text; |
1265 |
|
1266 |
if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) |
1267 |
{ |
1268 |
png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); |
1269 |
png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); |
1270 |
} |
1271 |
} |
1272 |
#endif |
1273 |
#if defined(PNG_tIME_SUPPORTED) |
1274 |
{ |
1275 |
png_timep mod_time; |
1276 |
|
1277 |
if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) |
1278 |
{ |
1279 |
png_set_tIME(write_ptr, write_end_info_ptr, mod_time); |
1280 |
#if defined(PNG_TIME_RFC1123_SUPPORTED) |
1281 |
/* We have to use png_memcpy instead of "=" because the string |
1282 |
pointed to by png_convert_to_rfc1123() gets free'ed before |
1283 |
we use it */ |
1284 |
png_memcpy(tIME_string, |
1285 |
png_convert_to_rfc1123(read_ptr, mod_time), |
1286 |
png_sizeof(tIME_string)); |
1287 |
tIME_string[png_sizeof(tIME_string) - 1] = '\0'; |
1288 |
tIME_chunk_present++; |
1289 |
#endif /* PNG_TIME_RFC1123_SUPPORTED */ |
1290 |
} |
1291 |
} |
1292 |
#endif |
1293 |
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) |
1294 |
{ |
1295 |
png_unknown_chunkp unknowns; |
1296 |
int num_unknowns; |
1297 |
num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, |
1298 |
&unknowns); |
1299 |
if (num_unknowns) |
1300 |
{ |
1301 |
png_size_t i; |
1302 |
png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, |
1303 |
num_unknowns); |
1304 |
/* Copy the locations from the read_info_ptr. The automatically |
1305 |
* generated locations in write_end_info_ptr are wrong because we |
1306 |
* haven't written the end_info yet. |
1307 |
*/ |
1308 |
for (i = 0; i < (png_size_t)num_unknowns; i++) |
1309 |
png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, |
1310 |
unknowns[i].location); |
1311 |
} |
1312 |
} |
1313 |
#endif |
1314 |
#ifdef PNG_WRITE_SUPPORTED |
1315 |
png_write_end(write_ptr, write_end_info_ptr); |
1316 |
#endif |
1317 |
|
1318 |
#ifdef PNG_EASY_ACCESS_SUPPORTED |
1319 |
if (verbose) |
1320 |
{ |
1321 |
png_uint_32 iwidth, iheight; |
1322 |
iwidth = png_get_image_width(write_ptr, write_info_ptr); |
1323 |
iheight = png_get_image_height(write_ptr, write_info_ptr); |
1324 |
fprintf(STDERR, "\n Image width = %lu, height = %lu\n", |
1325 |
(unsigned long)iwidth, (unsigned long)iheight); |
1326 |
} |
1327 |
#endif |
1328 |
|
1329 |
png_debug(0, "Destroying data structs"); |
1330 |
#ifdef SINGLE_ROWBUF_ALLOC |
1331 |
png_debug(1, "destroying row_buf for read_ptr"); |
1332 |
png_free(read_ptr, row_buf); |
1333 |
row_buf = NULL; |
1334 |
#endif /* SINGLE_ROWBUF_ALLOC */ |
1335 |
png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); |
1336 |
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); |
1337 |
#ifdef PNG_WRITE_SUPPORTED |
1338 |
png_debug(1, "destroying write_end_info_ptr"); |
1339 |
png_destroy_info_struct(write_ptr, &write_end_info_ptr); |
1340 |
png_debug(1, "destroying write_ptr, write_info_ptr"); |
1341 |
png_destroy_write_struct(&write_ptr, &write_info_ptr); |
1342 |
#endif |
1343 |
png_debug(0, "Destruction complete."); |
1344 |
|
1345 |
FCLOSE(fpin); |
1346 |
FCLOSE(fpout); |
1347 |
|
1348 |
png_debug(0, "Opening files for comparison"); |
1349 |
#if defined(_WIN32_WCE) |
1350 |
MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); |
1351 |
if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) |
1352 |
#else |
1353 |
if ((fpin = fopen(inname, "rb")) == NULL) |
1354 |
#endif |
1355 |
{ |
1356 |
fprintf(STDERR, "Could not find file %s\n", inname); |
1357 |
return (1); |
1358 |
} |
1359 |
|
1360 |
#if defined(_WIN32_WCE) |
1361 |
MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); |
1362 |
if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) |
1363 |
#else |
1364 |
if ((fpout = fopen(outname, "rb")) == NULL) |
1365 |
#endif |
1366 |
{ |
1367 |
fprintf(STDERR, "Could not find file %s\n", outname); |
1368 |
FCLOSE(fpin); |
1369 |
return (1); |
1370 |
} |
1371 |
|
1372 |
for (;;) |
1373 |
{ |
1374 |
png_size_t num_in, num_out; |
1375 |
|
1376 |
READFILE(fpin, inbuf, 1, num_in); |
1377 |
READFILE(fpout, outbuf, 1, num_out); |
1378 |
|
1379 |
if (num_in != num_out) |
1380 |
{ |
1381 |
fprintf(STDERR, "\nFiles %s and %s are of a different size\n", |
1382 |
inname, outname); |
1383 |
if (wrote_question == 0) |
1384 |
{ |
1385 |
fprintf(STDERR, |
1386 |
" Was %s written with the same maximum IDAT chunk size (%d bytes),", |
1387 |
inname, PNG_ZBUF_SIZE); |
1388 |
fprintf(STDERR, |
1389 |
"\n filtering heuristic (libpng default), compression"); |
1390 |
fprintf(STDERR, |
1391 |
" level (zlib default),\n and zlib version (%s)?\n\n", |
1392 |
ZLIB_VERSION); |
1393 |
wrote_question = 1; |
1394 |
} |
1395 |
FCLOSE(fpin); |
1396 |
FCLOSE(fpout); |
1397 |
return (0); |
1398 |
} |
1399 |
|
1400 |
if (!num_in) |
1401 |
break; |
1402 |
|
1403 |
if (png_memcmp(inbuf, outbuf, num_in)) |
1404 |
{ |
1405 |
fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); |
1406 |
if (wrote_question == 0) |
1407 |
{ |
1408 |
fprintf(STDERR, |
1409 |
" Was %s written with the same maximum IDAT chunk size (%d bytes),", |
1410 |
inname, PNG_ZBUF_SIZE); |
1411 |
fprintf(STDERR, |
1412 |
"\n filtering heuristic (libpng default), compression"); |
1413 |
fprintf(STDERR, |
1414 |
" level (zlib default),\n and zlib version (%s)?\n\n", |
1415 |
ZLIB_VERSION); |
1416 |
wrote_question = 1; |
1417 |
} |
1418 |
FCLOSE(fpin); |
1419 |
FCLOSE(fpout); |
1420 |
return (0); |
1421 |
} |
1422 |
} |
1423 |
|
1424 |
FCLOSE(fpin); |
1425 |
FCLOSE(fpout); |
1426 |
|
1427 |
return (0); |
1428 |
} |
1429 |
|
1430 |
/* Input and output filenames */ |
1431 |
#ifdef RISCOS |
1432 |
static PNG_CONST char *inname = "pngtest/png"; |
1433 |
static PNG_CONST char *outname = "pngout/png"; |
1434 |
#else |
1435 |
static PNG_CONST char *inname = "pngtest.png"; |
1436 |
static PNG_CONST char *outname = "pngout.png"; |
1437 |
#endif |
1438 |
|
1439 |
int |
1440 |
main(int argc, char *argv[]) |
1441 |
{ |
1442 |
int multiple = 0; |
1443 |
int ierror = 0; |
1444 |
|
1445 |
fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); |
1446 |
fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); |
1447 |
fprintf(STDERR, "%s", png_get_copyright(NULL)); |
1448 |
/* Show the version of libpng used in building the library */ |
1449 |
fprintf(STDERR, " library (%lu):%s", |
1450 |
(unsigned long)png_access_version_number(), |
1451 |
png_get_header_version(NULL)); |
1452 |
/* Show the version of libpng used in building the application */ |
1453 |
fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, |
1454 |
PNG_HEADER_VERSION_STRING); |
1455 |
fprintf(STDERR, " sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n", |
1456 |
(long)png_sizeof(png_struct), (long)png_sizeof(png_info)); |
1457 |
|
1458 |
/* Do some consistency checking on the memory allocation settings, I'm |
1459 |
* not sure this matters, but it is nice to know, the first of these |
1460 |
* tests should be impossible because of the way the macros are set |
1461 |
* in pngconf.h |
1462 |
*/ |
1463 |
#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) |
1464 |
fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); |
1465 |
#endif |
1466 |
/* I think the following can happen. */ |
1467 |
#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) |
1468 |
fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); |
1469 |
#endif |
1470 |
|
1471 |
if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) |
1472 |
{ |
1473 |
fprintf(STDERR, |
1474 |
"Warning: versions are different between png.h and png.c\n"); |
1475 |
fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); |
1476 |
fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); |
1477 |
++ierror; |
1478 |
} |
1479 |
|
1480 |
if (argc > 1) |
1481 |
{ |
1482 |
if (strcmp(argv[1], "-m") == 0) |
1483 |
{ |
1484 |
multiple = 1; |
1485 |
status_dots_requested = 0; |
1486 |
} |
1487 |
else if (strcmp(argv[1], "-mv") == 0 || |
1488 |
strcmp(argv[1], "-vm") == 0 ) |
1489 |
{ |
1490 |
multiple = 1; |
1491 |
verbose = 1; |
1492 |
status_dots_requested = 1; |
1493 |
} |
1494 |
else if (strcmp(argv[1], "-v") == 0) |
1495 |
{ |
1496 |
verbose = 1; |
1497 |
status_dots_requested = 1; |
1498 |
inname = argv[2]; |
1499 |
} |
1500 |
else |
1501 |
{ |
1502 |
inname = argv[1]; |
1503 |
status_dots_requested = 0; |
1504 |
} |
1505 |
} |
1506 |
|
1507 |
if (!multiple && argc == 3 + verbose) |
1508 |
outname = argv[2 + verbose]; |
1509 |
|
1510 |
if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) |
1511 |
{ |
1512 |
fprintf(STDERR, |
1513 |
"usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", |
1514 |
argv[0], argv[0]); |
1515 |
fprintf(STDERR, |
1516 |
" reads/writes one PNG file (without -m) or multiple files (-m)\n"); |
1517 |
fprintf(STDERR, |
1518 |
" with -m %s is used as a temporary file\n", outname); |
1519 |
exit(1); |
1520 |
} |
1521 |
|
1522 |
if (multiple) |
1523 |
{ |
1524 |
int i; |
1525 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
1526 |
int allocation_now = current_allocation; |
1527 |
#endif |
1528 |
for (i=2; i<argc; ++i) |
1529 |
{ |
1530 |
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) |
1531 |
int k; |
1532 |
#endif |
1533 |
int kerror; |
1534 |
fprintf(STDERR, "\n Testing %s:", argv[i]); |
1535 |
kerror = test_one_file(argv[i], outname); |
1536 |
if (kerror == 0) |
1537 |
{ |
1538 |
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) |
1539 |
fprintf(STDERR, "\n PASS (%lu zero samples)\n", |
1540 |
(unsigned long)zero_samples); |
1541 |
#else |
1542 |
fprintf(STDERR, " PASS\n"); |
1543 |
#endif |
1544 |
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) |
1545 |
for (k = 0; k<256; k++) |
1546 |
if (filters_used[k]) |
1547 |
fprintf(STDERR, " Filter %d was used %lu times\n", |
1548 |
k, (unsigned long)filters_used[k]); |
1549 |
#endif |
1550 |
#if defined(PNG_TIME_RFC1123_SUPPORTED) |
1551 |
if (tIME_chunk_present != 0) |
1552 |
fprintf(STDERR, " tIME = %s\n", tIME_string); |
1553 |
tIME_chunk_present = 0; |
1554 |
#endif /* PNG_TIME_RFC1123_SUPPORTED */ |
1555 |
} |
1556 |
else |
1557 |
{ |
1558 |
fprintf(STDERR, " FAIL\n"); |
1559 |
ierror += kerror; |
1560 |
} |
1561 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
1562 |
if (allocation_now != current_allocation) |
1563 |
fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", |
1564 |
current_allocation - allocation_now); |
1565 |
if (current_allocation != 0) |
1566 |
{ |
1567 |
memory_infop pinfo = pinformation; |
1568 |
|
1569 |
fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", |
1570 |
current_allocation); |
1571 |
while (pinfo != NULL) |
1572 |
{ |
1573 |
fprintf(STDERR, " %lu bytes at %x\n", |
1574 |
(unsigned long)pinfo->size, |
1575 |
(unsigned int) pinfo->pointer); |
1576 |
pinfo = pinfo->next; |
1577 |
} |
1578 |
} |
1579 |
#endif |
1580 |
} |
1581 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
1582 |
fprintf(STDERR, " Current memory allocation: %10d bytes\n", |
1583 |
current_allocation); |
1584 |
fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", |
1585 |
maximum_allocation); |
1586 |
fprintf(STDERR, " Total memory allocation: %10d bytes\n", |
1587 |
total_allocation); |
1588 |
fprintf(STDERR, " Number of allocations: %10d\n", |
1589 |
num_allocations); |
1590 |
#endif |
1591 |
} |
1592 |
else |
1593 |
{ |
1594 |
int i; |
1595 |
for (i = 0; i<3; ++i) |
1596 |
{ |
1597 |
int kerror; |
1598 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
1599 |
int allocation_now = current_allocation; |
1600 |
#endif |
1601 |
if (i == 1) status_dots_requested = 1; |
1602 |
else if (verbose == 0)status_dots_requested = 0; |
1603 |
if (i == 0 || verbose == 1 || ierror != 0) |
1604 |
fprintf(STDERR, "\n Testing %s:", inname); |
1605 |
kerror = test_one_file(inname, outname); |
1606 |
if (kerror == 0) |
1607 |
{ |
1608 |
if (verbose == 1 || i == 2) |
1609 |
{ |
1610 |
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) |
1611 |
int k; |
1612 |
#endif |
1613 |
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) |
1614 |
fprintf(STDERR, "\n PASS (%lu zero samples)\n", |
1615 |
(unsigned long)zero_samples); |
1616 |
#else |
1617 |
fprintf(STDERR, " PASS\n"); |
1618 |
#endif |
1619 |
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) |
1620 |
for (k = 0; k<256; k++) |
1621 |
if (filters_used[k]) |
1622 |
fprintf(STDERR, " Filter %d was used %lu times\n", |
1623 |
k, |
1624 |
(unsigned long)filters_used[k]); |
1625 |
#endif |
1626 |
#if defined(PNG_TIME_RFC1123_SUPPORTED) |
1627 |
if (tIME_chunk_present != 0) |
1628 |
fprintf(STDERR, " tIME = %s\n", tIME_string); |
1629 |
#endif /* PNG_TIME_RFC1123_SUPPORTED */ |
1630 |
} |
1631 |
} |
1632 |
else |
1633 |
{ |
1634 |
if (verbose == 0 && i != 2) |
1635 |
fprintf(STDERR, "\n Testing %s:", inname); |
1636 |
fprintf(STDERR, " FAIL\n"); |
1637 |
ierror += kerror; |
1638 |
} |
1639 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
1640 |
if (allocation_now != current_allocation) |
1641 |
fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", |
1642 |
current_allocation - allocation_now); |
1643 |
if (current_allocation != 0) |
1644 |
{ |
1645 |
memory_infop pinfo = pinformation; |
1646 |
|
1647 |
fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", |
1648 |
current_allocation); |
1649 |
while (pinfo != NULL) |
1650 |
{ |
1651 |
fprintf(STDERR, " %lu bytes at %x\n", |
1652 |
(unsigned long)pinfo->size, (unsigned int)pinfo->pointer); |
1653 |
pinfo = pinfo->next; |
1654 |
} |
1655 |
} |
1656 |
#endif |
1657 |
} |
1658 |
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG |
1659 |
fprintf(STDERR, " Current memory allocation: %10d bytes\n", |
1660 |
current_allocation); |
1661 |
fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", |
1662 |
maximum_allocation); |
1663 |
fprintf(STDERR, " Total memory allocation: %10d bytes\n", |
1664 |
total_allocation); |
1665 |
fprintf(STDERR, " Number of allocations: %10d\n", |
1666 |
num_allocations); |
1667 |
#endif |
1668 |
} |
1669 |
|
1670 |
#ifdef PNGTEST_TIMING |
1671 |
t_stop = (float)clock(); |
1672 |
t_misc += (t_stop - t_start); |
1673 |
t_start = t_stop; |
1674 |
fprintf(STDERR, " CPU time used = %.3f seconds", |
1675 |
(t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); |
1676 |
fprintf(STDERR, " (decoding %.3f,\n", |
1677 |
t_decode/(float)CLOCKS_PER_SEC); |
1678 |
fprintf(STDERR, " encoding %.3f ,", |
1679 |
t_encode/(float)CLOCKS_PER_SEC); |
1680 |
fprintf(STDERR, " other %.3f seconds)\n\n", |
1681 |
t_misc/(float)CLOCKS_PER_SEC); |
1682 |
#endif |
1683 |
|
1684 |
if (ierror == 0) |
1685 |
fprintf(STDERR, " libpng passes test\n"); |
1686 |
else |
1687 |
fprintf(STDERR, " libpng FAILS test\n"); |
1688 |
return (int)(ierror != 0); |
1689 |
} |
1690 |
|
1691 |
/* Generate a compiler error if there is an old png.h in the search path. */ |
1692 |
typedef version_1_2_39 your_png_h_is_not_version_1_2_39; |