imageAPI.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. // Pre-condition: image must exist and qualify as a texture according to image_isTexture
  77. // Side-effect: Creates a mip-map pyramid of lower resolution images from the current content
  78. // If successful, image_hasPyramid should return true from the image
  79. void image_generatePyramid(ImageRgbaU8& image);
  80. // Pre-condition: image must exist
  81. // Side-effect: Removes image's mip-map pyramid, including its buffer to save memory
  82. // If successful, image_hasPyramid should return false from the image
  83. void image_removePyramid(ImageRgbaU8& image);
  84. // Post-condition: Returns true iff image contains a mip-map pyramid generated by image_generatePyramid
  85. // Returns false without a warning if the image handle is empty
  86. bool image_hasPyramid(const ImageRgbaU8& image);
  87. // Post-condition: Returns true iff image fulfills the criterias for being a texture
  88. // Texture criterias:
  89. // * Each dimension of width and height should be a power-of-two
  90. // width = 2 ^ N
  91. // height = 2 ^ N
  92. // * Width and height should also be from 4 to 16384 pixels
  93. // Large enough to allow padding-free SIMD vectorization of 128-bit vectors (4 x 32 = 128)
  94. // Small enough to allow expressing the total size in bytes using a signed 32-bit integer
  95. // 4 <= width <= 16384
  96. // 4 <= height <= 16384
  97. // * Each row must consume the whole stride
  98. // Textures may not contain padding in the rows, but it's okay to use sub-images from a vertical atlas where the whole width is consumed
  99. // Returns false without a warning if the image handle is empty
  100. bool image_isTexture(const ImageRgbaU8& image);
  101. // Pixel access
  102. // Write a pixel to an image.
  103. // Out of bound is ignored silently without writing.
  104. // Empty images will be ignored safely.
  105. // 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.
  106. void image_writePixel(ImageU8& image, int32_t x, int32_t y, int32_t color); // Saturated to 0..255
  107. void image_writePixel(ImageU16& image, int32_t x, int32_t y, int32_t color); // Saturated to 0..65535
  108. void image_writePixel(ImageF32& image, int32_t x, int32_t y, float color);
  109. void image_writePixel(ImageRgbaU8& image, int32_t x, int32_t y, const ColorRgbaI32& color); // Saturated to 0..255
  110. // Read a pixel from an image.
  111. // Out of bound will return the border color.
  112. // Empty images will return zero.
  113. int32_t image_readPixel_border(const ImageU8& image, int32_t x, int32_t y, int32_t border = 0); // Can have negative value as border
  114. int32_t image_readPixel_border(const ImageU16& image, int32_t x, int32_t y, int32_t border = 0); // Can have negative value as border
  115. float image_readPixel_border(const ImageF32& image, int32_t x, int32_t y, float border = 0.0f);
  116. ColorRgbaI32 image_readPixel_border(const ImageRgbaU8& image, int32_t x, int32_t y, const ColorRgbaI32& border = ColorRgbaI32()); // Can have negative value as border
  117. // Read a pixel from an image.
  118. // Out of bound will return the closest pixel.
  119. // Empty images will return zero.
  120. uint8_t image_readPixel_clamp(const ImageU8& image, int32_t x, int32_t y);
  121. uint16_t image_readPixel_clamp(const ImageU16& image, int32_t x, int32_t y);
  122. float image_readPixel_clamp(const ImageF32& image, int32_t x, int32_t y);
  123. ColorRgbaI32 image_readPixel_clamp(const ImageRgbaU8& image, int32_t x, int32_t y);
  124. // Read a pixel from an image.
  125. // Out of bound will take the coordinates in modulo of the size.
  126. // Empty images will return zero.
  127. uint8_t image_readPixel_tile(const ImageU8& image, int32_t x, int32_t y);
  128. uint16_t image_readPixel_tile(const ImageU16& image, int32_t x, int32_t y);
  129. float image_readPixel_tile(const ImageF32& image, int32_t x, int32_t y);
  130. ColorRgbaI32 image_readPixel_tile(const ImageRgbaU8& image, int32_t x, int32_t y);
  131. // ------------------------ Below is untested! ------------------------ //
  132. // Loading and saving
  133. OrderedImageRgbaU8 image_load_RgbaU8(const String& filename, bool mustExist = true);
  134. bool image_save(const ImageRgbaU8 &image, const String& filename);
  135. // Fill all pixels with a uniform color
  136. void image_fill(ImageU8& image, int32_t color);
  137. void image_fill(ImageU16& image, int32_t color);
  138. void image_fill(ImageF32& image, float color);
  139. void image_fill(ImageRgbaU8& image, const ColorRgbaI32& color);
  140. // Clone
  141. // Get a deep clone of an image's content while discarding any pack order, padding and texture pyramids
  142. AlignedImageU8 image_clone(const ImageU8& image);
  143. AlignedImageU16 image_clone(const ImageU16& image);
  144. AlignedImageF32 image_clone(const ImageF32& image);
  145. OrderedImageRgbaU8 image_clone(const ImageRgbaU8& image);
  146. // Returns a copy of the image without any padding, which means that alignment cannot be guaranteed
  147. // Used when external image libraries don't allow it
  148. ImageRgbaU8 image_removePadding(const ImageRgbaU8& image);
  149. // Channel packing
  150. // Extract one channel
  151. AlignedImageU8 image_get_red(const ImageRgbaU8& image);
  152. AlignedImageU8 image_get_green(const ImageRgbaU8& image);
  153. AlignedImageU8 image_get_blue(const ImageRgbaU8& image);
  154. AlignedImageU8 image_get_alpha(const ImageRgbaU8& image);
  155. // Pack one channel
  156. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, int32_t blue, int32_t alpha);
  157. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, int32_t blue, int32_t alpha);
  158. OrderedImageRgbaU8 image_pack(int32_t red, int32_t green, const ImageU8& blue, int32_t alpha);
  159. OrderedImageRgbaU8 image_pack(int32_t red, int32_t green, int32_t blue, const ImageU8& alpha);
  160. // Pack two channels
  161. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, int32_t blue, int32_t alpha);
  162. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, const ImageU8& blue, int32_t alpha);
  163. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, int32_t blue, const ImageU8& alpha);
  164. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, const ImageU8& blue, int32_t alpha);
  165. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, int32_t blue, const ImageU8& alpha);
  166. OrderedImageRgbaU8 image_pack(int32_t red, int32_t green, const ImageU8& blue, const ImageU8& alpha);
  167. // Pack three channels
  168. OrderedImageRgbaU8 image_pack(int32_t red, const ImageU8& green, const ImageU8& blue, const ImageU8& alpha);
  169. OrderedImageRgbaU8 image_pack(const ImageU8& red, int32_t green, const ImageU8& blue, const ImageU8& alpha);
  170. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, int32_t blue, const ImageU8& alpha);
  171. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, const ImageU8& blue, int32_t alpha);
  172. // Pack four channels
  173. OrderedImageRgbaU8 image_pack(const ImageU8& red, const ImageU8& green, const ImageU8& blue, const ImageU8& alpha);
  174. // Ascii images
  175. String image_toAscii(const ImageU8& image, const String &alphabet);
  176. String image_toAscii(const ImageU8& image);
  177. AlignedImageU8 image_fromAscii(const String &content);
  178. // Comparisons
  179. // Get the maximum pixelwise difference between two images of the same format, or the highest possible value on failure
  180. // Useful for regression tests
  181. uint8_t image_maxDifference(const ImageU8& imageA, const ImageU8& imageB);
  182. uint16_t image_maxDifference(const ImageU16& imageA, const ImageU16& imageB);
  183. float image_maxDifference(const ImageF32& imageA, const ImageF32& imageB);
  184. uint8_t image_maxDifference(const ImageRgbaU8& imageA, const ImageRgbaU8& imageB);
  185. // Sub-images are viewports to another image's data
  186. // TODO: Aligned sub-images that only takes vertial sections using whole rows
  187. // TODO: Aligned sub-images that terminates with an error if the input rectangle isn't aligned
  188. // Start must be 16-byte aligned, end must be same as the parent or also 16-byte aligned
  189. // TODO: Make an optional warning for not returning the desired dimensions when out of bound
  190. // Get a sub-image sharing buffer and side-effects with the parent image
  191. // Returns the overlapping region if out of bound
  192. // Returns a null image if there are no overlapping pixels to return
  193. ImageU8 image_getSubImage(const ImageU8& image, const IRect& region);
  194. ImageU16 image_getSubImage(const ImageU16& image, const IRect& region);
  195. ImageF32 image_getSubImage(const ImageF32& image, const IRect& region);
  196. ImageRgbaU8 image_getSubImage(const ImageRgbaU8& image, const IRect& region);
  197. // Bound-checked pointer access (relatively safe compared to a raw pointer)
  198. // Returns a bound-checked pointer to the first byte at rowIndex
  199. // Bound-checked safe-pointers are equally fast as raw pointers in release mode
  200. // Warning! Bound-checked pointers are not reference counted, because that would be too slow for real-time graphics
  201. SafePointer<uint8_t> image_getSafePointer(const ImageU8& image, int rowIndex = 0);
  202. SafePointer<uint16_t> image_getSafePointer(const ImageU16& image, int rowIndex = 0);
  203. SafePointer<float> image_getSafePointer(const ImageF32& image, int rowIndex = 0);
  204. SafePointer<uint32_t> image_getSafePointer(const ImageRgbaU8& image, int rowIndex = 0);
  205. // Get a pointer iterating over individual channels instead of whole pixels
  206. SafePointer<uint8_t> image_getSafePointer_channels(const ImageRgbaU8& image, int rowIndex = 0);
  207. // The dangerous image API
  208. // Use of these methods can be spotted using a search for "_dangerous_" in your code
  209. // Replaces the destructor in image's buffer.
  210. // newDestructor is responsible for freeing the given data.
  211. // Use when the buffer's pointer is being sent to a function that promises to free the memory
  212. // For example: Creating buffers being wrapped as XLib images
  213. void image_dangerous_replaceDestructor(ImageU8& image, const std::function<void(uint8_t *)>& newDestructor);
  214. void image_dangerous_replaceDestructor(ImageU16& image, const std::function<void(uint8_t *)>& newDestructor);
  215. void image_dangerous_replaceDestructor(ImageF32& image, const std::function<void(uint8_t *)>& newDestructor);
  216. void image_dangerous_replaceDestructor(ImageRgbaU8& image, const std::function<void(uint8_t *)>& newDestructor);
  217. // Returns a pointer to the image's pixels
  218. // Warning! Reading elements larger than 8 bits will have lower and higher bytes stored based on local endianness
  219. // Warning! Using bytes outside of the [0 .. stride * height - 1] range may cause crashes and undefined behaviour
  220. // Warning! Using the pointer after the image's lifetime may cause crashes from trying to access freed memory
  221. uint8_t* image_dangerous_getData(const ImageU8& image);
  222. uint8_t* image_dangerous_getData(const ImageU16& image);
  223. uint8_t* image_dangerous_getData(const ImageF32& image);
  224. uint8_t* image_dangerous_getData(const ImageRgbaU8& image);
  225. }
  226. #endif