3 * Copyright (c) 2013 John Cunningham Bowler
5 * Last changed in libpng 1.6.1 [March 28, 2013]
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
11 * Load an arbitrary number of PNG files (from the command line, or, if there
12 * are no arguments on the command line, from stdin) then run a time test by
13 * reading each file by row. The test does nothing with the read result and
14 * does no transforms. The only output is a time as a floating point number of
15 * seconds with 9 decimal digits.
17 #define _POSIX_C_SOURCE 199309L /* for clock_gettime */
25 #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
29 /* Define the following to use this test against your installed libpng, rather
30 * than the one being built here:
32 #ifdef PNG_FREESTANDING_TESTS
35 # include "../../png.h"
38 static int read_png(FILE *fp
)
40 png_structp png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
,0,0,0);
41 png_infop info_ptr
= NULL
;
42 png_bytep row
= NULL
, display
= NULL
;
47 if (setjmp(png_jmpbuf(png_ptr
)))
49 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
50 if (row
!= NULL
) free(row
);
51 if (display
!= NULL
) free(display
);
55 png_init_io(png_ptr
, fp
);
57 info_ptr
= png_create_info_struct(png_ptr
);
59 png_error(png_ptr
, "OOM allocating info structure");
61 png_read_info(png_ptr
, info_ptr
);
64 png_size_t rowbytes
= png_get_rowbytes(png_ptr
, info_ptr
);
66 row
= malloc(rowbytes
);
67 display
= malloc(rowbytes
);
69 if (row
== NULL
|| display
== NULL
)
70 png_error(png_ptr
, "OOM allocating row buffers");
73 png_uint_32 height
= png_get_image_height(png_ptr
, info_ptr
);
74 int passes
= png_set_interlace_handling(png_ptr
);
77 png_start_read_image(png_ptr
);
79 for (pass
= 0; pass
< passes
; ++pass
)
81 png_uint_32 y
= height
;
83 /* NOTE: this trashes the row each time; interlace handling won't
84 * work, but this avoids memory thrashing for speed testing.
87 png_read_row(png_ptr
, row
, display
);
92 /* Make sure to read to the end of the file: */
93 png_read_end(png_ptr
, info_ptr
);
94 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
100 static int mytime(struct timespec
*t
)
102 /* Do the timing using clock_gettime and the per-process timer. */
103 if (!clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, t
))
106 perror("CLOCK_PROCESS_CPUTIME_ID");
107 fprintf(stderr
, "timepng: could not get the time\n");
111 static int perform_one_test(FILE *fp
, int nfiles
)
114 struct timespec before
, after
;
116 /* Clear out all errors: */
121 for (i
=0; i
<nfiles
; ++i
)
127 perror("temporary file");
128 fprintf(stderr
, "file %d: error reading PNG data\n", i
);
135 perror("temporary file");
136 fprintf(stderr
, "file %d: error from libpng\n", i
);
147 /* Work out the time difference and print it - this is the only output,
148 * so flush it immediately.
150 unsigned long s
= after
.tv_sec
- before
.tv_sec
;
151 long ns
= after
.tv_nsec
- before
.tv_nsec
;
160 fprintf(stderr
, "timepng: bad clock from kernel\n");
165 printf("%lu.%.9ld\n", s
, ns
);
169 fprintf(stderr
, "timepng: error writing output\n");
173 /* Successful return */
181 static int add_one_file(FILE *fp
, char *name
)
183 FILE *ip
= fopen(name
, "rb");
191 if (ch
== EOF
) break;
198 fprintf(stderr
, "%s: read error\n", name
);
206 perror("temporary file");
207 fprintf(stderr
, "temporary file write error\n");
215 fprintf(stderr
, "%s: open failed\n", name
);
222 int main(int argc
, char **argv
)
225 FILE *fp
= tmpfile();
236 for (i
=1; i
<argc
; ++i
)
238 if (add_one_file(fp
, argv
[i
]))
251 char filename
[FILENAME_MAX
+1];
253 while (fgets(filename
, FILENAME_MAX
+1, stdin
))
255 size_t len
= strlen(filename
);
257 if (filename
[len
-1] == '\n')
260 if (add_one_file(fp
, filename
))
272 fprintf(stderr
, "timepng: truncated file name ...%s\n",
281 fprintf(stderr
, "timepng: stdin: read error\n");
289 ok
= perform_one_test(fp
, nfiles
);
292 fprintf(stderr
, "usage: timepng {files} or ls files | timepng\n");
299 fprintf(stderr
, "timepng: could not open temporary file\n");
301 /* Exit code 0 on success. */