readpng.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* http://www.libpng.org/pub/png/book/chapter13.html */
  2. #include "png.h"
  3. static png_structp png_ptr;
  4. static png_infop info_ptr;
  5. static unsigned int width;
  6. static unsigned int height;
  7. static int bit_depth;
  8. static int color_type;
  9. void readpng_version_info();
  10. int readpng_init(FILE*, long*, long*);
  11. int readpng_get_bgcolor(unsigned char *red, unsigned char *green, unsigned char *blue);
  12. void readpng_version_info() {
  13. fprintf(stderr, " compiled with libpng %s; using libpng %s\n", PNG_LIBPNG_VER_STRING, png_libpng_ver);
  14. //fprintf(stderr, " compiled with zlip %s; using zlib %s\n", ZLIB_VERSION, zlib_version);
  15. }
  16. int readpng_init(FILE *infile, long *pWidth, long *pHeight) {
  17. /* 1 housekeeping */
  18. unsigned char sig[8];
  19. fread(sig, 1, 8, infile);
  20. if (!png_check_sig(sig, 8))
  21. return 1; // bad signature
  22. png_ptr = png_create_read_struct(
  23. PNG_LIBPNG_VER_STRING,
  24. NULL,
  25. NULL,
  26. NULL
  27. );
  28. if (!png_ptr)
  29. return 4; // out of memory
  30. info_ptr = png_create_info_struct(png_ptr);
  31. if (!info_ptr) {
  32. png_destroy_read_struct(&png_ptr, NULL, NULL);
  33. return 4; // out of memory
  34. }
  35. if (setjmp(png_jmpbuf(png_ptr))) {
  36. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  37. return 2;
  38. }
  39. /* 2 actual png reading */
  40. png_init_io(png_ptr, infile);
  41. png_set_sig_bytes(png_ptr, 8);
  42. png_read_info(png_ptr, info_ptr);
  43. png_get_IHDR(
  44. png_ptr, info_ptr,
  45. &width, &height,
  46. &bit_depth, &color_type,
  47. NULL, NULL, NULL
  48. );
  49. *pWidth = width;
  50. *pHeight = height;
  51. return 0;
  52. }
  53. int readpng_get_bgcolor(unsigned char *red, unsigned char *green, unsigned char *blue) {
  54. if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
  55. return 1;
  56. png_color_16p pbackground;
  57. png_get_bKGD(png_ptr, info_ptr, &pbackground);
  58. /* half bit_depth requires bitshifts */
  59. if (bit_depth == 16) {
  60. *red = pbackground->red >> 8;
  61. *green = pbackground->green >> 8;
  62. *blue = pbackground->blue >> 8;
  63. /* grayscale is treated specially */
  64. } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
  65. /* bit_depth of 1 gives us only 2 colors */
  66. if (bit_depth == 1)
  67. *red = *green = *blue = pbackground->gray ? 255 : 0;
  68. /* bit_depth of 2 gives us 3 as max value */
  69. else if (bit_depth == 2)
  70. *red = *green = *blue = (255/3) * pbackground->gray;
  71. /* bit_depth of 4 gives us 15 as max value */
  72. else
  73. *red = *green = *blue = (255/15) * pbackground->gray;
  74. } else {
  75. *red = pbackground->red;
  76. *green = pbackground->green;
  77. *blue = pbackground->blue;
  78. }
  79. return 0;
  80. }