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