1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * This file is part of openfx-supportext <https://github.com/devernay/openfx-supportext>,
4 * Copyright (C) 2013-2018 INRIA
5 *
6 * openfx-supportext is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * openfx-supportext is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with openfx-supportext. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
18 * ***** END LICENSE BLOCK ***** */
19
20 //
21 // ofxsCopier.h
22 //
23
24 #ifndef IO_ofxsCopier_h
25 #define IO_ofxsCopier_h
26
27 #include <cstring>
28 #include <algorithm>
29
30 #include "ofxsPixelProcessor.h"
31 #include "ofxsMaskMix.h"
32
33 namespace OFX {
34 // Base class for the RGBA and the Alpha processor
35
36 template <class PIX, int nComponents>
37 class PixelCopier
38 : public OFX::PixelProcessorFilterBase
39 {
40 public:
41 // ctor
PixelCopier(OFX::ImageEffect & instance)42 PixelCopier(OFX::ImageEffect &instance)
43 : OFX::PixelProcessorFilterBase(instance)
44 {
45 }
46
47 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)48 void multiThreadProcessImages(OfxRectI procWindow)
49 {
50 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
51 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
52 if (_dstBounds.x1 > procWindow.x1) {
53 procWindow.x1 = _dstBounds.x1;
54 }
55 if (_dstBounds.x2 < procWindow.x2) {
56 procWindow.x2 = _dstBounds.x2;
57 }
58 if (_dstBounds.y1 > procWindow.y1) {
59 procWindow.y1 = _dstBounds.y1;
60 }
61 if (_dstBounds.y2 < procWindow.y2) {
62 procWindow.y2 = _dstBounds.y2;
63 }
64
65 int rowBytes = sizeof(PIX) * nComponents * (procWindow.x2 - procWindow.x1);
66
67 for (int dsty = procWindow.y1; dsty < procWindow.y2; ++dsty) {
68 if ( _effect.abort() ) {
69 break;
70 }
71
72 PIX *dstPix = (PIX *) getDstPixelAddress(procWindow.x1, dsty);
73 assert(dstPix);
74 if (!dstPix) {
75 // coverity[dead_error_line]
76 continue;
77 }
78
79 int srcy = dsty;
80
81 if (_srcBoundary == 1) {
82 if (_srcBounds.y2 <= srcy) {
83 srcy = _srcBounds.y2 - 1;
84 }
85 if (srcy < _srcBounds.y1) {
86 srcy = _srcBounds.y1;
87 }
88 } else if (_srcBoundary == 2) {
89 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) ) {
90 srcy = _srcBounds.y1 + positive_modulo(srcy - _srcBounds.y1, _srcBounds.y2 - _srcBounds.y1);
91 }
92 }
93
94 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) || (_srcBounds.y2 <= _srcBounds.y1) ) {
95 assert(_srcBoundary == 0);
96 std::memset(dstPix, 0, rowBytes);
97 } else {
98 int x1 = (std::max)(_srcBounds.x1, procWindow.x1);
99 int x2 = (std::min)(_srcBounds.x2, procWindow.x2);
100 // start of line may be black
101 if (procWindow.x1 < x1) {
102 if ( (_srcBoundary != 1) && (_srcBoundary != 2) ) {
103 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (x1 - procWindow.x1) );
104 dstPix += nComponents * (x1 - procWindow.x1);
105 } else if (_srcBoundary == 1) {
106 const PIX *srcPix = (const PIX *) getSrcPixelAddress(x1, srcy);
107 assert(srcPix);
108 if (!srcPix) {
109 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (x1 - procWindow.x1) );
110 dstPix += nComponents * (x1 - procWindow.x1);
111 } else {
112 # ifdef DEBUG
113 for (int c = 0; c < nComponents; ++c) {
114 assert( !OFX::IsNaN(srcPix[c]) ); // check for NaN
115 }
116 # endif
117 for (int x = procWindow.x1; x < x1; ++x) {
118 std::copy(srcPix, srcPix + nComponents, dstPix);
119 dstPix += nComponents;
120 }
121 }
122 } else if (_srcBoundary == 2) {
123 int srcx = procWindow.x1;
124 if ( (srcx < _srcBounds.x1) || (_srcBounds.x2 <= srcx) ) {
125 srcx = _srcBounds.x1 + positive_modulo(srcx - _srcBounds.x1, _srcBounds.x2 - _srcBounds.x1);
126 }
127
128 const PIX *srcPix = (const PIX *) getSrcPixelAddress(srcx, srcy);
129 assert(srcPix);
130 if (!srcPix) {
131 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (x1 - procWindow.x1) );
132 dstPix += nComponents * (x1 - procWindow.x1);
133 } else {
134 for (int x = procWindow.x1; x < x1; ++x) {
135 # ifdef DEBUG
136 for (int c = 0; c < nComponents; ++c) {
137 assert( !OFX::IsNaN(srcPix[c]) ); // check for NaN
138 }
139 # endif
140 std::copy(srcPix, srcPix + nComponents, dstPix);
141 dstPix += nComponents;
142 ++srcx;
143 if (_srcBounds.x2 <= srcx) {
144 srcx -= (_srcBounds.x2 - _srcBounds.x1);
145 srcPix -= (_srcBounds.x2 - _srcBounds.x1) * nComponents;
146 }
147 }
148 }
149 }
150 }
151 // then, copy the relevant fraction of src
152 if ( (x1 < x2) && (procWindow.x1 <= x1) && (x2 <= procWindow.x2) ) {
153 const PIX *srcPix = (const PIX *) getSrcPixelAddress(x1, srcy);
154 assert(srcPix);
155 if (!srcPix) {
156 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (x2 - x1) );
157 } else {
158 # ifdef DEBUG
159 for (int c = 0; c < nComponents * (x2 - x1); ++c) {
160 assert( !OFX::IsNaN(srcPix[c]) ); // check for NaN
161 }
162 # endif
163 std::memcpy( dstPix, srcPix, sizeof(PIX) * nComponents * (x2 - x1) );
164 }
165 dstPix += nComponents * (x2 - x1);
166 }
167 // end of line may be black
168 if (x2 < procWindow.x2) {
169 if ( (_srcBoundary != 1) && (_srcBoundary != 2) ) {
170 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (procWindow.x2 - x2) );
171 dstPix += nComponents * (procWindow.x2 - x2);
172 } else if (_srcBoundary == 1) {
173 const PIX *srcPix = (const PIX *) getSrcPixelAddress(x2 - 1, srcy);
174 assert(srcPix);
175 if (!srcPix) {
176 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (procWindow.x2 - x2) );
177 } else {
178 for (int x = x2; x < procWindow.x2; ++x) {
179 std::memcpy( dstPix, srcPix, sizeof(PIX) * nComponents );
180 dstPix += nComponents;
181 }
182 }
183 } else if (_srcBoundary == 2) {
184 int srcx = x2;
185 while (_srcBounds.x2 <= srcx) {
186 srcx -= (_srcBounds.x2 - _srcBounds.x1);
187 }
188
189 const PIX *srcPix = (const PIX *) getSrcPixelAddress(srcx, srcy);
190 assert(srcPix);
191 if (!srcPix) {
192 std::memset( dstPix, 0, sizeof(PIX) * nComponents * (procWindow.x2 - x2) );
193 dstPix += nComponents * (procWindow.x2 - x2);
194 } else {
195 for (int x = x2; x < procWindow.x2; ++x) {
196 # ifdef DEBUG
197 for (int c = 0; c < nComponents; ++c) {
198 assert( !OFX::IsNaN(srcPix[c]) ); // check for NaN
199 }
200 # endif
201 std::copy(srcPix, srcPix + nComponents, dstPix);
202 dstPix += nComponents;
203 ++srcx;
204 if (_srcBounds.x2 <= srcx) {
205 srcx -= (_srcBounds.x2 - _srcBounds.x1);
206 srcPix -= (_srcBounds.x2 - _srcBounds.x1) * nComponents;
207 }
208 }
209 }
210 }
211 }
212 }
213 }
214 } // multiThreadProcessImages
215 };
216
217 /*
218 * @brief Same as PixelCopier except that the alpha channel is set to maxValue instead of being copied
219 */
220 template <class PIX, int nComponents, int maxValue>
221 class PixelCopierOpaque
222 : public OFX::PixelProcessorFilterBase
223 {
224 public:
225 // ctor
PixelCopierOpaque(OFX::ImageEffect & instance)226 PixelCopierOpaque(OFX::ImageEffect &instance)
227 : OFX::PixelProcessorFilterBase(instance)
228 {
229 }
230
231 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)232 void multiThreadProcessImages(OfxRectI procWindow)
233 {
234 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
235 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
236 if (_dstBounds.x1 > procWindow.x1) {
237 procWindow.x1 = _dstBounds.x1;
238 }
239 if (_dstBounds.x2 < procWindow.x2) {
240 procWindow.x2 = _dstBounds.x2;
241 }
242 if (_dstBounds.y1 > procWindow.y1) {
243 procWindow.y1 = _dstBounds.y1;
244 }
245 if (_dstBounds.y2 < procWindow.y2) {
246 procWindow.y2 = _dstBounds.y2;
247 }
248 assert(nComponents == 4 || nComponents == 1);
249 for (int dsty = procWindow.y1; dsty < procWindow.y2; ++dsty) {
250 if ( _effect.abort() ) {
251 break;
252 }
253
254 int srcy = dsty;
255
256 if (_srcBoundary == 1) {
257 if (_srcBounds.y2 <= srcy) {
258 srcy = _srcBounds.y2 - 1;
259 }
260 if (srcy < _srcBounds.y1) {
261 srcy = _srcBounds.y1;
262 }
263 } else if (_srcBoundary == 2) {
264 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) ) {
265 srcy = _srcBounds.y1 + positive_modulo(srcy - _srcBounds.y1, _srcBounds.y2 - _srcBounds.y1);
266 }
267 }
268
269 PIX *dstPix = (PIX *) getDstPixelAddress(procWindow.x1, dsty);
270 assert(dstPix);
271 if (!dstPix) {
272 // coverity[dead_error_line]
273 continue;
274 }
275
276 for (int dstx = procWindow.x1; dstx < procWindow.x2; ++dstx) {
277 int srcx = dstx;
278
279 if (_srcBoundary == 1) {
280 if (_srcBounds.x2 <= srcx) {
281 srcx = _srcBounds.x2 - 1;
282 }
283 if (srcx < _srcBounds.x1) {
284 srcx = _srcBounds.x1;
285 }
286 } else if (_srcBoundary == 2) {
287 if ( (srcx < _srcBounds.x1) || (_srcBounds.x2 <= srcx) ) {
288 srcx = _srcBounds.x1 + positive_modulo(srcx - _srcBounds.x1, _srcBounds.x2 - _srcBounds.x1);
289 }
290 }
291
292 // origPix is at dstx,dsty
293 const PIX *srcPix = (const PIX *) getSrcPixelAddress(srcx, srcy);
294 if (srcPix) {
295 std::copy(srcPix, srcPix + nComponents - 1, dstPix);
296 dstPix[nComponents - 1] = maxValue;
297 } else {
298 std::fill( dstPix, dstPix + nComponents, PIX() ); // no src pixel here, be black and transparent
299 }
300 // increment the dst pixel
301 dstPix += nComponents;
302 }
303 }
304 } // multiThreadProcessImages
305 };
306
307
308 template <class PIX, int nComponents, int maxValue, bool masked>
309 class PixelCopierMaskMix
310 : public OFX::PixelProcessorFilterBase
311 {
312 public:
313 // ctor
PixelCopierMaskMix(OFX::ImageEffect & instance)314 PixelCopierMaskMix(OFX::ImageEffect &instance)
315 : OFX::PixelProcessorFilterBase(instance)
316 {
317 }
318
319 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)320 void multiThreadProcessImages(OfxRectI procWindow)
321 {
322 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
323 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
324 if (_dstBounds.x1 > procWindow.x1) {
325 procWindow.x1 = _dstBounds.x1;
326 }
327 if (_dstBounds.x2 < procWindow.x2) {
328 procWindow.x2 = _dstBounds.x2;
329 }
330 if (_dstBounds.y1 > procWindow.y1) {
331 procWindow.y1 = _dstBounds.y1;
332 }
333 if (_dstBounds.y2 < procWindow.y2) {
334 procWindow.y2 = _dstBounds.y2;
335 }
336 float tmpPix[nComponents];
337
338 for (int dsty = procWindow.y1; dsty < procWindow.y2; ++dsty) {
339 if ( _effect.abort() ) {
340 break;
341 }
342
343 int srcy = dsty;
344
345 if (_srcBoundary == 1) {
346 if (_srcBounds.y2 <= srcy) {
347 srcy = _srcBounds.y2 - 1;
348 }
349 if (srcy < _srcBounds.y1) {
350 srcy = _srcBounds.y1;
351 }
352 } else if (_srcBoundary == 2) {
353 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) ) {
354 srcy = _srcBounds.y1 + positive_modulo(srcy - _srcBounds.y1, _srcBounds.y2 - _srcBounds.y1);
355 }
356 }
357
358 PIX *dstPix = (PIX *) getDstPixelAddress(procWindow.x1, dsty);
359 assert(dstPix);
360 if (!dstPix) {
361 // coverity[dead_error_line]
362 continue;
363 }
364
365 for (int dstx = procWindow.x1; dstx < procWindow.x2; ++dstx) {
366 int srcx = dstx;
367
368 if (_srcBoundary == 1) {
369 if (_srcBounds.x2 <= srcx) {
370 srcx = _srcBounds.x2 - 1;
371 }
372 if (srcx < _srcBounds.x1) {
373 srcx = _srcBounds.x1;
374 }
375 } else if (_srcBoundary == 2) {
376 if ( (srcx < _srcBounds.x1) || (_srcBounds.x2 <= srcx) ) {
377 srcx = _srcBounds.x1 + positive_modulo(srcx - _srcBounds.x1, _srcBounds.x2 - _srcBounds.x1);
378 }
379 }
380
381 // origPix is at dstx,dsty
382 const PIX *origPix = (const PIX *) (_origImg ? _origImg->getPixelAddress(dstx, dsty) : 0);
383 const PIX *srcPix = (const PIX *) getSrcPixelAddress(srcx, srcy);
384 if (srcPix) {
385 std::copy(srcPix, srcPix + nComponents, tmpPix);
386 } else {
387 std::fill(tmpPix, tmpPix + nComponents, 0.f); // no src pixel here, be black and transparent
388 }
389 // dstx,dsty are the mask image coordinates (no boundary conditions)
390 ofxsMaskMixPix<PIX, nComponents, maxValue, masked>(tmpPix, dstx, dsty, origPix, _doMasking, _maskImg, (float)_mix, _maskInvert, dstPix);
391 // increment the dst pixel
392 dstPix += nComponents;
393 }
394 }
395 } // multiThreadProcessImages
396 };
397
398 template <class SRCPIX, int srcNComponents, int srcMaxValue, class DSTPIX, int dstNComponents, int dstMaxValue>
399 class PixelCopierUnPremult
400 : public OFX::PixelProcessorFilterBase
401 {
402 public:
403 // ctor
PixelCopierUnPremult(OFX::ImageEffect & instance)404 PixelCopierUnPremult(OFX::ImageEffect &instance)
405 : OFX::PixelProcessorFilterBase(instance)
406 {
407 assert( (srcNComponents == 3 || srcNComponents == 4) && (dstNComponents == 3 || dstNComponents == 4) );
408 }
409
410 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)411 void multiThreadProcessImages(OfxRectI procWindow)
412 {
413 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
414 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
415 if (_dstBounds.x1 > procWindow.x1) {
416 procWindow.x1 = _dstBounds.x1;
417 }
418 if (_dstBounds.x2 < procWindow.x2) {
419 procWindow.x2 = _dstBounds.x2;
420 }
421 if (_dstBounds.y1 > procWindow.y1) {
422 procWindow.y1 = _dstBounds.y1;
423 }
424 if (_dstBounds.y2 < procWindow.y2) {
425 procWindow.y2 = _dstBounds.y2;
426 }
427 float unpPix[4];
428
429 for (int dsty = procWindow.y1; dsty < procWindow.y2; ++dsty) {
430 if ( _effect.abort() ) {
431 break;
432 }
433
434 int srcy = dsty;
435
436 if (_srcBoundary == 1) {
437 if (_srcBounds.y2 <= srcy) {
438 srcy = _srcBounds.y2 - 1;
439 }
440 if (srcy < _srcBounds.y1) {
441 srcy = _srcBounds.y1;
442 }
443 } else if (_srcBoundary == 2) {
444 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) ) {
445 srcy = _srcBounds.y1 + positive_modulo(srcy - _srcBounds.y1, _srcBounds.y2 - _srcBounds.y1);
446 }
447 }
448
449 DSTPIX *dstPix = (DSTPIX *) getDstPixelAddress(procWindow.x1, dsty);
450 assert(dstPix);
451 if (!dstPix) {
452 // coverity[dead_error_line]
453 continue;
454 }
455
456 for (int dstx = procWindow.x1; dstx < procWindow.x2; ++dstx) {
457 int srcx = dstx;
458
459 if (_srcBoundary == 1) {
460 if (_srcBounds.x2 <= srcx) {
461 srcx = _srcBounds.x2 - 1;
462 }
463 if (srcx < _srcBounds.x1) {
464 srcx = _srcBounds.x1;
465 }
466 } else if (_srcBoundary == 2) {
467 if ( (srcx < _srcBounds.x1) || (_srcBounds.x2 <= srcx) ) {
468 srcx = _srcBounds.x1 + positive_modulo(srcx - _srcBounds.x1, _srcBounds.x2 - _srcBounds.x1);
469 }
470 }
471
472 const SRCPIX *srcPix = (const SRCPIX *) getSrcPixelAddress(srcx, srcy);
473 ofxsUnPremult<SRCPIX, srcNComponents, srcMaxValue>(srcPix, unpPix, _premult, _premultChannel);
474 for (int c = 0; c < dstNComponents; ++c) {
475 float v = unpPix[c] * dstMaxValue;
476 dstPix[c] = ofxsClampIfInt<DSTPIX, dstMaxValue>(v, 0, dstMaxValue);
477 }
478 // increment the dst pixel
479 dstPix += dstNComponents;
480 }
481 }
482 } // multiThreadProcessImages
483 };
484
485 template <class SRCPIX, int srcNComponents, int srcMaxValue, class DSTPIX, int dstNComponents, int dstMaxValue>
486 class PixelCopierPremult
487 : public OFX::PixelProcessorFilterBase
488 {
489 public:
490 // ctor
PixelCopierPremult(OFX::ImageEffect & instance)491 PixelCopierPremult(OFX::ImageEffect &instance)
492 : OFX::PixelProcessorFilterBase(instance)
493 {
494 assert(srcMaxValue);
495 assert( (srcNComponents == 3 || srcNComponents == 4) && (dstNComponents == 3 || dstNComponents == 4) );
496 }
497
498 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)499 void multiThreadProcessImages(OfxRectI procWindow)
500 {
501 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
502 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
503 if (_dstBounds.x1 > procWindow.x1) {
504 procWindow.x1 = _dstBounds.x1;
505 }
506 if (_dstBounds.x2 < procWindow.x2) {
507 procWindow.x2 = _dstBounds.x2;
508 }
509 if (_dstBounds.y1 > procWindow.y1) {
510 procWindow.y1 = _dstBounds.y1;
511 }
512 if (_dstBounds.y2 < procWindow.y2) {
513 procWindow.y2 = _dstBounds.y2;
514 }
515 for (int dsty = procWindow.y1; dsty < procWindow.y2; ++dsty) {
516 if ( _effect.abort() ) {
517 break;
518 }
519
520 int srcy = dsty;
521
522 if (_srcBoundary == 1) {
523 if (_srcBounds.y2 <= srcy) {
524 srcy = _srcBounds.y2 - 1;
525 }
526 if (srcy < _srcBounds.y1) {
527 srcy = _srcBounds.y1;
528 }
529 } else if (_srcBoundary == 2) {
530 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) ) {
531 srcy = _srcBounds.y1 + positive_modulo(srcy - _srcBounds.y1, _srcBounds.y2 - _srcBounds.y1);
532 }
533 }
534
535 DSTPIX *dstPix = (DSTPIX *) getDstPixelAddress(procWindow.x1, dsty);
536 assert(dstPix);
537 if (!dstPix) {
538 // coverity[dead_error_line]
539 continue;
540 }
541
542 for (int dstx = procWindow.x1; dstx < procWindow.x2; ++dstx) {
543 int srcx = dstx;
544
545 if (_srcBoundary == 1) {
546 if (_srcBounds.x2 <= srcx) {
547 srcx = _srcBounds.x2 - 1;
548 }
549 if (srcx < _srcBounds.x1) {
550 srcx = _srcBounds.x1;
551 }
552 } else if (_srcBoundary == 2) {
553 if ( (srcx < _srcBounds.x1) || (_srcBounds.x2 <= srcx) ) {
554 srcx = _srcBounds.x1 + positive_modulo(srcx - _srcBounds.x1, _srcBounds.x2 - _srcBounds.x1);
555 }
556 }
557
558 const SRCPIX *srcPix = (const SRCPIX *) getSrcPixelAddress(srcx, srcy);
559 if (!srcPix) {
560 // no source, be black and transparent
561 for (int c = 0; c < dstNComponents; ++c) {
562 dstPix[c] = DSTPIX();
563 }
564 } else {
565 float unpPix[4];
566 if (srcNComponents == 1) {
567 unpPix[0] = 0.f;
568 unpPix[1] = 0.f;
569 unpPix[2] = 0.f;
570 unpPix[3] = srcPix[0] * (1.f / srcMaxValue);
571 } else {
572 unpPix[0] = srcPix[0] * (1.f / srcMaxValue);
573 unpPix[1] = srcPix[1] * (1.f / srcMaxValue);
574 unpPix[2] = srcPix[2] * (1.f / srcMaxValue);
575 unpPix[3] = (srcNComponents == 4) ? (srcPix[3] * (1.f / srcMaxValue)) : 1.0f;
576 }
577 float pPix[dstNComponents];
578 // unpPix is in [0, 1]
579 // premultiply and denormalize in [0, maxValue]
580 // if premult is false, just denormalize
581 ofxsPremult<DSTPIX, dstNComponents, dstMaxValue>(unpPix, pPix, _premult, _premultChannel);
582 for (int c = 0; c < dstNComponents; ++c) {
583 dstPix[c] = ofxsClampIfInt<DSTPIX, dstMaxValue>(pPix[c], 0, dstMaxValue);
584 }
585 }
586 // increment the dst pixel
587 dstPix += dstNComponents;
588 }
589 }
590 } // multiThreadProcessImages
591 };
592
593 // _srcBoundarys The border condition type { 0=zero | 1=dirichlet | 2=periodic }.
594 // template to do the RGBA processing
595 template <class SRCPIX, int srcNComponents, int srcMaxValue, class DSTPIX, int dstNComponents, int dstMaxValue>
596 class PixelCopierPremultMaskMix
597 : public OFX::PixelProcessorFilterBase
598 {
599 public:
600 // ctor
PixelCopierPremultMaskMix(OFX::ImageEffect & instance)601 PixelCopierPremultMaskMix(OFX::ImageEffect &instance)
602 : OFX::PixelProcessorFilterBase(instance)
603 {
604 assert( (srcNComponents == 3 || srcNComponents == 4) && (dstNComponents == 3 || dstNComponents == 4) );
605 }
606
607 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)608 void multiThreadProcessImages(OfxRectI procWindow)
609 {
610 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
611 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
612 if (_dstBounds.x1 > procWindow.x1) {
613 procWindow.x1 = _dstBounds.x1;
614 }
615 if (_dstBounds.x2 < procWindow.x2) {
616 procWindow.x2 = _dstBounds.x2;
617 }
618 if (_dstBounds.y1 > procWindow.y1) {
619 procWindow.y1 = _dstBounds.y1;
620 }
621 if (_dstBounds.y2 < procWindow.y2) {
622 procWindow.y2 = _dstBounds.y2;
623 }
624 float unpPix[4];
625
626 if (srcNComponents == 3) {
627 unpPix[3] = 1.f;
628 }
629 for (int dsty = procWindow.y1; dsty < procWindow.y2; ++dsty) {
630 if ( _effect.abort() ) {
631 break;
632 }
633
634 int srcy = dsty;
635
636 if (_srcBoundary == 1) {
637 if (_srcBounds.y2 <= srcy) {
638 srcy = _srcBounds.y2 - 1;
639 }
640 if (srcy < _srcBounds.y1) {
641 srcy = _srcBounds.y1;
642 }
643 } else if (_srcBoundary == 2) {
644 if ( (srcy < _srcBounds.y1) || (_srcBounds.y2 <= srcy) ) {
645 srcy = _srcBounds.y1 + positive_modulo(srcy - _srcBounds.y1, _srcBounds.y2 - _srcBounds.y1);
646 }
647 }
648
649 DSTPIX *dstPix = (DSTPIX *) getDstPixelAddress(procWindow.x1, dsty);
650 assert(dstPix);
651 if (!dstPix) {
652 // coverity[dead_error_line]
653 continue;
654 }
655
656 for (int dstx = procWindow.x1; dstx < procWindow.x2; ++dstx) {
657 int srcx = dstx;
658
659 if (_srcBoundary == 1) {
660 if (_srcBounds.x2 <= srcx) {
661 srcx = _srcBounds.x2 - 1;
662 }
663 if (srcx < _srcBounds.x1) {
664 srcx = _srcBounds.x1;
665 }
666 } else if (_srcBoundary == 2) {
667 if ( (srcx < _srcBounds.x1) || (_srcBounds.x2 <= srcx) ) {
668 srcx = _srcBounds.x1 + positive_modulo(srcx - _srcBounds.x1, _srcBounds.x2 - _srcBounds.x1);
669 }
670 }
671 // origPix is at dstx,dsty
672 const DSTPIX *origPix = (const DSTPIX *) (_origImg ? _origImg->getPixelAddress(dstx, dsty) : 0);
673 const SRCPIX *srcPix = (const SRCPIX *) getSrcPixelAddress(srcx, srcy);
674 for (int c = 0; c < srcNComponents; ++c) {
675 unpPix[c] = (srcPix ? (srcPix[c] * (1.f / srcMaxValue)) : 0.f);
676 }
677 // dstx,dsty are the mask image coordinates (no boundary conditions)
678 ofxsPremultMaskMixPix<DSTPIX, dstNComponents, dstMaxValue, true>(unpPix, _premult, _premultChannel, dstx, dsty, origPix, _doMasking, _maskImg, (float)_mix, _maskInvert, dstPix);
679 // increment the dst pixel
680 dstPix += dstNComponents;
681 }
682 }
683 } // multiThreadProcessImages
684 };
685
686 template <class PIX>
687 class BlackFiller
688 : public OFX::PixelProcessorFilterBase
689 {
690 public:
691 // ctor
BlackFiller(OFX::ImageEffect & instance,int comps)692 BlackFiller(OFX::ImageEffect &instance,
693 int comps)
694 : OFX::PixelProcessorFilterBase(instance)
695 , _nComponents(comps)
696 {
697 }
698
699 // and do some processing
multiThreadProcessImages(OfxRectI procWindow)700 void multiThreadProcessImages(OfxRectI procWindow)
701 {
702 assert(_dstBounds.x1 <= procWindow.x1 && procWindow.x2 <= _dstBounds.x2 && _dstBounds.y1 <= procWindow.y1 && procWindow.y2 <= _dstBounds.y2);
703 // for more safety, make sure procWindow is within dstBounds (as covered by the above assert)
704 if (_dstBounds.x1 > procWindow.x1) {
705 procWindow.x1 = _dstBounds.x1;
706 }
707 if (_dstBounds.x2 < procWindow.x2) {
708 procWindow.x2 = _dstBounds.x2;
709 }
710 if (_dstBounds.y1 > procWindow.y1) {
711 procWindow.y1 = _dstBounds.y1;
712 }
713 if (_dstBounds.y2 < procWindow.y2) {
714 procWindow.y2 = _dstBounds.y2;
715 }
716 int rowSize = _nComponents * (procWindow.x2 - procWindow.x1);
717
718 for (int y = procWindow.y1; y < procWindow.y2; ++y) {
719 if ( _effect.abort() ) {
720 break;
721 }
722
723 PIX *dstPix = (PIX *) getDstPixelAddress(procWindow.x1, y);
724 assert(dstPix);
725 if (!dstPix) {
726 // coverity[dead_error_line]
727 continue;
728 }
729 std::fill( dstPix, dstPix + rowSize, PIX() );
730 }
731 }
732
733 private:
734 int _nComponents;
735 };
736
737 // black fillers, non-threaded versions
738 template<class PIX>
739 void
fillBlackNTForDepth(const OfxRectI & renderWindow,void * dstPixelData,const OfxRectI & dstBounds,int dstPixelComponentCount,int dstRowBytes)740 fillBlackNTForDepth(const OfxRectI & renderWindow,
741 void *dstPixelData,
742 const OfxRectI & dstBounds,
743 int dstPixelComponentCount,
744 int dstRowBytes)
745 {
746 assert(dstPixelData);
747 // do the rendering
748 int dstRowElements = dstRowBytes / sizeof(PIX);
749 int x1 = (std::max)(renderWindow.x1, dstBounds.x1);
750 int x2 = (std::min)(renderWindow.x2, dstBounds.x2);
751 int y1 = (std::max)(renderWindow.y1, dstBounds.y1);
752 int y2 = (std::min)(renderWindow.y2, dstBounds.y2);
753 PIX* dstPixels = (PIX*)dstPixelData + (size_t)(y1 - dstBounds.y1) * dstRowElements + (x1 - dstBounds.x1) * dstPixelComponentCount;
754 int rowElements = dstPixelComponentCount * (x2 - renderWindow.x1);
755
756 for (int y = y1; y < y2; ++y, dstPixels += dstRowElements) {
757 std::fill( dstPixels, dstPixels + rowElements, PIX() ); // no src pixel here, be black and transparent
758 }
759 }
760
761 inline void
fillBlackNT(const OfxRectI & renderWindow,void * dstPixelData,const OfxRectI & dstBounds,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)762 fillBlackNT(const OfxRectI & renderWindow,
763 void *dstPixelData,
764 const OfxRectI & dstBounds,
765 int dstPixelComponentCount,
766 OFX::BitDepthEnum dstBitDepth,
767 int dstRowBytes)
768 {
769 assert(dstPixelData);
770 if (!dstPixelData) {
771 // coverity[dead_error_line]
772 return;
773 }
774 // do the rendering
775 if ( (dstBitDepth != OFX::eBitDepthUByte) && (dstBitDepth != OFX::eBitDepthUShort) && (dstBitDepth != OFX::eBitDepthHalf) && (dstBitDepth != OFX::eBitDepthFloat) ) {
776 OFX::throwSuiteStatusException(kOfxStatErrFormat);
777
778 return;
779 }
780 if (dstBitDepth == OFX::eBitDepthUByte) {
781 fillBlackNTForDepth<unsigned char>(renderWindow,
782 dstPixelData, dstBounds, dstPixelComponentCount, dstRowBytes);
783 } else if ( (dstBitDepth == OFX::eBitDepthUShort) || (dstBitDepth == OFX::eBitDepthHalf) ) {
784 fillBlackNTForDepth<unsigned short>(renderWindow,
785 dstPixelData, dstBounds, dstPixelComponentCount, dstRowBytes);
786 } else if (dstBitDepth == OFX::eBitDepthFloat) {
787 fillBlackNTForDepth<float>(renderWindow,
788 dstPixelData, dstBounds, dstPixelComponentCount, dstRowBytes);
789 } // switch
790 }
791
792 inline void
fillBlackNT(const OfxRectI & renderWindow,OFX::Image * dstImg)793 fillBlackNT(const OfxRectI & renderWindow,
794 OFX::Image* dstImg)
795 {
796 void* dstPixelData;
797 OfxRectI dstBounds;
798 OFX::PixelComponentEnum dstPixelComponents;
799 OFX::BitDepthEnum dstBitDepth;
800 int dstRowBytes;
801
802 assert(dstImg);
803 if (!dstImg) {
804 // coverity[dead_error_line]
805 return;
806 }
807 getImageData(dstImg, &dstPixelData, &dstBounds, &dstPixelComponents, &dstBitDepth, &dstRowBytes);
808 int dstPixelComponentCount = dstImg->getPixelComponentCount();
809
810 return fillBlackNT(renderWindow, dstPixelData, dstBounds, dstPixelComponentCount, dstBitDepth, dstRowBytes);
811 }
812
813 #if 0 // Don't use threaded version: very probably less efficient
814
815 // black fillers, threaded versions
816 template<class PIX, int nComponents>
817 void
818 fillBlackForDepthAndComponents(OFX::ImageEffect &instance,
819 const OfxRectI & renderWindow,
820 PIX *dstPixelData,
821 const OfxRectI & dstBounds,
822 OFX::PixelComponentEnum dstPixelComponents,
823 int dstPixelComponentCount,
824 OFX::BitDepthEnum dstBitDepth,
825 int dstRowBytes)
826 {
827 (void)dstPixelComponents;
828 (void)dstBitDepth;
829
830 OFX::BlackFiller<PIX> processor(instance, nComponents);
831 // set the images
832 processor.setDstImg(dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
833
834 // set the render window
835 processor.setRenderWindow(renderWindow);
836
837 // Call the base class process member, this will call the derived templated process code
838 processor.process();
839 }
840
841 template<class PIX>
842 void
843 fillBlackForDepth(OFX::ImageEffect &instance,
844 const OfxRectI & renderWindow,
845 void *dstPixelData,
846 const OfxRectI & dstBounds,
847 OFX::PixelComponentEnum dstPixelComponents,
848 int dstPixelComponentCount,
849 OFX::BitDepthEnum dstBitDepth,
850 int dstRowBytes)
851 {
852 assert(dstPixelData);
853 if (!dstPixelData) {
854 // coverity[dead_error_line]
855 return;
856 }
857 // do the rendering
858 if ( (dstPixelComponentCount < 0) || (4 < dstPixelComponentCount) ) {
859 OFX::throwSuiteStatusException(kOfxStatErrFormat);
860
861 return;
862 }
863 if (dstPixelComponentCount == 4) {
864 fillBlackForDepthAndComponents<PIX, 4>(instance, renderWindow,
865 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
866 } else if (dstPixelComponentCount == 3) {
867 fillBlackForDepthAndComponents<PIX, 3>(instance, renderWindow,
868 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
869 } else if (dstPixelComponentCount == 2) {
870 fillBlackForDepthAndComponents<PIX, 2>(instance, renderWindow,
871 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
872 } else if (dstPixelComponentCount == 1) {
873 fillBlackForDepthAndComponents<PIX, 1>(instance, renderWindow,
874 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
875 } // switch
876 }
877
878 inline void
879 fillBlack(OFX::ImageEffect &instance,
880 const OfxRectI & renderWindow,
881 void *dstPixelData,
882 const OfxRectI & dstBounds,
883 OFX::PixelComponentEnum dstPixelComponents,
884 int dstPixelComponentCount,
885 OFX::BitDepthEnum dstBitDepth,
886 int dstRowBytes)
887 {
888 assert(dstPixelData);
889 if (!dstPixelData) {
890 // coverity[dead_error_line]
891 return;
892 }
893 // do the rendering
894 if ( (dstBitDepth != OFX::eBitDepthUByte) && (dstBitDepth != OFX::eBitDepthUShort) && (dstBitDepth != OFX::eBitDepthHalf) && (dstBitDepth != OFX::eBitDepthFloat) ) {
895 OFX::throwSuiteStatusException(kOfxStatErrFormat);
896
897 return;
898 }
899 if (dstBitDepth == OFX::eBitDepthUByte) {
900 fillBlackForDepth<unsigned char>(instance, renderWindow,
901 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
902 } else if ( (dstBitDepth == OFX::eBitDepthUShort) || (dstBitDepth == OFX::eBitDepthHalf) ) {
903 fillBlackForDepth<unsigned short>(instance, renderWindow,
904 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
905 } else if (dstBitDepth == OFX::eBitDepthFloat) {
906 fillBlackForDepth<float>(instance, renderWindow,
907 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
908 } // switch
909 }
910
911 inline void
912 fillBlack(OFX::ImageEffect &instance,
913 const OfxRectI & renderWindow,
914 OFX::Image* dstImg)
915 {
916 void* dstPixelData;
917 OfxRectI dstBounds;
918 OFX::PixelComponentEnum dstPixelComponents;
919 OFX::BitDepthEnum dstBitDepth;
920 int dstRowBytes;
921
922 assert(dstImg);
923 if (!dstImg) {
924 // coverity[dead_error_line]
925 return;
926 }
927 getImageData(dstImg, &dstPixelData, &dstBounds, &dstPixelComponents, &dstBitDepth, &dstRowBytes);
928 int dstPixelComponentCount = dstImg->getPixelComponentCount();
929
930 return fillBlack(instance, renderWindow, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
931 }
932
933 #else // if 0
934
935 // Use non-threaded version: probably more efficient
936
937 inline void
fillBlack(OFX::ImageEffect & instance,const OfxRectI & renderWindow,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)938 fillBlack(OFX::ImageEffect &instance,
939 const OfxRectI & renderWindow,
940 void *dstPixelData,
941 const OfxRectI & dstBounds,
942 OFX::PixelComponentEnum dstPixelComponents,
943 int dstPixelComponentCount,
944 OFX::BitDepthEnum dstBitDepth,
945 int dstRowBytes)
946 {
947 (void)instance;
948 (void)dstPixelComponents;
949
950 return fillBlackNT(renderWindow, dstPixelData, dstBounds, dstPixelComponentCount, dstBitDepth, dstRowBytes);
951 }
952
953 inline void
fillBlack(OFX::ImageEffect & instance,const OfxRectI & renderWindow,OFX::Image * dstImg)954 fillBlack(OFX::ImageEffect &instance,
955 const OfxRectI & renderWindow,
956 OFX::Image* dstImg)
957 {
958 (void)instance;
959
960 return fillBlackNT(renderWindow, dstImg);
961 }
962
963 #endif // if 0
964
965 // pixel copiers, non-threaded versions
966 template<class PIX, int nComponents>
967 void
copyPixelsNTForDepthAndComponents(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const PIX * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,PIX * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)968 copyPixelsNTForDepthAndComponents(OFX::ImageEffect &instance,
969 const OfxRectI & renderWindow,
970 const PIX *srcPixelData,
971 const OfxRectI & srcBounds,
972 OFX::PixelComponentEnum srcPixelComponents,
973 int srcPixelComponentCount,
974 OFX::BitDepthEnum srcBitDepth,
975 int srcRowBytes,
976 PIX *dstPixelData,
977 const OfxRectI & dstBounds,
978 OFX::PixelComponentEnum dstPixelComponents,
979 int dstPixelComponentCount,
980 OFX::BitDepthEnum dstBitDepth,
981 int dstRowBytes)
982 {
983 assert(srcBitDepth == dstBitDepth);
984 assert(srcPixelComponentCount == dstPixelComponentCount);
985 assert(srcPixelComponentCount == nComponents);
986 (void)srcPixelComponents;
987 (void)srcPixelComponentCount;
988 (void)srcBitDepth;
989 (void)dstPixelComponents;
990 (void)dstPixelComponentCount;
991 (void)dstBitDepth;
992 (void)instance;
993
994 unsigned int srcRowElements = srcRowBytes / sizeof(PIX);
995 assert(srcBounds.y1 <= renderWindow.y1 && renderWindow.y1 <= renderWindow.y2 && renderWindow.y2 <= srcBounds.y2);
996 assert(srcBounds.x1 <= renderWindow.x1 && renderWindow.x1 <= renderWindow.x2 && renderWindow.x2 <= srcBounds.x2);
997 int x1 = (std::max)( renderWindow.x1, (std::max)(dstBounds.x1, srcBounds.x1) );
998 int x2 = (std::min)( renderWindow.x2, (std::min)(dstBounds.x2, srcBounds.x2) );
999 int y1 = (std::max)( renderWindow.y1, (std::max)(dstBounds.y1, srcBounds.y1) );
1000 int y2 = (std::min)( renderWindow.y2, (std::min)(dstBounds.y2, srcBounds.y2) );
1001 const PIX* srcPixels = srcPixelData + (size_t)(y1 - srcBounds.y1) * srcRowElements + (x1 - srcBounds.x1) * nComponents;
1002 unsigned int dstRowElements = dstRowBytes / sizeof(PIX);
1003 PIX* dstPixels = dstPixelData + (size_t)(y1 - dstBounds.y1) * dstRowElements + (x1 - dstBounds.x1) * nComponents;
1004 unsigned int rowBytes = sizeof(PIX) * nComponents * (x2 - x1);
1005
1006 for (int y = y1; y < y2; ++y, srcPixels += srcRowElements, dstPixels += dstRowElements) {
1007 std::memcpy(dstPixels, srcPixels, rowBytes);
1008 }
1009 }
1010
1011 template<class PIX>
1012 void
copyPixelsNTForDepth(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1013 copyPixelsNTForDepth(OFX::ImageEffect &instance,
1014 const OfxRectI & renderWindow,
1015 const void *srcPixelData,
1016 const OfxRectI & srcBounds,
1017 OFX::PixelComponentEnum srcPixelComponents,
1018 int srcPixelComponentCount,
1019 OFX::BitDepthEnum srcBitDepth,
1020 int srcRowBytes,
1021 void *dstPixelData,
1022 const OfxRectI & dstBounds,
1023 OFX::PixelComponentEnum dstPixelComponents,
1024 int dstPixelComponentCount,
1025 OFX::BitDepthEnum dstBitDepth,
1026 int dstRowBytes)
1027 {
1028 assert(srcPixelData && dstPixelData);
1029 assert(srcBitDepth == dstBitDepth);
1030 assert(srcPixelComponentCount == dstPixelComponentCount);
1031 // do the rendering
1032 if ( (dstPixelComponents != OFX::ePixelComponentRGBA) && (dstPixelComponents != OFX::ePixelComponentRGB) && (dstPixelComponents != OFX::ePixelComponentAlpha) ) {
1033 OFX::throwSuiteStatusException(kOfxStatErrFormat);
1034
1035 return;
1036 }
1037 if (dstPixelComponents == OFX::ePixelComponentRGBA) {
1038 copyPixelsNTForDepthAndComponents<PIX, 4>(instance, renderWindow,
1039 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1040 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1041 } else if (dstPixelComponents == OFX::ePixelComponentRGB) {
1042 copyPixelsNTForDepthAndComponents<PIX, 3>(instance, renderWindow,
1043 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1044 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1045 } else if (dstPixelComponents == OFX::ePixelComponentAlpha) {
1046 copyPixelsNTForDepthAndComponents<PIX, 1>(instance, renderWindow,
1047 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1048 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1049 } // switch
1050 }
1051
1052 inline void
copyPixelsNT(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1053 copyPixelsNT(OFX::ImageEffect &instance,
1054 const OfxRectI & renderWindow,
1055 const void *srcPixelData,
1056 const OfxRectI & srcBounds,
1057 OFX::PixelComponentEnum srcPixelComponents,
1058 int srcPixelComponentCount,
1059 OFX::BitDepthEnum srcBitDepth,
1060 int srcRowBytes,
1061 void *dstPixelData,
1062 const OfxRectI & dstBounds,
1063 OFX::PixelComponentEnum dstPixelComponents,
1064 int dstPixelComponentCount,
1065 OFX::BitDepthEnum dstBitDepth,
1066 int dstRowBytes)
1067 {
1068 assert(srcPixelData && dstPixelData);
1069 assert(srcBitDepth == dstBitDepth);
1070 assert(srcPixelComponentCount == dstPixelComponentCount);
1071
1072 // do the rendering
1073 if ( (dstBitDepth != OFX::eBitDepthUByte) && (dstBitDepth != OFX::eBitDepthUShort) && (dstBitDepth != OFX::eBitDepthHalf) && (dstBitDepth != OFX::eBitDepthFloat) ) {
1074 OFX::throwSuiteStatusException(kOfxStatErrFormat);
1075
1076 return;
1077 }
1078 if (dstBitDepth == OFX::eBitDepthUByte) {
1079 copyPixelsNTForDepth<unsigned char>(instance, renderWindow,
1080 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1081 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1082 } else if ( (dstBitDepth == OFX::eBitDepthUShort) || (dstBitDepth == OFX::eBitDepthHalf) ) {
1083 copyPixelsNTForDepth<unsigned short>(instance, renderWindow,
1084 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1085 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1086 } else if (dstBitDepth == OFX::eBitDepthFloat) {
1087 copyPixelsNTForDepth<float>(instance, renderWindow,
1088 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1089 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1090 } // switch
1091 }
1092
1093 // pixel copiers, threaded versions
1094 template<class PIX, int nComponents>
1095 void
copyPixelsForDepthAndComponents(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const PIX * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,PIX * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1096 copyPixelsForDepthAndComponents(OFX::ImageEffect &instance,
1097 const OfxRectI & renderWindow,
1098 const PIX *srcPixelData,
1099 const OfxRectI & srcBounds,
1100 OFX::PixelComponentEnum srcPixelComponents,
1101 int srcPixelComponentCount,
1102 OFX::BitDepthEnum srcBitDepth,
1103 int srcRowBytes,
1104 PIX *dstPixelData,
1105 const OfxRectI & dstBounds,
1106 OFX::PixelComponentEnum dstPixelComponents,
1107 int dstPixelComponentCount,
1108 OFX::BitDepthEnum dstBitDepth,
1109 int dstRowBytes)
1110 {
1111 assert(srcPixelData && dstPixelData);
1112 //assert(srcBounds.y1 <= renderWindow.y1 && renderWindow.y1 <= renderWindow.y2 && renderWindow.y2 <= srcBounds.y2); // not necessary, PixelCopier should handle this
1113 //assert(srcBounds.x1 <= renderWindow.x1 && renderWindow.x1 <= renderWindow.x2 && renderWindow.x2 <= srcBounds.x2); // not necessary, PixelCopier should handle this
1114 assert(srcBitDepth == dstBitDepth);
1115 assert(srcPixelComponentCount == dstPixelComponentCount);
1116 (void)srcPixelComponents;
1117 (void)srcBitDepth;
1118 (void)dstPixelComponents;
1119 (void)dstBitDepth;
1120
1121 OFX::PixelCopier<PIX, nComponents> processor(instance);
1122 // set the images
1123 processor.setDstImg(dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1124 processor.setSrcImg(srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes, 0);
1125
1126 // set the render window
1127 processor.setRenderWindow(renderWindow);
1128
1129 // Call the base class process member, this will call the derived templated process code
1130 processor.process();
1131 }
1132
1133 template<class PIX>
1134 void
copyPixelsForDepth(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1135 copyPixelsForDepth(OFX::ImageEffect &instance,
1136 const OfxRectI & renderWindow,
1137 const void *srcPixelData,
1138 const OfxRectI & srcBounds,
1139 OFX::PixelComponentEnum srcPixelComponents,
1140 int srcPixelComponentCount,
1141 OFX::BitDepthEnum srcBitDepth,
1142 int srcRowBytes,
1143 void *dstPixelData,
1144 const OfxRectI & dstBounds,
1145 OFX::PixelComponentEnum dstPixelComponents,
1146 int dstPixelComponentCount,
1147 OFX::BitDepthEnum dstBitDepth,
1148 int dstRowBytes)
1149 {
1150 assert(srcPixelData && dstPixelData);
1151 assert(srcBitDepth == dstBitDepth);
1152 assert(srcPixelComponentCount == dstPixelComponentCount);
1153 // do the rendering
1154 if ( (dstPixelComponentCount < 0) || (4 < dstPixelComponentCount) ) {
1155 OFX::throwSuiteStatusException(kOfxStatErrFormat);
1156
1157 return;
1158 }
1159 if (dstPixelComponentCount == 4) {
1160 copyPixelsForDepthAndComponents<PIX, 4>(instance, renderWindow,
1161 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1162 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1163 } else if (dstPixelComponentCount == 3) {
1164 copyPixelsForDepthAndComponents<PIX, 3>(instance, renderWindow,
1165 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1166 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1167 } else if (dstPixelComponentCount == 2) {
1168 copyPixelsForDepthAndComponents<PIX, 2>(instance, renderWindow,
1169 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1170 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1171 } else if (dstPixelComponentCount == 1) {
1172 copyPixelsForDepthAndComponents<PIX, 1>(instance, renderWindow,
1173 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1174 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1175 } // switch
1176 }
1177
1178 inline void
copyPixels(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1179 copyPixels(OFX::ImageEffect &instance,
1180 const OfxRectI & renderWindow,
1181 const void *srcPixelData,
1182 const OfxRectI & srcBounds,
1183 OFX::PixelComponentEnum srcPixelComponents,
1184 int srcPixelComponentCount,
1185 OFX::BitDepthEnum srcBitDepth,
1186 int srcRowBytes,
1187 void *dstPixelData,
1188 const OfxRectI & dstBounds,
1189 OFX::PixelComponentEnum dstPixelComponents,
1190 int dstPixelComponentCount,
1191 OFX::BitDepthEnum dstBitDepth,
1192 int dstRowBytes)
1193 {
1194 assert(dstPixelData);
1195 if (!srcPixelData) {
1196 // no input, be black and transparent
1197 return fillBlack(instance, renderWindow,
1198 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1199 }
1200 assert(srcPixelComponentCount == dstPixelComponentCount && srcBitDepth == dstBitDepth);
1201 // do the rendering
1202 if ( (dstBitDepth != OFX::eBitDepthUByte) && (dstBitDepth != OFX::eBitDepthUShort) && (dstBitDepth != OFX::eBitDepthHalf) && (dstBitDepth != OFX::eBitDepthFloat) ) {
1203 OFX::throwSuiteStatusException(kOfxStatErrFormat);
1204
1205 return;
1206 }
1207 if (dstBitDepth == OFX::eBitDepthUByte) {
1208 copyPixelsForDepth<unsigned char>(instance, renderWindow,
1209 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1210 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1211 } else if ( (dstBitDepth == OFX::eBitDepthUShort) || (dstBitDepth == OFX::eBitDepthHalf) ) {
1212 copyPixelsForDepth<unsigned short>(instance, renderWindow,
1213 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1214 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1215 } else if (dstBitDepth == OFX::eBitDepthFloat) {
1216 copyPixelsForDepth<float>(instance, renderWindow,
1217 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1218 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1219 } // switch
1220 }
1221
1222 inline void
copyPixels(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const OFX::Image * srcImg,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1223 copyPixels(OFX::ImageEffect &instance,
1224 const OfxRectI & renderWindow,
1225 const OFX::Image* srcImg,
1226 void *dstPixelData,
1227 const OfxRectI & dstBounds,
1228 OFX::PixelComponentEnum dstPixelComponents,
1229 int dstPixelComponentCount,
1230 OFX::BitDepthEnum dstBitDepth,
1231 int dstRowBytes)
1232 {
1233 const void* srcPixelData;
1234 OfxRectI srcBounds;
1235 OFX::PixelComponentEnum srcPixelComponents;
1236 OFX::BitDepthEnum srcBitDepth;
1237 int srcRowBytes;
1238
1239 getImageData(srcImg, &srcPixelData, &srcBounds, &srcPixelComponents, &srcBitDepth, &srcRowBytes);
1240 int srcPixelComponentCount = srcImg->getPixelComponentCount();
1241
1242 return copyPixels(instance, renderWindow, srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1243 }
1244
1245 inline void
copyPixels(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const OFX::Image * srcImg,OFX::Image * dstImg)1246 copyPixels(OFX::ImageEffect &instance,
1247 const OfxRectI & renderWindow,
1248 const OFX::Image* srcImg,
1249 OFX::Image* dstImg)
1250 {
1251 void* dstPixelData;
1252 OfxRectI dstBounds;
1253 OFX::PixelComponentEnum dstPixelComponents;
1254 OFX::BitDepthEnum dstBitDepth;
1255 int dstRowBytes;
1256
1257 getImageData(dstImg, &dstPixelData, &dstBounds, &dstPixelComponents, &dstBitDepth, &dstRowBytes);
1258 int dstPixelComponentCount = dstImg->getPixelComponentCount();
1259
1260 return copyPixels(instance, renderWindow, srcImg, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1261 }
1262
1263 inline void
copyPixels(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,OFX::Image * dstImg)1264 copyPixels(OFX::ImageEffect &instance,
1265 const OfxRectI & renderWindow,
1266 const void *srcPixelData,
1267 const OfxRectI & srcBounds,
1268 OFX::PixelComponentEnum srcPixelComponents,
1269 int srcPixelComponentCount,
1270 OFX::BitDepthEnum srcBitDepth,
1271 int srcRowBytes,
1272 OFX::Image* dstImg)
1273 {
1274 void* dstPixelData;
1275 OfxRectI dstBounds;
1276 OFX::PixelComponentEnum dstPixelComponents;
1277 OFX::BitDepthEnum dstBitDepth;
1278 int dstRowBytes;
1279
1280 getImageData(dstImg, &dstPixelData, &dstBounds, &dstPixelComponents, &dstBitDepth, &dstRowBytes);
1281 int dstPixelComponentCount = dstImg->getPixelComponentCount();
1282
1283 return copyPixels(instance, renderWindow, srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1284 }
1285
1286 // pixel copiers, threaded versions
1287 template<class PIX, int nComponents, int maxValue>
1288 void
copyPixelsOpaqueForDepthAndComponents(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const PIX * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,PIX * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1289 copyPixelsOpaqueForDepthAndComponents(OFX::ImageEffect &instance,
1290 const OfxRectI & renderWindow,
1291 const PIX *srcPixelData,
1292 const OfxRectI & srcBounds,
1293 OFX::PixelComponentEnum srcPixelComponents,
1294 int srcPixelComponentCount,
1295 OFX::BitDepthEnum srcBitDepth,
1296 int srcRowBytes,
1297 PIX *dstPixelData,
1298 const OfxRectI & dstBounds,
1299 OFX::PixelComponentEnum dstPixelComponents,
1300 int dstPixelComponentCount,
1301 OFX::BitDepthEnum dstBitDepth,
1302 int dstRowBytes)
1303 {
1304 assert(srcPixelData && dstPixelData);
1305 //assert(srcBounds.y1 <= renderWindow.y1 && renderWindow.y1 <= renderWindow.y2 && renderWindow.y2 <= srcBounds.y2); // not necessary, PixelCopier should handle this
1306 //assert(srcBounds.x1 <= renderWindow.x1 && renderWindow.x1 <= renderWindow.x2 && renderWindow.x2 <= srcBounds.x2); // not necessary, PixelCopier should handle this
1307 assert(srcPixelComponents == dstPixelComponents && srcBitDepth == dstBitDepth);
1308 assert(srcPixelComponentCount == dstPixelComponentCount);
1309 (void)srcPixelComponents;
1310 (void)srcBitDepth;
1311 (void)dstPixelComponents;
1312 (void)dstBitDepth;
1313
1314 OFX::PixelCopierOpaque<PIX, nComponents, maxValue> processor(instance);
1315 // set the images
1316 processor.setDstImg(dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1317 processor.setSrcImg(srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes, 0);
1318
1319 // set the render window
1320 processor.setRenderWindow(renderWindow);
1321
1322 // Call the base class process member, this will call the derived templated process code
1323 processor.process();
1324 }
1325
1326 template<class PIX, int maxValue>
1327 void
copyPixelsOpaqueForDepth(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1328 copyPixelsOpaqueForDepth(OFX::ImageEffect &instance,
1329 const OfxRectI & renderWindow,
1330 const void *srcPixelData,
1331 const OfxRectI & srcBounds,
1332 OFX::PixelComponentEnum srcPixelComponents,
1333 int srcPixelComponentCount,
1334 OFX::BitDepthEnum srcBitDepth,
1335 int srcRowBytes,
1336 void *dstPixelData,
1337 const OfxRectI & dstBounds,
1338 OFX::PixelComponentEnum dstPixelComponents,
1339 int dstPixelComponentCount,
1340 OFX::BitDepthEnum dstBitDepth,
1341 int dstRowBytes)
1342 {
1343 if ( (dstPixelComponentCount < 0) || (4 < dstPixelComponentCount) ) {
1344 OFX::throwSuiteStatusException(kOfxStatErrFormat);
1345
1346 return;
1347 }
1348 assert(srcPixelData && dstPixelData);
1349 assert(srcPixelComponents == dstPixelComponents && srcBitDepth == dstBitDepth);
1350 assert(srcPixelComponentCount == dstPixelComponentCount);
1351 // do the rendering
1352 if ( (dstPixelComponentCount == 4) || (dstPixelComponentCount == 1) ) {
1353 if (dstPixelComponentCount == 4) {
1354 copyPixelsOpaqueForDepthAndComponents<PIX, 4, maxValue>(instance, renderWindow,
1355 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1356 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1357 } else {
1358 copyPixelsOpaqueForDepthAndComponents<PIX, 1, maxValue>(instance, renderWindow,
1359 (const PIX*)srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1360 (PIX *)dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1361 }
1362 } else {
1363 copyPixelsForDepth<PIX>(instance, renderWindow,
1364 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1365 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1366 }
1367 }
1368
1369 inline void
copyPixelsOpaque(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1370 copyPixelsOpaque(OFX::ImageEffect &instance,
1371 const OfxRectI & renderWindow,
1372 const void *srcPixelData,
1373 const OfxRectI & srcBounds,
1374 OFX::PixelComponentEnum srcPixelComponents,
1375 int srcPixelComponentCount,
1376 OFX::BitDepthEnum srcBitDepth,
1377 int srcRowBytes,
1378 void *dstPixelData,
1379 const OfxRectI & dstBounds,
1380 OFX::PixelComponentEnum dstPixelComponents,
1381 int dstPixelComponentCount,
1382 OFX::BitDepthEnum dstBitDepth,
1383 int dstRowBytes)
1384 {
1385 if ( ( (dstPixelComponents != ePixelComponentRGBA) && (dstPixelComponents != ePixelComponentAlpha) ) ||
1386 !srcPixelData ) {
1387 assert(dstPixelComponentCount != 4 || !srcPixelData);
1388
1389 return copyPixels(instance,
1390 renderWindow,
1391 srcPixelData,
1392 srcBounds,
1393 srcPixelComponents,
1394 srcPixelComponentCount,
1395 srcBitDepth,
1396 srcRowBytes,
1397 dstPixelData,
1398 dstBounds,
1399 dstPixelComponents,
1400 dstPixelComponentCount,
1401 dstBitDepth,
1402 dstRowBytes);
1403 }
1404 assert(dstPixelData && srcPixelData);
1405 assert(srcPixelComponents == dstPixelComponents && srcBitDepth == dstBitDepth);
1406 // do the rendering
1407 switch (dstBitDepth) {
1408 case OFX::eBitDepthUByte: {
1409 copyPixelsOpaqueForDepth<unsigned char, 255>(instance, renderWindow,
1410 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1411 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1412 break;
1413 }
1414 case OFX::eBitDepthUShort: {
1415 copyPixelsOpaqueForDepth<unsigned short, 65535>(instance, renderWindow,
1416 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1417 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1418 break;
1419 }
1420 case OFX::eBitDepthHalf: {
1421 // the unsigned short representation of 1.h is 15360
1422 // #include <OpenEXR/half.h>
1423 // half one(1.);
1424 // cout << "the unsigned short representation of 1.h is " << one.bits() << endl;
1425 copyPixelsOpaqueForDepth<unsigned short, 15360>(instance, renderWindow,
1426 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1427 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1428 break;
1429 }
1430 case OFX::eBitDepthFloat: {
1431 copyPixelsOpaqueForDepth<float, 1>(instance, renderWindow,
1432 srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes,
1433 dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1434 break;
1435 }
1436 default:
1437 OFX::throwSuiteStatusException(kOfxStatErrFormat);
1438
1439 return;
1440 } // switch
1441 } // copyPixelsOpaque
1442
1443 inline void
copyPixelsOpaque(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const OFX::Image * srcImg,void * dstPixelData,const OfxRectI & dstBounds,OFX::PixelComponentEnum dstPixelComponents,int dstPixelComponentCount,OFX::BitDepthEnum dstBitDepth,int dstRowBytes)1444 copyPixelsOpaque(OFX::ImageEffect &instance,
1445 const OfxRectI & renderWindow,
1446 const OFX::Image* srcImg,
1447 void *dstPixelData,
1448 const OfxRectI & dstBounds,
1449 OFX::PixelComponentEnum dstPixelComponents,
1450 int dstPixelComponentCount,
1451 OFX::BitDepthEnum dstBitDepth,
1452 int dstRowBytes)
1453 {
1454 const void* srcPixelData;
1455 OfxRectI srcBounds;
1456 OFX::PixelComponentEnum srcPixelComponents;
1457 OFX::BitDepthEnum srcBitDepth;
1458 int srcRowBytes;
1459
1460 getImageData(srcImg, &srcPixelData, &srcBounds, &srcPixelComponents, &srcBitDepth, &srcRowBytes);
1461 int srcPixelComponentCount = srcImg->getPixelComponentCount();
1462
1463 return copyPixelsOpaque(instance, renderWindow, srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1464 }
1465
1466 inline void
copyPixelsOpaque(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const OFX::Image * srcImg,OFX::Image * dstImg)1467 copyPixelsOpaque(OFX::ImageEffect &instance,
1468 const OfxRectI & renderWindow,
1469 const OFX::Image* srcImg,
1470 OFX::Image* dstImg)
1471 {
1472 void* dstPixelData;
1473 OfxRectI dstBounds;
1474 OFX::PixelComponentEnum dstPixelComponents;
1475 OFX::BitDepthEnum dstBitDepth;
1476 int dstRowBytes;
1477
1478 getImageData(dstImg, &dstPixelData, &dstBounds, &dstPixelComponents, &dstBitDepth, &dstRowBytes);
1479 int dstPixelComponentCount = dstImg->getPixelComponentCount();
1480
1481 return copyPixelsOpaque(instance, renderWindow, srcImg, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1482 }
1483
1484 inline void
copyPixelsOpaque(OFX::ImageEffect & instance,const OfxRectI & renderWindow,const void * srcPixelData,const OfxRectI & srcBounds,OFX::PixelComponentEnum srcPixelComponents,int srcPixelComponentCount,OFX::BitDepthEnum srcBitDepth,int srcRowBytes,OFX::Image * dstImg)1485 copyPixelsOpaque(OFX::ImageEffect &instance,
1486 const OfxRectI & renderWindow,
1487 const void *srcPixelData,
1488 const OfxRectI & srcBounds,
1489 OFX::PixelComponentEnum srcPixelComponents,
1490 int srcPixelComponentCount,
1491 OFX::BitDepthEnum srcBitDepth,
1492 int srcRowBytes,
1493 OFX::Image* dstImg)
1494 {
1495 void* dstPixelData;
1496 OfxRectI dstBounds;
1497 OFX::PixelComponentEnum dstPixelComponents;
1498 OFX::BitDepthEnum dstBitDepth;
1499 int dstRowBytes;
1500
1501 getImageData(dstImg, &dstPixelData, &dstBounds, &dstPixelComponents, &dstBitDepth, &dstRowBytes);
1502 int dstPixelComponentCount = dstImg->getPixelComponentCount();
1503
1504 return copyPixelsOpaque(instance, renderWindow, srcPixelData, srcBounds, srcPixelComponents, srcPixelComponentCount, srcBitDepth, srcRowBytes, dstPixelData, dstBounds, dstPixelComponents, dstPixelComponentCount, dstBitDepth, dstRowBytes);
1505 }
1506 } // OFX
1507
1508 #endif // ifndef IO_ofxsCopier_h
1509