diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/libpng/example.c')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/libpng/example.c | 862 |
1 files changed, 0 insertions, 862 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/example.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/example.c deleted file mode 100644 index ec53a8c..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/libpng/example.c +++ /dev/null | |||
@@ -1,862 +0,0 @@ | |||
1 | |||
2 | #if 0 /* in case someone actually tries to compile this */ | ||
3 | |||
4 | /* example.c - an example of using libpng | ||
5 | * Last changed in libpng 1.5.7 [December 15, 2011] | ||
6 | * Maintained 1998-2011 Glenn Randers-Pehrson | ||
7 | * Maintained 1996, 1997 Andreas Dilger | ||
8 | * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc. | ||
9 | */ | ||
10 | |||
11 | /* This is an example of how to use libpng to read and write PNG files. | ||
12 | * The file libpng-manual.txt is much more verbose then this. If you have not | ||
13 | * read it, do so first. This was designed to be a starting point of an | ||
14 | * implementation. This is not officially part of libpng, is hereby placed | ||
15 | * in the public domain, and therefore does not require a copyright notice. | ||
16 | * To the extent possible under law, the authors have waived all copyright and | ||
17 | * related or neighboring rights to this file. | ||
18 | * | ||
19 | * This file does not currently compile, because it is missing certain | ||
20 | * parts, like allocating memory to hold an image. You will have to | ||
21 | * supply these parts to get it to compile. For an example of a minimal | ||
22 | * working PNG reader/writer, see pngtest.c, included in this distribution; | ||
23 | * see also the programs in the contrib directory. | ||
24 | */ | ||
25 | |||
26 | #define _POSIX_SOURCE 1 /* libpng and zlib are POSIX-compliant. You may | ||
27 | * change this if your application uses non-POSIX | ||
28 | * extensions. */ | ||
29 | |||
30 | #include "png.h" | ||
31 | |||
32 | /* The png_jmpbuf() macro, used in error handling, became available in | ||
33 | * libpng version 1.0.6. If you want to be able to run your code with older | ||
34 | * versions of libpng, you must define the macro yourself (but only if it | ||
35 | * is not already defined by libpng!). | ||
36 | */ | ||
37 | |||
38 | #ifndef png_jmpbuf | ||
39 | # define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf) | ||
40 | #endif | ||
41 | |||
42 | /* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() | ||
43 | * returns zero if the image is a PNG and nonzero if it isn't a PNG. | ||
44 | * | ||
45 | * The function check_if_png() shown here, but not used, returns nonzero (true) | ||
46 | * if the file can be opened and is a PNG, 0 (false) otherwise. | ||
47 | * | ||
48 | * If this call is successful, and you are going to keep the file open, | ||
49 | * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once | ||
50 | * you have created the png_ptr, so that libpng knows your application | ||
51 | * has read that many bytes from the start of the file. Make sure you | ||
52 | * don't call png_set_sig_bytes() with more than 8 bytes read or give it | ||
53 | * an incorrect number of bytes read, or you will either have read too | ||
54 | * many bytes (your fault), or you are telling libpng to read the wrong | ||
55 | * number of magic bytes (also your fault). | ||
56 | * | ||
57 | * Many applications already read the first 2 or 4 bytes from the start | ||
58 | * of the image to determine the file type, so it would be easiest just | ||
59 | * to pass the bytes to png_sig_cmp() or even skip that if you know | ||
60 | * you have a PNG file, and call png_set_sig_bytes(). | ||
61 | */ | ||
62 | #define PNG_BYTES_TO_CHECK 4 | ||
63 | int check_if_png(char *file_name, FILE **fp) | ||
64 | { | ||
65 | char buf[PNG_BYTES_TO_CHECK]; | ||
66 | |||
67 | /* Open the prospective PNG file. */ | ||
68 | if ((*fp = fopen(file_name, "rb")) == NULL) | ||
69 | return 0; | ||
70 | |||
71 | /* Read in some of the signature bytes */ | ||
72 | if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) | ||
73 | return 0; | ||
74 | |||
75 | /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. | ||
76 | Return nonzero (true) if they match */ | ||
77 | |||
78 | return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); | ||
79 | } | ||
80 | |||
81 | /* Read a PNG file. You may want to return an error code if the read | ||
82 | * fails (depending upon the failure). There are two "prototypes" given | ||
83 | * here - one where we are given the filename, and we need to open the | ||
84 | * file, and the other where we are given an open file (possibly with | ||
85 | * some or all of the magic bytes read - see comments above). | ||
86 | */ | ||
87 | #ifdef open_file /* prototype 1 */ | ||
88 | void read_png(char *file_name) /* We need to open the file */ | ||
89 | { | ||
90 | png_structp png_ptr; | ||
91 | png_infop info_ptr; | ||
92 | unsigned int sig_read = 0; | ||
93 | png_uint_32 width, height; | ||
94 | int bit_depth, color_type, interlace_type; | ||
95 | FILE *fp; | ||
96 | |||
97 | if ((fp = fopen(file_name, "rb")) == NULL) | ||
98 | return (ERROR); | ||
99 | |||
100 | #else no_open_file /* prototype 2 */ | ||
101 | void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ | ||
102 | { | ||
103 | png_structp png_ptr; | ||
104 | png_infop info_ptr; | ||
105 | png_uint_32 width, height; | ||
106 | int bit_depth, color_type, interlace_type; | ||
107 | #endif no_open_file /* Only use one prototype! */ | ||
108 | |||
109 | /* Create and initialize the png_struct with the desired error handler | ||
110 | * functions. If you want to use the default stderr and longjump method, | ||
111 | * you can supply NULL for the last three parameters. We also supply the | ||
112 | * the compiler header file version, so that we know if the application | ||
113 | * was compiled with a compatible version of the library. REQUIRED | ||
114 | */ | ||
115 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, | ||
116 | png_voidp user_error_ptr, user_error_fn, user_warning_fn); | ||
117 | |||
118 | if (png_ptr == NULL) | ||
119 | { | ||
120 | fclose(fp); | ||
121 | return (ERROR); | ||
122 | } | ||
123 | |||
124 | /* Allocate/initialize the memory for image information. REQUIRED. */ | ||
125 | info_ptr = png_create_info_struct(png_ptr); | ||
126 | if (info_ptr == NULL) | ||
127 | { | ||
128 | fclose(fp); | ||
129 | png_destroy_read_struct(&png_ptr, NULL, NULL); | ||
130 | return (ERROR); | ||
131 | } | ||
132 | |||
133 | /* Set error handling if you are using the setjmp/longjmp method (this is | ||
134 | * the normal method of doing things with libpng). REQUIRED unless you | ||
135 | * set up your own error handlers in the png_create_read_struct() earlier. | ||
136 | */ | ||
137 | |||
138 | if (setjmp(png_jmpbuf(png_ptr))) | ||
139 | { | ||
140 | /* Free all of the memory associated with the png_ptr and info_ptr */ | ||
141 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
142 | fclose(fp); | ||
143 | /* If we get here, we had a problem reading the file */ | ||
144 | return (ERROR); | ||
145 | } | ||
146 | |||
147 | /* One of the following I/O initialization methods is REQUIRED */ | ||
148 | #ifdef streams /* PNG file I/O method 1 */ | ||
149 | /* Set up the input control if you are using standard C streams */ | ||
150 | png_init_io(png_ptr, fp); | ||
151 | |||
152 | #else no_streams /* PNG file I/O method 2 */ | ||
153 | /* If you are using replacement read functions, instead of calling | ||
154 | * png_init_io() here you would call: | ||
155 | */ | ||
156 | png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); | ||
157 | /* where user_io_ptr is a structure you want available to the callbacks */ | ||
158 | #endif no_streams /* Use only one I/O method! */ | ||
159 | |||
160 | /* If we have already read some of the signature */ | ||
161 | png_set_sig_bytes(png_ptr, sig_read); | ||
162 | |||
163 | #ifdef hilevel | ||
164 | /* | ||
165 | * If you have enough memory to read in the entire image at once, | ||
166 | * and you need to specify only transforms that can be controlled | ||
167 | * with one of the PNG_TRANSFORM_* bits (this presently excludes | ||
168 | * quantizing, filling, setting background, and doing gamma | ||
169 | * adjustment), then you can read the entire image (including | ||
170 | * pixels) into the info structure with this call: | ||
171 | */ | ||
172 | png_read_png(png_ptr, info_ptr, png_transforms, NULL); | ||
173 | |||
174 | #else | ||
175 | /* OK, you're doing it the hard way, with the lower-level functions */ | ||
176 | |||
177 | /* The call to png_read_info() gives us all of the information from the | ||
178 | * PNG file before the first IDAT (image data chunk). REQUIRED | ||
179 | */ | ||
180 | png_read_info(png_ptr, info_ptr); | ||
181 | |||
182 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, | ||
183 | &interlace_type, NULL, NULL); | ||
184 | |||
185 | /* Set up the data transformations you want. Note that these are all | ||
186 | * optional. Only call them if you want/need them. Many of the | ||
187 | * transformations only work on specific types of images, and many | ||
188 | * are mutually exclusive. | ||
189 | */ | ||
190 | |||
191 | /* Tell libpng to strip 16 bit/color files down to 8 bits/color. | ||
192 | * Use accurate scaling if it's available, otherwise just chop off the | ||
193 | * low byte. | ||
194 | */ | ||
195 | #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED | ||
196 | png_set_scale_16(png_ptr); | ||
197 | #else | ||
198 | png_set_strip_16(png_ptr); | ||
199 | #endif | ||
200 | |||
201 | /* Strip alpha bytes from the input data without combining with the | ||
202 | * background (not recommended). | ||
203 | */ | ||
204 | png_set_strip_alpha(png_ptr); | ||
205 | |||
206 | /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single | ||
207 | * byte into separate bytes (useful for paletted and grayscale images). | ||
208 | */ | ||
209 | png_set_packing(png_ptr); | ||
210 | |||
211 | /* Change the order of packed pixels to least significant bit first | ||
212 | * (not useful if you are using png_set_packing). */ | ||
213 | png_set_packswap(png_ptr); | ||
214 | |||
215 | /* Expand paletted colors into true RGB triplets */ | ||
216 | if (color_type == PNG_COLOR_TYPE_PALETTE) | ||
217 | png_set_palette_to_rgb(png_ptr); | ||
218 | |||
219 | /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ | ||
220 | if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) | ||
221 | png_set_expand_gray_1_2_4_to_8(png_ptr); | ||
222 | |||
223 | /* Expand paletted or RGB images with transparency to full alpha channels | ||
224 | * so the data will be available as RGBA quartets. | ||
225 | */ | ||
226 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) | ||
227 | png_set_tRNS_to_alpha(png_ptr); | ||
228 | |||
229 | /* Set the background color to draw transparent and alpha images over. | ||
230 | * It is possible to set the red, green, and blue components directly | ||
231 | * for paletted images instead of supplying a palette index. Note that | ||
232 | * even if the PNG file supplies a background, you are not required to | ||
233 | * use it - you should use the (solid) application background if it has one. | ||
234 | */ | ||
235 | |||
236 | png_color_16 my_background, *image_background; | ||
237 | |||
238 | if (png_get_bKGD(png_ptr, info_ptr, &image_background)) | ||
239 | png_set_background(png_ptr, image_background, | ||
240 | PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); | ||
241 | else | ||
242 | png_set_background(png_ptr, &my_background, | ||
243 | PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); | ||
244 | |||
245 | /* Some suggestions as to how to get a screen gamma value | ||
246 | * | ||
247 | * Note that screen gamma is the display_exponent, which includes | ||
248 | * the CRT_exponent and any correction for viewing conditions | ||
249 | */ | ||
250 | if (/* We have a user-defined screen gamma value */) | ||
251 | { | ||
252 | screen_gamma = user-defined screen_gamma; | ||
253 | } | ||
254 | /* This is one way that applications share the same screen gamma value */ | ||
255 | else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) | ||
256 | { | ||
257 | screen_gamma = atof(gamma_str); | ||
258 | } | ||
259 | /* If we don't have another value */ | ||
260 | else | ||
261 | { | ||
262 | screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly | ||
263 | lit room */ | ||
264 | screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ | ||
265 | } | ||
266 | |||
267 | /* Tell libpng to handle the gamma conversion for you. The final call | ||
268 | * is a good guess for PC generated images, but it should be configurable | ||
269 | * by the user at run time by the user. It is strongly suggested that | ||
270 | * your application support gamma correction. | ||
271 | */ | ||
272 | |||
273 | int intent; | ||
274 | |||
275 | if (png_get_sRGB(png_ptr, info_ptr, &intent)) | ||
276 | png_set_gamma(png_ptr, screen_gamma, 0.45455); | ||
277 | else | ||
278 | { | ||
279 | double image_gamma; | ||
280 | if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) | ||
281 | png_set_gamma(png_ptr, screen_gamma, image_gamma); | ||
282 | else | ||
283 | png_set_gamma(png_ptr, screen_gamma, 0.45455); | ||
284 | } | ||
285 | |||
286 | #ifdef PNG_READ_QUANTIZE_SUPPORTED | ||
287 | /* Quantize RGB files down to 8 bit palette or reduce palettes | ||
288 | * to the number of colors available on your screen. | ||
289 | */ | ||
290 | if (color_type & PNG_COLOR_MASK_COLOR) | ||
291 | { | ||
292 | int num_palette; | ||
293 | png_colorp palette; | ||
294 | |||
295 | /* This reduces the image to the application supplied palette */ | ||
296 | if (/* We have our own palette */) | ||
297 | { | ||
298 | /* An array of colors to which the image should be quantized */ | ||
299 | png_color std_color_cube[MAX_SCREEN_COLORS]; | ||
300 | |||
301 | png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS, | ||
302 | MAX_SCREEN_COLORS, NULL, 0); | ||
303 | } | ||
304 | /* This reduces the image to the palette supplied in the file */ | ||
305 | else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) | ||
306 | { | ||
307 | png_uint_16p histogram = NULL; | ||
308 | |||
309 | png_get_hIST(png_ptr, info_ptr, &histogram); | ||
310 | |||
311 | png_set_quantize(png_ptr, palette, num_palette, | ||
312 | max_screen_colors, histogram, 0); | ||
313 | } | ||
314 | } | ||
315 | #endif /* PNG_READ_QUANTIZE_SUPPORTED */ | ||
316 | |||
317 | /* Invert monochrome files to have 0 as white and 1 as black */ | ||
318 | png_set_invert_mono(png_ptr); | ||
319 | |||
320 | /* If you want to shift the pixel values from the range [0,255] or | ||
321 | * [0,65535] to the original [0,7] or [0,31], or whatever range the | ||
322 | * colors were originally in: | ||
323 | */ | ||
324 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) | ||
325 | { | ||
326 | png_color_8p sig_bit_p; | ||
327 | |||
328 | png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); | ||
329 | png_set_shift(png_ptr, sig_bit_p); | ||
330 | } | ||
331 | |||
332 | /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ | ||
333 | if (color_type & PNG_COLOR_MASK_COLOR) | ||
334 | png_set_bgr(png_ptr); | ||
335 | |||
336 | /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ | ||
337 | png_set_swap_alpha(png_ptr); | ||
338 | |||
339 | /* Swap bytes of 16 bit files to least significant byte first */ | ||
340 | png_set_swap(png_ptr); | ||
341 | |||
342 | /* Add filler (or alpha) byte (before/after each RGB triplet) */ | ||
343 | png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); | ||
344 | |||
345 | #ifdef PNG_READ_INTERLACING_SUPPORTED | ||
346 | /* Turn on interlace handling. REQUIRED if you are not using | ||
347 | * png_read_image(). To see how to handle interlacing passes, | ||
348 | * see the png_read_row() method below: | ||
349 | */ | ||
350 | number_passes = png_set_interlace_handling(png_ptr); | ||
351 | #else | ||
352 | number_passes = 1; | ||
353 | #endif /* PNG_READ_INTERLACING_SUPPORTED */ | ||
354 | |||
355 | |||
356 | /* Optional call to gamma correct and add the background to the palette | ||
357 | * and update info structure. REQUIRED if you are expecting libpng to | ||
358 | * update the palette for you (ie you selected such a transform above). | ||
359 | */ | ||
360 | png_read_update_info(png_ptr, info_ptr); | ||
361 | |||
362 | /* Allocate the memory to hold the image using the fields of info_ptr. */ | ||
363 | |||
364 | /* The easiest way to read the image: */ | ||
365 | png_bytep row_pointers[height]; | ||
366 | |||
367 | /* Clear the pointer array */ | ||
368 | for (row = 0; row < height; row++) | ||
369 | row_pointers[row] = NULL; | ||
370 | |||
371 | for (row = 0; row < height; row++) | ||
372 | row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, | ||
373 | info_ptr)); | ||
374 | |||
375 | /* Now it's time to read the image. One of these methods is REQUIRED */ | ||
376 | #ifdef entire /* Read the entire image in one go */ | ||
377 | png_read_image(png_ptr, row_pointers); | ||
378 | |||
379 | #else no_entire /* Read the image one or more scanlines at a time */ | ||
380 | /* The other way to read images - deal with interlacing: */ | ||
381 | |||
382 | for (pass = 0; pass < number_passes; pass++) | ||
383 | { | ||
384 | #ifdef single /* Read the image a single row at a time */ | ||
385 | for (y = 0; y < height; y++) | ||
386 | { | ||
387 | png_read_rows(png_ptr, &row_pointers[y], NULL, 1); | ||
388 | } | ||
389 | |||
390 | #else no_single /* Read the image several rows at a time */ | ||
391 | for (y = 0; y < height; y += number_of_rows) | ||
392 | { | ||
393 | #ifdef sparkle /* Read the image using the "sparkle" effect. */ | ||
394 | png_read_rows(png_ptr, &row_pointers[y], NULL, | ||
395 | number_of_rows); | ||
396 | #else no_sparkle /* Read the image using the "rectangle" effect */ | ||
397 | png_read_rows(png_ptr, NULL, &row_pointers[y], | ||
398 | number_of_rows); | ||
399 | #endif no_sparkle /* Use only one of these two methods */ | ||
400 | } | ||
401 | |||
402 | /* If you want to display the image after every pass, do so here */ | ||
403 | #endif no_single /* Use only one of these two methods */ | ||
404 | } | ||
405 | #endif no_entire /* Use only one of these two methods */ | ||
406 | |||
407 | /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ | ||
408 | png_read_end(png_ptr, info_ptr); | ||
409 | #endif hilevel | ||
410 | |||
411 | /* At this point you have read the entire image */ | ||
412 | |||
413 | /* Clean up after the read, and free any memory allocated - REQUIRED */ | ||
414 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
415 | |||
416 | /* Close the file */ | ||
417 | fclose(fp); | ||
418 | |||
419 | /* That's it */ | ||
420 | return (OK); | ||
421 | } | ||
422 | |||
423 | /* Progressively read a file */ | ||
424 | |||
425 | int | ||
426 | initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) | ||
427 | { | ||
428 | /* Create and initialize the png_struct with the desired error handler | ||
429 | * functions. If you want to use the default stderr and longjump method, | ||
430 | * you can supply NULL for the last three parameters. We also check that | ||
431 | * the library version is compatible in case we are using dynamically | ||
432 | * linked libraries. | ||
433 | */ | ||
434 | *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, | ||
435 | png_voidp user_error_ptr, user_error_fn, user_warning_fn); | ||
436 | |||
437 | if (*png_ptr == NULL) | ||
438 | { | ||
439 | *info_ptr = NULL; | ||
440 | return (ERROR); | ||
441 | } | ||
442 | |||
443 | *info_ptr = png_create_info_struct(png_ptr); | ||
444 | |||
445 | if (*info_ptr == NULL) | ||
446 | { | ||
447 | png_destroy_read_struct(png_ptr, info_ptr, NULL); | ||
448 | return (ERROR); | ||
449 | } | ||
450 | |||
451 | if (setjmp(png_jmpbuf((*png_ptr)))) | ||
452 | { | ||
453 | png_destroy_read_struct(png_ptr, info_ptr, NULL); | ||
454 | return (ERROR); | ||
455 | } | ||
456 | |||
457 | /* This one's new. You will need to provide all three | ||
458 | * function callbacks, even if you aren't using them all. | ||
459 | * If you aren't using all functions, you can specify NULL | ||
460 | * parameters. Even when all three functions are NULL, | ||
461 | * you need to call png_set_progressive_read_fn(). | ||
462 | * These functions shouldn't be dependent on global or | ||
463 | * static variables if you are decoding several images | ||
464 | * simultaneously. You should store stream specific data | ||
465 | * in a separate struct, given as the second parameter, | ||
466 | * and retrieve the pointer from inside the callbacks using | ||
467 | * the function png_get_progressive_ptr(png_ptr). | ||
468 | */ | ||
469 | png_set_progressive_read_fn(*png_ptr, (void *)stream_data, | ||
470 | info_callback, row_callback, end_callback); | ||
471 | |||
472 | return (OK); | ||
473 | } | ||
474 | |||
475 | int | ||
476 | process_data(png_structp *png_ptr, png_infop *info_ptr, | ||
477 | png_bytep buffer, png_uint_32 length) | ||
478 | { | ||
479 | if (setjmp(png_jmpbuf((*png_ptr)))) | ||
480 | { | ||
481 | /* Free the png_ptr and info_ptr memory on error */ | ||
482 | png_destroy_read_struct(png_ptr, info_ptr, NULL); | ||
483 | return (ERROR); | ||
484 | } | ||
485 | |||
486 | /* This one's new also. Simply give it chunks of data as | ||
487 | * they arrive from the data stream (in order, of course). | ||
488 | * On segmented machines, don't give it any more than 64K. | ||
489 | * The library seems to run fine with sizes of 4K, although | ||
490 | * you can give it much less if necessary (I assume you can | ||
491 | * give it chunks of 1 byte, but I haven't tried with less | ||
492 | * than 256 bytes yet). When this function returns, you may | ||
493 | * want to display any rows that were generated in the row | ||
494 | * callback, if you aren't already displaying them there. | ||
495 | */ | ||
496 | png_process_data(*png_ptr, *info_ptr, buffer, length); | ||
497 | return (OK); | ||
498 | } | ||
499 | |||
500 | info_callback(png_structp png_ptr, png_infop info) | ||
501 | { | ||
502 | /* Do any setup here, including setting any of the transformations | ||
503 | * mentioned in the Reading PNG files section. For now, you _must_ | ||
504 | * call either png_start_read_image() or png_read_update_info() | ||
505 | * after all the transformations are set (even if you don't set | ||
506 | * any). You may start getting rows before png_process_data() | ||
507 | * returns, so this is your last chance to prepare for that. | ||
508 | */ | ||
509 | } | ||
510 | |||
511 | row_callback(png_structp png_ptr, png_bytep new_row, | ||
512 | png_uint_32 row_num, int pass) | ||
513 | { | ||
514 | /* | ||
515 | * This function is called for every row in the image. If the | ||
516 | * image is interlaced, and you turned on the interlace handler, | ||
517 | * this function will be called for every row in every pass. | ||
518 | * | ||
519 | * In this function you will receive a pointer to new row data from | ||
520 | * libpng called new_row that is to replace a corresponding row (of | ||
521 | * the same data format) in a buffer allocated by your application. | ||
522 | * | ||
523 | * The new row data pointer "new_row" may be NULL, indicating there is | ||
524 | * no new data to be replaced (in cases of interlace loading). | ||
525 | * | ||
526 | * If new_row is not NULL then you need to call | ||
527 | * png_progressive_combine_row() to replace the corresponding row as | ||
528 | * shown below: | ||
529 | */ | ||
530 | |||
531 | /* Get pointer to corresponding row in our | ||
532 | * PNG read buffer. | ||
533 | */ | ||
534 | png_bytep old_row = ((png_bytep *)our_data)[row_num]; | ||
535 | |||
536 | #ifdef PNG_READ_INTERLACING_SUPPORTED | ||
537 | /* If both rows are allocated then copy the new row | ||
538 | * data to the corresponding row data. | ||
539 | */ | ||
540 | if ((old_row != NULL) && (new_row != NULL)) | ||
541 | png_progressive_combine_row(png_ptr, old_row, new_row); | ||
542 | |||
543 | /* | ||
544 | * The rows and passes are called in order, so you don't really | ||
545 | * need the row_num and pass, but I'm supplying them because it | ||
546 | * may make your life easier. | ||
547 | * | ||
548 | * For the non-NULL rows of interlaced images, you must call | ||
549 | * png_progressive_combine_row() passing in the new row and the | ||
550 | * old row, as demonstrated above. You can call this function for | ||
551 | * NULL rows (it will just return) and for non-interlaced images | ||
552 | * (it just does the png_memcpy for you) if it will make the code | ||
553 | * easier. Thus, you can just do this for all cases: | ||
554 | */ | ||
555 | |||
556 | png_progressive_combine_row(png_ptr, old_row, new_row); | ||
557 | |||
558 | /* where old_row is what was displayed for previous rows. Note | ||
559 | * that the first pass (pass == 0 really) will completely cover | ||
560 | * the old row, so the rows do not have to be initialized. After | ||
561 | * the first pass (and only for interlaced images), you will have | ||
562 | * to pass the current row as new_row, and the function will combine | ||
563 | * the old row and the new row. | ||
564 | */ | ||
565 | #endif /* PNG_READ_INTERLACING_SUPPORTED */ | ||
566 | } | ||
567 | |||
568 | end_callback(png_structp png_ptr, png_infop info) | ||
569 | { | ||
570 | /* This function is called when the whole image has been read, | ||
571 | * including any chunks after the image (up to and including | ||
572 | * the IEND). You will usually have the same info chunk as you | ||
573 | * had in the header, although some data may have been added | ||
574 | * to the comments and time fields. | ||
575 | * | ||
576 | * Most people won't do much here, perhaps setting a flag that | ||
577 | * marks the image as finished. | ||
578 | */ | ||
579 | } | ||
580 | |||
581 | /* Write a png file */ | ||
582 | void write_png(char *file_name /* , ... other image information ... */) | ||
583 | { | ||
584 | FILE *fp; | ||
585 | png_structp png_ptr; | ||
586 | png_infop info_ptr; | ||
587 | png_colorp palette; | ||
588 | |||
589 | /* Open the file */ | ||
590 | fp = fopen(file_name, "wb"); | ||
591 | if (fp == NULL) | ||
592 | return (ERROR); | ||
593 | |||
594 | /* Create and initialize the png_struct with the desired error handler | ||
595 | * functions. If you want to use the default stderr and longjump method, | ||
596 | * you can supply NULL for the last three parameters. We also check that | ||
597 | * the library version is compatible with the one used at compile time, | ||
598 | * in case we are using dynamically linked libraries. REQUIRED. | ||
599 | */ | ||
600 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, | ||
601 | png_voidp user_error_ptr, user_error_fn, user_warning_fn); | ||
602 | |||
603 | if (png_ptr == NULL) | ||
604 | { | ||
605 | fclose(fp); | ||
606 | return (ERROR); | ||
607 | } | ||
608 | |||
609 | /* Allocate/initialize the image information data. REQUIRED */ | ||
610 | info_ptr = png_create_info_struct(png_ptr); | ||
611 | if (info_ptr == NULL) | ||
612 | { | ||
613 | fclose(fp); | ||
614 | png_destroy_write_struct(&png_ptr, NULL); | ||
615 | return (ERROR); | ||
616 | } | ||
617 | |||
618 | /* Set error handling. REQUIRED if you aren't supplying your own | ||
619 | * error handling functions in the png_create_write_struct() call. | ||
620 | */ | ||
621 | if (setjmp(png_jmpbuf(png_ptr))) | ||
622 | { | ||
623 | /* If we get here, we had a problem writing the file */ | ||
624 | fclose(fp); | ||
625 | png_destroy_write_struct(&png_ptr, &info_ptr); | ||
626 | return (ERROR); | ||
627 | } | ||
628 | |||
629 | /* One of the following I/O initialization functions is REQUIRED */ | ||
630 | |||
631 | #ifdef streams /* I/O initialization method 1 */ | ||
632 | /* Set up the output control if you are using standard C streams */ | ||
633 | png_init_io(png_ptr, fp); | ||
634 | |||
635 | #else no_streams /* I/O initialization method 2 */ | ||
636 | /* If you are using replacement write functions, instead of calling | ||
637 | * png_init_io() here you would call | ||
638 | */ | ||
639 | png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, | ||
640 | user_IO_flush_function); | ||
641 | /* where user_io_ptr is a structure you want available to the callbacks */ | ||
642 | #endif no_streams /* Only use one initialization method */ | ||
643 | |||
644 | #ifdef hilevel | ||
645 | /* This is the easy way. Use it if you already have all the | ||
646 | * image info living in the structure. You could "|" many | ||
647 | * PNG_TRANSFORM flags into the png_transforms integer here. | ||
648 | */ | ||
649 | png_write_png(png_ptr, info_ptr, png_transforms, NULL); | ||
650 | |||
651 | #else | ||
652 | /* This is the hard way */ | ||
653 | |||
654 | /* Set the image information here. Width and height are up to 2^31, | ||
655 | * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on | ||
656 | * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, | ||
657 | * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, | ||
658 | * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or | ||
659 | * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST | ||
660 | * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED | ||
661 | */ | ||
662 | png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, | ||
663 | PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); | ||
664 | |||
665 | /* Set the palette if there is one. REQUIRED for indexed-color images */ | ||
666 | palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH | ||
667 | * png_sizeof(png_color)); | ||
668 | /* ... Set palette colors ... */ | ||
669 | png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); | ||
670 | /* You must not free palette here, because png_set_PLTE only makes a link to | ||
671 | * the palette that you malloced. Wait until you are about to destroy | ||
672 | * the png structure. | ||
673 | */ | ||
674 | |||
675 | /* Optional significant bit (sBIT) chunk */ | ||
676 | png_color_8 sig_bit; | ||
677 | |||
678 | /* If we are dealing with a grayscale image then */ | ||
679 | sig_bit.gray = true_bit_depth; | ||
680 | |||
681 | /* Otherwise, if we are dealing with a color image then */ | ||
682 | sig_bit.red = true_red_bit_depth; | ||
683 | sig_bit.green = true_green_bit_depth; | ||
684 | sig_bit.blue = true_blue_bit_depth; | ||
685 | |||
686 | /* If the image has an alpha channel then */ | ||
687 | sig_bit.alpha = true_alpha_bit_depth; | ||
688 | |||
689 | png_set_sBIT(png_ptr, info_ptr, &sig_bit); | ||
690 | |||
691 | |||
692 | /* Optional gamma chunk is strongly suggested if you have any guess | ||
693 | * as to the correct gamma of the image. | ||
694 | */ | ||
695 | png_set_gAMA(png_ptr, info_ptr, gamma); | ||
696 | |||
697 | /* Optionally write comments into the image */ | ||
698 | text_ptr[0].key = "Title"; | ||
699 | text_ptr[0].text = "Mona Lisa"; | ||
700 | text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; | ||
701 | text_ptr[0].itxt_length = 0; | ||
702 | text_ptr[0].lang = NULL; | ||
703 | text_ptr[0].lang_key = NULL; | ||
704 | text_ptr[1].key = "Author"; | ||
705 | text_ptr[1].text = "Leonardo DaVinci"; | ||
706 | text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; | ||
707 | text_ptr[1].itxt_length = 0; | ||
708 | text_ptr[1].lang = NULL; | ||
709 | text_ptr[1].lang_key = NULL; | ||
710 | text_ptr[2].key = "Description"; | ||
711 | text_ptr[2].text = "<long text>"; | ||
712 | text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; | ||
713 | text_ptr[2].itxt_length = 0; | ||
714 | text_ptr[2].lang = NULL; | ||
715 | text_ptr[2].lang_key = NULL; | ||
716 | png_set_text(png_ptr, info_ptr, text_ptr, 3); | ||
717 | |||
718 | /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */ | ||
719 | |||
720 | /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored | ||
721 | * on read and, if your application chooses to write them, they must | ||
722 | * be written in accordance with the sRGB profile | ||
723 | */ | ||
724 | |||
725 | /* Write the file header information. REQUIRED */ | ||
726 | png_write_info(png_ptr, info_ptr); | ||
727 | |||
728 | /* If you want, you can write the info in two steps, in case you need to | ||
729 | * write your private chunk ahead of PLTE: | ||
730 | * | ||
731 | * png_write_info_before_PLTE(write_ptr, write_info_ptr); | ||
732 | * write_my_chunk(); | ||
733 | * png_write_info(png_ptr, info_ptr); | ||
734 | * | ||
735 | * However, given the level of known- and unknown-chunk support in 1.2.0 | ||
736 | * and up, this should no longer be necessary. | ||
737 | */ | ||
738 | |||
739 | /* Once we write out the header, the compression type on the text | ||
740 | * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or | ||
741 | * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again | ||
742 | * at the end. | ||
743 | */ | ||
744 | |||
745 | /* Set up the transformations you want. Note that these are | ||
746 | * all optional. Only call them if you want them. | ||
747 | */ | ||
748 | |||
749 | /* Invert monochrome pixels */ | ||
750 | png_set_invert_mono(png_ptr); | ||
751 | |||
752 | /* Shift the pixels up to a legal bit depth and fill in | ||
753 | * as appropriate to correctly scale the image. | ||
754 | */ | ||
755 | png_set_shift(png_ptr, &sig_bit); | ||
756 | |||
757 | /* Pack pixels into bytes */ | ||
758 | png_set_packing(png_ptr); | ||
759 | |||
760 | /* Swap location of alpha bytes from ARGB to RGBA */ | ||
761 | png_set_swap_alpha(png_ptr); | ||
762 | |||
763 | /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into | ||
764 | * RGB (4 channels -> 3 channels). The second parameter is not used. | ||
765 | */ | ||
766 | png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); | ||
767 | |||
768 | /* Flip BGR pixels to RGB */ | ||
769 | png_set_bgr(png_ptr); | ||
770 | |||
771 | /* Swap bytes of 16-bit files to most significant byte first */ | ||
772 | png_set_swap(png_ptr); | ||
773 | |||
774 | /* Swap bits of 1, 2, 4 bit packed pixel formats */ | ||
775 | png_set_packswap(png_ptr); | ||
776 | |||
777 | /* Turn on interlace handling if you are not using png_write_image() */ | ||
778 | if (interlacing) | ||
779 | number_passes = png_set_interlace_handling(png_ptr); | ||
780 | |||
781 | else | ||
782 | number_passes = 1; | ||
783 | |||
784 | /* The easiest way to write the image (you may have a different memory | ||
785 | * layout, however, so choose what fits your needs best). You need to | ||
786 | * use the first method if you aren't handling interlacing yourself. | ||
787 | */ | ||
788 | png_uint_32 k, height, width; | ||
789 | png_byte image[height][width*bytes_per_pixel]; | ||
790 | png_bytep row_pointers[height]; | ||
791 | |||
792 | if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) | ||
793 | png_error (png_ptr, "Image is too tall to process in memory"); | ||
794 | |||
795 | for (k = 0; k < height; k++) | ||
796 | row_pointers[k] = image + k*width*bytes_per_pixel; | ||
797 | |||
798 | /* One of the following output methods is REQUIRED */ | ||
799 | |||
800 | #ifdef entire /* Write out the entire image data in one call */ | ||
801 | png_write_image(png_ptr, row_pointers); | ||
802 | |||
803 | /* The other way to write the image - deal with interlacing */ | ||
804 | |||
805 | #else no_entire /* Write out the image data by one or more scanlines */ | ||
806 | |||
807 | /* The number of passes is either 1 for non-interlaced images, | ||
808 | * or 7 for interlaced images. | ||
809 | */ | ||
810 | for (pass = 0; pass < number_passes; pass++) | ||
811 | { | ||
812 | /* Write a few rows at a time. */ | ||
813 | png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); | ||
814 | |||
815 | /* If you are only writing one row at a time, this works */ | ||
816 | for (y = 0; y < height; y++) | ||
817 | png_write_rows(png_ptr, &row_pointers[y], 1); | ||
818 | } | ||
819 | #endif no_entire /* Use only one output method */ | ||
820 | |||
821 | /* You can write optional chunks like tEXt, zTXt, and tIME at the end | ||
822 | * as well. Shouldn't be necessary in 1.2.0 and up as all the public | ||
823 | * chunks are supported and you can use png_set_unknown_chunks() to | ||
824 | * register unknown chunks into the info structure to be written out. | ||
825 | */ | ||
826 | |||
827 | /* It is REQUIRED to call this to finish writing the rest of the file */ | ||
828 | png_write_end(png_ptr, info_ptr); | ||
829 | #endif hilevel | ||
830 | |||
831 | /* If you png_malloced a palette, free it here (don't free info_ptr->palette, | ||
832 | * as recommended in versions 1.0.5m and earlier of this example; if | ||
833 | * libpng mallocs info_ptr->palette, libpng will free it). If you | ||
834 | * allocated it with malloc() instead of png_malloc(), use free() instead | ||
835 | * of png_free(). | ||
836 | */ | ||
837 | png_free(png_ptr, palette); | ||
838 | palette = NULL; | ||
839 | |||
840 | /* Similarly, if you png_malloced any data that you passed in with | ||
841 | * png_set_something(), such as a hist or trans array, free it here, | ||
842 | * when you can be sure that libpng is through with it. | ||
843 | */ | ||
844 | png_free(png_ptr, trans); | ||
845 | trans = NULL; | ||
846 | /* Whenever you use png_free() it is a good idea to set the pointer to | ||
847 | * NULL in case your application inadvertently tries to png_free() it | ||
848 | * again. When png_free() sees a NULL it returns without action, thus | ||
849 | * avoiding the double-free security problem. | ||
850 | */ | ||
851 | |||
852 | /* Clean up after the write, and free any memory allocated */ | ||
853 | png_destroy_write_struct(&png_ptr, &info_ptr); | ||
854 | |||
855 | /* Close the file */ | ||
856 | fclose(fp); | ||
857 | |||
858 | /* That's it */ | ||
859 | return (OK); | ||
860 | } | ||
861 | |||
862 | #endif /* if 0 */ | ||