2
0

imageAPI.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2017 to 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_API_IMAGE
  24. #define DFPSR_API_IMAGE
  25. #include "types.h"
  26. #include "../base/SafePointer.h"
  27. namespace dsr {
  28. // Constructors
  29. // Each row's start and stride is aligned to 16-bytes using padding at the end
  30. // This allow using in-place writing with aligned 16-byte SIMD vectors
  31. AlignedImageU8 image_create_U8(int32_t width, int32_t height);
  32. AlignedImageU16 image_create_U16(int32_t width, int32_t height);
  33. AlignedImageF32 image_create_F32(int32_t width, int32_t height);
  34. OrderedImageRgbaU8 image_create_RgbaU8(int32_t width, int32_t height);
  35. AlignedImageRgbaU8 image_create_RgbaU8_native(int32_t width, int32_t height, PackOrderIndex packOrderIndex);
  36. // Properties
  37. // Returns image's width in pixels or 0 on null image
  38. int32_t image_getWidth(const ImageU8& image);
  39. int32_t image_getWidth(const ImageU16& image);
  40. int32_t image_getWidth(const ImageF32& image);
  41. int32_t image_getWidth(const ImageRgbaU8& image);
  42. // Returns image's height in pixels or 0 on null image
  43. int32_t image_getHeight(const ImageU8& image);
  44. int32_t image_getHeight(const ImageU16& image);
  45. int32_t image_getHeight(const ImageF32& image);
  46. int32_t image_getHeight(const ImageRgbaU8& image);
  47. // Returns image's stride in bytes or 0 on null image
  48. // Stride is the offset from the beginning of one row to another
  49. // May be larger than width times pixel size
  50. // * If padding is used to align with 16-bytes
  51. // * Or the buffer is shared with a larger image
  52. int32_t image_getStride(const ImageU8& image);
  53. int32_t image_getStride(const ImageU16& image);
  54. int32_t image_getStride(const ImageF32& image);
  55. int32_t image_getStride(const ImageRgbaU8& image);
  56. // Get a rectangle from the image's dimensions with the top left corner set to (0, 0)
  57. // Useful for clipping to an image's bounds or subdividing space for a graphical user interface
  58. IRect image_getBound(const ImageU8& image);
  59. IRect image_getBound(const ImageU16& image);
  60. IRect image_getBound(const ImageF32& image);
  61. IRect image_getBound(const ImageRgbaU8& image);
  62. // Returns false on null, true otherwise
  63. bool image_exists(const ImageU8& image);
  64. bool image_exists(const ImageU16& image);
  65. bool image_exists(const ImageF32& image);
  66. bool image_exists(const ImageRgbaU8& image);
  67. // Returns the number of handles to the image
  68. // References to a handle doesn't count, only when a handle is stored by value
  69. int image_useCount(const ImageU8& image);
  70. int image_useCount(const ImageU16& image);
  71. int image_useCount(const ImageF32& image);
  72. int image_useCount(const ImageRgbaU8& image);
  73. // Returns the image's pack order index
  74. PackOrderIndex image_getPackOrderIndex(const ImageRgbaU8& image);
  75. // Texture
  76. // TODO: A method for removing the pyramid
  77. void image_generatePyramid(ImageRgbaU8& image);
  78. bool image_hasPyramid(const ImageRgbaU8& image);
  79. bool image_isTexture(const ImageRgbaU8& image);
  80. // Pixel access
  81. // Write a pixel to an image.
  82. // Out of bound is ignored silently without writing.
  83. // Empty images will be ignored safely.
  84. // Packed is faster if the color can be packed in advance for multiple pixels or comes directly from an image of the same rgba order.
  85. void image_writePixel(ImageU8& image, int32_t x, int32_t y, int32_t color); // Saturated to 0..255
  86. void image_writePixel(ImageU16& image, int32_t x, int32_t y, int32_t color); // Saturated to 0..65535
  87. void image_writePixel(ImageF32& image, int32_t x, int32_t y, float color);
  88. void image_writePixel(ImageRgbaU8& image, int32_t x, int32_t y, const ColorRgbaI32& color); // Saturated to 0..255
  89. // Read a pixel from an image.
  90. // Out of bound will return the border color.
  91. // Empty images will return zero.
  92. int32_t image_readPixel_border(const ImageU8& image, int32_t x, int32_t y, int32_t border = 0); // Can have negative value as border
  93. int32_t image_readPixel_border(const ImageU16& image, int32_t x, int32_t y, int32_t border = 0); // Can have negative value as border
  94. float image_readPixel_border(const ImageF32& image, int32_t x, int32_t y, float border = 0.0f);
  95. ColorRgbaI32 image_readPixel_border(const ImageRgbaU8& image, int32_t x, int32_t y, const ColorRgbaI32& border = ColorRgbaI32()); // Can have negative value as border
  96. // Read a pixel from an image.
  97. // Out of bound will return the closest pixel.
  98. // Empty images will return zero.
  99. uint8_t image_readPixel_clamp(const ImageU8& image, int32_t x, int32_t y);
  100. uint16_t image_readPixel_clamp(const ImageU16& image, int32_t x, int32_t y);
  101. float image_readPixel_clamp(const ImageF32& image, int32_t x, int32_t y);
  102. ColorRgbaI32 image_readPixel_clamp(const ImageRgbaU8& image, int32_t x, int32_t y);
  103. // Read a pixel from an image.
  104. // Out of bound will take the coordinates in modulo of the size.
  105. // Empty images will return zero.
  106. uint8_t image_readPixel_tile(const ImageU8& image, int32_t x, int32_t y);
  107. uint16_t image_readPixel_tile(const ImageU16& image, int32_t x, int32_t y);
  108. float image_readPixel_tile(const ImageF32& image, int32_t x, int32_t y);
  109. ColorRgbaI32 image_readPixel_tile(const ImageRgbaU8& image, int32_t x, int32_t y);
  110. // ------------------------ Below is untested! ------------------------ //
  111. // Loading and saving
  112. OrderedImageRgbaU8 image_load_RgbaU8(const String& filename, bool mustExist = true);
  113. bool image_save(const ImageRgbaU8 &image, const String& filename);
  114. // Fill all pixels with a uniform color
  115. void image_fill(ImageU8& image, int32_t color);
  116. void image_fill(ImageU16& image, int32_t color);
  117. void image_fill(ImageF32& image, float color);
  118. void image_fill(ImageRgbaU8& image, const ColorRgbaI32& color);
  119. // Clone
  120. // Get a deep clone of an image's content while discarding any pack order, padding and texture pyramids
  121. AlignedImageU8 image_clone(const ImageU8& image);
  122. AlignedImageU16 image_clone(const ImageU16& image);
  123. AlignedImageF32 image_clone(const ImageF32& image);
  124. OrderedImageRgbaU8 image_clone(const ImageRgbaU8& image);
  125. // Returns a copy of the image without any padding, which means that alignment cannot be guaranteed
  126. // Used when external image libraries don't allow it
  127. ImageRgbaU8 image_removePadding(const ImageRgbaU8& image);
  128. // Channel packing
  129. // Extract one channel
  130. AlignedImageU8 image_get_red(const ImageRgbaU8& image);
  131. AlignedImageU8 image_get_green(const ImageRgbaU8& image);
  132. AlignedImageU8 image_get_blue(const ImageRgbaU8& image);
  133. AlignedImageU8 image_get_alpha(const ImageRgbaU8& image);
  134. // Pack one channel
  135. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, int32_t blue, int32_t alpha);
  136. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, int32_t blue, int32_t alpha);
  137. OrderedImageRgbaU8 image_pack(int32_t red, int32_t green, const ImageU8& blue, int32_t alpha);
  138. OrderedImageRgbaU8 image_pack(int32_t red, int32_t green, int32_t blue, const ImageU8& alpha);
  139. // Pack two channels
  140. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, int32_t blue, int32_t alpha);
  141. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, const ImageU8& blue, int32_t alpha);
  142. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, int32_t blue, const ImageU8& alpha);
  143. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, const ImageU8& blue, int32_t alpha);
  144. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, int32_t blue, const ImageU8& alpha);
  145. OrderedImageRgbaU8 image_pack(int32_t red, int32_t green, const ImageU8& blue, const ImageU8& alpha);
  146. // Pack three channels
  147. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, const ImageU8& blue, const ImageU8& alpha);
  148. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, const ImageU8& blue, const ImageU8& alpha);
  149. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, int32_t blue, const ImageU8& alpha);
  150. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, const ImageU8& blue, int32_t alpha);
  151. // Pack four channels
  152. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, const ImageU8& blue, const ImageU8& alpha);
  153. // Ascii images
  154. String image_toAscii(const ImageU8& image, const String &alphabet);
  155. String image_toAscii(const ImageU8& image);
  156. AlignedImageU8 image_fromAscii(const String &content);
  157. // Comparisons
  158. // Get the maximum pixelwise difference between two images of the same format, or the highest possible value on failure
  159. // Useful for regression tests
  160. uint8_t image_maxDifference(const ImageU8& imageA, const ImageU8& imageB);
  161. uint16_t image_maxDifference(const ImageU16& imageA, const ImageU16& imageB);
  162. float image_maxDifference(const ImageF32& imageA, const ImageF32& imageB);
  163. uint8_t image_maxDifference(const ImageRgbaU8& imageA, const ImageRgbaU8& imageB);
  164. // Sub-images are viewports to another image's data
  165. // TODO: Aligned sub-images that only takes vertial sections using whole rows
  166. // TODO: Aligned sub-images that terminates with an error if the input rectangle isn't aligned
  167. // Start must be 16-byte aligned, end must be same as the parent or also 16-byte aligned
  168. // TODO: Make an optional warning for not returning the desired dimensions when out of bound
  169. // Get a sub-image sharing buffer and side-effects with the parent image
  170. // Returns the overlapping region if out of bound
  171. // Returns a null image if there are no overlapping pixels to return
  172. ImageU8 image_getSubImage(const ImageU8& image, const IRect& region);
  173. ImageU16 image_getSubImage(const ImageU16& image, const IRect& region);
  174. ImageF32 image_getSubImage(const ImageF32& image, const IRect& region);
  175. ImageRgbaU8 image_getSubImage(const ImageRgbaU8& image, const IRect& region);
  176. // Bound-checked pointer access (relatively safe compared to a raw pointer)
  177. // Returns a bound-checked pointer to the first byte at rowIndex
  178. // Bound-checked safe-pointers are equally fast as raw pointers in release mode
  179. // Warning! Bound-checked pointers are not reference counted, because that would be too slow for real-time graphics
  180. SafePointer<uint8_t> image_getSafePointer(const ImageU8& image, int rowIndex = 0);
  181. SafePointer<uint16_t> image_getSafePointer(const ImageU16& image, int rowIndex = 0);
  182. SafePointer<float> image_getSafePointer(const ImageF32& image, int rowIndex = 0);
  183. SafePointer<uint32_t> image_getSafePointer(const ImageRgbaU8& image, int rowIndex = 0);
  184. // Get a pointer iterating over individual channels instead of whole pixels
  185. SafePointer<uint8_t> image_getSafePointer_channels(const ImageRgbaU8& image, int rowIndex = 0);
  186. // The dangerous image API
  187. // Use of these methods can be spotted using a search for "_dangerous_" in your code
  188. // Replaces the destructor in image's buffer.
  189. // newDestructor is responsible for freeing the given data.
  190. // Use when the buffer's pointer is being sent to a function that promises to free the memory
  191. // For example: Creating buffers being wrapped as XLib images
  192. void image_dangerous_replaceDestructor(ImageU8& image, const std::function<void(uint8_t *)>& newDestructor);
  193. void image_dangerous_replaceDestructor(ImageU16& image, const std::function<void(uint8_t *)>& newDestructor);
  194. void image_dangerous_replaceDestructor(ImageF32& image, const std::function<void(uint8_t *)>& newDestructor);
  195. void image_dangerous_replaceDestructor(ImageRgbaU8& image, const std::function<void(uint8_t *)>& newDestructor);
  196. // Returns a pointer to the image's pixels
  197. // Warning! Reading elements larger than 8 bits will have lower and higher bytes stored based on local endianness
  198. // Warning! Using bytes outside of the [0 .. stride * height - 1] range may cause crashes and undefined behaviour
  199. // Warning! Using the pointer after the image's lifetime may cause crashes from trying to access freed memory
  200. uint8_t* image_dangerous_getData(ImageU8& image);
  201. uint8_t* image_dangerous_getData(ImageU16& image);
  202. uint8_t* image_dangerous_getData(ImageF32& image);
  203. uint8_t* image_dangerous_getData(ImageRgbaU8& image);
  204. }
  205. #endif