stbImageWrapper.cpp 3.0 KB

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