imageAPI.h 14 KB

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