2 * Cinelerra :: Blue Banana - color modification plugin for Cinelerra-CV
3 * Copyright (C) 2012-2013 Monty <monty@xiph.org>
5 * This program 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.
10 * This program 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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 static inline void rgb8_to_RGB(unsigned char *row, float *R, float *G, float *B, int w){
23 *R++ = *row++*.0039215686f;
24 *G++ = *row++*.0039215686f;
25 *B++ = *row++*.0039215686f;
29 static inline void rgba8_to_RGBA(unsigned char *row, float *R, float *G, float *B, float *A, int w){
31 *R++ = *row++*.0039215686f;
32 *G++ = *row++*.0039215686f;
33 *B++ = *row++*.0039215686f;
34 *A++ = *row++*.0039215686f;
38 static inline void rgbF_to_RGB(float *row, float *R, float *G, float *B, int w){
46 static inline void rgbaF_to_RGBA(float *row, float *R, float *G, float *B, float *A, int w){
56 // Full swing and bt601 are chosen below to conform to existing Cinelerra convention.
57 // It's not correct, but it's consistent.
86 #define Kg (1.f-Kr-Kb)
88 #define Br (.5f*-Kr/(1.f-Kb))
89 #define Bg (.5f*-Kg/(1.f-Kb))
93 #define Rg (.5f*-Kg/(1.f-Kr))
94 #define Rb (.5f*-Kb/(1.f-Kr))
96 #define Rv (2.f*(1.f-Kr))
97 #define Gu (2.f*(1.f-Kb)*Kb/Kg)
98 #define Gv (2.f*(1.f-Kr)*Kr/Kg)
99 #define Bu (2.f*(1.f-Kb))
101 static inline void yuv8_to_RGB(unsigned char *row, float *R, float *G, float *B, int w){
103 float y = (*row++-Y_SHIFT) * (1.f/Y_SWING);
104 float u = (*row++-C_SHIFT);
105 float v = (*row++-C_SHIFT);
106 *R++ = y + (Rv/C_SWING)*v;
107 *G++ = y - (Gu/C_SWING)*u - (Gv/C_SWING)*v;
108 *B++ = y + (Bu/C_SWING)*u;
112 static inline void yuva8_to_RGBA(unsigned char *row, float *R, float *G, float *B, float *A, int w){
114 float y = (*row++-Y_SHIFT) * (1.f/Y_SWING);
115 float u = (*row++-C_SHIFT);
116 float v = (*row++-C_SHIFT);
117 *R++ = y + (Rv/C_SWING)*v;
118 *G++ = y - (Gu/C_SWING)*u - (Gv/C_SWING)*v;
119 *B++ = y + (Bu/C_SWING)*u;
120 *A++ = *row++*(1.f/255.f);
124 static inline void RGB_to_yuv8(float *R, float *G, float *B, float *S, float F, unsigned char *row, int w, int bpp){
127 if(F<1.-SELECT_THRESH){
130 float y = (Y_SHIFT + (Kr*Y_SWING)**R + (Kg*Y_SWING)**G + (Kb*Y_SWING)**B - row[0])*s + row[0] +.5f;
131 float u = (C_SHIFT + (Br*C_SWING)**R + (Bg*C_SWING)**G + (Bb*C_SWING)**B - row[1])*s + row[1] +.5f;
132 float v = (C_SHIFT + (Rr*C_SWING)**R++ + (Rg*C_SWING)**G++ + (Rb*C_SWING)**B++ - row[2])*s + row[2] +.5f;
133 row[0] = CLAMP(y,CLAMP_LO,CLAMP_HI);
134 row[1] = CLAMP(u,CLAMP_LO,CLAMP_HI);
135 row[2] = CLAMP(v,CLAMP_LO,CLAMP_HI);
140 float y = (Y_SHIFT + (Kr*Y_SWING)**R + (Kg*Y_SWING)**G + (Kb*Y_SWING)**B - row[0])**S + row[0] +.5f;
141 float u = (C_SHIFT + (Br*C_SWING)**R + (Bg*C_SWING)**G + (Bb*C_SWING)**B - row[1])**S + row[1] +.5f;
142 float v = (C_SHIFT + (Rr*C_SWING)**R++ + (Rg*C_SWING)**G++ + (Rb*C_SWING)**B++ - row[2])**S++ + row[2] +.5f;
143 row[0] = CLAMP(y,CLAMP_LO,CLAMP_HI);
144 row[1] = CLAMP(u,CLAMP_LO,CLAMP_HI);
145 row[2] = CLAMP(v,CLAMP_LO,CLAMP_HI);
150 if(F<1.-SELECT_THRESH){
152 float y = (Y_SHIFT + (Kr*Y_SWING)**R + (Kg*Y_SWING)**G + (Kb*Y_SWING)**B - row[0])*F + row[0] +.5f;
153 float u = (C_SHIFT + (Br*C_SWING)**R + (Bg*C_SWING)**G + (Bb*C_SWING)**B - row[1])*F + row[1] +.5f;
154 float v = (C_SHIFT + (Rr*C_SWING)**R++ + (Rg*C_SWING)**G++ + (Rb*C_SWING)**B++ - row[2])*F + row[2] +.5f;
155 row[0] = CLAMP(y,CLAMP_LO,CLAMP_HI);
156 row[1] = CLAMP(u,CLAMP_LO,CLAMP_HI);
157 row[2] = CLAMP(v,CLAMP_LO,CLAMP_HI);
162 float y = (Y_SHIFT+.5f) + (Kr*Y_SWING)**R + (Kg*Y_SWING)**G + (Kb*Y_SWING)**B ;
163 float u = (C_SHIFT+.5f) + (Br*C_SWING)**R + (Bg*C_SWING)**G + (Bb*C_SWING)**B ;
164 float v = (C_SHIFT+.5f) + (Rr*C_SWING)**R++ + (Rg*C_SWING)**G++ + (Rb*C_SWING)**B++;
165 row[0] = CLAMP(y,CLAMP_LO,CLAMP_HI);
166 row[1] = CLAMP(u,CLAMP_LO,CLAMP_HI);
167 row[2] = CLAMP(v,CLAMP_LO,CLAMP_HI);
175 static inline void RGB_to_rgb8(float *R, float *G, float *B, float *S, float F, unsigned char *row, int w, int bpp){
178 if(F<1.-SELECT_THRESH){
181 float r = (*R++*255.f-row[0])* s +row[0] +.5f;
182 float g = (*G++*255.f-row[1])* s +row[1] +.5f;
183 float b = (*B++*255.f-row[2])* s +row[2] +.5f;
184 row[0] = CLAMP(r,0,255);
185 row[1] = CLAMP(g,0,255);
186 row[2] = CLAMP(b,0,255);
193 float r = (*R++*255.f-row[0])* *S +row[0] +.5f;
194 float g = (*G++*255.f-row[1])* *S +row[1] +.5f;
195 float b = (*B++*255.f-row[2])* *S++ +row[2] +.5f;
196 row[0] = CLAMP(r,0,255);
197 row[1] = CLAMP(g,0,255);
198 row[2] = CLAMP(b,0,255);
203 if(F<1.-SELECT_THRESH){
205 float r = (*R++*255.f-row[0])* F +row[0] +.5f;
206 float g = (*G++*255.f-row[1])* F +row[1] +.5f;
207 float b = (*B++*255.f-row[2])* F +row[2] +.5f;
208 row[0] = CLAMP(r,0,255);
209 row[1] = CLAMP(g,0,255);
210 row[2] = CLAMP(b,0,255);
215 float r = *R++*255.f +.5f;
216 float g = *G++*255.f +.5f;
217 float b = *B++*255.f +.5f;
218 row[0] = CLAMP(r,0,255);
219 row[1] = CLAMP(g,0,255);
220 row[2] = CLAMP(b,0,255);
228 static inline void Aal_to_alp8(float *S, float F, unsigned char *row, int w, int bpp){
231 float a = *S*F*255.f +.5f;
232 row[3] = CLAMP(a,0,255);
236 float a = F*255.f +.5f;
237 unsigned char s = CLAMP(a,0,255);
238 while(w--){ row[3] = s; row+=bpp; }
243 static inline void RGB_to_rgbF(float *R, float *G, float *B, float *S, float F, float *row, int w, int bpp){
246 if(F<1.-SELECT_THRESH){
249 row[0] = (*R++-row[0])* s +row[0];
250 row[1] = (*G++-row[1])* s +row[1];
251 row[2] = (*B++-row[2])* s +row[2];
256 row[0] = (*R++-row[0])* *S +row[0];
257 row[1] = (*G++-row[1])* *S +row[1];
258 row[2] = (*B++-row[2])* *S++ +row[2];
263 if(F<1.-SELECT_THRESH){
265 row[0] = (*R++-row[0])* F +row[0];
266 row[1] = (*G++-row[1])* F +row[1];
267 row[2] = (*B++-row[2])* F +row[2];
282 static inline void Aal_to_alpF(float *S, float F, float *row, int w, int bpp){
291 while(w--){ row[3] = a; row+=bpp; }
296 static inline void unmask_rgba8(unsigned char *row,int w){
303 static inline void unmask_rgbaF(float *row, int w){
310 static inline void unmask_yuva8(unsigned char *row, int w){
317 // A modified HSV colorspace: saturation is calculated using |V| + a
318 // fixed bias to shift the absolute blackpoint well below the in-use
319 // color range. This eliminates the singularity and desaturates
320 // values near the functional blackpoint (zero). The modifications
321 // also allows us to use HSV with footroom without clipping chroma
324 // H is constrained to the range 0 to 1.
325 // S is strictly >=0 but the upper range is technically unbounded.
326 // It is reasonable to clip to the reference range [0:1]
327 // V is unbounded and may extend considerably below 0 and above 1 depending on foot and head room
329 /* Simple mods of the original Cinelerra conversion routines */
330 static inline void RGB_to_HSpV(float R, float G, float B, float &H, float &Sp, float &V){
334 H = 2 + (B-R) / (G-B);
335 Sp = (G-B)/(fabs(V)+HSpV_SATURATION_BIAS)*HSpV_SATURATION_SCALE;
339 H = 2 + (B-R) / (G-R);
340 Sp = (G-R)/(fabs(V)+HSpV_SATURATION_BIAS)*HSpV_SATURATION_SCALE;
343 H = 4 + (R-G) / (B-R);
344 Sp = (B-R)/(fabs(V)+HSpV_SATURATION_BIAS)*HSpV_SATURATION_SCALE;
351 Sp = (R-B)/(fabs(V)+HSpV_SATURATION_BIAS)*HSpV_SATURATION_SCALE;
355 H = 6 + (G-B) / (R-G);
356 Sp = (R-G)/(fabs(V)+HSpV_SATURATION_BIAS)*HSpV_SATURATION_SCALE;
359 H = 4 + (R-G) / (B-G+.0001);
360 Sp = (B-G)/(fabs(V)+HSpV_SATURATION_BIAS)*HSpV_SATURATION_SCALE;
366 static inline void HSpV_to_RGB(float H, float Sp, float V, float &R, float &G, float &B){
367 float vp = (fabs(V)+HSpV_SATURATION_BIAS)*Sp*HSpV_SATURATION_ISCALE;
403 static inline void HSpV_correct_RGB(float H, float Sp, float &V, float &R, float &G, float &B){
404 float vp = Sp<0.f?0.f:(fabs(V)+HSpV_SATURATION_BIAS)*Sp*HSpV_SATURATION_ISCALE;
408 R = V = R*R_TO_Y + (G-(H-i-1)*vp)*G_TO_Y + (B+vp)*B_TO_Y;
413 G = V = (R+(H-i)*vp)*R_TO_Y + G*G_TO_Y + (B+vp)*B_TO_Y;
418 G = V = (R+vp)*R_TO_Y + G*G_TO_Y + (B-(H-i-1)*vp)*B_TO_Y;
423 B = V = (R+vp)*R_TO_Y + (G+(H-i)*vp)*G_TO_Y + B*B_TO_Y;
428 B = V = (R-(H-i-1)*vp)*R_TO_Y + (G+vp)*G_TO_Y + B*B_TO_Y;
433 R = V = R*R_TO_Y + (G+vp)*G_TO_Y + (B+(H-i)*vp)*B_TO_Y;