Image.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "Image.h"
  2. #include "Base.h"
  3. namespace gameplay
  4. {
  5. Image::Image() :
  6. _data(NULL), _format(RGBA), _width(0), _height(0), _bpp(0)
  7. {
  8. }
  9. Image::~Image()
  10. {
  11. delete[] _data;
  12. }
  13. Image* Image::create(const char* path)
  14. {
  15. // Open the file.
  16. FILE* fp = fopen(path, "rb");
  17. if (fp == NULL)
  18. {
  19. LOG(1, "Failed to open image file '%s'.\n", path);
  20. return NULL;
  21. }
  22. // Verify PNG signature.
  23. unsigned char sig[8];
  24. if (fread(sig, 1, 8, fp) != 8 || png_sig_cmp(sig, 0, 8) != 0)
  25. {
  26. LOG(1, "Failed to load file '%s'; not a valid PNG.\n", path);
  27. if (fclose(fp) != 0)
  28. {
  29. LOG(1, "Failed to close image file '%s'.\n", path);
  30. }
  31. return NULL;
  32. }
  33. // Initialize png read struct (last three parameters use stderr+longjump if NULL).
  34. png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  35. if (png == NULL)
  36. {
  37. LOG(1, "Failed to create PNG structure for reading PNG file '%s'.\n", path);
  38. if (fclose(fp) != 0)
  39. {
  40. LOG(1, "Failed to close image file '%s'.\n", path);
  41. }
  42. return NULL;
  43. }
  44. // Initialize info struct.
  45. png_infop info = png_create_info_struct(png);
  46. if (info == NULL)
  47. {
  48. LOG(1, "Failed to create PNG info structure for PNG file '%s'.\n", path);
  49. if (fclose(fp) != 0)
  50. {
  51. LOG(1, "Failed to close image file '%s'.\n", path);
  52. }
  53. png_destroy_read_struct(&png, NULL, NULL);
  54. return NULL;
  55. }
  56. // Initialize file io.
  57. png_init_io(png, fp);
  58. // Indicate that we already read the first 8 bytes (signature).
  59. png_set_sig_bytes(png, 8);
  60. // Read the entire image into memory.
  61. png_read_png(png, info, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
  62. Image* image = new Image();
  63. image->_width = png_get_image_width(png, info);
  64. image->_height = png_get_image_height(png, info);
  65. png_byte colorType = png_get_color_type(png, info);
  66. switch (colorType)
  67. {
  68. case PNG_COLOR_TYPE_GRAY:
  69. image->_bpp = 1;
  70. image->_format = Image::LUMINANCE;
  71. break;
  72. case PNG_COLOR_TYPE_RGBA:
  73. image->_bpp = 4;
  74. image->_format = Image::RGBA;
  75. break;
  76. case PNG_COLOR_TYPE_RGB:
  77. image->_bpp = 3;
  78. image->_format = Image::RGB;
  79. break;
  80. default:
  81. LOG(1, "Unsupported PNG color type (%d) for image file '%s'.\n", (int)colorType, path);
  82. if (fclose(fp) != 0)
  83. {
  84. LOG(1, "Failed to close image file '%s'.\n", path);
  85. }
  86. png_destroy_read_struct(&png, &info, NULL);
  87. return NULL;
  88. }
  89. size_t stride = png_get_rowbytes(png, info);
  90. // Allocate image data.
  91. image->_data = new unsigned char[stride * image->_height];
  92. // Read rows into image data.
  93. png_bytepp rows = png_get_rows(png, info);
  94. for (unsigned int i = 0; i < image->_height; ++i)
  95. {
  96. memcpy(image->_data+(stride * i), rows[i], stride);
  97. }
  98. // Clean up.
  99. png_destroy_read_struct(&png, &info, NULL);
  100. if (fclose(fp) != 0)
  101. {
  102. LOG(1, "Failed to close image file '%s'.\n", path);
  103. }
  104. return image;
  105. }
  106. Image* Image::create(Format format, unsigned int width, unsigned int height)
  107. {
  108. unsigned int bpp;
  109. switch (format)
  110. {
  111. case LUMINANCE:
  112. bpp = 1;
  113. break;
  114. case RGB:
  115. bpp = 3;
  116. break;
  117. case RGBA:
  118. bpp = 4;
  119. break;
  120. default:
  121. LOG(1, "Invalid image format passed to create.\n");
  122. return NULL;
  123. }
  124. Image* image = new Image();
  125. image->_format = format;
  126. image->_width = width;
  127. image->_height = height;
  128. image->_bpp = bpp;
  129. image->_data = new unsigned char[width * height * bpp];
  130. memset(image->_data, 0, width * height * bpp);
  131. return image;
  132. }
  133. void* Image::getData() const
  134. {
  135. return _data;
  136. }
  137. void Image::setData(void* data)
  138. {
  139. memcpy(_data, data, _width * _height * _bpp);
  140. }
  141. Image::Format Image::getFormat() const
  142. {
  143. return _format;
  144. }
  145. unsigned int Image::getHeight() const
  146. {
  147. return _height;
  148. }
  149. unsigned int Image::getWidth() const
  150. {
  151. return _width;
  152. }
  153. unsigned int Image::getBpp() const
  154. {
  155. return _bpp;
  156. }
  157. int getPNGColorType(Image::Format format)
  158. {
  159. switch (format)
  160. {
  161. case Image::LUMINANCE:
  162. return PNG_COLOR_TYPE_GRAY;
  163. case Image::RGB:
  164. return PNG_COLOR_TYPE_RGB;
  165. case Image::RGBA:
  166. return PNG_COLOR_TYPE_RGBA;
  167. }
  168. return PNG_COLOR_TYPE_RGBA;
  169. }
  170. void Image::save(const char* path)
  171. {
  172. png_structp png_ptr = NULL;
  173. png_infop info_ptr = NULL;
  174. png_bytep row = NULL;
  175. unsigned int stride;
  176. int index;
  177. FILE* fp = fopen(path, "wb");
  178. if (fp == NULL)
  179. {
  180. LOG(1, "Error: Failed to open image for writing: %s\n", path);
  181. goto error;
  182. }
  183. png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  184. if (png_ptr == NULL)
  185. {
  186. LOG(1, "Error: Write struct creation failed: %s\n", path);
  187. goto error;
  188. }
  189. info_ptr = png_create_info_struct(png_ptr);
  190. if (info_ptr == NULL)
  191. {
  192. LOG(1, "Error: Info struct creation failed: %s\n", path);
  193. goto error;
  194. }
  195. png_init_io(png_ptr, fp);
  196. png_set_IHDR(png_ptr, info_ptr, _width, _height, 8, getPNGColorType(_format), PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  197. png_write_info(png_ptr, info_ptr);
  198. // Allocate memory for a single row of image data
  199. stride = _bpp * _width * sizeof(png_byte);
  200. row = (png_bytep)malloc(stride);
  201. index = 0;
  202. for (unsigned int y = 0; y < _height; ++y)
  203. {
  204. for (unsigned int x = 0; x < stride; ++x)
  205. {
  206. // Write data
  207. row[x] = (png_byte)_data[index++];
  208. }
  209. png_write_row(png_ptr, row);
  210. }
  211. png_write_end(png_ptr, NULL);
  212. error:
  213. if (fp)
  214. fclose(fp);
  215. if (row)
  216. free(row);
  217. if (info_ptr)
  218. png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
  219. if (png_ptr)
  220. png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
  221. }
  222. }