1 /* input and output is an array of double
2 * the array has thee dimensions of the followin size: width, height, 3
4 * note: source and destination may point ot the same array
7 double black_level = 0.00;
8 double white_level = 1.00;
9 int scale_levels = 0; /* scale between black and white level */
10 double fade_level = 0.20;
11 int yuv_mod = 0; /* UV vectors are not affected by lightness of the pixle */
15 * Instead of having U and V vector length affected by the lightnes of the
16 * pixle, we only apply the saturation to U and V. This prevents change of
17 * saturation when convertig YUV /with different Y) back to RGB.
20 inline double max_rgb(double r, double g, double b)
34 /* modified YUV space */
35 inline void rgb2yuv_pixle_mod(double r, double g, double b, double *y, double *u, double *v)
38 double r_, g_, b_, y_;
40 /* 1. scale RGB to maximum lightness */
41 /* 1.1 find maximum value */
42 max = max_rgb(r, g, b);
43 /* 1.2 if value is too low, assume grey pixle */
48 /* 1.3 use max to scale RGB to max lightness */
53 /* 2. convert to modified YUV */
54 /* 2.1 use Y from original RGB */
55 *y = 0.299*r + 0.587*g + 0.114*b;
56 /* 2.2 use UV from scaled RGB */
57 y_ = 0.299*r_ + 0.587*g_ + 0.114*b_;
62 void rgb2yuv_pixle(double r, double g, double b, double *y, double *u, double *v)
65 rgb2yuv_pixle_mod(r, g, b, y, u, v);
68 *y = 0.299*r + 0.587*g + 0.114*b;
73 void rgb2yuv(double *src, double *dst, int width, int height)
76 double r, g, b, y, u, v;
78 for (i = 0, ii = width * height; i < ii; i++) {
84 rgb2yuv_pixle(r, g, b, &y, &u, &v);
92 inline int _scale_levels(double *y, double *r, double *g, double *b)
96 /* prevent from crashing/artefacts, if black level is at full level */
97 if (black_level > 0.999) {
101 if (white_level < 0.001) {
105 if (white_level - black_level < 0.001) {
106 *r = *b = 1.0 ; *g = 0.0;
109 /* scale down, black level becomes 0 */
110 if (black_level > 0.0 || white_level < 1.0) {
111 ny = (*y - black_level) / (white_level - black_level);
132 inline void _unscale_levels(double *r, double *g, double *b)
136 /* scale up, so 0 becomes black level */
137 if (black_level > 0.0 || white_level < 1.0) {
138 *r = black_level + *r * (white_level - black_level);
139 *g = black_level + *g * (white_level - black_level);
140 *b = black_level + *b * (white_level - black_level);
144 /* modified YUV space */
145 void yuv2rgb_pixle_mod(double y, double u, double v, double *r, double *g, double *b)
147 double r_, g_, b_, y_;
149 double is_dist, must_dist;
151 if (_scale_levels(&y, r, g, b))
154 /* 1. get RGB from U and V with maximum lightness */
155 /* 1.1 U and V conversion without Y */
157 g_ = -0.395*u - 0.581*v;
159 /* 1.2 find maximum value */
160 max = max_rgb(r_, g_, b_);
161 /* 1.3 maximize RGB */
166 /* 2. calculate scale factor to scale RGB (with max lightness) to target Y */
167 /* 2.1 calculate Y of scaled RGB */
168 y_ = 0.299*r_ + 0.587*g_ + 0.114*b_;
169 /* 2.2 calculate scale factor */
172 /* 3. scale RGB (with max lightness) to target Y and clip (by reducing saturation), if needed */
173 /* 3.1 scale RGB with factor */
177 /* 3.2 finx max value to clip if needed */
178 max = max_rgb(r_, g_, b_);
179 /* 3.3 clip by reducing saturation */
183 *r = (r_-y)/is_dist*must_dist + y;
184 *g = (g_-y)/is_dist*must_dist + y;
185 *b = (b_-y)/is_dist*must_dist + y;
192 _unscale_levels(r, g, b);
195 //#define SCALE_LEVEL
196 void yuv2rgb_pixle(double y, double u, double v, double *r, double *g, double *b)
198 double nu, nv, uv, nuv;
202 yuv2rgb_pixle_mod(y, u, v, r, g, b);
206 if (_scale_levels(&y, r, g, b))
209 /* scale UV vector lengh between black level and fade level */
210 if (y < fade_level && fade_level > 0.001) {
211 fade = y / fade_level;
216 /* convert YUV to RGB */
218 *g = y - 0.395*u - 0.581*v;
221 /* clip UV vector length, if green exceed range */
223 uv = 0.395*u + 0.581*v;
228 *g = y - 0.395*u - 0.581*v;
232 uv = 0.395*u + 0.581*v;
237 *g = y - 0.395*u - 0.581*v;
240 /* clip UV vector length, if red exceed range */
246 *g = y - 0.395*u - 0.581*v;
254 *g = y - 0.395*u - 0.581*v;
257 /* clip UV vector length, if blue exceed range */
263 *g = y - 0.395*u - 0.581*v;
271 *g = y - 0.395*u - 0.581*v;
275 _unscale_levels(r, g, b);
278 void yuv2rgb(double *src, double *dst, int width, int height)
281 double r, g, b, y, u, v;
283 for (i = 0, ii = width * height; i < ii; i++) {
287 v = src[i + ii + ii];
289 yuv2rgb_pixle(y, u, v, &r, &g, &b);
293 dst[i + ii + ii] = b;