Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

png.cpp 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*!
  2. * \file src/utils/png.cpp
  3. * \brief PNG image reader
  4. *
  5. * https://github.com/DavidEGrayson/ahrs-visualizer/blob/master/png_texture.cpp
  6. * http://zarb.org/~gc/html/libpng.html
  7. *
  8. * \author xythobuz
  9. */
  10. #include <png.h>
  11. #include <cstdio>
  12. #include "global.h"
  13. #include "utils/png.h"
  14. #ifdef DEBUG
  15. #include "Console.h"
  16. #define pngPrint getConsole().print
  17. #else
  18. void pngPrint(...) { }
  19. #endif
  20. int pngLoad(const char *filename, unsigned char **image, unsigned int *width, unsigned int *height) {
  21. png_byte header[8];
  22. assert(filename != NULL);
  23. assert(filename[0] != '\0');
  24. assert(image != NULL);
  25. assert(width != NULL);
  26. assert(height != NULL);
  27. FILE *fp = fopen(filename, "rb");
  28. if (fp == NULL) {
  29. pngPrint("Could not open %s", filename);
  30. return -1;
  31. }
  32. fread(header, 1, 8, fp);
  33. if (png_sig_cmp(header, 0, 8)) {
  34. pngPrint("File %s is not a PNG.", filename);
  35. fclose(fp);
  36. return -2;
  37. }
  38. png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  39. if (!png_ptr) {
  40. pngPrint("png_create_read_struct returned 0.");
  41. fclose(fp);
  42. return -3;
  43. }
  44. png_infop info_ptr = png_create_info_struct(png_ptr);
  45. if (!info_ptr) {
  46. pngPrint("png_create_info_struct returned 0.");
  47. png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
  48. fclose(fp);
  49. return -4;
  50. }
  51. png_infop end_info = png_create_info_struct(png_ptr);
  52. if (!end_info) {
  53. pngPrint("png_create_info_struct returned 0.");
  54. png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
  55. fclose(fp);
  56. return -5;
  57. }
  58. if (setjmp(png_jmpbuf(png_ptr))) {
  59. pngPrint("Error from libpng");
  60. png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  61. fclose(fp);
  62. return -6;
  63. }
  64. png_init_io(png_ptr, fp);
  65. png_set_sig_bytes(png_ptr, 8);
  66. png_read_info(png_ptr, info_ptr);
  67. int bit_depth, color_type;
  68. png_get_IHDR(png_ptr, info_ptr, width, height, &bit_depth, &color_type,
  69. NULL, NULL, NULL);
  70. if (bit_depth != 8) {
  71. pngPrint("%s: Unsupported bit depth %d. Must be 8.", filename, bit_depth);
  72. return -7;
  73. }
  74. png_read_update_info(png_ptr, info_ptr);
  75. int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  76. png_byte *image_data = new png_byte[(rowbytes * *height) + 15];
  77. png_bytep *row_pointers = new png_bytep[*height];
  78. for (unsigned int i = 0; i < *height; i++)
  79. row_pointers[*height - 1 - i] = image_data + i * rowbytes;
  80. png_read_image(png_ptr, row_pointers);
  81. png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  82. delete [] row_pointers;
  83. fclose(fp);
  84. if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  85. *image = image_data;
  86. } else {
  87. *image = new unsigned char[*width * *height * 4];
  88. if (color_type == PNG_COLOR_TYPE_RGB) {
  89. for (unsigned int i = 0; i < (*width * *height); i++) {
  90. *image[i * 4] = image_data[i * 3];
  91. *image[(i * 4) + 1] = image_data[(i * 3) + 1];
  92. *image[(i * 4) + 2] = image_data[(i * 3) + 2];
  93. *image[(i * 4) + 3] = 255;
  94. }
  95. } else {
  96. pngPrint("%s: Unknown libpng color type %d.", filename, color_type);
  97. delete [] image_data;
  98. delete [] *image;
  99. *image = NULL;
  100. return -8;
  101. }
  102. delete [] image_data;
  103. }
  104. return 0;
  105. }
  106. int pngSave(const char *filename, unsigned char *image, unsigned int width, unsigned int height) {
  107. assert(filename != NULL);
  108. assert(filename[0] != '\0');
  109. assert(image != NULL);
  110. assert(width > 0);
  111. assert(height > 0);
  112. FILE *fp = fopen(filename, "wb");
  113. if (!fp) {
  114. pngPrint("File %s could not be opened for writing", filename);
  115. return -1;
  116. }
  117. png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  118. if (!png_ptr) {
  119. pngPrint("png_create_write_struct failed");
  120. fclose(fp);
  121. return -2;
  122. }
  123. png_infop info_ptr = png_create_info_struct(png_ptr);
  124. if (!info_ptr) {
  125. pngPrint("png_create_info_struct failed");
  126. fclose(fp);
  127. return -3;
  128. }
  129. if (setjmp(png_jmpbuf(png_ptr))) {
  130. pngPrint("Error during init_io");
  131. fclose(fp);
  132. return -4;
  133. }
  134. png_init_io(png_ptr, fp);
  135. if (setjmp(png_jmpbuf(png_ptr))) {
  136. pngPrint("Error during writing header");
  137. fclose(fp);
  138. return -5;
  139. }
  140. png_set_IHDR(png_ptr, info_ptr, width, height,
  141. 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
  142. PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  143. png_write_info(png_ptr, info_ptr);
  144. png_bytep *row_pointers = new png_bytep[height];
  145. for (unsigned int i = 0; i < height; i++)
  146. row_pointers[height - 1 - i] = image + (i * width * 4);
  147. if (setjmp(png_jmpbuf(png_ptr))) {
  148. pngPrint("Error during writing bytes");
  149. delete [] row_pointers;
  150. fclose(fp);
  151. return -6;
  152. }
  153. png_write_image(png_ptr, row_pointers);
  154. if (setjmp(png_jmpbuf(png_ptr))) {
  155. pngPrint("Error during end of write");
  156. delete [] row_pointers;
  157. fclose(fp);
  158. return -7;
  159. }
  160. png_write_end(png_ptr, NULL);
  161. delete [] row_pointers;
  162. fclose(fp);
  163. return 0;
  164. }