stbImageWrapper.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. 
  2. #define STB_IMAGE_IMPLEMENTATION
  3. #include "stb_image.h"
  4. #define STB_IMAGE_WRITE_IMPLEMENTATION
  5. #include "stb_image_write.h"
  6. #include "stbImageWrapper.h"
  7. namespace dsr {
  8. OrderedImageRgbaU8 image_stb_decode_RgbaU8(const SafePointer<uint8_t> data, int size) {
  9. #ifdef SAFE_POINTER_CHECKS
  10. // If the safe pointer has debug information, use it to assert that size is within bound.
  11. data.assertInside("image_stb_decode_RgbaU8 (data)", data.getUnsafe(), (size_t)size);
  12. #endif
  13. int width, height, bpp;
  14. uint8_t *rawPixelData = stbi_load_from_memory(data.getUnsafe(), size, &width, &height, &bpp, 4);
  15. if (rawPixelData == nullptr) {
  16. return OrderedImageRgbaU8(); // Return null
  17. }
  18. // Create a padded buffer
  19. OrderedImageRgbaU8 result = image_create_RgbaU8(width, height);
  20. // Copy the data
  21. int rowSize = width * 4;
  22. int32_t targetStride = image_getStride(result);
  23. const uint8_t *sourceRow = rawPixelData;
  24. uint8_t* targetRow = image_dangerous_getData(result);
  25. for (int32_t y = 0; y < height; y++) {
  26. // Copy a row without touching the padding
  27. memcpy(targetRow, sourceRow, rowSize);
  28. // Add stride using single byte elements
  29. targetRow += targetStride;
  30. sourceRow += rowSize;
  31. }
  32. // Free the unpadded image
  33. free((void*)rawPixelData);
  34. return result;
  35. }
  36. // Pre-condition: Images that STB image don't have stride implementations for must be given unpadded images.
  37. Buffer image_stb_encode(const ImageRgbaU8 &image, ImageFileFormat format, int quality) {
  38. int width = image_getWidth(image);
  39. int height = image_getHeight(image);
  40. List<uint8_t> targetList;
  41. // Reserve enough memory for an uncompressed file to reduce the need for reallcation.
  42. targetList.reserve(width * height * 4 + 2048);
  43. stbi_write_func* writer = [](void* context, void* data, int size) {
  44. List<uint8_t>* target = (List<uint8_t>*)context;
  45. for (int i = 0; i < size; i++) {
  46. target->push(((uint8_t*)data)[i]);
  47. }
  48. };
  49. bool success = false;
  50. if (format == ImageFileFormat::JPG) {
  51. success = stbi_write_jpg_to_func(writer, &targetList, width, height, 4, image_dangerous_getData(image), quality);
  52. } else if (format == ImageFileFormat::PNG) {
  53. success = stbi_write_png_to_func(writer, &targetList, width, height, 4, image_dangerous_getData(image), image_getStride(image));
  54. } else if (format == ImageFileFormat::TGA) {
  55. success = stbi_write_tga_to_func(writer, &targetList, width, height, 4, image_dangerous_getData(image));
  56. } else if (format == ImageFileFormat::BMP) {
  57. success = stbi_write_bmp_to_func(writer, &targetList, width, height, 4, image_dangerous_getData(image));
  58. }
  59. if (success) {
  60. // Copy data to a new buffer once the total size is known.
  61. Buffer result = buffer_create(targetList.length());
  62. uint8_t* targetData = buffer_dangerous_getUnsafeData(result);
  63. memcpy(targetData, &targetList[0], targetList.length());
  64. return result; // Return the buffer on success.
  65. } else {
  66. return Buffer(); // Return a null handle on failure.
  67. }
  68. }
  69. }