cms_interface.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /* Copyright (c) the JPEG XL Project Authors. All rights reserved.
  2. *
  3. * Use of this source code is governed by a BSD-style
  4. * license that can be found in the LICENSE file.
  5. */
  6. /** @addtogroup libjxl_color
  7. * @{
  8. * @file cms_interface.h
  9. * @brief Interface to allow the injection of different color management systems
  10. * (CMSes, also called color management modules, or CMMs) in JPEG XL.
  11. *
  12. * A CMS is needed by the JPEG XL encoder and decoder to perform colorspace
  13. * conversions. This defines an interface that can be implemented for different
  14. * CMSes and then passed to the library.
  15. */
  16. #ifndef JXL_CMS_INTERFACE_H_
  17. #define JXL_CMS_INTERFACE_H_
  18. #include <jxl/color_encoding.h>
  19. #include <jxl/types.h>
  20. #include <stddef.h>
  21. #include <stdint.h>
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. /** Parses an ICC profile and populates @p c and @p cmyk with the data.
  26. *
  27. * @param user_data @ref JxlCmsInterface::set_fields_data passed as-is.
  28. * @param icc_data the ICC data to parse.
  29. * @param icc_size how many bytes of icc_data are valid.
  30. * @param c a @ref JxlColorEncoding to populate if applicable.
  31. * @param cmyk a boolean to set to whether the colorspace is a CMYK colorspace.
  32. * @return Whether the relevant fields in @p c were successfully populated.
  33. */
  34. typedef JXL_BOOL (*jpegxl_cms_set_fields_from_icc_func)(void* user_data,
  35. const uint8_t* icc_data,
  36. size_t icc_size,
  37. JxlColorEncoding* c,
  38. JXL_BOOL* cmyk);
  39. /** Represents an input or output colorspace to a color transform, as a
  40. * serialized ICC profile. */
  41. typedef struct {
  42. /** The serialized ICC profile. This is guaranteed to be present and valid. */
  43. struct {
  44. const uint8_t* data;
  45. size_t size;
  46. } icc;
  47. /** Structured representation of the colorspace, if applicable. If all fields
  48. * are different from their "unknown" value, then this is equivalent to the
  49. * ICC representation of the colorspace. If some are "unknown", those that are
  50. * not are still valid and can still be used on their own if they are useful.
  51. */
  52. JxlColorEncoding color_encoding;
  53. /** Number of components per pixel. This can be deduced from the other
  54. * representations of the colorspace but is provided for convenience and
  55. * validation. */
  56. size_t num_channels;
  57. } JxlColorProfile;
  58. /** Allocates and returns the data needed for @p num_threads parallel transforms
  59. * from the @p input colorspace to @p output, with up to @p pixels_per_thread
  60. * pixels to transform per call to @ref JxlCmsInterface::run. @p init_data comes
  61. * directly from the @ref JxlCmsInterface instance. Since @c run only receives
  62. * the data returned by @c init, a reference to @p init_data should be kept
  63. * there if access to it is desired in @c run. Likewise for @ref
  64. * JxlCmsInterface::destroy.
  65. *
  66. * The ICC data in @p input and @p output is guaranteed to outlive the @c init /
  67. * @c run / @c destroy cycle.
  68. *
  69. * @param init_data @ref JxlCmsInterface::init_data passed as-is.
  70. * @param num_threads the maximum number of threads from which
  71. * @ref JxlCmsInterface::run will be called.
  72. * @param pixels_per_thread the maximum number of pixels that each call to
  73. * @ref JxlCmsInterface::run will have to transform.
  74. * @param input_profile the input colorspace for the transform.
  75. * @param output_profile the colorspace to which @ref JxlCmsInterface::run
  76. * should convert the input data.
  77. * @param intensity_target for colorspaces where luminance is relative
  78. * (essentially: not PQ), indicates the luminance at which (1, 1, 1) will
  79. * be displayed. This is useful for conversions between PQ and a relative
  80. * luminance colorspace, in either direction: @p intensity_target cd/m²
  81. * in PQ should map to and from (1, 1, 1) in the relative one.\n
  82. * It is also used for conversions to and from HLG, as it is
  83. * scene-referred while other colorspaces are assumed to be
  84. * display-referred. That is, conversions from HLG should apply the OOTF
  85. * for a peak display luminance of @p intensity_target, and conversions
  86. * to HLG should undo it. The OOTF is a gamma function applied to the
  87. * luminance channel (https://www.itu.int/rec/R-REC-BT.2100-2-201807-I
  88. * page 7), with the gamma value computed as
  89. * <tt>1.2 * 1.111^log2(intensity_target / 1000)</tt> (footnote 2 page 8
  90. * of the same document).
  91. * @return The data needed for the transform, or @c NULL in case of failure.
  92. * This will be passed to the other functions as @c user_data.
  93. */
  94. typedef void* (*jpegxl_cms_init_func)(void* init_data, size_t num_threads,
  95. size_t pixels_per_thread,
  96. const JxlColorProfile* input_profile,
  97. const JxlColorProfile* output_profile,
  98. float intensity_target);
  99. /** Returns a buffer that can be used by callers of the interface to store the
  100. * input of the conversion or read its result, if they pass it as the input or
  101. * output of the @c run function.
  102. * @param user_data the data returned by @c init.
  103. * @param thread the index of the thread for which to return a buffer.
  104. * @return A buffer that can be used by the caller for passing to @c run.
  105. */
  106. typedef float* (*jpegxl_cms_get_buffer_func)(void* user_data, size_t thread);
  107. /** Executes one transform and returns true on success or false on error. It
  108. * must be possible to call this from different threads with different values
  109. * for @p thread, all between 0 (inclusive) and the value of @p num_threads
  110. * passed to @c init (exclusive). It is allowed to implement this by locking
  111. * such that the transforms are essentially performed sequentially, if such a
  112. * performance profile is acceptable. @p user_data is the data returned by
  113. * @c init.
  114. * The buffers each contain @p num_pixels × @c num_channels interleaved floating
  115. * point (0..1) samples where @c num_channels is the number of color channels of
  116. * their respective color profiles. It is guaranteed that the only case in which
  117. * they might overlap is if the output has fewer channels than the input, in
  118. * which case the pointers may be identical.
  119. * For CMYK data, 0 represents the maximum amount of ink while 1 represents no
  120. * ink.
  121. * @param user_data the data returned by @c init.
  122. * @param thread the index of the thread from which the function is being
  123. * called.
  124. * @param input_buffer the buffer containing the pixel data to be transformed.
  125. * @param output_buffer the buffer receiving the transformed pixel data.
  126. * @param num_pixels the number of pixels to transform from @p input to
  127. * @p output.
  128. * @return ::JXL_TRUE on success, ::JXL_FALSE on failure.
  129. */
  130. typedef JXL_BOOL (*jpegxl_cms_run_func)(void* user_data, size_t thread,
  131. const float* input_buffer,
  132. float* output_buffer,
  133. size_t num_pixels);
  134. /** Performs the necessary clean-up and frees the memory allocated for user
  135. * data.
  136. */
  137. typedef void (*jpegxl_cms_destroy_func)(void*);
  138. /**
  139. * Interface for performing colorspace transforms. The @c init function can be
  140. * called several times to instantiate several transforms, including before
  141. * other transforms have been destroyed.
  142. *
  143. * The call sequence for a given colorspace transform could look like the
  144. * following:
  145. * @dot
  146. * digraph calls {
  147. * newrank = true
  148. * node [shape = box, fontname = monospace]
  149. * init [label = "user_data <- init(\l\
  150. * init_data = data,\l\
  151. * num_threads = 3,\l\
  152. * pixels_per_thread = 20,\l\
  153. * input = (sRGB, 3 channels),\l\
  154. * output = (Display-P3, 3 channels),\l\
  155. * intensity_target = 255\l\
  156. * )\l"]
  157. * subgraph cluster_0 {
  158. * color = lightgrey
  159. * label = "thread 1"
  160. * labeljust = "c"
  161. * run_1_1 [label = "run(\l\
  162. * user_data,\l\
  163. * thread = 1,\l\
  164. * input = in[0],\l\
  165. * output = out[0],\l\
  166. * num_pixels = 20\l\
  167. * )\l"]
  168. * run_1_2 [label = "run(\l\
  169. * user_data,\l\
  170. * thread = 1,\l\
  171. * input = in[3],\l\
  172. * output = out[3],\l\
  173. * num_pixels = 20\l\
  174. * )\l"]
  175. * }
  176. * subgraph cluster_1 {
  177. * color = lightgrey
  178. * label = "thread 2"
  179. * labeljust = "l"
  180. * run_2_1 [label = "run(\l\
  181. * user_data,\l\
  182. * thread = 2,\l\
  183. * input = in[1],\l\
  184. * output = out[1],\l\
  185. * num_pixels = 20\l\
  186. * )\l"]
  187. * run_2_2 [label = "run(\l\
  188. * user_data,\l\
  189. * thread = 2,\l\
  190. * input = in[4],\l\
  191. * output = out[4],\l\
  192. * num_pixels = 13\l\
  193. * )\l"]
  194. * }
  195. * subgraph cluster_3 {
  196. * color = lightgrey
  197. * label = "thread 3"
  198. * labeljust = "c"
  199. * run_3_1 [label = "run(\l\
  200. * user_data,\l\
  201. * thread = 3,\l\
  202. * input = in[2],\l\
  203. * output = out[2],\l\
  204. * num_pixels = 20\l\
  205. * )\l"]
  206. * }
  207. * init -> {run_1_1; run_2_1; run_3_1; rank = same}
  208. * run_1_1 -> run_1_2
  209. * run_2_1 -> run_2_2
  210. * {run_1_2; run_2_2, run_3_1} -> "destroy(user_data)"
  211. * }
  212. * @enddot
  213. */
  214. typedef struct {
  215. /** CMS-specific data that will be passed to @ref set_fields_from_icc. */
  216. void* set_fields_data;
  217. /** Populates a @ref JxlColorEncoding from an ICC profile. */
  218. jpegxl_cms_set_fields_from_icc_func set_fields_from_icc;
  219. /** CMS-specific data that will be passed to @ref init. */
  220. void* init_data;
  221. /** Prepares a colorspace transform as described in the documentation of @ref
  222. * jpegxl_cms_init_func. */
  223. jpegxl_cms_init_func init;
  224. /** Returns a buffer that can be used as input to @c run. */
  225. jpegxl_cms_get_buffer_func get_src_buf;
  226. /** Returns a buffer that can be used as output from @c run. */
  227. jpegxl_cms_get_buffer_func get_dst_buf;
  228. /** Executes the transform on a batch of pixels, per @ref jpegxl_cms_run_func.
  229. */
  230. jpegxl_cms_run_func run;
  231. /** Cleans up the transform. */
  232. jpegxl_cms_destroy_func destroy;
  233. } JxlCmsInterface;
  234. #ifdef __cplusplus
  235. }
  236. #endif
  237. #endif /* JXL_CMS_INTERFACE_H_ */
  238. /** @} */