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