imageAPI.h 14 KB

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