1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Author: Peter Schlaile < peter [at] schlaile [dot] de >
17 */
18
19 /** \file
20 * \ingroup spseq
21 */
22
23 #include <math.h>
24 #include <string.h>
25
26 #include "BLI_task.h"
27 #include "BLI_utildefines.h"
28
29 #include "IMB_colormanagement.h"
30 #include "IMB_imbuf.h"
31 #include "IMB_imbuf_types.h"
32
33 #include "atomic_ops.h"
34
35 #include "sequencer_intern.h"
36
37 /* XXX, why is this function better than BLI_math version?
38 * only difference is it does some normalize after, need to double check on this - campbell */
rgb_to_yuv_normalized(const float rgb[3],float yuv[3])39 static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
40 {
41 yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
42 yuv[1] = 0.492f * (rgb[2] - yuv[0]);
43 yuv[2] = 0.877f * (rgb[0] - yuv[0]);
44
45 /* Normalize. */
46 yuv[1] *= 255.0f / (122 * 2.0f);
47 yuv[1] += 0.5f;
48
49 yuv[2] *= 255.0f / (157 * 2.0f);
50 yuv[2] += 0.5f;
51 }
52
scope_put_pixel(const uchar * table,uchar * pos)53 static void scope_put_pixel(const uchar *table, uchar *pos)
54 {
55 uchar newval = table[*pos];
56 pos[0] = pos[1] = pos[2] = newval;
57 pos[3] = 255;
58 }
59
scope_put_pixel_single(const uchar * table,uchar * pos,int col)60 static void scope_put_pixel_single(const uchar *table, uchar *pos, int col)
61 {
62 char newval = table[pos[col]];
63 pos[col] = newval;
64 pos[3] = 255;
65 }
66
wform_put_line(int w,uchar * last_pos,uchar * new_pos)67 static void wform_put_line(int w, uchar *last_pos, uchar *new_pos)
68 {
69 if (last_pos > new_pos) {
70 uchar *temp = new_pos;
71 new_pos = last_pos;
72 last_pos = temp;
73 }
74
75 while (last_pos < new_pos) {
76 if (last_pos[0] == 0) {
77 last_pos[0] = last_pos[1] = last_pos[2] = 32;
78 last_pos[3] = 255;
79 }
80 last_pos += 4 * w;
81 }
82 }
83
wform_put_line_single(int w,uchar * last_pos,uchar * new_pos,int col)84 static void wform_put_line_single(int w, uchar *last_pos, uchar *new_pos, int col)
85 {
86 if (last_pos > new_pos) {
87 uchar *temp = new_pos;
88 new_pos = last_pos;
89 last_pos = temp;
90 }
91
92 while (last_pos < new_pos) {
93 if (last_pos[col] == 0) {
94 last_pos[col] = 32;
95 last_pos[3] = 255;
96 }
97 last_pos += 4 * w;
98 }
99 }
100
wform_put_border(uchar * tgt,int w,int h)101 static void wform_put_border(uchar *tgt, int w, int h)
102 {
103 int x, y;
104
105 for (x = 0; x < w; x++) {
106 uchar *p = tgt + 4 * x;
107 p[1] = p[3] = 155;
108 p[4 * w + 1] = p[4 * w + 3] = 155;
109 p = tgt + 4 * (w * (h - 1) + x);
110 p[1] = p[3] = 155;
111 p[-4 * w + 1] = p[-4 * w + 3] = 155;
112 }
113
114 for (y = 0; y < h; y++) {
115 uchar *p = tgt + 4 * w * y;
116 p[1] = p[3] = 155;
117 p[4 + 1] = p[4 + 3] = 155;
118 p = tgt + 4 * (w * y + w - 1);
119 p[1] = p[3] = 155;
120 p[-4 + 1] = p[-4 + 3] = 155;
121 }
122 }
123
wform_put_gridrow(uchar * tgt,float perc,int w,int h)124 static void wform_put_gridrow(uchar *tgt, float perc, int w, int h)
125 {
126 tgt += (int)(perc / 100.0f * h) * w * 4;
127
128 for (int i = 0; i < w * 2; i++) {
129 tgt[0] = 255;
130
131 tgt += 4;
132 }
133 }
134
wform_put_grid(uchar * tgt,int w,int h)135 static void wform_put_grid(uchar *tgt, int w, int h)
136 {
137 wform_put_gridrow(tgt, 90.0, w, h);
138 wform_put_gridrow(tgt, 70.0, w, h);
139 wform_put_gridrow(tgt, 10.0, w, h);
140 }
141
make_waveform_view_from_ibuf_byte(ImBuf * ibuf)142 static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
143 {
144 ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
145 int x, y;
146 const uchar *src = (uchar *)ibuf->rect;
147 uchar *tgt = (uchar *)rval->rect;
148 int w = ibuf->x + 3;
149 int h = 515;
150 float waveform_gamma = 0.2;
151 uchar wtable[256];
152
153 wform_put_grid(tgt, w, h);
154 wform_put_border(tgt, w, h);
155
156 for (x = 0; x < 256; x++) {
157 wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
158 }
159
160 for (y = 0; y < ibuf->y; y++) {
161 uchar *last_p = NULL;
162
163 for (x = 0; x < ibuf->x; x++) {
164 const uchar *rgb = src + 4 * (ibuf->x * y + x);
165 float v = (float)IMB_colormanagement_get_luminance_byte(rgb) / 255.0f;
166 uchar *p = tgt;
167 p += 4 * (w * ((int)(v * (h - 3)) + 1) + x + 1);
168
169 scope_put_pixel(wtable, p);
170 p += 4 * w;
171 scope_put_pixel(wtable, p);
172
173 if (last_p != NULL) {
174 wform_put_line(w, last_p, p);
175 }
176 last_p = p;
177 }
178 }
179
180 return rval;
181 }
182
make_waveform_view_from_ibuf_float(ImBuf * ibuf)183 static ImBuf *make_waveform_view_from_ibuf_float(ImBuf *ibuf)
184 {
185 ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
186 int x, y;
187 const float *src = ibuf->rect_float;
188 uchar *tgt = (uchar *)rval->rect;
189 int w = ibuf->x + 3;
190 int h = 515;
191 float waveform_gamma = 0.2;
192 uchar wtable[256];
193
194 wform_put_grid(tgt, w, h);
195
196 for (x = 0; x < 256; x++) {
197 wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
198 }
199
200 for (y = 0; y < ibuf->y; y++) {
201 uchar *last_p = NULL;
202
203 for (x = 0; x < ibuf->x; x++) {
204 const float *rgb = src + 4 * (ibuf->x * y + x);
205 float v = IMB_colormanagement_get_luminance(rgb);
206 uchar *p = tgt;
207
208 CLAMP(v, 0.0f, 1.0f);
209
210 p += 4 * (w * ((int)(v * (h - 3)) + 1) + x + 1);
211
212 scope_put_pixel(wtable, p);
213 p += 4 * w;
214 scope_put_pixel(wtable, p);
215
216 if (last_p != NULL) {
217 wform_put_line(w, last_p, p);
218 }
219 last_p = p;
220 }
221 }
222
223 wform_put_border(tgt, w, h);
224
225 return rval;
226 }
227
make_waveform_view_from_ibuf(ImBuf * ibuf)228 ImBuf *make_waveform_view_from_ibuf(ImBuf *ibuf)
229 {
230 if (ibuf->rect_float) {
231 return make_waveform_view_from_ibuf_float(ibuf);
232 }
233 return make_waveform_view_from_ibuf_byte(ibuf);
234 }
235
make_sep_waveform_view_from_ibuf_byte(ImBuf * ibuf)236 static ImBuf *make_sep_waveform_view_from_ibuf_byte(ImBuf *ibuf)
237 {
238 ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
239 int x, y;
240 const uchar *src = (const uchar *)ibuf->rect;
241 uchar *tgt = (uchar *)rval->rect;
242 int w = ibuf->x + 3;
243 int sw = ibuf->x / 3;
244 int h = 515;
245 float waveform_gamma = 0.2;
246 uchar wtable[256];
247
248 wform_put_grid(tgt, w, h);
249
250 for (x = 0; x < 256; x++) {
251 wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
252 }
253
254 for (y = 0; y < ibuf->y; y++) {
255 uchar *last_p[3] = {NULL, NULL, NULL};
256
257 for (x = 0; x < ibuf->x; x++) {
258 int c;
259 const uchar *rgb = src + 4 * (ibuf->x * y + x);
260 for (c = 0; c < 3; c++) {
261 uchar *p = tgt;
262 p += 4 * (w * ((rgb[c] * (h - 3)) / 255 + 1) + c * sw + x / 3 + 1);
263
264 scope_put_pixel_single(wtable, p, c);
265 p += 4 * w;
266 scope_put_pixel_single(wtable, p, c);
267
268 if (last_p[c] != NULL) {
269 wform_put_line_single(w, last_p[c], p, c);
270 }
271 last_p[c] = p;
272 }
273 }
274 }
275
276 wform_put_border(tgt, w, h);
277
278 return rval;
279 }
280
make_sep_waveform_view_from_ibuf_float(ImBuf * ibuf)281 static ImBuf *make_sep_waveform_view_from_ibuf_float(ImBuf *ibuf)
282 {
283 ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect);
284 int x, y;
285 const float *src = ibuf->rect_float;
286 uchar *tgt = (uchar *)rval->rect;
287 int w = ibuf->x + 3;
288 int sw = ibuf->x / 3;
289 int h = 515;
290 float waveform_gamma = 0.2;
291 uchar wtable[256];
292
293 wform_put_grid(tgt, w, h);
294
295 for (x = 0; x < 256; x++) {
296 wtable[x] = (uchar)(pow(((float)x + 1) / 256, waveform_gamma) * 255);
297 }
298
299 for (y = 0; y < ibuf->y; y++) {
300 uchar *last_p[3] = {NULL, NULL, NULL};
301
302 for (x = 0; x < ibuf->x; x++) {
303 int c;
304 const float *rgb = src + 4 * (ibuf->x * y + x);
305 for (c = 0; c < 3; c++) {
306 uchar *p = tgt;
307 float v = rgb[c];
308
309 CLAMP(v, 0.0f, 1.0f);
310
311 p += 4 * (w * ((int)(v * (h - 3)) + 1) + c * sw + x / 3 + 1);
312
313 scope_put_pixel_single(wtable, p, c);
314 p += 4 * w;
315 scope_put_pixel_single(wtable, p, c);
316
317 if (last_p[c] != NULL) {
318 wform_put_line_single(w, last_p[c], p, c);
319 }
320 last_p[c] = p;
321 }
322 }
323 }
324
325 wform_put_border(tgt, w, h);
326
327 return rval;
328 }
329
make_sep_waveform_view_from_ibuf(ImBuf * ibuf)330 ImBuf *make_sep_waveform_view_from_ibuf(ImBuf *ibuf)
331 {
332 if (ibuf->rect_float) {
333 return make_sep_waveform_view_from_ibuf_float(ibuf);
334 }
335 return make_sep_waveform_view_from_ibuf_byte(ibuf);
336 }
337
draw_zebra_byte(ImBuf * src,ImBuf * ibuf,float perc)338 static void draw_zebra_byte(ImBuf *src, ImBuf *ibuf, float perc)
339 {
340 uint limit = 255.0f * perc / 100.0f;
341 uchar *p = (uchar *)src->rect;
342 uchar *o = (uchar *)ibuf->rect;
343 int x;
344 int y;
345
346 for (y = 0; y < ibuf->y; y++) {
347 for (x = 0; x < ibuf->x; x++) {
348 uchar r = *p++;
349 uchar g = *p++;
350 uchar b = *p++;
351 uchar a = *p++;
352
353 if (r >= limit || g >= limit || b >= limit) {
354 if (((x + y) & 0x08) != 0) {
355 r = 255 - r;
356 g = 255 - g;
357 b = 255 - b;
358 }
359 }
360 *o++ = r;
361 *o++ = g;
362 *o++ = b;
363 *o++ = a;
364 }
365 }
366 }
367
draw_zebra_float(ImBuf * src,ImBuf * ibuf,float perc)368 static void draw_zebra_float(ImBuf *src, ImBuf *ibuf, float perc)
369 {
370 float limit = perc / 100.0f;
371 const float *p = src->rect_float;
372 uchar *o = (uchar *)ibuf->rect;
373 int x;
374 int y;
375
376 for (y = 0; y < ibuf->y; y++) {
377 for (x = 0; x < ibuf->x; x++) {
378 float r = *p++;
379 float g = *p++;
380 float b = *p++;
381 float a = *p++;
382
383 if (r >= limit || g >= limit || b >= limit) {
384 if (((x + y) & 0x08) != 0) {
385 r = -r;
386 g = -g;
387 b = -b;
388 }
389 }
390
391 *o++ = unit_float_to_uchar_clamp(r);
392 *o++ = unit_float_to_uchar_clamp(g);
393 *o++ = unit_float_to_uchar_clamp(b);
394 *o++ = unit_float_to_uchar_clamp(a);
395 }
396 }
397 }
398
make_zebra_view_from_ibuf(ImBuf * ibuf,float perc)399 ImBuf *make_zebra_view_from_ibuf(ImBuf *ibuf, float perc)
400 {
401 ImBuf *new_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rect);
402
403 if (ibuf->rect_float) {
404 draw_zebra_float(ibuf, new_ibuf, perc);
405 }
406 else {
407 draw_zebra_byte(ibuf, new_ibuf, perc);
408 }
409 return new_ibuf;
410 }
411
draw_histogram_marker(ImBuf * ibuf,int x)412 static void draw_histogram_marker(ImBuf *ibuf, int x)
413 {
414 uchar *p = (uchar *)ibuf->rect;
415 int barh = ibuf->y * 0.1;
416
417 p += 4 * (x + ibuf->x * (ibuf->y - barh + 1));
418
419 for (int i = 0; i < barh - 1; i++) {
420 p[0] = p[1] = p[2] = 255;
421 p += ibuf->x * 4;
422 }
423 }
424
draw_histogram_bar(ImBuf * ibuf,int x,float val,int col)425 static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
426 {
427 uchar *p = (uchar *)ibuf->rect;
428 int barh = ibuf->y * val * 0.9f;
429
430 p += 4 * (x + ibuf->x);
431
432 for (int i = 0; i < barh; i++) {
433 p[col] = 255;
434 p += ibuf->x * 4;
435 }
436 }
437
438 #define HIS_STEPS 512
439
440 typedef struct MakeHistogramViewData {
441 const ImBuf *ibuf;
442 } MakeHistogramViewData;
443
make_histogram_view_from_ibuf_byte_fn(void * __restrict userdata,const int y,const TaskParallelTLS * __restrict tls)444 static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata,
445 const int y,
446 const TaskParallelTLS *__restrict tls)
447 {
448 MakeHistogramViewData *data = userdata;
449 const ImBuf *ibuf = data->ibuf;
450 const uchar *src = (uchar *)ibuf->rect;
451
452 uint32_t(*cur_bins)[HIS_STEPS] = tls->userdata_chunk;
453
454 for (int x = 0; x < ibuf->x; x++) {
455 const uchar *pixel = src + (y * ibuf->x + x) * 4;
456
457 for (int j = 3; j--;) {
458 cur_bins[j][pixel[j]]++;
459 }
460 }
461 }
462
make_histogram_view_from_ibuf_reduce(const void * __restrict UNUSED (userdata),void * __restrict chunk_join,void * __restrict chunk)463 static void make_histogram_view_from_ibuf_reduce(const void *__restrict UNUSED(userdata),
464 void *__restrict chunk_join,
465 void *__restrict chunk)
466 {
467 uint32_t(*join_bins)[HIS_STEPS] = chunk_join;
468 uint32_t(*bins)[HIS_STEPS] = chunk;
469
470 for (int j = 3; j--;) {
471 for (int i = 0; i < HIS_STEPS; i++) {
472 join_bins[j][i] += bins[j][i];
473 }
474 }
475 }
476
make_histogram_view_from_ibuf_byte(ImBuf * ibuf)477 static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
478 {
479 ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
480 int x;
481 uint nr, ng, nb;
482
483 uint bins[3][HIS_STEPS];
484
485 memset(bins, 0, sizeof(bins));
486
487 MakeHistogramViewData data = {
488 .ibuf = ibuf,
489 };
490 TaskParallelSettings settings;
491 BLI_parallel_range_settings_defaults(&settings);
492 settings.use_threading = (ibuf->y >= 256);
493 settings.userdata_chunk = bins;
494 settings.userdata_chunk_size = sizeof(bins);
495 settings.func_reduce = make_histogram_view_from_ibuf_reduce;
496 BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_fn, &settings);
497
498 nr = nb = ng = 0;
499 for (x = 0; x < HIS_STEPS; x++) {
500 if (bins[0][x] > nr) {
501 nr = bins[0][x];
502 }
503 if (bins[1][x] > ng) {
504 ng = bins[1][x];
505 }
506 if (bins[2][x] > nb) {
507 nb = bins[2][x];
508 }
509 }
510
511 for (x = 0; x < HIS_STEPS; x++) {
512 if (nr) {
513 draw_histogram_bar(rval, x * 2 + 1, ((float)bins[0][x]) / nr, 0);
514 draw_histogram_bar(rval, x * 2 + 2, ((float)bins[0][x]) / nr, 0);
515 }
516 if (ng) {
517 draw_histogram_bar(rval, x * 2 + 1, ((float)bins[1][x]) / ng, 1);
518 draw_histogram_bar(rval, x * 2 + 2, ((float)bins[1][x]) / ng, 1);
519 }
520 if (nb) {
521 draw_histogram_bar(rval, x * 2 + 1, ((float)bins[2][x]) / nb, 2);
522 draw_histogram_bar(rval, x * 2 + 2, ((float)bins[2][x]) / nb, 2);
523 }
524 }
525
526 wform_put_border((uchar *)rval->rect, rval->x, rval->y);
527
528 return rval;
529 }
530
get_bin_float(float f)531 BLI_INLINE int get_bin_float(float f)
532 {
533 if (f < -0.25f) {
534 return 0;
535 }
536 if (f >= 1.25f) {
537 return 511;
538 }
539
540 return (int)(((f + 0.25f) / 1.5f) * 512);
541 }
542
make_histogram_view_from_ibuf_float_fn(void * __restrict userdata,const int y,const TaskParallelTLS * __restrict tls)543 static void make_histogram_view_from_ibuf_float_fn(void *__restrict userdata,
544 const int y,
545 const TaskParallelTLS *__restrict tls)
546 {
547 const MakeHistogramViewData *data = userdata;
548 const ImBuf *ibuf = data->ibuf;
549 const float *src = ibuf->rect_float;
550
551 uint32_t(*cur_bins)[HIS_STEPS] = tls->userdata_chunk;
552
553 for (int x = 0; x < ibuf->x; x++) {
554 const float *pixel = src + (y * ibuf->x + x) * 4;
555
556 for (int j = 3; j--;) {
557 cur_bins[j][get_bin_float(pixel[j])]++;
558 }
559 }
560 }
561
make_histogram_view_from_ibuf_float(ImBuf * ibuf)562 static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
563 {
564 ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
565 int nr, ng, nb;
566 int x;
567
568 uint bins[3][HIS_STEPS];
569
570 memset(bins, 0, sizeof(bins));
571
572 MakeHistogramViewData data = {
573 .ibuf = ibuf,
574 };
575 TaskParallelSettings settings;
576 BLI_parallel_range_settings_defaults(&settings);
577 settings.use_threading = (ibuf->y >= 256);
578 settings.userdata_chunk = bins;
579 settings.userdata_chunk_size = sizeof(bins);
580 settings.func_reduce = make_histogram_view_from_ibuf_reduce;
581 BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_fn, &settings);
582
583 nr = nb = ng = 0;
584 for (x = 0; x < HIS_STEPS; x++) {
585 if (bins[0][x] > nr) {
586 nr = bins[0][x];
587 }
588 if (bins[1][x] > ng) {
589 ng = bins[1][x];
590 }
591 if (bins[2][x] > nb) {
592 nb = bins[2][x];
593 }
594 }
595
596 for (x = 0; x < HIS_STEPS; x++) {
597 if (nr) {
598 draw_histogram_bar(rval, x + 1, ((float)bins[0][x]) / nr, 0);
599 }
600 if (ng) {
601 draw_histogram_bar(rval, x + 1, ((float)bins[1][x]) / ng, 1);
602 }
603 if (nb) {
604 draw_histogram_bar(rval, x + 1, ((float)bins[2][x]) / nb, 2);
605 }
606 }
607
608 draw_histogram_marker(rval, get_bin_float(0.0));
609 draw_histogram_marker(rval, get_bin_float(1.0));
610 wform_put_border((uchar *)rval->rect, rval->x, rval->y);
611
612 return rval;
613 }
614
615 #undef HIS_STEPS
616
make_histogram_view_from_ibuf(ImBuf * ibuf)617 ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf)
618 {
619 if (ibuf->rect_float) {
620 return make_histogram_view_from_ibuf_float(ibuf);
621 }
622 return make_histogram_view_from_ibuf_byte(ibuf);
623 }
624
vectorscope_put_cross(uchar r,uchar g,uchar b,char * tgt,int w,int h,int size)625 static void vectorscope_put_cross(uchar r, uchar g, uchar b, char *tgt, int w, int h, int size)
626 {
627 float rgb[3], yuv[3];
628 char *p;
629 int x = 0;
630 int y = 0;
631
632 rgb[0] = (float)r / 255.0f;
633 rgb[1] = (float)g / 255.0f;
634 rgb[2] = (float)b / 255.0f;
635 rgb_to_yuv_normalized(rgb, yuv);
636
637 p = tgt + 4 * (w * (int)((yuv[2] * (h - 3) + 1)) + (int)((yuv[1] * (w - 3) + 1)));
638
639 if (r == 0 && g == 0 && b == 0) {
640 r = 255;
641 }
642
643 for (y = -size; y <= size; y++) {
644 for (x = -size; x <= size; x++) {
645 char *q = p + 4 * (y * w + x);
646 q[0] = r;
647 q[1] = g;
648 q[2] = b;
649 q[3] = 255;
650 }
651 }
652 }
653
make_vectorscope_view_from_ibuf_byte(ImBuf * ibuf)654 static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
655 {
656 ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
657 int x, y;
658 const char *src = (const char *)ibuf->rect;
659 char *tgt = (char *)rval->rect;
660 float rgb[3], yuv[3];
661 int w = 515;
662 int h = 515;
663 float scope_gamma = 0.2;
664 uchar wtable[256];
665
666 for (x = 0; x < 256; x++) {
667 wtable[x] = (uchar)(pow(((float)x + 1) / 256, scope_gamma) * 255);
668 }
669
670 for (x = 0; x < 256; x++) {
671 vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
672 vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
673 vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
674 vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
675 vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
676 vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
677 }
678
679 for (y = 0; y < ibuf->y; y++) {
680 for (x = 0; x < ibuf->x; x++) {
681 const char *src1 = src + 4 * (ibuf->x * y + x);
682 char *p;
683
684 rgb[0] = (float)src1[0] / 255.0f;
685 rgb[1] = (float)src1[1] / 255.0f;
686 rgb[2] = (float)src1[2] / 255.0f;
687 rgb_to_yuv_normalized(rgb, yuv);
688
689 p = tgt + 4 * (w * (int)((yuv[2] * (h - 3) + 1)) + (int)((yuv[1] * (w - 3) + 1)));
690 scope_put_pixel(wtable, (uchar *)p);
691 }
692 }
693
694 vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
695
696 return rval;
697 }
698
make_vectorscope_view_from_ibuf_float(ImBuf * ibuf)699 static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
700 {
701 ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
702 int x, y;
703 const float *src = ibuf->rect_float;
704 char *tgt = (char *)rval->rect;
705 float rgb[3], yuv[3];
706 int w = 515;
707 int h = 515;
708 float scope_gamma = 0.2;
709 uchar wtable[256];
710
711 for (x = 0; x < 256; x++) {
712 wtable[x] = (uchar)(pow(((float)x + 1) / 256, scope_gamma) * 255);
713 }
714
715 for (x = 0; x <= 255; x++) {
716 vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
717 vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
718 vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
719 vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
720 vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
721 vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
722 }
723
724 for (y = 0; y < ibuf->y; y++) {
725 for (x = 0; x < ibuf->x; x++) {
726 const float *src1 = src + 4 * (ibuf->x * y + x);
727 const char *p;
728
729 memcpy(rgb, src1, sizeof(float[3]));
730
731 clamp_v3(rgb, 0.0f, 1.0f);
732
733 rgb_to_yuv_normalized(rgb, yuv);
734
735 p = tgt + 4 * (w * (int)((yuv[2] * (h - 3) + 1)) + (int)((yuv[1] * (w - 3) + 1)));
736 scope_put_pixel(wtable, (uchar *)p);
737 }
738 }
739
740 vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
741
742 return rval;
743 }
744
make_vectorscope_view_from_ibuf(ImBuf * ibuf)745 ImBuf *make_vectorscope_view_from_ibuf(ImBuf *ibuf)
746 {
747 if (ibuf->rect_float) {
748 return make_vectorscope_view_from_ibuf_float(ibuf);
749 }
750 return make_vectorscope_view_from_ibuf_byte(ibuf);
751 }
752