example.c 31 KB

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