Blender V5.0
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
8
9#include <algorithm>
10#include <cstddef>
11
12#include "IMB_imbuf.hh"
13#include "IMB_imbuf_types.hh"
14
15#include "BLI_math_vector.h"
16#include "BLI_utildefines.h"
17
18#include "DNA_scene_types.h"
19
20/* prototypes */
21struct Stereo3DData;
22static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d);
23static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d);
24
26 struct {
27 float *left, *right, *stereo;
29 struct {
32 size_t x, y, channels;
34};
35
36/* -------------------------------------------------------------------- */
39
41{
42 int x, y;
43 size_t width = s3d->x;
44 size_t height = s3d->y;
45 const size_t channels = s3d->channels;
46
47 const int stride_from = width;
48 const int stride_to = width;
49
50 const int anaglyph_encoding[3][3] = {
51 {0, 1, 1},
52 {1, 0, 1},
53 {0, 0, 1},
54 };
55
56 int r, g, b;
57
58 r = anaglyph_encoding[mode][0];
59 g = anaglyph_encoding[mode][1];
60 b = anaglyph_encoding[mode][2];
61
62 if (s3d->is_float) {
63 float *rect_left = s3d->rectf.left;
64 float *rect_right = s3d->rectf.right;
65 float *rect_to = s3d->rectf.stereo;
66
67 if (channels == 3) {
68 for (y = 0; y < height; y++) {
69 float *to = rect_to + stride_to * y * 3;
70 float *from[2] = {
71 rect_left + stride_from * y * 3,
72 rect_right + stride_from * y * 3,
73 };
74
75 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
76 to[0] = from[r][0];
77 to[1] = from[g][1];
78 to[2] = from[b][2];
79 }
80 }
81 }
82 else if (channels == 4) {
83 for (y = 0; y < height; y++) {
84 float *to = rect_to + stride_to * y * 4;
85 float *from[2] = {
86 rect_left + stride_from * y * 4,
87 rect_right + stride_from * y * 4,
88 };
89
90 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
91 to[0] = from[r][0];
92 to[1] = from[g][1];
93 to[2] = from[b][2];
94 to[3] = std::max(from[0][3], from[1][3]);
95 }
96 }
97 }
98 }
99 else {
100 uchar *rect_left = s3d->rect.left;
101 uchar *rect_right = s3d->rect.right;
102 uchar *rect_to = s3d->rect.stereo;
103
104 if (channels == 3) {
105 for (y = 0; y < height; y++) {
106 uchar *to = rect_to + stride_to * y * 3;
107 uchar *from[2] = {
108 rect_left + stride_from * y * 3,
109 rect_right + stride_from * y * 3,
110 };
111
112 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
113 to[0] = from[r][0];
114 to[1] = from[g][1];
115 to[2] = from[b][2];
116 }
117 }
118 }
119 else if (channels == 4) {
120 for (y = 0; y < height; y++) {
121 uchar *to = rect_to + stride_to * y * 4;
122 uchar *from[2] = {
123 rect_left + stride_from * y * 4,
124 rect_right + stride_from * y * 4,
125 };
126
127 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
128 to[0] = from[r][0];
129 to[1] = from[g][1];
130 to[2] = from[b][2];
131 to[3] = std::max(from[0][3], from[1][3]);
132 }
133 }
134 }
135 }
136}
137
139 enum eStereo3dInterlaceType mode,
140 const bool swap)
141{
142 int x, y;
143 size_t width = s3d->x;
144 size_t height = s3d->y;
145 const size_t channels = s3d->channels;
146
147 const int stride_from = width;
148 const int stride_to = width;
149
150 if (s3d->is_float) {
151 const float *rect_left = s3d->rectf.left;
152 const float *rect_right = s3d->rectf.right;
153 float *rect_to = s3d->rectf.stereo;
154
155 switch (mode) {
156 case S3D_INTERLACE_ROW: {
157 char i = char(swap);
158 for (y = 0; y < height; y++) {
159 float *to = rect_to + stride_to * y * channels;
160 const float *from[2] = {
161 rect_left + stride_from * y * channels,
162 rect_right + stride_from * y * channels,
163 };
164 memcpy(to, from[i], sizeof(float) * channels * stride_from);
165 i = !i;
166 }
167 break;
168 }
170 if (channels == 1) {
171 for (y = 0; y < height; y++) {
172 float *to = rect_to + stride_to * y;
173 const float *from[2] = {
174 rect_left + stride_from * y,
175 rect_right + stride_from * y,
176 };
177
178 char i = char(swap);
179 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
180 to[0] = from[i][0];
181 i = !i;
182 }
183 }
184 }
185 else if (channels == 3) {
186 for (y = 0; y < height; y++) {
187 float *to = rect_to + stride_to * y * 3;
188 const float *from[2] = {
189 rect_left + stride_from * y * 3,
190 rect_right + stride_from * y * 3,
191 };
192
193 char i = char(swap);
194 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
195 copy_v3_v3(to, from[i]);
196 i = !i;
197 }
198 }
199 }
200 else if (channels == 4) {
201 for (y = 0; y < height; y++) {
202 float *to = rect_to + stride_to * y * channels;
203 const float *from[2] = {
204 rect_left + stride_from * y * channels,
205 rect_right + stride_from * y * channels,
206 };
207
208 char i = char(swap);
209 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
210 copy_v4_v4(to, from[i]);
211 i = !i;
212 }
213 }
214 }
215 break;
216 }
218 if (channels == 1) {
219 char i = char(swap);
220 for (y = 0; y < height; y++) {
221 float *to = rect_to + stride_to * y;
222 const float *from[2] = {
223 rect_left + stride_from * y,
224 rect_right + stride_from * y,
225 };
226 char j = i;
227 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
228 to[0] = from[j][0];
229 j = !j;
230 }
231 i = !i;
232 }
233 }
234 else if (channels == 3) {
235 char i = char(swap);
236 for (y = 0; y < height; y++) {
237 float *to = rect_to + stride_to * y * 3;
238 const float *from[2] = {
239 rect_left + stride_from * y * 3,
240 rect_right + stride_from * y * 3,
241 };
242 char j = i;
243 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
244 copy_v3_v3(to, from[j]);
245 j = !j;
246 }
247 i = !i;
248 }
249 }
250 else if (channels == 4) {
251 char i = char(swap);
252 for (y = 0; y < height; y++) {
253 float *to = rect_to + stride_to * y * 4;
254 const float *from[2] = {
255 rect_left + stride_from * y * 4,
256 rect_right + stride_from * y * 4,
257 };
258 char j = i;
259 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
260 copy_v4_v4(to, from[j]);
261 j = !j;
262 }
263 i = !i;
264 }
265 }
266 break;
267 }
268 default: {
269 break;
270 }
271 }
272 }
273 else {
274 const uchar *rect_left = s3d->rect.left;
275 const uchar *rect_right = s3d->rect.right;
276 uchar *rect_to = s3d->rect.stereo;
277
278 switch (mode) {
279 case S3D_INTERLACE_ROW: {
280 char i = char(swap);
281 for (y = 0; y < height; y++) {
282 uchar *to = rect_to + stride_to * y * channels;
283 const uchar *from[2] = {
284 rect_left + stride_from * y * channels,
285 rect_right + stride_from * y * channels,
286 };
287 memcpy(to, from[i], sizeof(uchar) * channels * stride_from);
288 i = !i;
289 }
290 break;
291 }
293 if (channels == 1) {
294 for (y = 0; y < height; y++) {
295 uchar *to = rect_to + stride_to * y;
296 const uchar *from[2] = {
297 rect_left + stride_from * y,
298 rect_right + stride_from * y,
299 };
300 char i = char(swap);
301 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
302 to[0] = from[i][0];
303 i = !i;
304 }
305 }
306 }
307 else if (channels == 3) {
308 for (y = 0; y < height; y++) {
309 uchar *to = rect_to + stride_to * y * 3;
310 const uchar *from[2] = {
311 rect_left + stride_from * y * 3,
312 rect_right + stride_from * y * 3,
313 };
314 char i = char(swap);
315 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
316 copy_v3_v3_uchar(to, from[i]);
317 i = !i;
318 }
319 }
320 }
321 else if (channels == 4) {
322 for (y = 0; y < height; y++) {
323 uchar *to = rect_to + stride_to * y * 4;
324 const uchar *from[2] = {
325 rect_left + stride_from * y * 4,
326 rect_right + stride_from * y * 4,
327 };
328 char i = char(swap);
329 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
330 copy_v4_v4_uchar(to, from[i]);
331 i = !i;
332 }
333 }
334 }
335 break;
336 }
338 if (channels == 1) {
339 char i = char(swap);
340 for (y = 0; y < height; y++) {
341 uchar *to = rect_to + stride_to * y;
342 const uchar *from[2] = {
343 rect_left + stride_from * y,
344 rect_right + stride_from * y,
345 };
346 char j = i;
347 for (x = 0; x < width; x++, from[0] += 1, from[1] += 1, to += 1) {
348 to[0] = from[j][0];
349 j = !j;
350 }
351 i = !i;
352 }
353 }
354 else if (channels == 3) {
355 char i = char(swap);
356 for (y = 0; y < height; y++) {
357 uchar *to = rect_to + stride_to * y * 3;
358 const uchar *from[2] = {
359 rect_left + stride_from * y * 3,
360 rect_right + stride_from * y * 3,
361 };
362 char j = i;
363 for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
364 copy_v3_v3_uchar(to, from[j]);
365 j = !j;
366 }
367 i = !i;
368 }
369 }
370 else if (channels == 4) {
371 char i = char(swap);
372 for (y = 0; y < height; y++) {
373 uchar *to = rect_to + stride_to * y * 4;
374 const uchar *from[2] = {
375 rect_left + stride_from * y * 4,
376 rect_right + stride_from * y * 4,
377 };
378 char j = i;
379 for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
380 copy_v4_v4_uchar(to, from[j]);
381 j = !j;
382 }
383 i = !i;
384 }
385 }
386 break;
387 }
388 default: {
389 break;
390 }
391 }
392 }
393}
394
395/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
396static void imb_stereo3d_write_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
397{
398 int y;
399 size_t width = s3d->x;
400 size_t height = s3d->y;
401 const size_t channels = s3d->channels;
402
403 const int stride_from = width;
404 const int stride_to = width * 2;
405
406 const int l = int(crosseyed);
407 const int r = !l;
408
409 if (s3d->is_float) {
410 const float *rect_left = s3d->rectf.left;
411 const float *rect_right = s3d->rectf.right;
412 float *rect_to = s3d->rectf.stereo;
413
414 for (y = 0; y < height; y++) {
415 float *to = rect_to + stride_to * y * channels;
416 const float *from[2] = {
417 rect_left + stride_from * y * channels,
418 rect_right + stride_from * y * channels,
419 };
420
421 memcpy(to, from[l], sizeof(float) * channels * stride_from);
422 memcpy(to + channels * stride_from, from[r], sizeof(float) * channels * stride_from);
423 }
424 }
425 else {
426 const uchar *rect_left = s3d->rect.left;
427 const uchar *rect_right = s3d->rect.right;
428 uchar *rect_to = s3d->rect.stereo;
429
430 for (y = 0; y < height; y++) {
431 uchar *to = rect_to + stride_to * y * channels;
432 const uchar *from[2] = {
433 rect_left + stride_from * y * channels,
434 rect_right + stride_from * y * channels,
435 };
436
437 memcpy(to, from[l], sizeof(uchar) * channels * stride_from);
438 memcpy(to + channels * stride_from, from[r], sizeof(uchar) * channels * stride_from);
439 }
440 }
441}
442
443/* stereo3d output (s3d->rectf.stereo) is always unsqueezed */
445{
446 int y;
447 size_t width = s3d->x;
448 size_t height = s3d->y;
449 const size_t channels = s3d->channels;
450
451 const int stride_from = width;
452 const int stride_to = width;
453
454 if (s3d->is_float) {
455 const float *rect_left = s3d->rectf.left;
456 const float *rect_right = s3d->rectf.right;
457 float *rect_to = s3d->rectf.stereo;
458
459 for (y = 0; y < height; y++) {
460 float *to = rect_to + stride_to * y * channels;
461 const float *from[2] = {
462 rect_left + stride_from * y * channels,
463 rect_right + stride_from * y * channels,
464 };
465
466 memcpy(to, from[1], sizeof(float) * channels * stride_from);
467 memcpy(
468 to + channels * height * stride_from, from[0], sizeof(float) * channels * stride_from);
469 }
470 }
471 else {
472 const uchar *rect_left = s3d->rect.left;
473 const uchar *rect_right = s3d->rect.right;
474 uchar *rect_to = s3d->rect.stereo;
475
476 for (y = 0; y < height; y++) {
477 uchar *to = rect_to + stride_to * y * channels;
478 const uchar *from[2] = {
479 rect_left + stride_from * y * channels,
480 rect_right + stride_from * y * channels,
481 };
482
483 memcpy(to, from[1], sizeof(uchar) * channels * stride_from);
484 memcpy(
485 to + channels * height * stride_from, from[0], sizeof(uchar) * channels * stride_from);
486 }
487 }
488}
489
491
492/* -------------------------------------------------------------------- */
495
496void IMB_stereo3d_write_dimensions(const char mode,
497 const bool is_squeezed,
498 const size_t width,
499 const size_t height,
500 size_t *r_width,
501 size_t *r_height)
502{
503 switch (mode) {
505 *r_width = is_squeezed ? width : width * 2;
506 *r_height = height;
507 break;
508 }
510 *r_width = width;
511 *r_height = is_squeezed ? height : height * 2;
512 break;
513 }
516 default: {
517 *r_width = width;
518 *r_height = height;
519 break;
520 }
521 }
522}
523
524void IMB_stereo3d_read_dimensions(const char mode,
525 const bool is_squeezed,
526 const size_t width,
527 const size_t height,
528 size_t *r_width,
529 size_t *r_height)
530{
531 switch (mode) {
533 *r_width = is_squeezed ? width / 2 : width;
534 *r_height = height;
535 break;
536 }
538 *r_width = width;
539 *r_height = is_squeezed ? height / 2 : height;
540 break;
541 }
544 default: {
545 *r_width = width;
546 *r_height = height;
547 break;
548 }
549 }
550}
551
553
554/* -------------------------------------------------------------------- */
557
559 const Stereo3dFormat *s3d,
560 const size_t x,
561 const size_t y)
562{
564 return;
565 }
566
567 if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) {
568 return;
569 }
570
572}
573
575 const Stereo3dFormat *s3d,
576 const size_t x,
577 const size_t y)
578{
580 return;
581 }
582
583 if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) {
584 return;
585 }
586
588}
589
591
592/* -------------------------------------------------------------------- */
595
597 const bool is_float,
598 const size_t x,
599 const size_t y,
600 const size_t channels,
601 int *rect_left,
602 int *rect_right,
603 int *rect_stereo,
604 float *rectf_left,
605 float *rectf_right,
606 float *rectf_stereo)
607{
608 s3d_data->is_float = is_float;
609 s3d_data->x = x;
610 s3d_data->y = y;
611 s3d_data->channels = channels;
612 s3d_data->rect.left = (uchar *)rect_left;
613 s3d_data->rect.right = (uchar *)rect_right;
614 s3d_data->rect.stereo = (uchar *)rect_stereo;
615 s3d_data->rectf.left = rectf_left;
616 s3d_data->rectf.right = rectf_right;
617 s3d_data->rectf.stereo = rectf_stereo;
618}
619
620ImBuf *IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right)
621{
622 ImBuf *ibuf_stereo = nullptr;
623 Stereo3DData s3d_data = {{nullptr}};
624 size_t width, height;
625 const bool is_byte = ibuf_left->byte_buffer.data && ibuf_right->byte_buffer.data;
626 const bool is_float = ibuf_left->float_buffer.data && ibuf_right->float_buffer.data &&
627 !(is_byte && im_format->depth <= 8);
628
629 if (!(is_float || is_byte)) {
630 return nullptr;
631 }
632
634 im_format->stereo3d_format.display_mode, false, ibuf_left->x, ibuf_left->y, &width, &height);
635 ibuf_stereo = IMB_allocImBuf(width, height, ibuf_left->planes, 0);
636
637 if (is_float) {
638 IMB_alloc_float_pixels(ibuf_stereo, ibuf_left->channels);
639 ibuf_stereo->float_buffer.colorspace = ibuf_left->float_buffer.colorspace;
640 }
641 else {
642 IMB_alloc_byte_pixels(ibuf_stereo);
643 ibuf_stereo->byte_buffer.colorspace = ibuf_left->byte_buffer.colorspace;
644 }
645
646 ibuf_stereo->flags = ibuf_left->flags;
647
648 imb_stereo3d_data_init(&s3d_data,
649 is_float,
650 ibuf_left->x,
651 ibuf_left->y,
652 ibuf_left->channels,
653 (int *)ibuf_left->byte_buffer.data,
654 (int *)ibuf_right->byte_buffer.data,
655 (int *)ibuf_stereo->byte_buffer.data,
656 ibuf_left->float_buffer.data,
657 ibuf_right->float_buffer.data,
658 ibuf_stereo->float_buffer.data);
659
660 imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format);
661 imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y);
662
663 return ibuf_stereo;
664}
665
666static void imb_stereo3d_write_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
667{
668 switch (s3d->display_mode) {
671 break;
675 (s3d->flag & S3D_INTERLACE_SWAP) != 0);
676 break;
679 break;
682 break;
683 default:
684 break;
685 }
686}
687
689
690/* -------------------------------------------------------------------- */
693
695{
696 int x, y;
697 size_t width = s3d->x;
698 size_t height = s3d->y;
699 const size_t channels = s3d->channels;
700
701 const int stride_from = width;
702 const int stride_to = width;
703
704 const int anaglyph_encoding[3][3] = {
705 {0, 1, 1},
706 {1, 0, 1},
707 {0, 0, 1},
708 };
709
710 int r, g, b;
711
712 r = anaglyph_encoding[mode][0];
713 g = anaglyph_encoding[mode][1];
714 b = anaglyph_encoding[mode][2];
715
716 if (s3d->is_float) {
717 float *rect_left = s3d->rectf.left;
718 float *rect_right = s3d->rectf.right;
719 float *rect_from = s3d->rectf.stereo;
720
721 if (channels == 3) {
722 for (y = 0; y < height; y++) {
723 float *from = rect_from + stride_from * y * 3;
724 float *to[2] = {
725 rect_left + stride_to * y * 3,
726 rect_right + stride_to * y * 3,
727 };
728
729 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
730 to[r][0] = from[0];
731 to[g][1] = from[1];
732 to[b][2] = from[2];
733 }
734 }
735 }
736 else if (channels == 4) {
737 for (y = 0; y < height; y++) {
738 float *from = rect_from + stride_from * y * 4;
739 float *to[2] = {
740 rect_left + stride_to * y * 4,
741 rect_right + stride_to * y * 4,
742 };
743
744 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
745 to[r][0] = from[0];
746 to[g][1] = from[1];
747 to[b][2] = from[2];
748 to[0][3] = to[1][3] = from[3];
749 }
750 }
751 }
752 }
753 else {
754 uchar *rect_left = s3d->rect.left;
755 uchar *rect_right = s3d->rect.right;
756 uchar *rect_from = s3d->rect.stereo;
757
758 if (channels == 3) {
759 for (y = 0; y < height; y++) {
760 uchar *from = rect_from + stride_from * y * 3;
761 uchar *to[2] = {
762 rect_left + stride_to * y * 3,
763 rect_right + stride_to * y * 3,
764 };
765
766 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
767 to[r][0] = from[0];
768 to[g][1] = from[1];
769 to[b][2] = from[2];
770 }
771 }
772 }
773 else if (channels == 4) {
774 for (y = 0; y < height; y++) {
775 uchar *from = rect_from + stride_from * y * 4;
776 uchar *to[2] = {
777 rect_left + stride_to * y * 4,
778 rect_right + stride_to * y * 4,
779 };
780
781 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
782 to[r][0] = from[0];
783 to[g][1] = from[1];
784 to[b][2] = from[2];
785 to[0][3] = to[1][3] = from[3];
786 }
787 }
788 }
789 }
790}
791
793 enum eStereo3dInterlaceType mode,
794 const bool swap)
795{
796 int x, y;
797 size_t width = s3d->x;
798 size_t height = s3d->y;
799 const size_t channels = s3d->channels;
800
801 const int stride_from = width;
802 const int stride_to = width;
803
804 if (s3d->is_float) {
805 float *rect_left = s3d->rectf.left;
806 float *rect_right = s3d->rectf.right;
807 const float *rect_from = s3d->rectf.stereo;
808
809 switch (mode) {
810 case S3D_INTERLACE_ROW: {
811 char i = char(swap);
812 for (y = 0; y < height; y++) {
813 const float *from = rect_from + stride_from * y * channels;
814 float *to[2] = {
815 rect_left + stride_to * y * channels,
816 rect_right + stride_to * y * channels,
817 };
818 memcpy(to[i], from, sizeof(float) * channels * stride_to);
819 i = !i;
820 }
821 break;
822 }
824 if (channels == 1) {
825 for (y = 0; y < height; y++) {
826 const float *from = rect_from + stride_from * y;
827 float *to[2] = {
828 rect_left + stride_to * y,
829 rect_right + stride_to * y,
830 };
831
832 char i = char(swap);
833 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
834 to[i][0] = from[0];
835 i = !i;
836 }
837 }
838 }
839 else if (channels == 3) {
840 for (y = 0; y < height; y++) {
841 const float *from = rect_from + stride_from * y * 3;
842 float *to[2] = {
843 rect_left + stride_to * y * 3,
844 rect_right + stride_to * y * 3,
845 };
846
847 char i = char(swap);
848 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
849 copy_v3_v3(to[i], from);
850 i = !i;
851 }
852 }
853 }
854 else if (channels == 4) {
855 for (y = 0; y < height; y++) {
856 const float *from = rect_from + stride_from * y * channels;
857 float *to[2] = {
858 rect_left + stride_to * y * channels,
859 rect_right + stride_to * y * channels,
860 };
861
862 char i = char(swap);
863 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
864 copy_v4_v4(to[i], from);
865 i = !i;
866 }
867 }
868 }
869 break;
870 }
872 if (channels == 1) {
873 char i = char(swap);
874 for (y = 0; y < height; y++) {
875 const float *from = rect_from + stride_from * y;
876 float *to[2] = {
877 rect_left + stride_to * y,
878 rect_right + stride_to * y,
879 };
880 char j = i;
881 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
882 to[j][0] = from[0];
883 j = !j;
884 }
885 i = !i;
886 }
887 }
888 else if (channels == 3) {
889 char i = char(swap);
890 for (y = 0; y < height; y++) {
891 const float *from = rect_from + stride_from * y * 3;
892 float *to[2] = {
893 rect_left + stride_to * y * 3,
894 rect_right + stride_to * y * 3,
895 };
896 char j = i;
897 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
898 copy_v3_v3(to[j], from);
899 j = !j;
900 }
901 i = !i;
902 }
903 }
904 else if (channels == 4) {
905 char i = char(swap);
906 for (y = 0; y < height; y++) {
907 const float *from = rect_from + stride_from * y * 4;
908 float *to[2] = {
909 rect_left + stride_to * y * 4,
910 rect_right + stride_to * y * 4,
911 };
912 char j = i;
913 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
914 copy_v4_v4(to[j], from);
915 j = !j;
916 }
917 i = !i;
918 }
919 }
920 break;
921 }
922 default: {
923 break;
924 }
925 }
926 }
927 else {
928 uchar *rect_left = s3d->rect.right;
929 uchar *rect_right = s3d->rect.left;
930 const uchar *rect_from = s3d->rect.stereo;
931
932 switch (mode) {
933 case S3D_INTERLACE_ROW: {
934 char i = char(swap);
935 for (y = 0; y < height; y++) {
936 const uchar *from = rect_from + stride_from * y * channels;
937 uchar *to[2] = {
938 rect_left + stride_to * y * channels,
939 rect_right + stride_to * y * channels,
940 };
941 memcpy(to[i], from, sizeof(uchar) * channels * stride_to);
942 i = !i;
943 }
944 break;
945 }
947 if (channels == 1) {
948 for (y = 0; y < height; y++) {
949 const uchar *from = rect_from + stride_from * y;
950 uchar *to[2] = {
951 rect_left + stride_to * y,
952 rect_right + stride_to * y,
953 };
954 char i = char(swap);
955 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
956 to[i][0] = from[0];
957 i = !i;
958 }
959 }
960 }
961 else if (channels == 3) {
962 for (y = 0; y < height; y++) {
963 const uchar *from = rect_from + stride_from * y * 3;
964 uchar *to[2] = {
965 rect_left + stride_to * y * 3,
966 rect_right + stride_to * y * 3,
967 };
968 char i = char(swap);
969 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
970 copy_v3_v3_uchar(to[i], from);
971 i = !i;
972 }
973 }
974 }
975 else if (channels == 4) {
976 for (y = 0; y < height; y++) {
977 const uchar *from = rect_from + stride_from * y * 4;
978 uchar *to[2] = {
979 rect_left + stride_to * y * 4,
980 rect_right + stride_to * y * 4,
981 };
982 char i = char(swap);
983 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
984 copy_v4_v4_uchar(to[i], from);
985 i = !i;
986 }
987 }
988 }
989 break;
990 }
992 if (channels == 1) {
993 char i = char(swap);
994 for (y = 0; y < height; y++) {
995 const uchar *from = rect_from + stride_from * y;
996 uchar *to[2] = {
997 rect_left + stride_to * y,
998 rect_right + stride_to * y,
999 };
1000 char j = i;
1001 for (x = 0; x < width; x++, from += 1, to[0] += 1, to[1] += 1) {
1002 to[j][0] = from[0];
1003 j = !j;
1004 }
1005 i = !i;
1006 }
1007 }
1008 else if (channels == 3) {
1009 char i = char(swap);
1010 for (y = 0; y < height; y++) {
1011 const uchar *from = rect_from + stride_from * y * 3;
1012 uchar *to[2] = {
1013 rect_left + stride_to * y * 3,
1014 rect_right + stride_to * y * 3,
1015 };
1016 char j = i;
1017 for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
1018 copy_v3_v3_uchar(to[j], from);
1019 j = !j;
1020 }
1021 i = !i;
1022 }
1023 }
1024 else if (channels == 4) {
1025 char i = char(swap);
1026 for (y = 0; y < height; y++) {
1027 const uchar *from = rect_from + stride_from * y * 4;
1028 uchar *to[2] = {
1029 rect_left + stride_to * y * 4,
1030 rect_right + stride_to * y * 4,
1031 };
1032 char j = i;
1033 for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
1034 copy_v4_v4_uchar(to[j], from);
1035 j = !j;
1036 }
1037 i = !i;
1038 }
1039 }
1040 break;
1041 }
1042 default: {
1043 break;
1044 }
1045 }
1046 }
1047}
1048
1049/* stereo input (s3d->rectf.stereo) is always unsqueezed */
1050static void imb_stereo3d_read_sidebyside(const Stereo3DData *s3d, const bool crosseyed)
1051{
1052 int y;
1053 size_t width = s3d->x;
1054 size_t height = s3d->y;
1055 const size_t channels = s3d->channels;
1056
1057 const int stride_from = width * 2;
1058 const int stride_to = width;
1059
1060 const int l = int(crosseyed);
1061 const int r = !l;
1062
1063 if (s3d->is_float) {
1064 float *rect_left = s3d->rectf.left;
1065 float *rect_right = s3d->rectf.right;
1066 const float *rect_from = s3d->rectf.stereo;
1067
1068 for (y = 0; y < height; y++) {
1069 const float *from = rect_from + stride_from * y * channels;
1070 float *to[2] = {
1071 rect_left + stride_to * y * channels,
1072 rect_right + stride_to * y * channels,
1073 };
1074
1075 memcpy(to[l], from, sizeof(float) * channels * stride_to);
1076 memcpy(to[r], from + channels * stride_to, sizeof(float) * channels * stride_to);
1077 }
1078 }
1079 else {
1080 uchar *rect_left = s3d->rect.left;
1081 uchar *rect_right = s3d->rect.right;
1082 const uchar *rect_from = s3d->rect.stereo;
1083
1084 /* always RGBA input/output */
1085 for (y = 0; y < height; y++) {
1086 const uchar *from = rect_from + stride_from * y * channels;
1087 uchar *to[2] = {
1088 rect_left + stride_to * y * channels,
1089 rect_right + stride_to * y * channels,
1090 };
1091
1092 memcpy(to[l], from, sizeof(uchar) * channels * stride_to);
1093 memcpy(to[r], from + channels * stride_to, sizeof(uchar) * channels * stride_to);
1094 }
1095 }
1096}
1097
1098/* stereo input (s3d->rectf.stereo) is always unsqueezed */
1100{
1101 int y;
1102 size_t width = s3d->x;
1103 size_t height = s3d->y;
1104 const size_t channels = s3d->channels;
1105
1106 const int stride_from = width;
1107 const int stride_to = width;
1108
1109 if (s3d->is_float) {
1110 float *rect_left = s3d->rectf.left;
1111 float *rect_right = s3d->rectf.right;
1112 const float *rect_from = s3d->rectf.stereo;
1113
1114 for (y = 0; y < height; y++) {
1115 const float *from = rect_from + stride_from * y * channels;
1116 float *to[2] = {
1117 rect_left + stride_to * y * channels,
1118 rect_right + stride_to * y * channels,
1119 };
1120
1121 memcpy(to[1], from, sizeof(float) * channels * stride_to);
1122 memcpy(to[0], from + channels * height * stride_to, sizeof(float) * channels * stride_to);
1123 }
1124 }
1125 else {
1126 uchar *rect_left = s3d->rect.left;
1127 uchar *rect_right = s3d->rect.right;
1128 const uchar *rect_from = s3d->rect.stereo;
1129
1130 for (y = 0; y < height; y++) {
1131 const uchar *from = rect_from + stride_from * y * channels;
1132 uchar *to[2] = {
1133 rect_left + stride_to * y * channels,
1134 rect_right + stride_to * y * channels,
1135 };
1136
1137 memcpy(to[1], from, sizeof(uchar) * channels * stride_to);
1138 memcpy(to[0], from + channels * height * stride_to, sizeof(uchar) * channels * stride_to);
1139 }
1140 }
1141}
1142
1144
1145/* -------------------------------------------------------------------- */
1148
1150 ImBuf *ibuf_stereo3d,
1151 ImBuf **r_ibuf_left,
1152 ImBuf **r_ibuf_right)
1153{
1154 Stereo3DData s3d_data = {{nullptr}};
1155 ImBuf *ibuf_left, *ibuf_right;
1156 size_t width, height;
1157 const bool is_float = (ibuf_stereo3d->float_buffer.data != nullptr);
1158
1160 ((s3d->flag & S3D_SQUEEZED_FRAME) == 0),
1161 ibuf_stereo3d->x,
1162 ibuf_stereo3d->y,
1163 &width,
1164 &height);
1165
1166 ibuf_left = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, 0);
1167 ibuf_right = IMB_allocImBuf(width, height, ibuf_stereo3d->planes, 0);
1168
1169 if (is_float) {
1170 IMB_alloc_float_pixels(ibuf_left, ibuf_stereo3d->channels);
1171 IMB_alloc_float_pixels(ibuf_right, ibuf_stereo3d->channels);
1172 }
1173 else {
1174 IMB_alloc_byte_pixels(ibuf_left);
1175 IMB_alloc_byte_pixels(ibuf_right);
1176 }
1177
1178 ibuf_left->flags = ibuf_stereo3d->flags;
1179 ibuf_right->flags = ibuf_stereo3d->flags;
1180
1181 /* we always work with unsqueezed formats */
1183 ((s3d->flag & S3D_SQUEEZED_FRAME) == 0),
1184 ibuf_stereo3d->x,
1185 ibuf_stereo3d->y,
1186 &width,
1187 &height);
1188 imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height);
1189
1190 imb_stereo3d_data_init(&s3d_data,
1191 is_float,
1192 ibuf_left->x,
1193 ibuf_left->y,
1194 ibuf_left->channels,
1195 (int *)ibuf_left->byte_buffer.data,
1196 (int *)ibuf_right->byte_buffer.data,
1197 (int *)ibuf_stereo3d->byte_buffer.data,
1198 ibuf_left->float_buffer.data,
1199 ibuf_right->float_buffer.data,
1200 ibuf_stereo3d->float_buffer.data);
1201
1202 imb_stereo3d_read_doit(&s3d_data, s3d);
1203
1204 IMB_freeImBuf(ibuf_stereo3d);
1205
1206 *r_ibuf_left = ibuf_left;
1207 *r_ibuf_right = ibuf_right;
1208}
1209
1210static void imb_stereo3d_read_doit(Stereo3DData *s3d_data, const Stereo3dFormat *s3d)
1211{
1212 switch (s3d->display_mode) {
1215 break;
1219 (s3d->flag & S3D_INTERLACE_SWAP) != 0);
1220 break;
1223 break;
1226 break;
1227 default:
1228 break;
1229 }
1230}
1231
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
#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
bool IMB_alloc_byte_pixels(ImBuf *ibuf, bool initialize_pixels=true)
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
bool IMB_alloc_float_pixels(ImBuf *ibuf, const unsigned int channels, bool initialize_pixels=true)
bool IMB_scale(ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:465
ATTR_WARN_UNUSED_RESULT const BMLoop * l
#define swap(a, b)
Definition sort.cc:59
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_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)
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)
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)
const ColorSpace * colorspace
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
Stereo3dFormat stereo3d_format
float * right
struct Stereo3DData::@363160034305141071371165026206172015102252241336 rect
struct Stereo3DData::@121156067217161233333254230355172316377216147166 rectf
float * stereo
size_t channels
i
Definition text_draw.cc:230