Image.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. GP_ASSERT(path);
  9. // Open the file.
  10. FILE* fp = FileSystem::openFile(path, "rb");
  11. if (fp == NULL)
  12. {
  13. GP_ERROR("Failed to open image file '%s'.", path);
  14. return NULL;
  15. }
  16. // Verify PNG signature.
  17. unsigned char sig[8];
  18. if (fread(sig, 1, 8, fp) != 8 || png_sig_cmp(sig, 0, 8) != 0)
  19. {
  20. GP_ERROR("Failed to load file '%s'; not a valid PNG.", path);
  21. if (fclose(fp) != 0)
  22. {
  23. GP_ERROR("Failed to close image file '%s'.", path);
  24. }
  25. return NULL;
  26. }
  27. // Initialize png read struct (last three parameters use stderr+longjump if NULL).
  28. png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  29. if (png == NULL)
  30. {
  31. GP_ERROR("Failed to create PNG structure for reading PNG file '%s'.", path);
  32. if (fclose(fp) != 0)
  33. {
  34. GP_ERROR("Failed to close image file '%s'.", path);
  35. }
  36. return NULL;
  37. }
  38. // Initialize info struct.
  39. png_infop info = png_create_info_struct(png);
  40. if (info == NULL)
  41. {
  42. GP_ERROR("Failed to create PNG info structure for PNG file '%s'.", path);
  43. if (fclose(fp) != 0)
  44. {
  45. GP_ERROR("Failed to close image file '%s'.", path);
  46. }
  47. png_destroy_read_struct(&png, NULL, NULL);
  48. return NULL;
  49. }
  50. // Set up error handling (required without using custom error handlers above).
  51. if (setjmp(png_jmpbuf(png)))
  52. {
  53. GP_ERROR("Failed to set up error handling for reading PNG file '%s'.", path);
  54. if (fclose(fp) != 0)
  55. {
  56. GP_ERROR("Failed to close image file '%s'.", path);
  57. }
  58. png_destroy_read_struct(&png, &info, NULL);
  59. return NULL;
  60. }
  61. // Initialize file io.
  62. png_init_io(png, fp);
  63. // Indicate that we already read the first 8 bytes (signature).
  64. png_set_sig_bytes(png, 8);
  65. // Read the entire image into memory.
  66. png_read_png(png, info, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
  67. Image* image = new Image();
  68. image->_width = png_get_image_width(png, info);
  69. image->_height = png_get_image_height(png, info);
  70. png_byte colorType = png_get_color_type(png, info);
  71. switch (colorType)
  72. {
  73. case PNG_COLOR_TYPE_RGBA:
  74. image->_format = Image::RGBA;
  75. break;
  76. case PNG_COLOR_TYPE_RGB:
  77. image->_format = Image::RGB;
  78. break;
  79. default:
  80. GP_ERROR("Unsupported PNG color type (%d) for image file '%s'.", (int)colorType, path);
  81. if (fclose(fp) != 0)
  82. {
  83. GP_ERROR("Failed to close image file '%s'.", path);
  84. }
  85. png_destroy_read_struct(&png, &info, NULL);
  86. return NULL;
  87. }
  88. unsigned int stride = png_get_rowbytes(png, info);
  89. // Allocate image data.
  90. image->_data = new unsigned char[stride * image->_height];
  91. // Read rows into image data.
  92. png_bytepp rows = png_get_rows(png, info);
  93. for (unsigned int i = 0; i < image->_height; ++i)
  94. {
  95. memcpy(image->_data+(stride * (image->_height-1-i)), rows[i], stride);
  96. }
  97. // Clean up.
  98. png_destroy_read_struct(&png, &info, NULL);
  99. if (fclose(fp) != 0)
  100. {
  101. GP_ERROR("Failed to close image file '%s'.", path);
  102. }
  103. return image;
  104. }
  105. Image::Image()
  106. {
  107. // Unused
  108. }
  109. Image::~Image()
  110. {
  111. SAFE_DELETE_ARRAY(_data);
  112. }
  113. }