Image.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "Base.h"
  2. #include "FileSystem.h"
  3. #include "Image.h"
  4. namespace gameplay
  5. {
  6. Image* Image::create(const char* path)
  7. {
  8. // Open the file.
  9. FILE* fp = FileSystem::openFile(path, "rb");
  10. if (fp == NULL)
  11. {
  12. return NULL;
  13. }
  14. // Verify PNG signature.
  15. unsigned char sig[8];
  16. if (fread(sig, 1, 8, fp) != 8 || png_sig_cmp(sig, 0, 8) != 0)
  17. {
  18. LOG_ERROR_VARG("Texture is not a valid PNG: %s", path);
  19. fclose(fp);
  20. return NULL;
  21. }
  22. // Initialize png read struct (last three parameters use stderr+longjump if NULL).
  23. png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  24. if (png == NULL)
  25. {
  26. fclose(fp);
  27. return NULL;
  28. }
  29. // Initialize info struct.
  30. png_infop info = png_create_info_struct(png);
  31. if (info == NULL)
  32. {
  33. fclose(fp);
  34. png_destroy_read_struct(&png, NULL, NULL);
  35. return NULL;
  36. }
  37. // Set up error handling (required without using custom error handlers above).
  38. if (setjmp(png_jmpbuf(png)))
  39. {
  40. fclose(fp);
  41. png_destroy_read_struct(&png, &info, NULL);
  42. return NULL;
  43. }
  44. // Initialize file io.
  45. png_init_io(png, fp);
  46. // Indicate that we already read the first 8 bytes (signature).
  47. png_set_sig_bytes(png, 8);
  48. // Read the entire image into memory.
  49. png_read_png(png, info, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
  50. Image* image = new Image();
  51. image->_width = png_get_image_width(png, info);
  52. image->_height = png_get_image_height(png, info);
  53. png_byte colorType = png_get_color_type(png, info);
  54. switch (colorType)
  55. {
  56. case PNG_COLOR_TYPE_RGBA:
  57. image->_format = Image::RGBA;
  58. break;
  59. case PNG_COLOR_TYPE_RGB:
  60. image->_format = Image::RGB;
  61. break;
  62. default:
  63. LOG_ERROR_VARG("Unsupported PNG color type (%d) for texture: %s", (int)colorType, path);
  64. fclose(fp);
  65. png_destroy_read_struct(&png, &info, NULL);
  66. return NULL;
  67. }
  68. unsigned int stride = png_get_rowbytes(png, info);
  69. // Allocate image data.
  70. image->_data = new unsigned char[stride * image->_height];
  71. // Read rows into image data.
  72. png_bytepp rows = png_get_rows(png, info);
  73. for (unsigned int i = 0; i < image->_height; ++i)
  74. {
  75. memcpy(image->_data+(stride * (image->_height-1-i)), rows[i], stride);
  76. }
  77. // Clean up.
  78. png_destroy_read_struct(&png, &info, NULL);
  79. fclose(fp);
  80. return image;
  81. }
  82. Image::Image()
  83. {
  84. // Unused
  85. }
  86. Image::~Image()
  87. {
  88. SAFE_DELETE_ARRAY(_data);
  89. }
  90. }