Blender V4.3
stereoimbuf.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2015 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <algorithm>
10#include <cstddef>
11
12#include "IMB_imbuf.hh"
13#include "IMB_imbuf_types.hh"
14
15#include "imbuf.hh"
16
17#include "MEM_guardedalloc.h"
18
19#include "BLI_math_vector.h"
20#include "BLI_utildefines.h"
21
22#include "DNA_scene_types.h"
23#include "DNA_userdef_types.h"
24
25/* prototypes */
26struct Stereo3DData;
27static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d);
28static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d);
29
31 struct {
32 float *left, *right, *stereo;
34 struct {
37 size_t x, y, channels;
39};
40
41/* -------------------------------------------------------------------- */
46{
47 int x, y;
48 size_t width = s3d->x;
49 size_t height = s3d->y;
50 const size_t channels = s3d->channels;
51
52 const int stride_from = width;
53 const int stride_to = width;
54
55 const int anaglyph_encoding[3][3] = {
56 {0, 1, 1},
57 {1, 0, 1},
58 {0, 0, 1},
59 };
60
61 int r, g, b;
62
63 r = anaglyph_encoding[mode][0];
64 g = anaglyph_encoding[mode][1];
65 b = anaglyph_encoding[mode][2];
66
67 if (s3d->is_float) {
68 float *rect_left = s3d->rectf.left;
69 float *rect_right = s3d->rectf.right;
70 float *rect_to = s3d->rectf.stereo;
71
72 if (channels == 3) {
73 for (y = 0; y < height; y++) {
74 float *to = rect_to + stride_to * y * 3;
75 float *from[2] = {
76 rect_left + stride_from * y * 3,
77 rect_right + stride_from * y * 3,
78 };
79
80 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
81 to[0] = from[r][0];
82 to[1] = from[g][1];
83 to[2] = from[b][2];
84 }
85 }
86 }
87 else if (channels == 4) {
88 for (y = 0; y < height; y++) {
89 float *to = rect_to + stride_to * y * 4;
90 float *from[2] = {
91 rect_left + stride_from * y * 4,
92 rect_right + stride_from * y * 4,
93 };
94
95 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
96 to[0] = from[r][0];
97 to[1] = from[g][1];
98 to[2] = from[b][2];
99 to[3] = std::max(from[0][3], from[1][3]);
100 }
101 }
102 }
103 }
104 else {
105 uchar *rect_left = s3d->rect.left;
106 uchar *rect_right = s3d->rect.right;
107 uchar *rect_to = s3d->rect.stereo;
108
109 if (channels == 3) {
110 for (y = 0; y < height; y++) {
111 uchar *to = rect_to + stride_to * y * 3;
112 uchar *from[2] = {
113 rect_left + stride_from * y * 3,
114 rect_right + stride_from * y * 3,
115 };
116
117 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
118 to[0] = from[r][0];
119 to[1] = from[g][1];
120 to[2] = from[b][2];
121 }
122 }
123 }
124 else if (channels == 4) {
125 for (y = 0; y < height; y++) {
126 uchar *to = rect_to + stride_to * y * 4;
127 uchar *from[2] = {
128 rect_left + stride_from * y * 4,
129 rect_right + stride_from * y * 4,
130 };
131
132 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
133 to[0] = from[r][0];
134 to[1] = from[g][1];
135 to[2] = from[b][2];
136 to[3] = std::max(from[0][3], from[1][3]);
137 }
138 }
139 }
140 }
141}
142
144 enum eStereo3dInterlaceType mode,
145 const bool swap)
146{
147 int x, y;
148 size_t width = s3d->x;
149 size_t height = s3d->y;
150 const size_t channels = s3d->channels;
151
152 const int stride_from = width;
153 const int stride_to = width;
154
155 if (s3d->is_float) {
156 const float *rect_left = s3d->rectf.left;
157 const float *rect_right = s3d->rectf.right;
158 float *rect_to = s3d->rectf.stereo;
159
160 switch (mode) {
161 case S3D_INTERLACE_ROW: {
162 char i = char(swap);
163 for (y = 0; y < height; y++) {
164 float *to = rect_to + stride_to * y * channels;
165 const float *from[2] = {
166 rect_left + stride_from * y * channels,
167 rect_right + stride_from * y * channels,
168 };
169 memcpy(to, from[i], sizeof(float) * channels * stride_from);
170 i = !i;
171 }
172 break;
173 }
175 if (channels == 1) {
176 for (y = 0; y < height; y++) {
177 float *to = rect_to + stride_to * y;
178 const float *from[2] = {
179 rect_left + stride_from * y,
180 rect_right + stride_from * y,
181 };
182
183 char i = char(swap);
184 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
185 to[0] = from[i][0];
186 i = !i;
187 }
188 }
189 }
190 else if (channels == 3) {
191 for (y = 0; y < height; y++) {
192 float *to = rect_to + stride_to * y * 3;
193 const float *from[2] = {
194 rect_left + stride_from * y * 3,
195 rect_right + stride_from * y * 3,
196 };
197
198 char i = char(swap);
199 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
200 copy_v3_v3(to, from[i]);
201 i = !i;
202 }
203 }
204 }
205 else if (channels == 4) {
206 for (y = 0; y < height; y++) {
207 float *to = rect_to + stride_to * y * channels;
208 const float *from[2] = {
209 rect_left + stride_from * y * channels,
210 rect_right + stride_from * y * channels,
211 };
212
213 char i = char(swap);
214 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
215 copy_v4_v4(to, from[i]);
216 i = !i;
217 }
218 }
219 }
220 break;
221 }
223 if (channels == 1) {
224 char i = char(swap);
225 for (y = 0; y < height; y++) {
226 float *to = rect_to + stride_to * y;
227 const float *from[2] = {
228 rect_left + stride_from * y,
229 rect_right + stride_from * y,
230 };
231 char j = i;
232 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
233 to[0] = from[j][0];
234 j = !j;
235 }
236 i = !i;
237 }
238 }
239 else if (channels == 3) {
240 char i = char(swap);
241 for (y = 0; y < height; y++) {
242 float *to = rect_to + stride_to * y * 3;
243 const float *from[2] = {
244 rect_left + stride_from * y * 3,
245 rect_right + stride_from * y * 3,
246 };
247 char j = i;
248 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
249 copy_v3_v3(to, from[j]);
250 j = !j;
251 }
252 i = !i;
253 }
254 }
255 else if (channels == 4) {
256 char i = char(swap);
257 for (y = 0; y < height; y++) {
258 float *to = rect_to + stride_to * y * 4;
259 const float *from[2] = {
260 rect_left + stride_from * y * 4,
261 rect_right + stride_from * y * 4,
262 };
263 char j = i;
264 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
265 copy_v4_v4(to, from[j]);
266 j = !j;
267 }
268 i = !i;
269 }
270 }
271 break;
272 }
273 default: {
274 break;
275 }
276 }
277 }
278 else {
279 const uchar *rect_left = s3d->rect.left;
280 const uchar *rect_right = s3d->rect.right;
281 uchar *rect_to = s3d->rect.stereo;
282
283 switch (mode) {
284 case S3D_INTERLACE_ROW: {
285 char i = char(swap);
286 for (y = 0; y < height; y++) {
287 uchar *to = rect_to + stride_to * y * channels;
288 const uchar *from[2] = {
289 rect_left + stride_from * y * channels,
290 rect_right + stride_from * y * channels,
291 };
292 memcpy(to, from[i], sizeof(uchar) * channels * stride_from);
293 i = !i;
294 }
295 break;
296 }
298 if (channels == 1) {
299 for (y = 0; y < height; y++) {
300 uchar *to = rect_to + stride_to * y;
301 const uchar *from[2] = {
302 rect_left + stride_from * y,
303 rect_right + stride_from * y,
304 };
305 char i = char(swap);
306 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
307 to[0] = from[i][0];
308 i = !i;
309 }
310 }
311 }
312 else if (channels == 3) {
313 for (y = 0; y < height; y++) {
314 uchar *to = rect_to + stride_to * y * 3;
315 const uchar *from[2] = {
316 rect_left + stride_from * y * 3,
317 rect_right + stride_from * y * 3,
318 };
319 char i = char(swap);
320 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
321 copy_v3_v3_uchar(to, from[i]);
322 i = !i;
323 }
324 }
325 }
326 else if (channels == 4) {
327 for (y = 0; y < height; y++) {
328 uchar *to = rect_to + stride_to * y * 4;
329 const uchar *from[2] = {
330 rect_left + stride_from * y * 4,
331 rect_right + stride_from * y * 4,
332 };
333 char i = char(swap);
334 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
335 copy_v4_v4_uchar(to, from[i]);
336 i = !i;
337 }
338 }
339 }
340 break;
341 }
343 if (channels == 1) {
344 char i = char(swap);
345 for (y = 0; y < height; y++) {
346 uchar *to = rect_to + stride_to * y;
347 const uchar *from[2] = {
348 rect_left + stride_from * y,
349 rect_right + stride_from * y,
350 };
351 char j = i;
352 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
353 to[0] = from[j][0];
354 j = !j;
355 }
356 i = !i;
357 }
358 }
359 else if (channels == 3) {
360 char i = char(swap);
361 for (y = 0; y < height; y++) {
362 uchar *to = rect_to + stride_to * y * 3;
363 const uchar *from[2] = {
364 rect_left + stride_from * y * 3,
365 rect_right + stride_from * y * 3,
366 };
367 char j = i;
368 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
369 copy_v3_v3_uchar(to, from[j]);
370 j = !j;
371 }
372 i = !i;
373 }
374 }
375 else if (channels == 4) {
376 char i = char(swap);
377 for (y = 0; y < height; y++) {
378 uchar *to = rect_to + stride_to * y * 4;
379 const uchar *from[2] = {
380 rect_left + stride_from * y * 4,
381 rect_right + stride_from * y * 4,
382 };
383 char j = i;
384 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
385 copy_v4_v4_uchar(to, from[j]);
386 j = !j;
387 }
388 i = !i;
389 }
390 }
391 break;
392 }
393 default: {
394 break;
395 }
396 }
397 }
398}
399
400/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
401static void imb_stereo3d_write_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
402{
403 int y;
404 size_t width = s3d->x;
405 size_t height = s3d->y;
406 const size_t channels = s3d->channels;
407
408 const int stride_from = width;
409 const int stride_to = width * 2;
410
411 const int l = int(crosseyed);
412 const int r = !l;
413
414 if (s3d->is_float) {
415 const float *rect_left = s3d->rectf.left;
416 const float *rect_right = s3d->rectf.right;
417 float *rect_to = s3d->rectf.stereo;
418
419 for (y = 0; y < height; y++) {
420 float *to = rect_to + stride_to * y * channels;
421 const float *from[2] = {
422 rect_left + stride_from * y * channels,
423 rect_right + stride_from * y * channels,
424 };
425
426 memcpy(to, from[l], sizeof(float) * channels * stride_from);
427 memcpy(to + channels * stride_from, from[r], sizeof(float) * channels * stride_from);
428 }
429 }
430 else {
431 const uchar *rect_left = s3d->rect.left;
432 const uchar *rect_right = s3d->rect.right;
433 uchar *rect_to = s3d->rect.stereo;
434
435 for (y = 0; y < height; y++) {
436 uchar *to = rect_to + stride_to * y * channels;
437 const uchar *from[2] = {
438 rect_left + stride_from * y * channels,
439 rect_right + stride_from * y * channels,
440 };
441
442 memcpy(to, from[l], sizeof(uchar) * channels * stride_from);
443 memcpy(to + channels * stride_from, from[r], sizeof(uchar) * channels * stride_from);
444 }
445 }
446}
447
448/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
450{
451 int y;
452 size_t width = s3d->x;
453 size_t height = s3d->y;
454 const size_t channels = s3d->channels;
455
456 const int stride_from = width;
457 const int stride_to = width;
458
459 if (s3d->is_float) {
460 const float *rect_left = s3d->rectf.left;
461 const float *rect_right = s3d->rectf.right;
462 float *rect_to = s3d->rectf.stereo;
463
464 for (y = 0; y < height; y++) {
465 float *to = rect_to + stride_to * y * channels;
466 const float *from[2] = {
467 rect_left + stride_from * y * channels,
468 rect_right + stride_from * y * channels,
469 };
470
471 memcpy(to, from[1], sizeof(float) * channels * stride_from);
472 memcpy(
473 to + channels * height * stride_from, from[0], sizeof(float) * channels * stride_from);
474 }
475 }
476 else {
477 const uchar *rect_left = s3d->rect.left;
478 const uchar *rect_right = s3d->rect.right;
479 uchar *rect_to = s3d->rect.stereo;
480
481 for (y = 0; y < height; y++) {
482 uchar *to = rect_to + stride_to * y * channels;
483 const uchar *from[2] = {
484 rect_left + stride_from * y * channels,
485 rect_right + stride_from * y * channels,
486 };
487
488 memcpy(to, from[1], sizeof(uchar) * channels * stride_from);
489 memcpy(
490 to + channels * height * stride_from, from[0], sizeof(uchar) * channels * stride_from);
491 }
492 }
493}
494
497/* -------------------------------------------------------------------- */
501void IMB_stereo3d_write_dimensions(const char mode,
502 const bool is_squeezed,
503 const size_t width,
504 const size_t height,
505 size_t *r_width,
506 size_t *r_height)
507{
508 switch (mode) {
510 *r_width = is_squeezed ? width : width * 2;
511 *r_height = height;
512 break;
513 }
515 *r_width = width;
516 *r_height = is_squeezed ? height : height * 2;
517 break;
518 }
521 default: {
522 *r_width = width;
523 *r_height = height;
524 break;
525 }
526 }
527}
528
529void IMB_stereo3d_read_dimensions(const char mode,
530 const bool is_squeezed,
531 const size_t width,
532 const size_t height,
533 size_t *r_width,
534 size_t *r_height)
535{
536 switch (mode) {
538 *r_width = is_squeezed ? width / 2 : width;
539 *r_height = height;
540 break;
541 }
543 *r_width = width;
544 *r_height = is_squeezed ? height / 2 : height;
545 break;
546 }
549 default: {
550 *r_width = width;
551 *r_height = height;
552 break;
553 }
554 }
555}
556
559/* -------------------------------------------------------------------- */
564 const Stereo3dFormat *s3d,
565 const size_t x,
566 const size_t y)
567{
569 return;
570 }
571
572 if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) {
573 return;
574 }
575
577}
578
580 const Stereo3dFormat *s3d,
581 const size_t x,
582 const size_t y)
583{
585 return;
586 }
587
588 if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) {
589 return;
590 }
591
593}
594
596 float *rectf, const Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
597{
598 ImBuf *ibuf;
599 size_t width, height;
600
602 return;
603 }
604
605 if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) {
606 return;
607 }
608
609 /* creates temporary imbuf to store the rectf */
610 IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height);
611 ibuf = IMB_allocImBuf(width, height, channels, IB_rectfloat);
612
614 rectf,
615 channels,
618 false,
619 width,
620 height,
621 width,
622 width);
623
625 memcpy(rectf, ibuf->float_buffer.data, x * y * sizeof(float[4]));
626 IMB_freeImBuf(ibuf);
627}
628
630 int *rect, const Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
631{
632 ImBuf *ibuf;
633 size_t width, height;
634
636 return;
637 }
638
639 if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) {
640 return;
641 }
642
643 /* creates temporary imbuf to store the rectf */
644 IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height);
645 ibuf = IMB_allocImBuf(width, height, channels, IB_rect);
646
648 (uchar *)rect,
651 false,
652 width,
653 height,
654 width,
655 width);
656
658 memcpy(rect, ibuf->byte_buffer.data, x * y * sizeof(uint));
659 IMB_freeImBuf(ibuf);
660}
661
664/* -------------------------------------------------------------------- */
669 const bool is_float,
670 const size_t x,
671 const size_t y,
672 const size_t channels,
673 int *rect_left,
674 int *rect_right,
675 int *rect_stereo,
676 float *rectf_left,
677 float *rectf_right,
678 float *rectf_stereo)
679{
680 s3d_data->is_float = is_float;
681 s3d_data->x = x;
682 s3d_data->y = y;
683 s3d_data->channels = channels;
684 s3d_data->rect.left = (uchar *)rect_left;
685 s3d_data->rect.right = (uchar *)rect_right;
686 s3d_data->rect.stereo = (uchar *)rect_stereo;
687 s3d_data->rectf.left = rectf_left;
688 s3d_data->rectf.right = rectf_right;
689 s3d_data->rectf.stereo = rectf_stereo;
690}
691
693 const size_t x,
694 const size_t y,
695 const size_t channels,
696 int *rect_left,
697 int *rect_right)
698{
699 int *rect_result;
700 Stereo3DData s3d_data = {{nullptr}};
701 size_t width, height;
702 const bool is_float = im_format->depth > 8;
703
705 im_format->stereo3d_format.display_mode, false, x, y, &width, &height);
706 rect_result = static_cast<int *>(MEM_mallocN(channels * sizeof(int) * width * height, __func__));
707
708 imb_stereo3d_data_init(&s3d_data,
709 is_float,
710 x,
711 y,
712 channels,
713 rect_left,
714 rect_right,
715 rect_result,
716 nullptr,
717 nullptr,
718 nullptr);
719 imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
720 imb_stereo3d_squeeze_rect(rect_result, &im_format->stereo3d_format, x, y, channels);
721
722 return rect_result;
723}
724
726 const size_t x,
727 const size_t y,
728 const size_t channels,
729 float *rectf_left,
730 float *rectf_right)
731{
732 float *rectf_result;
733 Stereo3DData s3d_data = {{nullptr}};
734 size_t width, height;
735 const bool is_float = im_format->depth > 8;
736
738 im_format->stereo3d_format.display_mode, false, x, y, &width, &height);
739 rectf_result = static_cast<float *>(
740 MEM_mallocN(channels * sizeof(float) * width * height, __func__));
741
742 imb_stereo3d_data_init(&s3d_data,
743 is_float,
744 x,
745 y,
746 channels,
747 nullptr,
748 nullptr,
749 nullptr,
750 rectf_left,
751 rectf_right,
752 rectf_result);
753 imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
754 imb_stereo3d_squeeze_rectf(rectf_result, &im_format->stereo3d_format, x, y, channels);
755
756 return rectf_result;
757}
758
759ImBuf *IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
760{
761 ImBuf *ibuf_stereo = nullptr;
762 Stereo3DData s3d_data = {{nullptr}};
763 size_t width, height;
764 const bool is_float = im_format->depth > 8;
765
767 im_format->stereo3d_format.display_mode, false, ibuf_left->x, ibuf_left->y, &width, &height);
768 ibuf_stereo = IMB_allocImBuf(width, height, ibuf_left->planes, 0);
769
770 if (is_float) {
771 imb_addrectfloatImBuf(ibuf_stereo, ibuf_left->channels);
772 ibuf_stereo->float_buffer.colorspace = ibuf_left->float_buffer.colorspace;
773 }
774 else {
775 imb_addrectImBuf(ibuf_stereo);
776 ibuf_stereo->byte_buffer.colorspace = ibuf_left->byte_buffer.colorspace;
777 }
778
779 ibuf_stereo->flags = ibuf_left->flags;
780
781 imb_stereo3d_data_init(&s3d_data,
782 is_float,
783 ibuf_left->x,
784 ibuf_left->y,
785 ibuf_left->channels,
786 (int *)ibuf_left->byte_buffer.data,
787 (int *)ibuf_right->byte_buffer.data,
788 (int *)ibuf_stereo->byte_buffer.data,
789 ibuf_left->float_buffer.data,
790 ibuf_right->float_buffer.data,
791 ibuf_stereo->float_buffer.data);
792
793 imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
794 imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y);
795
796 return ibuf_stereo;
797}
798
799static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
800{
801 switch (s3d->display_mode) {
804 break;
808 (s3d->flag & S3D_INTERLACE_SWAP) != 0);
809 break;
812 break;
815 break;
816 default:
817 break;
818 }
819}
820
823/* -------------------------------------------------------------------- */
828{
829 int x, y;
830 size_t width = s3d->x;
831 size_t height = s3d->y;
832 const size_t channels = s3d->channels;
833
834 const int stride_from = width;
835 const int stride_to = width;
836
837 const int anaglyph_encoding[3][3] = {
838 {0, 1, 1},
839 {1, 0, 1},
840 {0, 0, 1},
841 };
842
843 int r, g, b;
844
845 r = anaglyph_encoding[mode][0];
846 g = anaglyph_encoding[mode][1];
847 b = anaglyph_encoding[mode][2];
848
849 if (s3d->is_float) {
850 float *rect_left = s3d->rectf.left;
851 float *rect_right = s3d->rectf.right;
852 float *rect_from = s3d->rectf.stereo;
853
854 if (channels == 3) {
855 for (y = 0; y < height; y++) {
856 float *from = rect_from + stride_from * y * 3;
857 float *to[2] = {
858 rect_left + stride_to * y * 3,
859 rect_right + stride_to * y * 3,
860 };
861
862 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
863 to[r][0] = from[0];
864 to[g][1] = from[1];
865 to[b][2] = from[2];
866 }
867 }
868 }
869 else if (channels == 4) {
870 for (y = 0; y < height; y++) {
871 float *from = rect_from + stride_from * y * 4;
872 float *to[2] = {
873 rect_left + stride_to * y * 4,
874 rect_right + stride_to * y * 4,
875 };
876
877 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
878 to[r][0] = from[0];
879 to[g][1] = from[1];
880 to[b][2] = from[2];
881 to[0][3] = to[1][3] = from[3];
882 }
883 }
884 }
885 }
886 else {
887 uchar *rect_left = s3d->rect.left;
888 uchar *rect_right = s3d->rect.right;
889 uchar *rect_from = s3d->rect.stereo;
890
891 if (channels == 3) {
892 for (y = 0; y < height; y++) {
893 uchar *from = rect_from + stride_from * y * 3;
894 uchar *to[2] = {
895 rect_left + stride_to * y * 3,
896 rect_right + stride_to * y * 3,
897 };
898
899 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
900 to[r][0] = from[0];
901 to[g][1] = from[1];
902 to[b][2] = from[2];
903 }
904 }
905 }
906 else if (channels == 4) {
907 for (y = 0; y < height; y++) {
908 uchar *from = rect_from + stride_from * y * 4;
909 uchar *to[2] = {
910 rect_left + stride_to * y * 4,
911 rect_right + stride_to * y * 4,
912 };
913
914 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
915 to[r][0] = from[0];
916 to[g][1] = from[1];
917 to[b][2] = from[2];
918 to[0][3] = to[1][3] = from[3];
919 }
920 }
921 }
922 }
923}
924
926 enum eStereo3dInterlaceType mode,
927 const bool swap)
928{
929 int x, y;
930 size_t width = s3d->x;
931 size_t height = s3d->y;
932 const size_t channels = s3d->channels;
933
934 const int stride_from = width;
935 const int stride_to = width;
936
937 if (s3d->is_float) {
938 float *rect_left = s3d->rectf.left;
939 float *rect_right = s3d->rectf.right;
940 const float *rect_from = s3d->rectf.stereo;
941
942 switch (mode) {
943 case S3D_INTERLACE_ROW: {
944 char i = char(swap);
945 for (y = 0; y < height; y++) {
946 const float *from = rect_from + stride_from * y * channels;
947 float *to[2] = {
948 rect_left + stride_to * y * channels,
949 rect_right + stride_to * y * channels,
950 };
951 memcpy(to[i], from, sizeof(float) * channels * stride_to);
952 i = !i;
953 }
954 break;
955 }
957 if (channels == 1) {
958 for (y = 0; y < height; y++) {
959 const float *from = rect_from + stride_from * y;
960 float *to[2] = {
961 rect_left + stride_to * y,
962 rect_right + stride_to * y,
963 };
964
965 char i = char(swap);
966 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
967 to[i][0] = from[0];
968 i = !i;
969 }
970 }
971 }
972 else if (channels == 3) {
973 for (y = 0; y < height; y++) {
974 const float *from = rect_from + stride_from * y * 3;
975 float *to[2] = {
976 rect_left + stride_to * y * 3,
977 rect_right + stride_to * y * 3,
978 };
979
980 char i = char(swap);
981 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
982 copy_v3_v3(to[i], from);
983 i = !i;
984 }
985 }
986 }
987 else if (channels == 4) {
988 for (y = 0; y < height; y++) {
989 const float *from = rect_from + stride_from * y * channels;
990 float *to[2] = {
991 rect_left + stride_to * y * channels,
992 rect_right + stride_to * y * channels,
993 };
994
995 char i = char(swap);
996 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
997 copy_v4_v4(to[i], from);
998 i = !i;
999 }
1000 }
1001 }
1002 break;
1003 }
1005 if (channels == 1) {
1006 char i = char(swap);
1007 for (y = 0; y < height; y++) {
1008 const float *from = rect_from + stride_from * y;
1009 float *to[2] = {
1010 rect_left + stride_to * y,
1011 rect_right + stride_to * y,
1012 };
1013 char j = i;
1014 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
1015 to[j][0] = from[0];
1016 j = !j;
1017 }
1018 i = !i;
1019 }
1020 }
1021 else if (channels == 3) {
1022 char i = char(swap);
1023 for (y = 0; y < height; y++) {
1024 const float *from = rect_from + stride_from * y * 3;
1025 float *to[2] = {
1026 rect_left + stride_to * y * 3,
1027 rect_right + stride_to * y * 3,
1028 };
1029 char j = i;
1030 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
1031 copy_v3_v3(to[j], from);
1032 j = !j;
1033 }
1034 i = !i;
1035 }
1036 }
1037 else if (channels == 4) {
1038 char i = char(swap);
1039 for (y = 0; y < height; y++) {
1040 const float *from = rect_from + stride_from * y * 4;
1041 float *to[2] = {
1042 rect_left + stride_to * y * 4,
1043 rect_right + stride_to * y * 4,
1044 };
1045 char j = i;
1046 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
1047 copy_v4_v4(to[j], from);
1048 j = !j;
1049 }
1050 i = !i;
1051 }
1052 }
1053 break;
1054 }
1055 default: {
1056 break;
1057 }
1058 }
1059 }
1060 else {
1061 uchar *rect_left = s3d->rect.right;
1062 uchar *rect_right = s3d->rect.left;
1063 const uchar *rect_from = s3d->rect.stereo;
1064
1065 switch (mode) {
1066 case S3D_INTERLACE_ROW: {
1067 char i = char(swap);
1068 for (y = 0; y < height; y++) {
1069 const uchar *from = rect_from + stride_from * y * channels;
1070 uchar *to[2] = {
1071 rect_left + stride_to * y * channels,
1072 rect_right + stride_to * y * channels,
1073 };
1074 memcpy(to[i], from, sizeof(uchar) * channels * stride_to);
1075 i = !i;
1076 }
1077 break;
1078 }
1079 case S3D_INTERLACE_COLUMN: {
1080 if (channels == 1) {
1081 for (y = 0; y < height; y++) {
1082 const uchar *from = rect_from + stride_from * y;
1083 uchar *to[2] = {
1084 rect_left + stride_to * y,
1085 rect_right + stride_to * y,
1086 };
1087 char i = char(swap);
1088 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
1089 to[i][0] = from[0];
1090 i = !i;
1091 }
1092 }
1093 }
1094 else if (channels == 3) {
1095 for (y = 0; y < height; y++) {
1096 const uchar *from = rect_from + stride_from * y * 3;
1097 uchar *to[2] = {
1098 rect_left + stride_to * y * 3,
1099 rect_right + stride_to * y * 3,
1100 };
1101 char i = char(swap);
1102 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
1103 copy_v3_v3_uchar(to[i], from);
1104 i = !i;
1105 }
1106 }
1107 }
1108 else if (channels == 4) {
1109 for (y = 0; y < height; y++) {
1110 const uchar *from = rect_from + stride_from * y * 4;
1111 uchar *to[2] = {
1112 rect_left + stride_to * y * 4,
1113 rect_right + stride_to * y * 4,
1114 };
1115 char i = char(swap);
1116 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
1117 copy_v4_v4_uchar(to[i], from);
1118 i = !i;
1119 }
1120 }
1121 }
1122 break;
1123 }
1125 if (channels == 1) {
1126 char i = char(swap);
1127 for (y = 0; y < height; y++) {
1128 const uchar *from = rect_from + stride_from * y;
1129 uchar *to[2] = {
1130 rect_left + stride_to * y,
1131 rect_right + stride_to * y,
1132 };
1133 char j = i;
1134 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
1135 to[j][0] = from[0];
1136 j = !j;
1137 }
1138 i = !i;
1139 }
1140 }
1141 else if (channels == 3) {
1142 char i = char(swap);
1143 for (y = 0; y < height; y++) {
1144 const uchar *from = rect_from + stride_from * y * 3;
1145 uchar *to[2] = {
1146 rect_left + stride_to * y * 3,
1147 rect_right + stride_to * y * 3,
1148 };
1149 char j = i;
1150 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
1151 copy_v3_v3_uchar(to[j], from);
1152 j = !j;
1153 }
1154 i = !i;
1155 }
1156 }
1157 else if (channels == 4) {
1158 char i = char(swap);
1159 for (y = 0; y < height; y++) {
1160 const uchar *from = rect_from + stride_from * y * 4;
1161 uchar *to[2] = {
1162 rect_left + stride_to * y * 4,
1163 rect_right + stride_to * y * 4,
1164 };
1165 char j = i;
1166 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
1167 copy_v4_v4_uchar(to[j], from);
1168 j = !j;
1169 }
1170 i = !i;
1171 }
1172 }
1173 break;
1174 }
1175 default: {
1176 break;
1177 }
1178 }
1179 }
1180}
1181
1182/* stereo input (s3d->rectf.stereo) is always unsqueezed */
1183static void imb_stereo3d_read_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
1184{
1185 int y;
1186 size_t width = s3d->x;
1187 size_t height = s3d->y;
1188 const size_t channels = s3d->channels;
1189
1190 const int stride_from = width * 2;
1191 const int stride_to = width;
1192
1193 const int l = int(crosseyed);
1194 const int r = !l;
1195
1196 if (s3d->is_float) {
1197 float *rect_left = s3d->rectf.left;
1198 float *rect_right = s3d->rectf.right;
1199 const float *rect_from = s3d->rectf.stereo;
1200
1201 for (y = 0; y < height; y++) {
1202 const float *from = rect_from + stride_from * y * channels;
1203 float *to[2] = {
1204 rect_left + stride_to * y * channels,
1205 rect_right + stride_to * y * channels,
1206 };
1207
1208 memcpy(to[l], from, sizeof(float) * channels * stride_to);
1209 memcpy(to[r], from + channels * stride_to, sizeof(float) * channels * stride_to);
1210 }
1211 }
1212 else {
1213 uchar *rect_left = s3d->rect.left;
1214 uchar *rect_right = s3d->rect.right;
1215 const uchar *rect_from = s3d->rect.stereo;
1216
1217 /* always RGBA input/output */
1218 for (y = 0; y < height; y++) {
1219 const uchar *from = rect_from + stride_from * y * channels;
1220 uchar *to[2] = {
1221 rect_left + stride_to * y * channels,
1222 rect_right + stride_to * y * channels,
1223 };
1224
1225 memcpy(to[l], from, sizeof(uchar) * channels * stride_to);
1226 memcpy(to[r], from + channels * stride_to, sizeof(uchar) * channels * stride_to);
1227 }
1228 }
1229}
1230
1231/* stereo input (s3d->rectf.stereo) is always unsqueezed */
1233{
1234 int y;
1235 size_t width = s3d->x;
1236 size_t height = s3d->y;
1237 const size_t channels = s3d->channels;
1238
1239 const int stride_from = width;
1240 const int stride_to = width;
1241
1242 if (s3d->is_float) {
1243 float *rect_left = s3d->rectf.left;
1244 float *rect_right = s3d->rectf.right;
1245 const float *rect_from = s3d->rectf.stereo;
1246
1247 for (y = 0; y < height; y++) {
1248 const float *from = rect_from + stride_from * y * channels;
1249 float *to[2] = {
1250 rect_left + stride_to * y * channels,
1251 rect_right + stride_to * y * channels,
1252 };
1253
1254 memcpy(to[1], from, sizeof(float) * channels * stride_to);
1255 memcpy(to[0], from + channels * height * stride_to, sizeof(float) * channels * stride_to);
1256 }
1257 }
1258 else {
1259 uchar *rect_left = s3d->rect.left;
1260 uchar *rect_right = s3d->rect.right;
1261 const uchar *rect_from = s3d->rect.stereo;
1262
1263 for (y = 0; y < height; y++) {
1264 const uchar *from = rect_from + stride_from * y * channels;
1265 uchar *to[2] = {
1266 rect_left + stride_to * y * channels,
1267 rect_right + stride_to * y * channels,
1268 };
1269
1270 memcpy(to[1], from, sizeof(uchar) * channels * stride_to);
1271 memcpy(to[0], from + channels * height * stride_to, sizeof(uchar) * channels * stride_to);
1272 }
1273 }
1274}
1275
1278/* -------------------------------------------------------------------- */
1283 ImBuf *ibuf_stereo3d,
1284 ImBuf **r_ibuf_left,
1285 ImBuf **r_ibuf_right)
1286{
1287 Stereo3DData s3d_data = {{nullptr}};
1288 ImBuf *ibuf_left, *ibuf_right;
1289 size_t width, height;
1290 const bool is_float = (ibuf_stereo3d->float_buffer.data != nullptr);
1291
1293 ((s3d->flag & S3D_SQUEEZED_FRAME) == 0),
1294 ibuf_stereo3d->x,
1295 ibuf_stereo3d->y,
1296 &width,
1297 &height);
1298
1299 ibuf_left = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, 0);
1300 ibuf_right = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, 0);
1301
1302 if (is_float) {
1303 imb_addrectfloatImBuf(ibuf_left, ibuf_stereo3d->channels);
1304 imb_addrectfloatImBuf(ibuf_right, ibuf_stereo3d->channels);
1305 }
1306 else {
1307 imb_addrectImBuf(ibuf_left);
1308 imb_addrectImBuf(ibuf_right);
1309 }
1310
1311 ibuf_left->flags = ibuf_stereo3d->flags;
1312 ibuf_right->flags = ibuf_stereo3d->flags;
1313
1314 /* we always work with unsqueezed formats */
1316 ((s3d->flag & S3D_SQUEEZED_FRAME) == 0),
1317 ibuf_stereo3d->x,
1318 ibuf_stereo3d->y,
1319 &width,
1320 &height);
1321 imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height);
1322
1323 imb_stereo3d_data_init(&s3d_data,
1324 is_float,
1325 ibuf_left->x,
1326 ibuf_left->y,
1327 ibuf_left->channels,
1328 (int *)ibuf_left->byte_buffer.data,
1329 (int *)ibuf_right->byte_buffer.data,
1330 (int *)ibuf_stereo3d->byte_buffer.data,
1331 ibuf_left->float_buffer.data,
1332 ibuf_right->float_buffer.data,
1333 ibuf_stereo3d->float_buffer.data);
1334
1335 imb_stereo3d_read_doit(&s3d_data, s3d);
1336
1337 IMB_freeImBuf(ibuf_stereo3d);
1338
1339 *r_ibuf_left = ibuf_left;
1340 *r_ibuf_right = ibuf_right;
1341}
1342
1343static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
1344{
1345 switch (s3d->display_mode) {
1348 break;
1352 (s3d->flag & S3D_INTERLACE_SWAP) != 0);
1353 break;
1356 break;
1359 break;
1360 default:
1361 break;
1362 }
1363}
1364
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned char uchar
unsigned int uint
#define ELEM(...)
eStereo3dAnaglyphType
@ S3D_SQUEEZED_FRAME
@ S3D_INTERLACE_SWAP
@ S3D_SIDEBYSIDE_CROSSEYED
@ S3D_DISPLAY_ANAGLYPH
@ S3D_DISPLAY_INTERLACE
@ S3D_DISPLAY_TOPBOTTOM
@ S3D_DISPLAY_SIDEBYSIDE
eStereo3dInterlaceType
@ S3D_INTERLACE_ROW
@ S3D_INTERLACE_COLUMN
@ S3D_INTERLACE_CHECKERBOARD
void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition divers.cc:625
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
Definition divers.cc:407
bool imb_addrectImBuf(ImBuf *ibuf, bool initialize_pixels=true)
bool IMB_scale(ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:779
bool imb_addrectfloatImBuf(ImBuf *ibuf, const unsigned int channels, bool initialize_pixels=true)
Contains defines and structs used throughout the imbuf module.
#define IB_PROFILE_SRGB
#define IB_PROFILE_LINEAR_RGB
@ IB_rectfloat
@ IB_rect
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
ATTR_WARN_UNUSED_RESULT const BMLoop * l
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
void IMB_freeImBuf(ImBuf *)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
static void imb_stereo3d_squeeze_ImBuf(ImBuf *ibuf, const Stereo3dFormat *s3d, const size_t x, const size_t y)
static void imb_stereo3d_read_interlace(const Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap)
static void imb_stereo3d_write_interlace(const Stereo3DData *s3d, enum eStereo3dInterlaceType mode, const bool swap)
static void imb_stereo3d_squeeze_rectf(float *rectf, const Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
static void imb_stereo3d_squeeze_rect(int *rect, const Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels)
static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
void IMB_ImBufFromStereo3d(const Stereo3dFormat *s3d, ImBuf *ibuf_stereo3d, ImBuf **r_ibuf_left, ImBuf **r_ibuf_right)
static void imb_stereo3d_write_anaglyph(const Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
static void imb_stereo3d_write_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
void IMB_stereo3d_write_dimensions(const char mode, const bool is_squeezed, const size_t width, const size_t height, size_t *r_width, size_t *r_height)
static void imb_stereo3d_read_anaglyph(const Stereo3DData *s3d, enum eStereo3dAnaglyphType mode)
int * IMB_stereo3d_from_rect(const ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, int *rect_left, int *rect_right)
static void imb_stereo3d_read_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
ImBuf * IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
float * IMB_stereo3d_from_rectf(const ImageFormatData *im_format, const size_t x, const size_t y, const size_t channels, float *rectf_left, float *rectf_right)
static void imb_stereo3d_data_init(Stereo3DData *s3d_data, const bool is_float, const size_t x, const size_t y, const size_t channels, int *rect_left, int *rect_right, int *rect_stereo, float *rectf_left, float *rectf_right, float *rectf_stereo)
static void imb_stereo3d_unsqueeze_ImBuf(ImBuf *ibuf, const Stereo3dFormat *s3d, const size_t x, const size_t y)
static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
void IMB_stereo3d_read_dimensions(const char mode, const bool is_squeezed, const size_t width, const size_t height, size_t *r_width, size_t *r_height)
static void imb_stereo3d_write_topbottom(const Stereo3DData *s3d)
static void imb_stereo3d_read_topbottom(const Stereo3DData *s3d)
ColorSpace * colorspace
ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
Stereo3dFormat stereo3d_format
float * right
struct Stereo3DData::@678 rect
float * stereo
struct Stereo3DData::@677 rectf
size_t channels