ImfRgbaYca.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. //
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Copyright (c) Contributors to the OpenEXR Project.
  4. //
  5. #ifndef INCLUDED_IMF_RGBA_YCA_H
  6. #define INCLUDED_IMF_RGBA_YCA_H
  7. //-----------------------------------------------------------------------------
  8. //
  9. // Conversion between RGBA (red, green, blue alpha)
  10. // and YCA (luminance, subsampled chroma, alpha) data:
  11. //
  12. // Luminance, Y, is computed as a weighted sum of R, G, and B:
  13. //
  14. // Y = yw.x * R + yw.y * G + yw.z * B
  15. //
  16. // Function computeYw() computes a set of RGB-to-Y weights, yw,
  17. // from a set of primary and white point chromaticities.
  18. //
  19. // Chroma, C, consists of two components, RY and BY:
  20. //
  21. // RY = (R - Y) / Y
  22. // BY = (B - Y) / Y
  23. //
  24. // For efficiency, the x and y subsampling rates for chroma are
  25. // hardwired to 2, and the chroma subsampling and reconstruction
  26. // filters are fixed 27-pixel wide windowed sinc functions.
  27. //
  28. // Starting with an image that has RGBA data for all pixels,
  29. //
  30. // RGBA RGBA RGBA RGBA ... RGBA RGBA
  31. // RGBA RGBA RGBA RGBA ... RGBA RGBA
  32. // RGBA RGBA RGBA RGBA ... RGBA RGBA
  33. // RGBA RGBA RGBA RGBA ... RGBA RGBA
  34. // ...
  35. // RGBA RGBA RGBA RGBA ... RGBA RGBA
  36. // RGBA RGBA RGBA RGBA ... RGBA RGBA
  37. //
  38. // function RGBAtoYCA() converts the pixels to YCA format:
  39. //
  40. // YCA YCA YCA YCA ... YCA YCA
  41. // YCA YCA YCA YCA ... YCA YCA
  42. // YCA YCA YCA YCA ... YCA YCA
  43. // YCA YCA YCA YCA ... YCA YCA
  44. // ...
  45. // YCA YCA YCA YCA ... YCA YCA
  46. // YCA YCA YCA YCA ... YCA YCA
  47. //
  48. // Next, decimateChomaHoriz() eliminates the chroma values from
  49. // the odd-numbered pixels in every scan line:
  50. //
  51. // YCA YA YCA YA ... YCA YA
  52. // YCA YA YCA YA ... YCA YA
  53. // YCA YA YCA YA ... YCA YA
  54. // YCA YA YCA YA ... YCA YA
  55. // ...
  56. // YCA YA YCA YA ... YCA YA
  57. // YCA YA YCA YA ... YCA YA
  58. //
  59. // decimateChromaVert() eliminates all chroma values from the
  60. // odd-numbered scan lines:
  61. //
  62. // YCA YA YCA YA ... YCA YA
  63. // YA YA YA YA ... YA YA
  64. // YCA YA YCA YA ... YCA YA
  65. // YA YA YA YA ... YA YA
  66. // ...
  67. // YCA YA YCA YA ... YCA YA
  68. // YA YA YA YA ... YA YA
  69. //
  70. // Finally, roundYCA() reduces the precision of the luminance
  71. // and chroma values so that the pixel data shrink more when
  72. // they are saved in a compressed file.
  73. //
  74. // The output of roundYCA() can be converted back to a set
  75. // of RGBA pixel data that is visually very similar to the
  76. // original RGBA image, by calling reconstructChromaHoriz(),
  77. // reconstructChromaVert(), YCAtoRGBA(), and finally
  78. // fixSaturation().
  79. //
  80. //-----------------------------------------------------------------------------
  81. #include "ImfExport.h"
  82. #include "ImfNamespace.h"
  83. #include "ImfRgba.h"
  84. #include "ImfChromaticities.h"
  85. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
  86. namespace RgbaYca {
  87. //
  88. // Width of the chroma subsampling and reconstruction filters
  89. //
  90. static const int N = 27;
  91. static const int N2 = N / 2;
  92. //
  93. // Convert a set of primary chromaticities into a set of weighting
  94. // factors for computing a pixels's luminance, Y, from R, G and B
  95. //
  96. IMF_EXPORT
  97. IMATH_NAMESPACE::V3f computeYw (const Chromaticities &cr);
  98. //
  99. // Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha):
  100. //
  101. // ycaOut[i].g = Y (rgbaIn[i]);
  102. // ycaOut[i].r = RY (rgbaIn[i]);
  103. // ycaOut[i].b = BY (rgbaIn[i]);
  104. // ycaOut[i].a = aIsValid? rgbaIn[i].a: 1
  105. //
  106. // yw is a set of RGB-to-Y weighting factors, as computed by computeYw().
  107. //
  108. IMF_EXPORT
  109. void RGBAtoYCA (const IMATH_NAMESPACE::V3f &yw,
  110. int n,
  111. bool aIsValid,
  112. const Rgba rgbaIn[/*n*/],
  113. Rgba ycaOut[/*n*/]);
  114. //
  115. // Perform horizontal low-pass filtering and subsampling of
  116. // the chroma channels of an array of n pixels. In order
  117. // to avoid indexing off the ends of the input array during
  118. // low-pass filtering, ycaIn must have N2 extra pixels at
  119. // both ends. Before calling decimateChromaHoriz(), the extra
  120. // pixels should be filled with copies of the first and last
  121. // "real" input pixel.
  122. //
  123. IMF_EXPORT
  124. void decimateChromaHoriz (int n,
  125. const Rgba ycaIn[/*n+N-1*/],
  126. Rgba ycaOut[/*n*/]);
  127. //
  128. // Perform vertical chroma channel low-pass filtering and subsampling.
  129. // N scan lines of input pixels are combined into a single scan line
  130. // of output pixels.
  131. //
  132. IMF_EXPORT
  133. void decimateChromaVert (int n,
  134. const Rgba * const ycaIn[N],
  135. Rgba ycaOut[/*n*/]);
  136. //
  137. // Round the luminance and chroma channels of an array of YCA
  138. // pixels that has already been filtered and subsampled.
  139. // The signifcands of the pixels' luminance and chroma values
  140. // are rounded to roundY and roundC bits respectively.
  141. //
  142. IMF_EXPORT
  143. void roundYCA (int n,
  144. unsigned int roundY,
  145. unsigned int roundC,
  146. const Rgba ycaIn[/*n*/],
  147. Rgba ycaOut[/*n*/]);
  148. //
  149. // For a scan line that has valid chroma data only for every other pixel,
  150. // reconstruct the missing chroma values.
  151. //
  152. IMF_EXPORT
  153. void reconstructChromaHoriz (int n,
  154. const Rgba ycaIn[/*n+N-1*/],
  155. Rgba ycaOut[/*n*/]);
  156. //
  157. // For a scan line that has only luminance and no valid chroma data,
  158. // reconstruct chroma from the surronding N scan lines.
  159. //
  160. IMF_EXPORT
  161. void reconstructChromaVert (int n,
  162. const Rgba * const ycaIn[N],
  163. Rgba ycaOut[/*n*/]);
  164. //
  165. // Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA.
  166. // This function is the inverse of RGBAtoYCA().
  167. // yw is a set of RGB-to-Y weighting factors, as computed by computeYw().
  168. //
  169. IMF_EXPORT
  170. void YCAtoRGBA (const IMATH_NAMESPACE::V3f &yw,
  171. int n,
  172. const Rgba ycaIn[/*n*/],
  173. Rgba rgbaOut[/*n*/]);
  174. //
  175. // Eliminate super-saturated pixels:
  176. //
  177. // Converting an image from RGBA to YCA, low-pass filtering chroma,
  178. // and converting the result back to RGBA can produce pixels with
  179. // super-saturated colors, where one or two of the RGB components
  180. // become zero or negative. (The low-pass and reconstruction filters
  181. // introduce some amount of ringing into the chroma components.
  182. // This can lead to negative RGB values near high-contrast edges.)
  183. //
  184. // The fixSaturation() function finds super-saturated pixels and
  185. // corrects them by desaturating their colors while maintaining
  186. // their luminance. fixSaturation() takes three adjacent input
  187. // scan lines, rgbaIn[0], rgbaIn[1], rgbaIn[2], adjusts the
  188. // saturation of rgbaIn[1], and stores the result in rgbaOut.
  189. //
  190. IMF_EXPORT
  191. void fixSaturation (const IMATH_NAMESPACE::V3f &yw,
  192. int n,
  193. const Rgba * const rgbaIn[3],
  194. Rgba rgbaOut[/*n*/]);
  195. } // namespace RgbaYca
  196. OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
  197. #endif