1 /* ***** BEGIN LICENSE BLOCK *****
2 * This file is part of openfx-misc <https://github.com/devernay/openfx-misc>,
3 * Copyright (C) 2013-2018 INRIA
4 *
5 * openfx-misc is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * openfx-misc is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with openfx-misc. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
17 * ***** END LICENSE BLOCK ***** */
18
19 /*
20 * OFX ColorTransform plugin.
21 */
22
23 #include <cmath>
24
25 #include "ofxsProcessing.H"
26 #include "ofxsMaskMix.h"
27 #include "ofxsMacros.h"
28 #include "ofxsLut.h"
29
30 using namespace OFX;
31
32 OFXS_NAMESPACE_ANONYMOUS_ENTER
33
34 #define kPluginRGBToHSVName "RGBToHSV"
35 #define kPluginRGBToHSVDescription "Convert from linear RGB to HSV color model (hue, saturation, value, as defined by A. R. Smith in 1978). H is in degrees, S and V are in the same units as RGB. RGB is gamma-compressed using the sRGB Opto-Electronic Transfer Function (OETF) before conversion."
36 #define kPluginRGBToHSVIdentifier "net.sf.openfx.RGBToHSV"
37
38 #define kPluginHSVToRGBName "HSVToRGB"
39 #define kPluginHSVToRGBDescription "Convert from HSV color model (hue, saturation, value, as defined by A. R. Smith in 1978) to linear RGB. H is in degrees, S and V are in the same units as RGB. RGB is gamma-decompressed using the sRGB Electro-Optical Transfer Function (EOTF) after conversion."
40 #define kPluginHSVToRGBIdentifier "net.sf.openfx.HSVToRGB"
41
42 #define kPluginRGBToHSLName "RGBToHSL"
43 #define kPluginRGBToHSLDescription "Convert from RGB to HSL color model (hue, saturation, lightness, as defined by Joblove and Greenberg in 1978). H is in degrees, S and L are in the same units as RGB. RGB is gamma-compressed using the sRGB Opto-Electronic Transfer Function (OETF) before conversion."
44 #define kPluginRGBToHSLIdentifier "net.sf.openfx.RGBToHSL"
45
46 #define kPluginHSLToRGBName "HSLToRGB"
47 #define kPluginHSLToRGBDescription "Convert from HSL color model (hue, saturation, lightness, as defined by Joblove and Greenberg in 1978) to linear RGB. H is in degrees, S and L are in the same units as RGB. RGB is gamma-decompressed using the sRGB Electro-Optical Transfer Function (EOTF) after conversion."
48 #define kPluginHSLToRGBIdentifier "net.sf.openfx.HSLToRGB"
49
50 #define kPluginRGBToHSIName "RGBToHSI"
51 #define kPluginRGBToHSIDescription "Convert from linear RGB to HSI color model (hue, saturation, intensity, as defined by Gonzalez and Woods in 1992). H is in degrees, S and I are in the same units as RGB. RGB is gamma-compressed using the sRGB Opto-Electronic Transfer Function (OETF) before conversion.\n" \
52 "The HSI colour space (hue, saturation and intensity) attempts to produce a more intuitive representation of colour. The I axis represents the luminance information. The H and S axes are polar coordinates on the plane orthogonal to I. H is the angle, specified such that red is at zero, green at 120 degrees, and blue at 240 degrees. Hue thus represents what humans implicitly understand as colour. S is the magnitude of the colour vector projected in the plane orthogonal to I, and so represents the difference between pastel colours (low saturation) and vibrant colours (high saturation). The main drawback of this colour space is that hue is undefined if saturation is zero, making error propagation in transformations from the RGB colour space more complicated.\n" \
53 "It should also be noted that, although the HSI colour space may be more intuitive, is not \"perceptual\", in the sense that small displacements of equal size in different parts of the colour space will be perceived by human observers as changes of different magnitude. Attempts have been made to define such colour spaces: CIE-LAB and CIE-LUV are two examples."
54 #define kPluginRGBToHSIIdentifier "net.sf.openfx.RGBToHSI"
55
56 #define kPluginHSIToRGBName "HSIToRGB"
57 #define kPluginHSIToRGBDescription "Convert from HSI color model (hue, saturation, intensity, as defined by Gonzalez and Woods in 1992) to linear RGB. H is in degrees, S and I are in the same units as RGB. RGB is gamma-decompressed using the sRGB Electro-Optical Transfer Function (EOTF) after conversion.\n" \
58 "The HSI colour space (hue, saturation and intensity) attempts to produce a more intuitive representation of colour. The I axis represents the luminance information. The H and S axes are polar coordinates on the plane orthogonal to I. H is the angle, specified such that red is at zero, green at 120 degrees, and blue at 240 degrees. Hue thus represents what humans implicitly understand as colour. S is the magnitude of the colour vector projected in the plane orthogonal to I, and so represents the difference between pastel colours (low saturation) and vibrant colours (high saturation). The main drawback of this colour space is that hue is undefined if saturation is zero, making error propagation in transformations from the RGB colour space more complicated.\n" \
59 "It should also be noted that, although the HSI colour space may be more intuitive, is not \"perceptual\", in the sense that small displacements of equal size in different parts of the colour space will be perceived by human observers as changes of different magnitude. Attempts have been made to define such colour spaces: CIE-LAB and CIE-LUV are two examples."
60 #define kPluginHSIToRGBIdentifier "net.sf.openfx.HSIToRGB"
61
62 #define kPluginRGBToYCbCr601Name "RGBToYCbCr601"
63 #define kPluginRGBToYCbCr601Description "Convert from linear RGB to YCbCr color model (ITU.BT-601). RGB is gamma-compressed using the sRGB Opto-Electronic Transfer Function (OETF) before conversion."
64 #define kPluginRGBToYCbCr601Identifier "net.sf.openfx.RGBToYCbCr601"
65
66 #define kPluginYCbCrToRGB601Name "YCbCrToRGB601"
67 #define kPluginYCbCrToRGB601Description "Convert from YCbCr color model (ITU.BT-601) to linear RGB. RGB is gamma-decompressed using the sRGB Electro-Optical Transfer Function (EOTF) after conversion."
68 #define kPluginYCbCrToRGB601Identifier "net.sf.openfx.YCbCrToRGB601"
69
70 #define kPluginRGBToYCbCr709Name "RGBToYCbCr709"
71 #define kPluginRGBToYCbCr709Description "Convert from linear RGB to YCbCr color model (ITU.BT-709). RGB is gamma-compressed using the Rec.709 Opto-Electronic Transfer Function (OETF) before conversion."
72 #define kPluginRGBToYCbCr709Identifier "net.sf.openfx.RGBToYCbCr709"
73
74 #define kPluginYCbCrToRGB709Name "YCbCrToRGB709"
75 #define kPluginYCbCrToRGB709Description "Convert from YCbCr color model (ITU.BT-709) to linear RGB. RGB is gamma-decompressed using the Rec.709 Electro-Optical Transfer Function (EOTF) after conversion."
76 #define kPluginYCbCrToRGB709Identifier "net.sf.openfx.YCbCrToRGB709"
77
78 #define kPluginRGBToYPbPr601Name "RGBToYPbPr601"
79 #define kPluginRGBToYPbPr601Description "Convert from RGB to YPbPr color model (ITU.BT-601). RGB is gamma-compressed using the sRGB Opto-Electronic Transfer Function (OETF) before conversion."
80 #define kPluginRGBToYPbPr601Identifier "net.sf.openfx.RGBToYPbPr601"
81
82 #define kPluginYPbPrToRGB601Name "YPbPrToRGB601"
83 #define kPluginYPbPrToRGB601Description "Convert from YPbPr color model (ITU.BT-601) to RGB. RGB is gamma-decompressed using the sRGB Electro-Optical Transfer Function (EOTF) after conversion."
84 #define kPluginYPbPrToRGB601Identifier "net.sf.openfx.YPbPrToRGB601"
85
86 #define kPluginRGBToYPbPr709Name "RGBToYPbPr709"
87 #define kPluginRGBToYPbPr709Description "Convert from RGB to YPbPr color model (ITU.BT-709). RGB is gamma-compressed using the Rec.709 Opto-Electronic Transfer Function (OETF) before conversion."
88 #define kPluginRGBToYPbPr709Identifier "net.sf.openfx.RGBToYPbPr709"
89
90 #define kPluginYPbPrToRGB709Name "YPbPrToRGB709"
91 #define kPluginYPbPrToRGB709Description "Convert from YPbPr color model (ITU.BT-709) to RGB. RGB is gamma-decompressed using the Rec.709 Electro-Optical Transfer Function (EOTF) after conversion."
92 #define kPluginYPbPrToRGB709Identifier "net.sf.openfx.YPbPrToRGB709"
93
94 #define kPluginRGBToYUV601Name "RGBToYUV601"
95 #define kPluginRGBToYUV601Description "Convert from RGB to YUV color model (ITU.BT-601). RGB is gamma-compressed using the sRGB Opto-Electronic Transfer Function (OETF) before conversion."
96 #define kPluginRGBToYUV601Identifier "net.sf.openfx.RGBToYUV601"
97
98 #define kPluginYUVToRGB601Name "YUVToRGB601"
99 #define kPluginYUVToRGB601Description "Convert from YUV color model (ITU.BT-601) to RGB. RGB is gamma-decompressed using the sRGB Electro-Optical Transfer Function (EOTF) after conversion."
100 #define kPluginYUVToRGB601Identifier "net.sf.openfx.YUVToRGB601"
101
102 #define kPluginRGBToYUV709Name "RGBToYUV709"
103 #define kPluginRGBToYUV709Description "Convert from RGB to YUV color model (ITU.BT-709). RGB is gamma-compressed using the Rec.709 Opto-Electronic Transfer Function (OETF) before conversion."
104 #define kPluginRGBToYUV709Identifier "net.sf.openfx.RGBToYUV709"
105
106 #define kPluginYUVToRGB709Name "YUVToRGB709"
107 #define kPluginYUVToRGB709Description "Convert from YUV color model (ITU.BT-709) to RGB. RGB is gamma-decompressed using the Rec.709 Electro-Optical Transfer Function (EOTF) after conversion."
108 #define kPluginYUVToRGB709Identifier "net.sf.openfx.YUVToRGB709"
109
110
111 #define kPluginRGB709ToXYZName "RGB709ToXYZ"
112 #define kPluginRGB709ToXYZDescription "Convert from RGB (Rec.709 with D65 illuminant) to XYZ color model. X, Y and Z are in the same units as RGB."
113 #define kPluginRGB709ToXYZIdentifier "net.sf.openfx.RGB709ToXYZ"
114
115 #define kPluginXYZToRGB709Name "XYZToRGB709"
116 #define kPluginXYZToRGB709Description "Convert from XYZ color model to RGB (Rec.709 with D65 illuminant). X, Y and Z are in the same units as RGB."
117 #define kPluginXYZToRGB709Identifier "net.sf.openfx.XYZToRGB709"
118
119 #define kPluginRGB709ToLabName "RGB709ToLab"
120 #define kPluginRGB709ToLabDescription "Convert from RGB (Rec.709 with D65 illuminant) to L*a*b color model. L*a*b coordinates are divided by 100 for better visualization."
121 #define kPluginRGB709ToLabIdentifier "net.sf.openfx.RGB709ToLab"
122
123 #define kPluginLabToRGB709Name "LabToRGB709"
124 #define kPluginLabToRGB709Description "Convert from L*a*b color model to RGB (Rec.709 with D65 illuminant). L*a*b coordinates are divided by 100 for better visualization."
125 #define kPluginLabToRGB709Identifier "net.sf.openfx.LabToRGB709"
126
127 #define kPluginXYZToLabName "XYZToLab"
128 #define kPluginXYZToLabDescription "Convert from CIE XYZ color space to CIE L*a*b color space. L*a*b coordinates are divided by 100 for better visualization."
129 #define kPluginXYZToLabIdentifier "net.sf.openfx.XYZToLab"
130
131 #define kPluginLabToXYZName "LabToXYZ"
132 #define kPluginLabToXYZDescription "Convert from CIE L*a*b color space to CIE XYZ color space. L*a*b coordinates are divided by 100 for better visualization."
133 #define kPluginLabToXYZIdentifier "net.sf.openfx.LabToXYZ"
134
135 #define kPluginXYZToxyYName "XYZToxyY"
136 #define kPluginXYZToxyYDescription "Convert from CIE XYZ color space to CIE xyY color space."
137 #define kPluginXYZToxyYIdentifier "net.sf.openfx.XYZToxyY"
138
139 #define kPluginxyYToXYZName "xyYToXYZ"
140 #define kPluginxyYToXYZDescription "Convert from CIE xyY color space to CIE XYZ color space."
141 #define kPluginxyYToXYZIdentifier "net.sf.openfx.xyYToXYZ"
142
143 #define kPluginGrouping "Color/Transform"
144
145 // history:
146 // 1.0 initial version
147 // 2.0 named plugins more consistently, add a few conversions
148 #define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
149 #define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.
150
151 #define kSupportsTiles 1
152 #define kSupportsMultiResolution 1
153 #define kSupportsRenderScale 1
154 #define kSupportsMultipleClipPARs false
155 #define kSupportsMultipleClipDepths false
156 #define kRenderThreadSafety eRenderFullySafe
157
158 #define kParamPremultRGBToXXXLabel "Unpremult"
159 #define kParamPremultRGBToXXXHint \
160 "Divide the image by the alpha channel before processing. " \
161 "Use if the input images are premultiplied."
162
163 #define kParamPremultXXXToRGBLabel "Premult"
164 #define kParamPremultXXXToRGBHint \
165 "Multiply the image by the alpha channel after processing. " \
166 "Use to get premultiplied output images."
167
168 #define kParamPremultChanged "premultChanged"
169
170
171 enum ColorTransformEnum
172 {
173 eColorTransformRGBToHSV,
174 eColorTransformHSVToRGB,
175 eColorTransformRGBToHSL,
176 eColorTransformHSLToRGB,
177 eColorTransformRGBToHSI,
178 eColorTransformHSIToRGB,
179 eColorTransformRGBToYCbCr601,
180 eColorTransformYCbCrToRGB601,
181 eColorTransformRGBToYCbCr709,
182 eColorTransformYCbCrToRGB709,
183 eColorTransformRGBToYPbPr601,
184 eColorTransformYPbPrToRGB601,
185 eColorTransformRGBToYPbPr709,
186 eColorTransformYPbPrToRGB709,
187 eColorTransformRGBToYUV601,
188 eColorTransformYUVToRGB601,
189 eColorTransformRGBToYUV709,
190 eColorTransformYUVToRGB709,
191 eColorTransformRGB709ToXYZ,
192 eColorTransformXYZToRGB709,
193 eColorTransformRGB709ToLab,
194 eColorTransformLabToRGB709,
195 eColorTransformXYZToLab,
196 eColorTransformLabToXYZ,
197 eColorTransformXYZToxyY,
198 eColorTransformxyYToXYZ,
199 };
200
201 #define toRGB(e) ( (e) == eColorTransformHSVToRGB || \
202 (e) == eColorTransformHSLToRGB || \
203 (e) == eColorTransformHSIToRGB || \
204 (e) == eColorTransformYCbCrToRGB601 || \
205 (e) == eColorTransformYCbCrToRGB709 || \
206 (e) == eColorTransformYPbPrToRGB601 || \
207 (e) == eColorTransformYPbPrToRGB709 || \
208 (e) == eColorTransformYUVToRGB601 || \
209 (e) == eColorTransformYUVToRGB709 || \
210 (e) == eColorTransformXYZToRGB709 || \
211 (e) == eColorTransformLabToRGB709 )
212
213 #define fromRGB(e) ( !toRGB(e) && ( (e) != eColorTransformXYZToLab ) && ( (e) != eColorTransformLabToXYZ ) && ( (e) != eColorTransformXYZToxyY ) && ( (e) != eColorTransformxyYToXYZ ) )
214
215 class ColorTransformProcessorBase
216 : public ImageProcessor
217 {
218 protected:
219 const Image *_srcImg;
220 bool _premult;
221 int _premultChannel;
222 double _mix;
223
224 public:
225
ColorTransformProcessorBase(ImageEffect & instance)226 ColorTransformProcessorBase(ImageEffect &instance)
227 : ImageProcessor(instance)
228 , _srcImg(NULL)
229 , _premult(false)
230 , _premultChannel(3)
231 , _mix(1.)
232 {
233 }
234
setSrcImg(const Image * v)235 void setSrcImg(const Image *v) {_srcImg = v; }
236
setValues(bool premult,int premultChannel)237 void setValues(bool premult,
238 int premultChannel)
239 {
240 _premult = premult;
241 _premultChannel = premultChannel;
242 }
243
244 private:
245 };
246
247
248 template <class PIX, int nComponents, int maxValue, ColorTransformEnum transform>
249 class ColorTransformProcessor
250 : public ColorTransformProcessorBase
251 {
252 public:
ColorTransformProcessor(ImageEffect & instance)253 ColorTransformProcessor(ImageEffect &instance)
254 : ColorTransformProcessorBase(instance)
255 {
256 }
257
multiThreadProcessImages(OfxRectI procWindow)258 void multiThreadProcessImages(OfxRectI procWindow)
259 {
260 assert(nComponents == 3 || nComponents == 4);
261 assert(_dstImg);
262 float unpPix[4];
263 float tmpPix[4];
264 const bool dounpremult = _premult && fromRGB(transform);
265 const bool dopremult = _premult && toRGB(transform);
266
267 for (int y = procWindow.y1; y < procWindow.y2; y++) {
268 if ( _effect.abort() ) {
269 break;
270 }
271
272 PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
273
274 for (int x = procWindow.x1; x < procWindow.x2; x++) {
275 const PIX *srcPix = (const PIX *) (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
276 ofxsUnPremult<PIX, nComponents, maxValue>(srcPix, unpPix, dounpremult, _premultChannel);
277 switch (transform) {
278 case eColorTransformRGBToHSV:
279 unpPix[0] = Color::to_func_srgb(unpPix[0]);
280 unpPix[1] = Color::to_func_srgb(unpPix[1]);
281 unpPix[2] = Color::to_func_srgb(unpPix[2]);
282 Color::rgb_to_hsv(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
283 break;
284
285 case eColorTransformHSVToRGB:
286 Color::hsv_to_rgb(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
287 tmpPix[0] = Color::from_func_srgb(tmpPix[0]);
288 tmpPix[1] = Color::from_func_srgb(tmpPix[1]);
289 tmpPix[2] = Color::from_func_srgb(tmpPix[2]);
290 break;
291
292 case eColorTransformRGBToHSL:
293 unpPix[0] = Color::to_func_srgb(unpPix[0]);
294 unpPix[1] = Color::to_func_srgb(unpPix[1]);
295 unpPix[2] = Color::to_func_srgb(unpPix[2]);
296 Color::rgb_to_hsl(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
297 break;
298
299 case eColorTransformHSLToRGB:
300 Color::hsl_to_rgb(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
301 tmpPix[0] = Color::from_func_srgb(tmpPix[0]);
302 tmpPix[1] = Color::from_func_srgb(tmpPix[1]);
303 tmpPix[2] = Color::from_func_srgb(tmpPix[2]);
304 break;
305
306 case eColorTransformRGBToHSI:
307 unpPix[0] = Color::to_func_srgb(unpPix[0]);
308 unpPix[1] = Color::to_func_srgb(unpPix[1]);
309 unpPix[2] = Color::to_func_srgb(unpPix[2]);
310 Color::rgb_to_hsi(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
311 break;
312
313 case eColorTransformHSIToRGB:
314 Color::hsi_to_rgb(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
315 tmpPix[0] = Color::from_func_srgb(tmpPix[0]);
316 tmpPix[1] = Color::from_func_srgb(tmpPix[1]);
317 tmpPix[2] = Color::from_func_srgb(tmpPix[2]);
318 break;
319
320
321 case eColorTransformRGBToYCbCr601:
322 unpPix[0] = Color::to_func_srgb(unpPix[0]);
323 unpPix[1] = Color::to_func_srgb(unpPix[1]);
324 unpPix[2] = Color::to_func_srgb(unpPix[2]);
325 Color::rgb_to_ycbcr601(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
326 break;
327
328 case eColorTransformYCbCrToRGB601:
329 Color::ycbcr_to_rgb601(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
330 tmpPix[0] = Color::from_func_srgb(tmpPix[0]);
331 tmpPix[1] = Color::from_func_srgb(tmpPix[1]);
332 tmpPix[2] = Color::from_func_srgb(tmpPix[2]);
333 break;
334
335 case eColorTransformRGBToYCbCr709:
336 unpPix[0] = Color::to_func_Rec709(unpPix[0]);
337 unpPix[1] = Color::to_func_Rec709(unpPix[1]);
338 unpPix[2] = Color::to_func_Rec709(unpPix[2]);
339 Color::rgb_to_ycbcr709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
340 break;
341
342 case eColorTransformYCbCrToRGB709:
343 Color::ycbcr_to_rgb709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
344 tmpPix[0] = Color::from_func_Rec709(tmpPix[0]);
345 tmpPix[1] = Color::from_func_Rec709(tmpPix[1]);
346 tmpPix[2] = Color::from_func_Rec709(tmpPix[2]);
347 break;
348
349 case eColorTransformRGBToYPbPr601:
350 unpPix[0] = Color::to_func_srgb(unpPix[0]);
351 unpPix[1] = Color::to_func_srgb(unpPix[1]);
352 unpPix[2] = Color::to_func_srgb(unpPix[2]);
353 Color::rgb_to_ypbpr601(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
354 break;
355
356 case eColorTransformYPbPrToRGB601:
357 Color::ypbpr_to_rgb601(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
358 tmpPix[0] = Color::from_func_srgb(tmpPix[0]);
359 tmpPix[1] = Color::from_func_srgb(tmpPix[1]);
360 tmpPix[2] = Color::from_func_srgb(tmpPix[2]);
361 break;
362
363 case eColorTransformRGBToYPbPr709:
364 unpPix[0] = Color::to_func_Rec709(unpPix[0]);
365 unpPix[1] = Color::to_func_Rec709(unpPix[1]);
366 unpPix[2] = Color::to_func_Rec709(unpPix[2]);
367 Color::rgb_to_ypbpr709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
368 break;
369
370 case eColorTransformYPbPrToRGB709:
371 Color::ypbpr_to_rgb709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
372 tmpPix[0] = Color::from_func_Rec709(tmpPix[0]);
373 tmpPix[1] = Color::from_func_Rec709(tmpPix[1]);
374 tmpPix[2] = Color::from_func_Rec709(tmpPix[2]);
375 break;
376
377 case eColorTransformRGBToYUV601:
378 unpPix[0] = Color::to_func_srgb(unpPix[0]);
379 unpPix[1] = Color::to_func_srgb(unpPix[1]);
380 unpPix[2] = Color::to_func_srgb(unpPix[2]);
381 Color::rgb_to_yuv601(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
382 break;
383
384 case eColorTransformYUVToRGB601:
385 Color::yuv_to_rgb601(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
386 tmpPix[0] = Color::from_func_srgb(tmpPix[0]);
387 tmpPix[1] = Color::from_func_srgb(tmpPix[1]);
388 tmpPix[2] = Color::from_func_srgb(tmpPix[2]);
389 break;
390
391 case eColorTransformRGBToYUV709:
392 unpPix[0] = Color::to_func_Rec709(unpPix[0]);
393 unpPix[1] = Color::to_func_Rec709(unpPix[1]);
394 unpPix[2] = Color::to_func_Rec709(unpPix[2]);
395 Color::rgb_to_yuv709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
396 break;
397
398 case eColorTransformYUVToRGB709:
399 Color::yuv_to_rgb709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
400 tmpPix[0] = Color::from_func_Rec709(tmpPix[0]);
401 tmpPix[1] = Color::from_func_Rec709(tmpPix[1]);
402 tmpPix[2] = Color::from_func_Rec709(tmpPix[2]);
403 break;
404
405 case eColorTransformRGB709ToXYZ:
406 Color::rgb709_to_xyz(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
407 break;
408
409 case eColorTransformXYZToRGB709:
410 Color::xyz_to_rgb709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
411 break;
412
413 case eColorTransformRGB709ToLab:
414 Color::rgb709_to_lab(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
415 tmpPix[0] /= 100;
416 tmpPix[1] /= 100;
417 tmpPix[2] /= 100;
418 break;
419
420 case eColorTransformLabToRGB709:
421 unpPix[0] *= 100;
422 unpPix[1] *= 100;
423 unpPix[2] *= 100;
424 Color::lab_to_rgb709(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
425 break;
426
427 case eColorTransformXYZToLab:
428 Color::xyz_to_lab(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
429 tmpPix[0] /= 100;
430 tmpPix[1] /= 100;
431 tmpPix[2] /= 100;
432 break;
433
434 case eColorTransformLabToXYZ:
435 unpPix[0] *= 100;
436 unpPix[1] *= 100;
437 unpPix[2] *= 100;
438 Color::lab_to_xyz(unpPix[0], unpPix[1], unpPix[2], &tmpPix[0], &tmpPix[1], &tmpPix[2]);
439 break;
440
441 case eColorTransformXYZToxyY: {
442 float X = unpPix[0];
443 float Y = unpPix[1];
444 float Z = unpPix[2];
445 float XYZ = X + Y + Z;
446 float invXYZ = XYZ <= 0 ? 0. : (1. / XYZ);
447 tmpPix[0] = X * invXYZ;
448 tmpPix[1] = Y * invXYZ;
449 tmpPix[2] = Y;
450 break;
451 }
452 case eColorTransformxyYToXYZ: {
453 float x = unpPix[0];
454 float y = unpPix[1];
455 float Y = unpPix[2];
456 float invy = (y <= 0) ? 0. : (1 / y);
457 tmpPix[0] = x * Y * invy;
458 tmpPix[1] = Y;
459 tmpPix[2] = (1 - x - y) * Y * invy;
460 break;
461 }
462 } // switch
463 tmpPix[3] = unpPix[3];
464 ofxsPremultMaskMixPix<PIX, nComponents, maxValue, true>(tmpPix, dopremult, _premultChannel, x, y, srcPix, /*doMasking=*/ false, /*maskImg=*/ NULL, /*mix=*/ 1.f, /*maskInvert=*/ false, dstPix);
465 // increment the dst pixel
466 dstPix += nComponents;
467 }
468 }
469 } // multiThreadProcessImages
470 };
471
472
473 ////////////////////////////////////////////////////////////////////////////////
474 /** @brief The plugin that does our work */
475 template <ColorTransformEnum transform>
476 class ColorTransformPlugin
477 : public ImageEffect
478 {
479 public:
480 /** @brief ctor */
ColorTransformPlugin(OfxImageEffectHandle handle)481 ColorTransformPlugin(OfxImageEffectHandle handle)
482 : ImageEffect(handle)
483 , _dstClip(NULL)
484 , _srcClip(NULL)
485 , _premult(NULL)
486 , _premultChannel(NULL)
487 , _premultChanged(NULL)
488 {
489 _dstClip = fetchClip(kOfxImageEffectOutputClipName);
490 assert( _dstClip && (!_dstClip->isConnected() || _dstClip->getPixelComponents() == ePixelComponentRGB ||
491 _dstClip->getPixelComponents() == ePixelComponentRGBA) );
492 _srcClip = getContext() == eContextGenerator ? NULL : fetchClip(kOfxImageEffectSimpleSourceClipName);
493 assert( (!_srcClip && getContext() == eContextGenerator) ||
494 ( _srcClip && (!_srcClip->isConnected() || _srcClip->getPixelComponents() == ePixelComponentRGB ||
495 _srcClip->getPixelComponents() == ePixelComponentRGBA) ) );
496 if ( fromRGB(transform) || toRGB(transform) ) {
497 _premult = fetchBooleanParam(kParamPremult);
498 _premultChannel = fetchChoiceParam(kParamPremultChannel);
499 assert(_premult && _premultChannel);
500 _premultChanged = fetchBooleanParam(kParamPremultChanged);
501 assert(_premultChanged);
502 }
503 }
504
505 private:
506 /* Override the render */
507 virtual void render(const RenderArguments &args) OVERRIDE FINAL;
508
509 /* set up and run a processor */
510 void setupAndProcess(ColorTransformProcessorBase &, const RenderArguments &args);
511
512 /** @brief get the clip preferences */
513 virtual void getClipPreferences(ClipPreferencesSetter &clipPreferences) OVERRIDE FINAL;
514
515 /** @brief called when a clip has just been changed in some way (a rewire maybe) */
516 virtual void changedClip(const InstanceChangedArgs &args, const std::string &clipName) OVERRIDE FINAL;
517 virtual void changedParam(const InstanceChangedArgs &args, const std::string ¶mName) OVERRIDE FINAL;
518
519 private:
520 // do not need to delete these, the ImageEffect is managing them for us
521 Clip *_dstClip;
522 Clip *_srcClip;
523 BooleanParam* _premult;
524 ChoiceParam* _premultChannel;
525 BooleanParam* _premultChanged; // set to true the first time the user connects src
526 };
527
528
529 ////////////////////////////////////////////////////////////////////////////////
530 /** @brief render for the filter */
531
532 ////////////////////////////////////////////////////////////////////////////////
533 // basic plugin render function, just a skelington to instantiate templates from
534
535 /* set up and run a processor */
536 template <ColorTransformEnum transform>
537 void
setupAndProcess(ColorTransformProcessorBase & processor,const RenderArguments & args)538 ColorTransformPlugin<transform>::setupAndProcess(ColorTransformProcessorBase &processor,
539 const RenderArguments &args)
540 {
541 auto_ptr<Image> dst( _dstClip->fetchImage(args.time) );
542
543 if ( !dst.get() ) {
544 throwSuiteStatusException(kOfxStatFailed);
545 }
546 BitDepthEnum dstBitDepth = dst->getPixelDepth();
547 PixelComponentEnum dstComponents = dst->getPixelComponents();
548 if ( ( dstBitDepth != _dstClip->getPixelDepth() ) ||
549 ( dstComponents != _dstClip->getPixelComponents() ) ) {
550 setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong depth or components");
551 throwSuiteStatusException(kOfxStatFailed);
552 }
553 if ( (dst->getRenderScale().x != args.renderScale.x) ||
554 ( dst->getRenderScale().y != args.renderScale.y) ||
555 ( ( dst->getField() != eFieldNone) /* for DaVinci Resolve */ && ( dst->getField() != args.fieldToRender) ) ) {
556 setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
557 throwSuiteStatusException(kOfxStatFailed);
558 }
559 auto_ptr<const Image> src( ( _srcClip && _srcClip->isConnected() ) ?
560 _srcClip->fetchImage(args.time) : 0 );
561 if ( src.get() ) {
562 if ( (src->getRenderScale().x != args.renderScale.x) ||
563 ( src->getRenderScale().y != args.renderScale.y) ||
564 ( ( src->getField() != eFieldNone) /* for DaVinci Resolve */ && ( src->getField() != args.fieldToRender) ) ) {
565 setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
566 throwSuiteStatusException(kOfxStatFailed);
567 }
568 BitDepthEnum srcBitDepth = src->getPixelDepth();
569 PixelComponentEnum srcComponents = src->getPixelComponents();
570 if ( (srcBitDepth != dstBitDepth) || (srcComponents != dstComponents) ) {
571 throwSuiteStatusException(kOfxStatErrImageFormat);
572 }
573 }
574
575 processor.setDstImg( dst.get() );
576 processor.setSrcImg( src.get() );
577 processor.setRenderWindow(args.renderWindow);
578
579 bool premult = false;
580 if (_premult) {
581 _premult->getValueAtTime(args.time, premult);
582 }
583 int premultChannel = 3;
584 if (_premultChannel) {
585 _premultChannel->getValueAtTime(args.time, premultChannel);
586 }
587
588 processor.setValues(premult, premultChannel);
589 processor.process();
590 } // >::setupAndProcess
591
592 // the overridden render function
593 template <ColorTransformEnum transform>
594 void
render(const RenderArguments & args)595 ColorTransformPlugin<transform>::render(const RenderArguments &args)
596 {
597 // instantiate the render code based on the pixel depth of the dst clip
598 BitDepthEnum dstBitDepth = _dstClip->getPixelDepth();
599 PixelComponentEnum dstComponents = _dstClip->getPixelComponents();
600
601 assert( kSupportsMultipleClipPARs || !_srcClip || _srcClip->getPixelAspectRatio() == _dstClip->getPixelAspectRatio() );
602 assert( kSupportsMultipleClipDepths || !_srcClip || _srcClip->getPixelDepth() == _dstClip->getPixelDepth() );
603 assert(dstComponents == ePixelComponentRGB || dstComponents == ePixelComponentRGBA);
604 if (dstComponents == ePixelComponentRGBA) {
605 switch (dstBitDepth) {
606 case eBitDepthUByte: {
607 ColorTransformProcessor<unsigned char, 4, 255, transform> fred(*this);
608 setupAndProcess(fred, args);
609 break;
610 }
611 case eBitDepthUShort: {
612 ColorTransformProcessor<unsigned short, 4, 65535, transform> fred(*this);
613 setupAndProcess(fred, args);
614 break;
615 }
616 case eBitDepthFloat: {
617 ColorTransformProcessor<float, 4, 1, transform> fred(*this);
618 setupAndProcess(fred, args);
619 break;
620 }
621 default:
622 throwSuiteStatusException(kOfxStatErrUnsupported);
623 }
624 } else {
625 assert(dstComponents == ePixelComponentRGB);
626 switch (dstBitDepth) {
627 case eBitDepthUByte: {
628 ColorTransformProcessor<unsigned char, 3, 255, transform> fred(*this);
629 setupAndProcess(fred, args);
630 break;
631 }
632 case eBitDepthUShort: {
633 ColorTransformProcessor<unsigned short, 3, 65535, transform> fred(*this);
634 setupAndProcess(fred, args);
635 break;
636 }
637 case eBitDepthFloat: {
638 ColorTransformProcessor<float, 3, 1, transform> fred(*this);
639 setupAndProcess(fred, args);
640 break;
641 }
642 default:
643 throwSuiteStatusException(kOfxStatErrUnsupported);
644 }
645 }
646 } // >::render
647
648 /* Override the clip preferences */
649 template <ColorTransformEnum transform>
650 void
getClipPreferences(ClipPreferencesSetter & clipPreferences)651 ColorTransformPlugin<transform>::getClipPreferences(ClipPreferencesSetter &clipPreferences)
652 {
653 if ( ( fromRGB(transform) || toRGB(transform) ) &&
654 _srcClip &&
655 ( !_srcClip->isConnected() || (_srcClip->getPixelComponents() == ePixelComponentRGBA) ) ) {
656 bool premult;
657 _premult->getValue(premult);
658 // set the premultiplication of _dstClip
659 if ( fromRGB(transform) ) {
660 // HSV is always unpremultiplied
661 clipPreferences.setOutputPremultiplication(eImageUnPreMultiplied);
662 } else {
663 // RGB
664 clipPreferences.setOutputPremultiplication(premult ? eImagePreMultiplied : eImageUnPreMultiplied);
665 }
666 }
667 }
668
669 template <ColorTransformEnum transform>
670 void
changedClip(const InstanceChangedArgs & args,const std::string & clipName)671 ColorTransformPlugin<transform>::changedClip(const InstanceChangedArgs &args,
672 const std::string &clipName)
673 {
674 if ( ( fromRGB(transform) || toRGB(transform) ) &&
675 (clipName == kOfxImageEffectSimpleSourceClipName) &&
676 _srcClip && _srcClip->isConnected() &&
677 !_premultChanged->getValue() &&
678 ( args.reason == eChangeUserEdit) ) {
679 if (_srcClip->getPixelComponents() != ePixelComponentRGBA) {
680 _premult->setValue(false);
681 } else {
682 switch ( _srcClip->getPreMultiplication() ) {
683 case eImageOpaque:
684 _premult->setValue(false);
685 break;
686 case eImagePreMultiplied:
687 _premult->setValue(true);
688 break;
689 case eImageUnPreMultiplied:
690 _premult->setValue(false);
691 break;
692 }
693 }
694 }
695 }
696
697 template <ColorTransformEnum transform>
698 void
changedParam(const InstanceChangedArgs & args,const std::string & paramName)699 ColorTransformPlugin<transform>::changedParam(const InstanceChangedArgs &args,
700 const std::string ¶mName)
701 {
702 if ( ( fromRGB(transform) || toRGB(transform) ) && (paramName == kParamPremult) && (args.reason == eChangeUserEdit) ) {
703 _premultChanged->setValue(true);
704 }
705 }
706
707 //mDeclarePluginFactory(ColorTransformPluginFactory, {ofxsThreadSuiteCheck();}, {});
708 template <ColorTransformEnum transform>
709 class ColorTransformPluginFactory
710 : public PluginFactoryHelper<ColorTransformPluginFactory<transform> >
711 {
712 public:
ColorTransformPluginFactory(const std::string & id,unsigned int verMaj,unsigned int verMin)713 ColorTransformPluginFactory(const std::string& id,
714 unsigned int verMaj,
715 unsigned int verMin) : PluginFactoryHelper<ColorTransformPluginFactory<transform> >(id, verMaj, verMin) {}
716
load()717 virtual void load() OVERRIDE FINAL {ofxsThreadSuiteCheck();};
718 //virtual void unload() OVERRIDE FINAL {};
719 virtual void describe(ImageEffectDescriptor &desc) OVERRIDE FINAL;
720 virtual void describeInContext(ImageEffectDescriptor &desc, ContextEnum context) OVERRIDE FINAL;
721 virtual ImageEffect* createInstance(OfxImageEffectHandle handle, ContextEnum context) OVERRIDE FINAL;
722 };
723
724 template <ColorTransformEnum transform>
725 void
describe(ImageEffectDescriptor & desc)726 ColorTransformPluginFactory<transform>::describe(ImageEffectDescriptor &desc)
727 {
728 // basic labels
729 switch (transform) {
730 case eColorTransformRGBToHSV:
731 desc.setLabel(kPluginRGBToHSVName);
732 desc.setPluginDescription(kPluginRGBToHSVDescription);
733 break;
734
735 case eColorTransformHSVToRGB:
736 desc.setLabel(kPluginHSVToRGBName);
737 desc.setPluginDescription(kPluginHSVToRGBDescription);
738 break;
739
740 case eColorTransformRGBToHSL:
741 desc.setLabel(kPluginRGBToHSLName);
742 desc.setPluginDescription(kPluginRGBToHSLDescription);
743 break;
744
745 case eColorTransformHSLToRGB:
746 desc.setLabel(kPluginHSLToRGBName);
747 desc.setPluginDescription(kPluginHSLToRGBDescription);
748 break;
749
750 case eColorTransformRGBToHSI:
751 desc.setLabel(kPluginRGBToHSIName);
752 desc.setPluginDescription(kPluginRGBToHSIDescription);
753 break;
754
755 case eColorTransformHSIToRGB:
756 desc.setLabel(kPluginHSIToRGBName);
757 desc.setPluginDescription(kPluginHSIToRGBDescription);
758 break;
759
760 case eColorTransformRGBToYCbCr601:
761 desc.setLabel(kPluginRGBToYCbCr601Name);
762 desc.setPluginDescription(kPluginRGBToYCbCr601Description);
763 break;
764
765 case eColorTransformYCbCrToRGB601:
766 desc.setLabel(kPluginYCbCrToRGB601Name);
767 desc.setPluginDescription(kPluginYCbCrToRGB601Description);
768 break;
769
770 case eColorTransformRGBToYCbCr709:
771 desc.setLabel(kPluginRGBToYCbCr709Name);
772 desc.setPluginDescription(kPluginRGBToYCbCr709Description);
773 break;
774
775 case eColorTransformYCbCrToRGB709:
776 desc.setLabel(kPluginYCbCrToRGB709Name);
777 desc.setPluginDescription(kPluginYCbCrToRGB709Description);
778 break;
779
780 case eColorTransformRGBToYPbPr601:
781 desc.setLabel(kPluginRGBToYPbPr601Name);
782 desc.setPluginDescription(kPluginRGBToYPbPr601Description);
783 break;
784
785 case eColorTransformYPbPrToRGB601:
786 desc.setLabel(kPluginYPbPrToRGB601Name);
787 desc.setPluginDescription(kPluginYPbPrToRGB601Description);
788 break;
789
790 case eColorTransformRGBToYPbPr709:
791 desc.setLabel(kPluginRGBToYPbPr709Name);
792 desc.setPluginDescription(kPluginRGBToYPbPr709Description);
793 break;
794
795 case eColorTransformYPbPrToRGB709:
796 desc.setLabel(kPluginYPbPrToRGB709Name);
797 desc.setPluginDescription(kPluginYPbPrToRGB709Description);
798 break;
799
800 case eColorTransformRGBToYUV601:
801 desc.setLabel(kPluginRGBToYUV601Name);
802 desc.setPluginDescription(kPluginRGBToYUV601Description);
803 break;
804
805 case eColorTransformYUVToRGB601:
806 desc.setLabel(kPluginYUVToRGB601Name);
807 desc.setPluginDescription(kPluginYUVToRGB601Description);
808 break;
809
810 case eColorTransformRGBToYUV709:
811 desc.setLabel(kPluginRGBToYUV709Name);
812 desc.setPluginDescription(kPluginRGBToYUV709Description);
813 break;
814
815 case eColorTransformYUVToRGB709:
816 desc.setLabel(kPluginYUVToRGB709Name);
817 desc.setPluginDescription(kPluginYUVToRGB709Description);
818 break;
819
820 case eColorTransformRGB709ToXYZ:
821 desc.setLabel(kPluginRGB709ToXYZName);
822 desc.setPluginDescription(kPluginRGB709ToXYZDescription);
823 break;
824
825 case eColorTransformXYZToRGB709:
826 desc.setLabel(kPluginXYZToRGB709Name);
827 desc.setPluginDescription(kPluginXYZToRGB709Description);
828 break;
829
830 case eColorTransformRGB709ToLab:
831 desc.setLabel(kPluginRGB709ToLabName);
832 desc.setPluginDescription(kPluginRGB709ToLabDescription);
833 break;
834
835 case eColorTransformLabToRGB709:
836 desc.setLabel(kPluginLabToRGB709Name);
837 desc.setPluginDescription(kPluginLabToRGB709Description);
838 break;
839
840 case eColorTransformXYZToLab:
841 desc.setLabel(kPluginXYZToLabName);
842 desc.setPluginDescription(kPluginXYZToLabDescription);
843 break;
844
845 case eColorTransformLabToXYZ:
846 desc.setLabel(kPluginLabToXYZName);
847 desc.setPluginDescription(kPluginLabToXYZDescription);
848 break;
849
850 case eColorTransformXYZToxyY:
851 desc.setLabel(kPluginXYZToxyYName);
852 desc.setPluginDescription(kPluginXYZToxyYDescription);
853 break;
854
855 case eColorTransformxyYToXYZ:
856 desc.setLabel(kPluginxyYToXYZName);
857 desc.setPluginDescription(kPluginxyYToXYZDescription);
858 break;
859 } // switch
860 desc.setPluginGrouping(kPluginGrouping);
861
862 desc.addSupportedContext(eContextFilter);
863 desc.addSupportedContext(eContextGeneral);
864 //desc.addSupportedContext(eContextPaint);
865 desc.addSupportedBitDepth(eBitDepthUByte);
866 desc.addSupportedBitDepth(eBitDepthUShort);
867 desc.addSupportedBitDepth(eBitDepthFloat);
868
869 // set a few flags
870 desc.setSingleInstance(false);
871 desc.setHostFrameThreading(false);
872 desc.setSupportsMultiResolution(kSupportsMultiResolution);
873 desc.setSupportsTiles(kSupportsTiles);
874 desc.setTemporalClipAccess(false);
875 desc.setRenderTwiceAlways(false);
876 desc.setSupportsMultipleClipPARs(kSupportsMultipleClipPARs);
877 desc.setSupportsMultipleClipDepths(kSupportsMultipleClipDepths);
878 desc.setRenderThreadSafety(kRenderThreadSafety);
879 #ifdef OFX_EXTENSIONS_NATRON
880 desc.setChannelSelector(ePixelComponentRGB);
881 #endif
882 } // >::describe
883
884 template <ColorTransformEnum transform>
885 void
describeInContext(ImageEffectDescriptor & desc,ContextEnum)886 ColorTransformPluginFactory<transform>::describeInContext(ImageEffectDescriptor &desc,
887 ContextEnum /*context*/)
888 {
889 // Source clip only in the filter context
890 // create the mandated source clip
891 ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
892
893 srcClip->addSupportedComponent(ePixelComponentRGBA);
894 srcClip->addSupportedComponent(ePixelComponentRGB);
895 srcClip->setTemporalClipAccess(false);
896 srcClip->setSupportsTiles(kSupportsTiles);
897 srcClip->setIsMask(false);
898
899 // create the mandated output clip
900 ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
901 dstClip->addSupportedComponent(ePixelComponentRGBA);
902 dstClip->addSupportedComponent(ePixelComponentRGB);
903 dstClip->setSupportsTiles(kSupportsTiles);
904
905 // make some pages and to things in
906 if ( fromRGB(transform) || toRGB(transform) ) {
907 PageParamDescriptor *page = desc.definePageParam("Controls");
908 {
909 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamPremult);
910 if ( fromRGB(transform) ) {
911 param->setLabel(kParamPremultRGBToXXXLabel);
912 param->setHint(kParamPremultRGBToXXXHint);
913 } else {
914 param->setLabel(kParamPremultXXXToRGBLabel);
915 param->setHint(kParamPremultXXXToRGBHint);
916 }
917 param->setLayoutHint(eLayoutHintNoNewLine, 1);
918 param->setAnimates(false);
919 desc.addClipPreferencesSlaveParam(*param);
920 if (page) {
921 page->addChild(*param);
922 }
923 }
924 {
925 // not yet implemented, for future use (whenever deep compositing is supported)
926 ChoiceParamDescriptor* param = desc.defineChoiceParam(kParamPremultChannel);
927 param->setLabel(kParamPremultChannelLabel);
928 param->setHint(kParamPremultChannelHint);
929 param->appendOption(kParamPremultChannelR);
930 param->appendOption(kParamPremultChannelG);
931 param->appendOption(kParamPremultChannelB);
932 param->appendOption(kParamPremultChannelA);
933 param->setDefault(3); // alpha
934 param->setIsSecretAndDisabled(true); // not yet implemented
935 if (page) {
936 page->addChild(*param);
937 }
938 }
939
940 {
941 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamPremultChanged);
942 param->setDefault(false);
943 param->setIsSecretAndDisabled(true);
944 param->setAnimates(false);
945 param->setEvaluateOnChange(false);
946 if (page) {
947 page->addChild(*param);
948 }
949 }
950 }
951 } // >::describeInContext
952
953 template <ColorTransformEnum transform>
954 ImageEffect*
createInstance(OfxImageEffectHandle handle,ContextEnum)955 ColorTransformPluginFactory<transform>::createInstance(OfxImageEffectHandle handle,
956 ContextEnum /*context*/)
957 {
958 return new ColorTransformPlugin<transform>(handle);
959 }
960
961 // RGBtoHSV
962 static ColorTransformPluginFactory<eColorTransformRGBToHSV> p1(kPluginRGBToHSVIdentifier, kPluginVersionMajor, kPluginVersionMinor);
963 // HSVtoRGB
964 static ColorTransformPluginFactory<eColorTransformHSVToRGB> p2(kPluginHSVToRGBIdentifier, kPluginVersionMajor, kPluginVersionMinor);
965 // RGBtoHSL
966 static ColorTransformPluginFactory<eColorTransformRGBToHSL> p3(kPluginRGBToHSLIdentifier, kPluginVersionMajor, kPluginVersionMinor);
967 // HSLtoRGB
968 static ColorTransformPluginFactory<eColorTransformHSLToRGB> p4(kPluginHSLToRGBIdentifier, kPluginVersionMajor, kPluginVersionMinor);
969 // RGBtoHSI
970 static ColorTransformPluginFactory<eColorTransformRGBToHSI> p5(kPluginRGBToHSIIdentifier, kPluginVersionMajor, kPluginVersionMinor);
971 // HSItoRGB
972 static ColorTransformPluginFactory<eColorTransformHSIToRGB> p6(kPluginHSIToRGBIdentifier, kPluginVersionMajor, kPluginVersionMinor);
973 // RGBToYCbCr601
974 static ColorTransformPluginFactory<eColorTransformRGBToYCbCr601> p7(kPluginRGBToYCbCr601Identifier, kPluginVersionMajor, kPluginVersionMinor);
975 // YCbCrToRGB601
976 static ColorTransformPluginFactory<eColorTransformYCbCrToRGB601> p8(kPluginYCbCrToRGB601Identifier, kPluginVersionMajor, kPluginVersionMinor);
977 // RGBToYCbCr709
978 static ColorTransformPluginFactory<eColorTransformRGBToYCbCr709> p17(kPluginRGBToYCbCr709Identifier, kPluginVersionMajor, kPluginVersionMinor);
979 // YCbCrToRGB709
980 static ColorTransformPluginFactory<eColorTransformYCbCrToRGB709> p18(kPluginYCbCrToRGB709Identifier, kPluginVersionMajor, kPluginVersionMinor);
981 // RGBToYPbPr601
982 static ColorTransformPluginFactory<eColorTransformRGBToYPbPr601> p9(kPluginRGBToYPbPr601Identifier, kPluginVersionMajor, kPluginVersionMinor);
983 // YPbPrToRGB601
984 static ColorTransformPluginFactory<eColorTransformYPbPrToRGB601> p10(kPluginYPbPrToRGB601Identifier, kPluginVersionMajor, kPluginVersionMinor);
985 // RGBToYPbPr709
986 static ColorTransformPluginFactory<eColorTransformRGBToYPbPr709> p15(kPluginRGBToYPbPr709Identifier, kPluginVersionMajor, kPluginVersionMinor);
987 // YPbPrToRGB709
988 static ColorTransformPluginFactory<eColorTransformYPbPrToRGB709> p16(kPluginYPbPrToRGB709Identifier, kPluginVersionMajor, kPluginVersionMinor);
989 // RGBToYUV601
990 static ColorTransformPluginFactory<eColorTransformRGBToYUV601> p19(kPluginRGBToYUV601Identifier, kPluginVersionMajor, kPluginVersionMinor);
991 // YUVToRGB601
992 static ColorTransformPluginFactory<eColorTransformYUVToRGB601> p20(kPluginYUVToRGB601Identifier, kPluginVersionMajor, kPluginVersionMinor);
993 // RGBToYUV709
994 static ColorTransformPluginFactory<eColorTransformRGBToYUV709> p21(kPluginRGBToYUV709Identifier, kPluginVersionMajor, kPluginVersionMinor);
995 // YUVToRGB709
996 static ColorTransformPluginFactory<eColorTransformYUVToRGB709> p22(kPluginYUVToRGB709Identifier, kPluginVersionMajor, kPluginVersionMinor);
997 // RGB709ToXYZ
998 static ColorTransformPluginFactory<eColorTransformRGB709ToXYZ> p11(kPluginRGB709ToXYZIdentifier, kPluginVersionMajor, kPluginVersionMinor);
999 // XYZToRGB709
1000 static ColorTransformPluginFactory<eColorTransformXYZToRGB709> p12(kPluginXYZToRGB709Identifier, kPluginVersionMajor, kPluginVersionMinor);
1001 // RGB709ToLab
1002 static ColorTransformPluginFactory<eColorTransformRGB709ToLab> p13(kPluginRGB709ToLabIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1003 // LabToRGB709
1004 static ColorTransformPluginFactory<eColorTransformLabToRGB709> p14(kPluginLabToRGB709Identifier, kPluginVersionMajor, kPluginVersionMinor);
1005 // XYZToLab
1006 static ColorTransformPluginFactory<eColorTransformXYZToLab> p23(kPluginXYZToLabIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1007 // LabToXYZ
1008 static ColorTransformPluginFactory<eColorTransformLabToXYZ> p24(kPluginLabToXYZIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1009 // XYZToxyY
1010 static ColorTransformPluginFactory<eColorTransformXYZToxyY> p25(kPluginXYZToxyYIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1011 // xyYToXYZ
1012 static ColorTransformPluginFactory<eColorTransformxyYToXYZ> p26(kPluginxyYToXYZIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1013
1014 mRegisterPluginFactoryInstance(p1)
1015 mRegisterPluginFactoryInstance(p2)
1016 mRegisterPluginFactoryInstance(p3)
1017 mRegisterPluginFactoryInstance(p4)
1018 mRegisterPluginFactoryInstance(p5)
1019 mRegisterPluginFactoryInstance(p6)
1020 mRegisterPluginFactoryInstance(p7)
1021 mRegisterPluginFactoryInstance(p8)
1022 mRegisterPluginFactoryInstance(p9)
1023 mRegisterPluginFactoryInstance(p10)
1024 mRegisterPluginFactoryInstance(p11)
1025 mRegisterPluginFactoryInstance(p12)
1026 mRegisterPluginFactoryInstance(p13)
1027 mRegisterPluginFactoryInstance(p14)
1028 mRegisterPluginFactoryInstance(p15)
1029 mRegisterPluginFactoryInstance(p16)
1030 mRegisterPluginFactoryInstance(p17)
1031 mRegisterPluginFactoryInstance(p18)
1032 mRegisterPluginFactoryInstance(p19)
1033 mRegisterPluginFactoryInstance(p20)
1034 mRegisterPluginFactoryInstance(p21)
1035 mRegisterPluginFactoryInstance(p22)
1036 mRegisterPluginFactoryInstance(p23)
1037 mRegisterPluginFactoryInstance(p24)
1038 mRegisterPluginFactoryInstance(p25)
1039 mRegisterPluginFactoryInstance(p26)
1040
1041 OFXS_NAMESPACE_ANONYMOUS_EXIT
1042