1 /*****************************************************************************/
2 // Copyright 2006-2008 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE: Adobe permits you to use, modify, and distribute this file in
6 // accordance with the terms of the Adobe license agreement accompanying it.
7 /*****************************************************************************/
8
9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_pixel_buffer.cpp#1 $ */
10 /* $DateTime: 2012/05/30 13:28:51 $ */
11 /* $Change: 832332 $ */
12 /* $Author: tknoll $ */
13
14 /*****************************************************************************/
15
16 #include "dng_pixel_buffer.h"
17
18 #include "dng_bottlenecks.h"
19 #include "dng_exceptions.h"
20 #include "dng_flags.h"
21 #include "dng_safe_arithmetic.h"
22 #include "dng_tag_types.h"
23 #include "dng_tag_values.h"
24 #include "dng_utils.h"
25
26 /*****************************************************************************/
27
28 namespace {
29
SafeUint32ToInt32Mult(uint32 arg1,uint32 arg2,int32 * result)30 bool SafeUint32ToInt32Mult(uint32 arg1, uint32 arg2, int32 *result) {
31 uint32 uint32_result;
32 return SafeUint32Mult(arg1, arg2, &uint32_result) &&
33 ConvertUint32ToInt32(uint32_result, result);
34 }
35
36 } // namespace
37
38 /*****************************************************************************/
39
OptimizeOrder(const void * & sPtr,void * & dPtr,uint32 sPixelSize,uint32 dPixelSize,uint32 & count0,uint32 & count1,uint32 & count2,int32 & sStep0,int32 & sStep1,int32 & sStep2,int32 & dStep0,int32 & dStep1,int32 & dStep2)40 void OptimizeOrder (const void *&sPtr,
41 void *&dPtr,
42 uint32 sPixelSize,
43 uint32 dPixelSize,
44 uint32 &count0,
45 uint32 &count1,
46 uint32 &count2,
47 int32 &sStep0,
48 int32 &sStep1,
49 int32 &sStep2,
50 int32 &dStep0,
51 int32 &dStep1,
52 int32 &dStep2)
53 {
54
55 uint32 step0;
56 uint32 step1;
57 uint32 step2;
58
59 // Optimize the order for the data that is most spread out.
60
61 uint32 sRange = Abs_int32 (sStep0) * (count0 - 1) +
62 Abs_int32 (sStep1) * (count1 - 1) +
63 Abs_int32 (sStep2) * (count2 - 1);
64
65 uint32 dRange = Abs_int32 (dStep0) * (count0 - 1) +
66 Abs_int32 (dStep1) * (count1 - 1) +
67 Abs_int32 (dStep2) * (count2 - 1);
68
69 if (dRange >= sRange)
70 {
71
72 if (dStep0 < 0)
73 {
74
75 sPtr = (const void *)
76 (((const uint8 *) sPtr) + (int32)(count0 - 1) * sStep0 * (int32)sPixelSize);
77
78 dPtr = (void *)
79 (((uint8 *) dPtr) + (int32)(count0 - 1) * dStep0 * (int32)dPixelSize);
80
81 sStep0 = -sStep0;
82 dStep0 = -dStep0;
83
84 }
85
86 if (dStep1 < 0)
87 {
88
89 sPtr = (const void *)
90 (((const uint8 *) sPtr) + (int32)(count1 - 1) * sStep1 * (int32)sPixelSize);
91
92 dPtr = (void *)
93 (((uint8 *) dPtr) + (int32)(count1 - 1) * dStep1 * (int32)dPixelSize);
94
95 sStep1 = -sStep1;
96 dStep1 = -dStep1;
97
98 }
99
100 if (dStep2 < 0)
101 {
102
103 sPtr = (const void *)
104 (((const uint8 *) sPtr) + (int32)(count2 - 1) * sStep2 * (int32)sPixelSize);
105
106 dPtr = (void *)
107 (((uint8 *) dPtr) + (int32)(count2 - 1) * dStep2 * (int32)dPixelSize);
108
109 sStep2 = -sStep2;
110 dStep2 = -dStep2;
111
112 }
113
114 step0 = (uint32) dStep0;
115 step1 = (uint32) dStep1;
116 step2 = (uint32) dStep2;
117
118 }
119
120 else
121 {
122
123 if (sStep0 < 0)
124 {
125
126 sPtr = (const void *)
127 (((const uint8 *) sPtr) + (int32)(count0 - 1) * sStep0 * (int32)sPixelSize);
128
129 dPtr = (void *)
130 (((uint8 *) dPtr) + (int32)(count0 - 1) * dStep0 * (int32)dPixelSize);
131
132 sStep0 = -sStep0;
133 dStep0 = -dStep0;
134
135 }
136
137 if (sStep1 < 0)
138 {
139
140 sPtr = (const void *)
141 (((const uint8 *) sPtr) + (int32)(count1 - 1) * sStep1 * (int32)sPixelSize);
142
143 dPtr = (void *)
144 (((uint8 *) dPtr) + (int32)(count1 - 1) * dStep1 * (int32)dPixelSize);
145
146 sStep1 = -sStep1;
147 dStep1 = -dStep1;
148
149 }
150
151 if (sStep2 < 0)
152 {
153
154 sPtr = (const void *)
155 (((const uint8 *) sPtr) + (int32)(count2 - 1) * sStep2 * (int32)sPixelSize);
156
157 dPtr = (void *)
158 (((uint8 *) dPtr) + (int32)(count2 - 1) * dStep2 * (int32)dPixelSize);
159
160 sStep2 = -sStep2;
161 dStep2 = -dStep2;
162
163 }
164
165 step0 = (uint32) sStep0;
166 step1 = (uint32) sStep1;
167 step2 = (uint32) sStep2;
168
169 }
170
171 if (count0 == 1) step0 = 0xFFFFFFFF;
172 if (count1 == 1) step1 = 0xFFFFFFFF;
173 if (count2 == 1) step2 = 0xFFFFFFFF;
174
175 uint32 index0;
176 uint32 index1;
177 uint32 index2;
178
179 if (step0 >= step1)
180 {
181
182 if (step1 >= step2)
183 {
184 index0 = 0;
185 index1 = 1;
186 index2 = 2;
187 }
188
189 else if (step2 >= step0)
190 {
191 index0 = 2;
192 index1 = 0;
193 index2 = 1;
194 }
195
196 else
197 {
198 index0 = 0;
199 index1 = 2;
200 index2 = 1;
201 }
202
203 }
204
205 else
206 {
207
208 if (step0 >= step2)
209 {
210 index0 = 1;
211 index1 = 0;
212 index2 = 2;
213 }
214
215 else if (step2 >= step1)
216 {
217 index0 = 2;
218 index1 = 1;
219 index2 = 0;
220 }
221
222 else
223 {
224 index0 = 1;
225 index1 = 2;
226 index2 = 0;
227 }
228
229 }
230
231 uint32 count [3];
232
233 count [0] = count0;
234 count [1] = count1;
235 count [2] = count2;
236
237 count0 = count [index0];
238 count1 = count [index1];
239 count2 = count [index2];
240
241 int32 step [3];
242
243 step [0] = sStep0;
244 step [1] = sStep1;
245 step [2] = sStep2;
246
247 sStep0 = step [index0];
248 sStep1 = step [index1];
249 sStep2 = step [index2];
250
251 step [0] = dStep0;
252 step [1] = dStep1;
253 step [2] = dStep2;
254
255 dStep0 = step [index0];
256 dStep1 = step [index1];
257 dStep2 = step [index2];
258
259 if (sStep0 == ((int32) count1) * sStep1 &&
260 dStep0 == ((int32) count1) * dStep1)
261 {
262 count1 *= count0;
263 count0 = 1;
264 }
265
266 if (sStep1 == ((int32) count2) * sStep2 &&
267 dStep1 == ((int32) count2) * dStep2)
268 {
269 count2 *= count1;
270 count1 = 1;
271 }
272
273 }
274
275 /*****************************************************************************/
276
OptimizeOrder(const void * & sPtr,uint32 sPixelSize,uint32 & count0,uint32 & count1,uint32 & count2,int32 & sStep0,int32 & sStep1,int32 & sStep2)277 void OptimizeOrder (const void *&sPtr,
278 uint32 sPixelSize,
279 uint32 &count0,
280 uint32 &count1,
281 uint32 &count2,
282 int32 &sStep0,
283 int32 &sStep1,
284 int32 &sStep2)
285 {
286
287 void *dPtr = NULL;
288
289 int32 dStep0 = sStep0;
290 int32 dStep1 = sStep1;
291 int32 dStep2 = sStep2;
292
293 OptimizeOrder (sPtr,
294 dPtr,
295 sPixelSize,
296 sPixelSize,
297 count0,
298 count1,
299 count2,
300 sStep0,
301 sStep1,
302 sStep2,
303 dStep0,
304 dStep1,
305 dStep2);
306
307 }
308
309 /*****************************************************************************/
310
OptimizeOrder(void * & dPtr,uint32 dPixelSize,uint32 & count0,uint32 & count1,uint32 & count2,int32 & dStep0,int32 & dStep1,int32 & dStep2)311 void OptimizeOrder (void *&dPtr,
312 uint32 dPixelSize,
313 uint32 &count0,
314 uint32 &count1,
315 uint32 &count2,
316 int32 &dStep0,
317 int32 &dStep1,
318 int32 &dStep2)
319 {
320
321 const void *sPtr = NULL;
322
323 int32 sStep0 = dStep0;
324 int32 sStep1 = dStep1;
325 int32 sStep2 = dStep2;
326
327 OptimizeOrder (sPtr,
328 dPtr,
329 dPixelSize,
330 dPixelSize,
331 count0,
332 count1,
333 count2,
334 sStep0,
335 sStep1,
336 sStep2,
337 dStep0,
338 dStep1,
339 dStep2);
340
341 }
342
343 /*****************************************************************************/
344
dng_pixel_buffer()345 dng_pixel_buffer::dng_pixel_buffer ()
346
347 : fArea ()
348 , fPlane (0)
349 , fPlanes (1)
350 , fRowStep (1)
351 , fColStep (1)
352 , fPlaneStep (1)
353 , fPixelType (ttUndefined)
354 , fPixelSize (0)
355 , fData (NULL)
356 , fDirty (true)
357
358 {
359
360 }
361
362 /*****************************************************************************/
363
dng_pixel_buffer(const dng_rect & area,uint32 plane,uint32 planes,uint32 pixelType,uint32 planarConfiguration,void * data)364 dng_pixel_buffer::dng_pixel_buffer (const dng_rect &area,
365 uint32 plane,
366 uint32 planes,
367 uint32 pixelType,
368 uint32 planarConfiguration,
369 void *data)
370
371 : fArea (area)
372 , fPlane (plane)
373 , fPlanes (planes)
374 , fRowStep (0)
375 , fColStep (0)
376 , fPlaneStep (0)
377 , fPixelType (pixelType)
378 , fPixelSize (TagTypeSize(pixelType))
379 , fData (data)
380 , fDirty (true)
381
382 {
383
384 const char *overflowMessage = "Arithmetic overflow in pixel buffer setup";
385
386 // Initialize fRowStep, fColStep and fPlaneStep according to the desired
387 // pixel layout.
388 switch (planarConfiguration)
389 {
390 case pcInterleaved:
391 fPlaneStep = 1;
392 if (!ConvertUint32ToInt32 (fPlanes, &fColStep) ||
393 !SafeUint32ToInt32Mult (fArea.W(), fPlanes, &fRowStep))
394 {
395 ThrowMemoryFull (overflowMessage);
396 }
397 break;
398 case pcPlanar:
399 fColStep = 1;
400 // Even though we've hardened dng_rect::W() to guarantee that it
401 // will never return a result that's out of range for an int32,
402 // we still protect the conversion for defense in depth.
403 if (!ConvertUint32ToInt32 (fArea.W(), &fRowStep) ||
404 !SafeUint32ToInt32Mult (fArea.H(), fArea.W(), &fPlaneStep))
405 {
406 ThrowMemoryFull (overflowMessage);
407 }
408 break;
409 case pcRowInterleaved:
410 case pcRowInterleavedAlign16:
411 {
412 fColStep = 1;
413 uint32 planeStepUint32;
414 if (planarConfiguration == pcRowInterleaved)
415 {
416 planeStepUint32 = fArea.W();
417 }
418 else
419 {
420 if (!RoundUpForPixelSize (fArea.W(), fPixelSize,
421 &planeStepUint32))
422 {
423 ThrowMemoryFull (overflowMessage);
424 }
425 }
426 if (!ConvertUint32ToInt32 (planeStepUint32, &fPlaneStep) ||
427 !SafeUint32ToInt32Mult (planeStepUint32, fPlanes, &fRowStep))
428 {
429 ThrowMemoryFull (overflowMessage);
430 }
431 break;
432 }
433 default:
434 ThrowProgramError ("Invalid value for 'planarConfiguration'");
435 break;
436 }
437
438 }
439
440 /*****************************************************************************/
441
dng_pixel_buffer(const dng_pixel_buffer & buffer)442 dng_pixel_buffer::dng_pixel_buffer (const dng_pixel_buffer &buffer)
443
444 : fArea (buffer.fArea)
445 , fPlane (buffer.fPlane)
446 , fPlanes (buffer.fPlanes)
447 , fRowStep (buffer.fRowStep)
448 , fColStep (buffer.fColStep)
449 , fPlaneStep (buffer.fPlaneStep)
450 , fPixelType (buffer.fPixelType)
451 , fPixelSize (buffer.fPixelSize)
452 , fData (buffer.fData)
453 , fDirty (buffer.fDirty)
454
455 {
456
457 }
458
459 /*****************************************************************************/
460
operator =(const dng_pixel_buffer & buffer)461 dng_pixel_buffer & dng_pixel_buffer::operator= (const dng_pixel_buffer &buffer)
462 {
463
464 fArea = buffer.fArea;
465 fPlane = buffer.fPlane;
466 fPlanes = buffer.fPlanes;
467 fRowStep = buffer.fRowStep;
468 fColStep = buffer.fColStep;
469 fPlaneStep = buffer.fPlaneStep;
470 fPixelType = buffer.fPixelType;
471 fPixelSize = buffer.fPixelSize;
472 fPixelType = buffer.fPixelType;
473 fData = buffer.fData;
474 fDirty = buffer.fDirty;
475
476 return *this;
477
478 }
479
480 /*****************************************************************************/
481
~dng_pixel_buffer()482 dng_pixel_buffer::~dng_pixel_buffer ()
483 {
484
485 }
486
487 /*****************************************************************************/
488
489 #if qDebugPixelType
490
CheckPixelType(uint32 pixelType) const491 void dng_pixel_buffer::CheckPixelType (uint32 pixelType) const
492 {
493
494 if (fPixelType != pixelType)
495 {
496
497 DNG_REPORT ("Pixel type access mismatch");
498
499 }
500
501 }
502
503 #endif
504
505 /*****************************************************************************/
506
PixelRange() const507 uint32 dng_pixel_buffer::PixelRange () const
508 {
509
510 switch (fPixelType)
511 {
512
513 case ttByte:
514 case ttSByte:
515 {
516 return 0x0FF;
517 }
518
519 case ttShort:
520 case ttSShort:
521 {
522 return 0x0FFFF;
523 }
524
525 case ttLong:
526 case ttSLong:
527 {
528 return 0xFFFFFFFF;
529 }
530
531 default:
532 break;
533
534 }
535
536 return 0;
537
538 }
539
540 /*****************************************************************************/
541
SetConstant(const dng_rect & area,uint32 plane,uint32 planes,uint32 value)542 void dng_pixel_buffer::SetConstant (const dng_rect &area,
543 uint32 plane,
544 uint32 planes,
545 uint32 value)
546 {
547
548 uint32 rows = area.H ();
549 uint32 cols = area.W ();
550
551 void *dPtr = DirtyPixel (area.t,
552 area.l,
553 plane);
554
555 int32 dRowStep = fRowStep;
556 int32 dColStep = fColStep;
557 int32 dPlaneStep = fPlaneStep;
558
559 OptimizeOrder (dPtr,
560 fPixelSize,
561 rows,
562 cols,
563 planes,
564 dRowStep,
565 dColStep,
566 dPlaneStep);
567
568 switch (fPixelSize)
569 {
570
571 case 1:
572 {
573
574 if (rows == 1 && cols == 1 && dPlaneStep == 1 && value == 0)
575 {
576
577 DoZeroBytes (dPtr, planes);
578
579 }
580
581 else
582 {
583
584 DoSetArea8 ((uint8 *) dPtr,
585 (uint8) value,
586 rows,
587 cols,
588 planes,
589 dRowStep,
590 dColStep,
591 dPlaneStep);
592
593 }
594
595 break;
596
597 }
598
599 case 2:
600 {
601
602 if (rows == 1 && cols == 1 && dPlaneStep == 1 && value == 0)
603 {
604
605 DoZeroBytes (dPtr, planes << 1);
606
607 }
608
609 else
610 {
611
612 DoSetArea16 ((uint16 *) dPtr,
613 (uint16) value,
614 rows,
615 cols,
616 planes,
617 dRowStep,
618 dColStep,
619 dPlaneStep);
620
621 }
622
623 break;
624
625 }
626
627 case 4:
628 {
629
630 if (rows == 1 && cols == 1 && dPlaneStep == 1 && value == 0)
631 {
632
633 DoZeroBytes (dPtr, planes << 2);
634
635 }
636
637 else
638 {
639
640 DoSetArea32 ((uint32 *) dPtr,
641 value,
642 rows,
643 cols,
644 planes,
645 dRowStep,
646 dColStep,
647 dPlaneStep);
648
649 }
650
651 break;
652
653 }
654
655 default:
656 {
657
658 ThrowNotYetImplemented ();
659
660 }
661
662 }
663
664 }
665
666 /*****************************************************************************/
667
SetZero(const dng_rect & area,uint32 plane,uint32 planes)668 void dng_pixel_buffer::SetZero (const dng_rect &area,
669 uint32 plane,
670 uint32 planes)
671 {
672
673 uint32 value = 0;
674
675 switch (fPixelType)
676 {
677
678 case ttByte:
679 case ttShort:
680 case ttLong:
681 case ttFloat:
682 {
683 break;
684 }
685
686 case ttSShort:
687 {
688 value = 0x8000;
689 break;
690 }
691
692 default:
693 {
694
695 ThrowNotYetImplemented ();
696
697 }
698
699 }
700
701 SetConstant (area,
702 plane,
703 planes,
704 value);
705
706 }
707
708 /*****************************************************************************/
709
CopyArea(const dng_pixel_buffer & src,const dng_rect & area,uint32 srcPlane,uint32 dstPlane,uint32 planes)710 void dng_pixel_buffer::CopyArea (const dng_pixel_buffer &src,
711 const dng_rect &area,
712 uint32 srcPlane,
713 uint32 dstPlane,
714 uint32 planes)
715 {
716
717 uint32 rows = area.H ();
718 uint32 cols = area.W ();
719
720 const void *sPtr = src.ConstPixel (area.t,
721 area.l,
722 srcPlane);
723
724 void *dPtr = DirtyPixel (area.t,
725 area.l,
726 dstPlane);
727
728 int32 sRowStep = src.fRowStep;
729 int32 sColStep = src.fColStep;
730 int32 sPlaneStep = src.fPlaneStep;
731
732 int32 dRowStep = fRowStep;
733 int32 dColStep = fColStep;
734 int32 dPlaneStep = fPlaneStep;
735
736 OptimizeOrder (sPtr,
737 dPtr,
738 src.fPixelSize,
739 fPixelSize,
740 rows,
741 cols,
742 planes,
743 sRowStep,
744 sColStep,
745 sPlaneStep,
746 dRowStep,
747 dColStep,
748 dPlaneStep);
749
750 if (fPixelType == src.fPixelType)
751 {
752
753 if (rows == 1 && cols == 1 && sPlaneStep == 1 && dPlaneStep == 1)
754 {
755
756 DoCopyBytes (sPtr,
757 dPtr,
758 planes * fPixelSize);
759
760 }
761
762 else switch (fPixelSize)
763 {
764
765 case 1:
766 {
767
768 DoCopyArea8 ((const uint8 *) sPtr,
769 (uint8 *) dPtr,
770 rows,
771 cols,
772 planes,
773 sRowStep,
774 sColStep,
775 sPlaneStep,
776 dRowStep,
777 dColStep,
778 dPlaneStep);
779
780 break;
781
782 }
783
784 case 2:
785 {
786
787 DoCopyArea16 ((const uint16 *) sPtr,
788 (uint16 *) dPtr,
789 rows,
790 cols,
791 planes,
792 sRowStep,
793 sColStep,
794 sPlaneStep,
795 dRowStep,
796 dColStep,
797 dPlaneStep);
798
799 break;
800
801 }
802
803 case 4:
804 {
805
806 DoCopyArea32 ((const uint32 *) sPtr,
807 (uint32 *) dPtr,
808 rows,
809 cols,
810 planes,
811 sRowStep,
812 sColStep,
813 sPlaneStep,
814 dRowStep,
815 dColStep,
816 dPlaneStep);
817
818 break;
819
820 }
821
822 default:
823 {
824
825 ThrowNotYetImplemented ();
826
827 }
828
829 }
830
831 }
832
833 else if (src.fPixelType == ttByte)
834 {
835
836 switch (fPixelType)
837 {
838
839 case ttShort:
840 {
841
842 DoCopyArea8_16 ((const uint8 *) sPtr,
843 (uint16 *) dPtr,
844 rows,
845 cols,
846 planes,
847 sRowStep,
848 sColStep,
849 sPlaneStep,
850 dRowStep,
851 dColStep,
852 dPlaneStep);
853
854 break;
855
856 }
857
858 case ttSShort:
859 {
860
861 DoCopyArea8_S16 ((const uint8 *) sPtr,
862 (int16 *) dPtr,
863 rows,
864 cols,
865 planes,
866 sRowStep,
867 sColStep,
868 sPlaneStep,
869 dRowStep,
870 dColStep,
871 dPlaneStep);
872
873 break;
874
875 }
876
877 case ttLong:
878 {
879
880 DoCopyArea8_32 ((const uint8 *) sPtr,
881 (uint32 *) dPtr,
882 rows,
883 cols,
884 planes,
885 sRowStep,
886 sColStep,
887 sPlaneStep,
888 dRowStep,
889 dColStep,
890 dPlaneStep);
891
892 break;
893
894 }
895
896 case ttFloat:
897 {
898
899 DoCopyArea8_R32 ((const uint8 *) sPtr,
900 (real32 *) dPtr,
901 rows,
902 cols,
903 planes,
904 sRowStep,
905 sColStep,
906 sPlaneStep,
907 dRowStep,
908 dColStep,
909 dPlaneStep,
910 src.PixelRange ());
911
912 break;
913
914 }
915
916 default:
917 {
918
919 ThrowNotYetImplemented ();
920
921 }
922
923 }
924
925 }
926
927 else if (src.fPixelType == ttShort)
928 {
929
930 switch (fPixelType)
931 {
932
933 case ttByte:
934 {
935
936 DoCopyArea8 (((const uint8 *) sPtr) + (qDNGBigEndian ? 1 : 0),
937 (uint8 *) dPtr,
938 rows,
939 cols,
940 planes,
941 sRowStep << 1,
942 sColStep << 1,
943 sPlaneStep << 1,
944 dRowStep,
945 dColStep,
946 dPlaneStep);
947
948 break;
949
950 }
951
952 case ttSShort:
953 {
954
955 DoCopyArea16_S16 ((const uint16 *) sPtr,
956 (int16 *) dPtr,
957 rows,
958 cols,
959 planes,
960 sRowStep,
961 sColStep,
962 sPlaneStep,
963 dRowStep,
964 dColStep,
965 dPlaneStep);
966
967 break;
968
969 }
970
971 case ttLong:
972 {
973
974 DoCopyArea16_32 ((const uint16 *) sPtr,
975 (uint32 *) dPtr,
976 rows,
977 cols,
978 planes,
979 sRowStep,
980 sColStep,
981 sPlaneStep,
982 dRowStep,
983 dColStep,
984 dPlaneStep);
985
986 break;
987
988 }
989
990 case ttFloat:
991 {
992
993 DoCopyArea16_R32 ((const uint16 *) sPtr,
994 (real32 *) dPtr,
995 rows,
996 cols,
997 planes,
998 sRowStep,
999 sColStep,
1000 sPlaneStep,
1001 dRowStep,
1002 dColStep,
1003 dPlaneStep,
1004 src.PixelRange ());
1005
1006 break;
1007
1008 }
1009
1010 default:
1011 {
1012
1013 ThrowNotYetImplemented ();
1014
1015 }
1016
1017 }
1018
1019 }
1020
1021 else if (src.fPixelType == ttSShort)
1022 {
1023
1024 switch (fPixelType)
1025 {
1026
1027 case ttByte:
1028 {
1029
1030 DoCopyArea8 (((const uint8 *) sPtr) + (qDNGBigEndian ? 1 : 0),
1031 (uint8 *) dPtr,
1032 rows,
1033 cols,
1034 planes,
1035 sRowStep << 1,
1036 sColStep << 1,
1037 sPlaneStep << 1,
1038 dRowStep,
1039 dColStep,
1040 dPlaneStep);
1041
1042 break;
1043
1044 }
1045
1046 case ttShort:
1047 {
1048
1049 // Moving between signed 16 bit values and unsigned 16
1050 // bit values just requires toggling the sign bit. So
1051 // we can use the "backwards" bottleneck.
1052
1053 DoCopyArea16_S16 ((const uint16 *) sPtr,
1054 (int16 *) dPtr,
1055 rows,
1056 cols,
1057 planes,
1058 sRowStep,
1059 sColStep,
1060 sPlaneStep,
1061 dRowStep,
1062 dColStep,
1063 dPlaneStep);
1064
1065 break;
1066
1067 }
1068
1069 case ttFloat:
1070 {
1071
1072 DoCopyAreaS16_R32 ((const int16 *) sPtr,
1073 (real32 *) dPtr,
1074 rows,
1075 cols,
1076 planes,
1077 sRowStep,
1078 sColStep,
1079 sPlaneStep,
1080 dRowStep,
1081 dColStep,
1082 dPlaneStep,
1083 src.PixelRange ());
1084
1085 break;
1086
1087 }
1088
1089 default:
1090 {
1091
1092 ThrowNotYetImplemented ();
1093
1094 }
1095
1096 }
1097
1098 }
1099
1100 else if (src.fPixelType == ttLong)
1101 {
1102
1103 switch (fPixelType)
1104 {
1105
1106 case ttByte:
1107 {
1108
1109 DoCopyArea8 (((const uint8 *) sPtr) + (qDNGBigEndian ? 3 : 0),
1110 (uint8 *) dPtr,
1111 rows,
1112 cols,
1113 planes,
1114 sRowStep << 2,
1115 sColStep << 2,
1116 sPlaneStep << 2,
1117 dRowStep,
1118 dColStep,
1119 dPlaneStep);
1120
1121 break;
1122
1123 }
1124
1125 case ttShort:
1126 {
1127
1128 DoCopyArea16 (((const uint16 *) sPtr) + (qDNGBigEndian ? 1 : 0),
1129 (uint16 *) dPtr,
1130 rows,
1131 cols,
1132 planes,
1133 sRowStep << 1,
1134 sColStep << 1,
1135 sPlaneStep << 1,
1136 dRowStep,
1137 dColStep,
1138 dPlaneStep);
1139
1140 break;
1141
1142 }
1143
1144 default:
1145 {
1146
1147 ThrowNotYetImplemented ();
1148
1149 }
1150
1151 }
1152
1153 }
1154
1155 else if (src.fPixelType == ttFloat)
1156 {
1157
1158 switch (fPixelType)
1159 {
1160
1161 case ttByte:
1162 {
1163
1164 DoCopyAreaR32_8 ((const real32 *) sPtr,
1165 (uint8 *) dPtr,
1166 rows,
1167 cols,
1168 planes,
1169 sRowStep,
1170 sColStep,
1171 sPlaneStep,
1172 dRowStep,
1173 dColStep,
1174 dPlaneStep,
1175 PixelRange ());
1176
1177 break;
1178
1179 }
1180
1181 case ttShort:
1182 {
1183
1184 DoCopyAreaR32_16 ((const real32 *) sPtr,
1185 (uint16 *) dPtr,
1186 rows,
1187 cols,
1188 planes,
1189 sRowStep,
1190 sColStep,
1191 sPlaneStep,
1192 dRowStep,
1193 dColStep,
1194 dPlaneStep,
1195 PixelRange ());
1196
1197 break;
1198
1199 }
1200
1201 case ttSShort:
1202 {
1203
1204 DoCopyAreaR32_S16 ((const real32 *) sPtr,
1205 (int16 *) dPtr,
1206 rows,
1207 cols,
1208 planes,
1209 sRowStep,
1210 sColStep,
1211 sPlaneStep,
1212 dRowStep,
1213 dColStep,
1214 dPlaneStep,
1215 PixelRange ());
1216
1217 break;
1218
1219 }
1220
1221 default:
1222 {
1223
1224 ThrowNotYetImplemented ();
1225
1226 }
1227
1228 }
1229
1230 }
1231
1232 else
1233 {
1234
1235 ThrowNotYetImplemented ();
1236
1237 }
1238
1239 }
1240
1241 /*****************************************************************************/
1242
RepeatPhase(const dng_rect & srcArea,const dng_rect & dstArea)1243 dng_point dng_pixel_buffer::RepeatPhase (const dng_rect &srcArea,
1244 const dng_rect &dstArea)
1245 {
1246
1247 int32 repeatV = srcArea.H ();
1248 int32 repeatH = srcArea.W ();
1249
1250 int32 phaseV;
1251 int32 phaseH;
1252
1253 if (srcArea.t >= dstArea.t)
1254 {
1255 phaseV = (repeatV - ((srcArea.t - dstArea.t) % repeatV)) % repeatV;
1256 }
1257 else
1258 {
1259 phaseV = (dstArea.t - srcArea.t) % repeatV;
1260 }
1261
1262 if (srcArea.l >= dstArea.l)
1263 {
1264 phaseH = (repeatH - ((srcArea.l - dstArea.l) % repeatH)) % repeatH;
1265 }
1266 else
1267 {
1268 phaseH = (dstArea.l - srcArea.l) % repeatH;
1269 }
1270
1271 return dng_point (phaseV, phaseH);
1272
1273 }
1274
1275 /*****************************************************************************/
1276
RepeatArea(const dng_rect & srcArea,const dng_rect & dstArea)1277 void dng_pixel_buffer::RepeatArea (const dng_rect &srcArea,
1278 const dng_rect &dstArea)
1279 {
1280
1281 dng_point repeat = srcArea.Size ();
1282
1283 dng_point phase = RepeatPhase (srcArea,
1284 dstArea);
1285
1286 const void *sPtr = ConstPixel (srcArea.t,
1287 srcArea.l,
1288 fPlane);
1289
1290 void *dPtr = DirtyPixel (dstArea.t,
1291 dstArea.l,
1292 fPlane);
1293
1294 uint32 rows = dstArea.H ();
1295 uint32 cols = dstArea.W ();
1296
1297 switch (fPixelSize)
1298 {
1299
1300 case 1:
1301 {
1302
1303 DoRepeatArea8 ((const uint8 *) sPtr,
1304 (uint8 *) dPtr,
1305 rows,
1306 cols,
1307 fPlanes,
1308 fRowStep,
1309 fColStep,
1310 fPlaneStep,
1311 repeat.v,
1312 repeat.h,
1313 phase.v,
1314 phase.h);
1315
1316 break;
1317
1318 }
1319
1320 case 2:
1321 {
1322
1323 DoRepeatArea16 ((const uint16 *) sPtr,
1324 (uint16 *) dPtr,
1325 rows,
1326 cols,
1327 fPlanes,
1328 fRowStep,
1329 fColStep,
1330 fPlaneStep,
1331 repeat.v,
1332 repeat.h,
1333 phase.v,
1334 phase.h);
1335
1336 break;
1337
1338 }
1339
1340 case 4:
1341 {
1342
1343 DoRepeatArea32 ((const uint32 *) sPtr,
1344 (uint32 *) dPtr,
1345 rows,
1346 cols,
1347 fPlanes,
1348 fRowStep,
1349 fColStep,
1350 fPlaneStep,
1351 repeat.v,
1352 repeat.h,
1353 phase.v,
1354 phase.h);
1355
1356 break;
1357
1358 }
1359
1360 default:
1361 {
1362
1363 ThrowNotYetImplemented ();
1364
1365 }
1366
1367 }
1368
1369 }
1370
1371 /*****************************************************************************/
1372
RepeatSubArea(const dng_rect subArea,uint32 repeatV,uint32 repeatH)1373 void dng_pixel_buffer::RepeatSubArea (const dng_rect subArea,
1374 uint32 repeatV,
1375 uint32 repeatH)
1376 {
1377
1378 if (fArea.t < subArea.t)
1379 {
1380
1381 RepeatArea (dng_rect (subArea.t , fArea.l,
1382 subArea.t + repeatV, fArea.r),
1383 dng_rect (fArea.t , fArea.l,
1384 subArea.t , fArea.r));
1385
1386 }
1387
1388 if (fArea.b > subArea.b)
1389 {
1390
1391 RepeatArea (dng_rect (subArea.b - repeatV, fArea.l,
1392 subArea.b , fArea.r),
1393 dng_rect (subArea.b , fArea.l,
1394 fArea.b , fArea.r));
1395
1396 }
1397
1398 if (fArea.l < subArea.l)
1399 {
1400
1401 RepeatArea (dng_rect (fArea.t, subArea.l ,
1402 fArea.b, subArea.l + repeatH),
1403 dng_rect (fArea.t, fArea.l ,
1404 fArea.b, subArea.l ));
1405
1406 }
1407
1408 if (fArea.r > subArea.r)
1409 {
1410
1411 RepeatArea (dng_rect (fArea.t, subArea.r - repeatH,
1412 fArea.b, subArea.r ),
1413 dng_rect (fArea.t, subArea.r ,
1414 fArea.b, fArea.r ));
1415
1416 }
1417
1418 }
1419
1420 /*****************************************************************************/
1421
ShiftRight(uint32 shift)1422 void dng_pixel_buffer::ShiftRight (uint32 shift)
1423 {
1424
1425 if (fPixelType != ttShort)
1426 {
1427
1428 ThrowNotYetImplemented ();
1429
1430 }
1431
1432 uint32 rows = fArea.H ();
1433 uint32 cols = fArea.W ();
1434
1435 uint32 planes = fPlanes;
1436
1437 void *dPtr = DirtyPixel (fArea.t,
1438 fArea.l,
1439 fPlane);
1440
1441 const void *sPtr = dPtr;
1442
1443 int32 sRowStep = fRowStep;
1444 int32 sColStep = fColStep;
1445 int32 sPlaneStep = fPlaneStep;
1446
1447 int32 dRowStep = fRowStep;
1448 int32 dColStep = fColStep;
1449 int32 dPlaneStep = fPlaneStep;
1450
1451 OptimizeOrder (sPtr,
1452 dPtr,
1453 fPixelSize,
1454 fPixelSize,
1455 rows,
1456 cols,
1457 planes,
1458 sRowStep,
1459 sColStep,
1460 sPlaneStep,
1461 dRowStep,
1462 dColStep,
1463 dPlaneStep);
1464
1465 DoShiftRight16 ((uint16 *) dPtr,
1466 rows,
1467 cols,
1468 planes,
1469 dRowStep,
1470 dColStep,
1471 dPlaneStep,
1472 shift);
1473
1474 }
1475
1476 /*****************************************************************************/
1477
FlipH()1478 void dng_pixel_buffer::FlipH ()
1479 {
1480
1481 fData = InternalPixel (fArea.t, fArea.r - 1);
1482
1483 fColStep = -fColStep;
1484
1485 }
1486
1487 /*****************************************************************************/
1488
FlipV()1489 void dng_pixel_buffer::FlipV ()
1490 {
1491
1492 fData = InternalPixel (fArea.b - 1, fArea.l);
1493
1494 fRowStep = -fRowStep;
1495
1496 }
1497
1498 /*****************************************************************************/
1499
FlipZ()1500 void dng_pixel_buffer::FlipZ ()
1501 {
1502
1503 fData = InternalPixel (fArea.t, fArea.l, fPlanes - 1);
1504
1505 fPlaneStep = -fPlaneStep;
1506
1507 }
1508
1509 /*****************************************************************************/
1510
EqualArea(const dng_pixel_buffer & src,const dng_rect & area,uint32 plane,uint32 planes) const1511 bool dng_pixel_buffer::EqualArea (const dng_pixel_buffer &src,
1512 const dng_rect &area,
1513 uint32 plane,
1514 uint32 planes) const
1515 {
1516
1517 uint32 rows = area.H ();
1518 uint32 cols = area.W ();
1519
1520 const void *sPtr = src.ConstPixel (area.t,
1521 area.l,
1522 plane);
1523
1524 const void *dPtr = ConstPixel (area.t,
1525 area.l,
1526 plane);
1527
1528 int32 sRowStep = src.fRowStep;
1529 int32 sColStep = src.fColStep;
1530 int32 sPlaneStep = src.fPlaneStep;
1531
1532 int32 dRowStep = fRowStep;
1533 int32 dColStep = fColStep;
1534 int32 dPlaneStep = fPlaneStep;
1535
1536 if (fPixelType == src.fPixelType)
1537 {
1538
1539 if (rows == 1 && cols == 1 && sPlaneStep == 1 && dPlaneStep == 1)
1540 {
1541
1542 return DoEqualBytes (sPtr,
1543 dPtr,
1544 planes * fPixelSize);
1545
1546 }
1547
1548 else switch (fPixelSize)
1549 {
1550
1551 case 1:
1552 {
1553
1554 return DoEqualArea8 ((const uint8 *) sPtr,
1555 (const uint8 *) dPtr,
1556 rows,
1557 cols,
1558 planes,
1559 sRowStep,
1560 sColStep,
1561 sPlaneStep,
1562 dRowStep,
1563 dColStep,
1564 dPlaneStep);
1565
1566 break;
1567
1568 }
1569
1570 case 2:
1571 {
1572
1573 return DoEqualArea16 ((const uint16 *) sPtr,
1574 (const uint16 *) dPtr,
1575 rows,
1576 cols,
1577 planes,
1578 sRowStep,
1579 sColStep,
1580 sPlaneStep,
1581 dRowStep,
1582 dColStep,
1583 dPlaneStep);
1584
1585 break;
1586
1587 }
1588
1589 case 4:
1590 {
1591
1592 return DoEqualArea32 ((const uint32 *) sPtr,
1593 (const uint32 *) dPtr,
1594 rows,
1595 cols,
1596 planes,
1597 sRowStep,
1598 sColStep,
1599 sPlaneStep,
1600 dRowStep,
1601 dColStep,
1602 dPlaneStep);
1603
1604 break;
1605
1606 }
1607
1608 default:
1609 {
1610
1611 ThrowNotYetImplemented ();
1612
1613 return false;
1614
1615 }
1616
1617 }
1618
1619 }
1620
1621 else
1622 return false;
1623
1624 }
1625
1626 /*****************************************************************************/
1627
1628 namespace
1629 {
1630
1631 template <typename T>
MaxDiff(const T * src1,int32 s1RowStep,int32 s1PlaneStep,const T * src2,int32 s2RowStep,int32 s2PlaneStep,uint32 rows,uint32 cols,uint32 planes)1632 real64 MaxDiff (const T *src1,
1633 int32 s1RowStep,
1634 int32 s1PlaneStep,
1635 const T *src2,
1636 int32 s2RowStep,
1637 int32 s2PlaneStep,
1638 uint32 rows,
1639 uint32 cols,
1640 uint32 planes)
1641 {
1642
1643 real64 result = 0.0;
1644
1645 for (uint32 plane = 0; plane < planes; plane++)
1646 {
1647
1648 const T *src1Save = src1;
1649 const T *src2Save = src2;
1650
1651 for (uint32 row = 0; row < rows; row++)
1652 {
1653
1654 for (uint32 col = 0; col < cols; col++)
1655 {
1656 real64 diff = fabs ((real64)src1 [col] - src2 [col]);
1657
1658 if (diff > result)
1659 result = diff;
1660
1661 }
1662
1663 src1 += s1RowStep;
1664 src2 += s2RowStep;
1665
1666 }
1667
1668 src1 = src1Save + s1PlaneStep;
1669 src2 = src2Save + s2PlaneStep;
1670
1671 }
1672
1673 return result;
1674
1675 }
1676
1677 template <typename T>
MaxDiff(const T * src1,int32 s1ColStep,int32 s1RowStep,int32 s1PlaneStep,const T * src2,int32 s2ColStep,int32 s2RowStep,int32 s2PlaneStep,uint32 rows,uint32 cols,uint32 planes)1678 real64 MaxDiff (const T *src1,
1679 int32 s1ColStep,
1680 int32 s1RowStep,
1681 int32 s1PlaneStep,
1682 const T *src2,
1683 int32 s2ColStep,
1684 int32 s2RowStep,
1685 int32 s2PlaneStep,
1686 uint32 rows,
1687 uint32 cols,
1688 uint32 planes)
1689 {
1690
1691 if (s1ColStep == s2ColStep &&
1692 s1ColStep == 1)
1693 return MaxDiff (src1,
1694 s1RowStep,
1695 s1PlaneStep,
1696 src2,
1697 s2RowStep,
1698 s2PlaneStep,
1699 rows,
1700 cols,
1701 planes);
1702
1703 real64 result = 0.0;
1704
1705 for (uint32 plane = 0; plane < planes; plane++)
1706 {
1707
1708 const T *src1Save = src1;
1709 const T *src2Save = src2;
1710
1711 for (uint32 row = 0; row < rows; row++)
1712 {
1713
1714 for (uint32 col = 0; col < cols; col++)
1715 {
1716 real64 diff = fabs ((real64)src1 [col * s1ColStep] - src2 [col * s2ColStep]);
1717
1718 if (diff > result)
1719 result = diff;
1720
1721 }
1722
1723 src1 += s1RowStep;
1724 src2 += s2RowStep;
1725
1726 }
1727
1728 src1 = src1Save + s1PlaneStep;
1729 src2 = src2Save + s2PlaneStep;
1730
1731 }
1732
1733
1734 return result;
1735
1736 }
1737 }
1738
MaximumDifference(const dng_pixel_buffer & rhs,const dng_rect & area,uint32 plane,uint32 planes) const1739 real64 dng_pixel_buffer::MaximumDifference (const dng_pixel_buffer &rhs,
1740 const dng_rect &area,
1741 uint32 plane,
1742 uint32 planes) const
1743 {
1744
1745 uint32 rows = area.H ();
1746 uint32 cols = area.W ();
1747
1748 const void *s1Ptr = rhs.ConstPixel (area.t,
1749 area.l,
1750 plane);
1751
1752 const void *s2Ptr = ConstPixel (area.t,
1753 area.l,
1754 plane);
1755
1756 int32 s1RowStep = rhs.fRowStep;
1757 int32 s1ColStep = rhs.fColStep;
1758 int32 s1PlaneStep = rhs.fPlaneStep;
1759
1760 int32 s2RowStep = fRowStep;
1761 int32 s2ColStep = fColStep;
1762 int32 s2PlaneStep = fPlaneStep;
1763
1764 if (fPixelType == rhs.fPixelType)
1765 {
1766
1767 switch (fPixelType)
1768 {
1769
1770 case ttByte:
1771 return MaxDiff ((const uint8 *)s1Ptr,
1772 s1ColStep,
1773 s1RowStep,
1774 s1PlaneStep,
1775 (const uint8 *)s2Ptr,
1776 s2ColStep,
1777 s2RowStep,
1778 s2PlaneStep,
1779 rows,
1780 cols,
1781 planes);
1782
1783 break;
1784
1785 case ttShort:
1786 return MaxDiff ((const uint16 *)s1Ptr,
1787 s1ColStep,
1788 s1RowStep,
1789 s1PlaneStep,
1790 (const uint16 *)s2Ptr,
1791 s2ColStep,
1792 s2RowStep,
1793 s2PlaneStep,
1794 rows,
1795 cols,
1796 planes);
1797
1798 break;
1799
1800 case ttLong:
1801 return MaxDiff ((const uint32 *)s1Ptr,
1802 s1ColStep,
1803 s1RowStep,
1804 s1PlaneStep,
1805 (const uint32 *)s2Ptr,
1806 s2ColStep,
1807 s2RowStep,
1808 s2PlaneStep,
1809 rows,
1810 cols,
1811 planes);
1812
1813 break;
1814
1815 case ttSByte:
1816 return MaxDiff ((const int8 *)s1Ptr,
1817 s1ColStep,
1818 s1RowStep,
1819 s1PlaneStep,
1820 (const int8 *)s2Ptr,
1821 s2ColStep,
1822 s2RowStep,
1823 s2PlaneStep,
1824 rows,
1825 cols,
1826 planes);
1827
1828 break;
1829
1830 case ttSShort:
1831 return MaxDiff ((const int16 *)s1Ptr,
1832 s1ColStep,
1833 s1RowStep,
1834 s1PlaneStep,
1835 (const int16 *)s2Ptr,
1836 s2ColStep,
1837 s2RowStep,
1838 s2PlaneStep,
1839 rows,
1840 cols,
1841 planes);
1842
1843 break;
1844
1845 case ttSLong:
1846 return MaxDiff ((const int32 *)s1Ptr,
1847 s1ColStep,
1848 s1RowStep,
1849 s1PlaneStep,
1850 (const int32 *)s2Ptr,
1851 s2ColStep,
1852 s2RowStep,
1853 s2PlaneStep,
1854 rows,
1855 cols,
1856 planes);
1857
1858 break;
1859
1860 case ttFloat:
1861 return MaxDiff ((const real32 *)s1Ptr,
1862 s1ColStep,
1863 s1RowStep,
1864 s1PlaneStep,
1865 (const real32 *)s2Ptr,
1866 s2ColStep,
1867 s2RowStep,
1868 s2PlaneStep,
1869 rows,
1870 cols,
1871 planes);
1872
1873 break;
1874
1875 case ttDouble:
1876 return MaxDiff ((const real64 *)s1Ptr,
1877 s1ColStep,
1878 s1RowStep,
1879 s1PlaneStep,
1880 (const real64 *)s2Ptr,
1881 s2ColStep,
1882 s2RowStep,
1883 s2PlaneStep,
1884 rows,
1885 cols,
1886 planes);
1887
1888 break;
1889
1890
1891 default:
1892 {
1893
1894 ThrowNotYetImplemented ();
1895
1896 return 0.0;
1897
1898 }
1899
1900 }
1901
1902 }
1903
1904 else
1905 ThrowProgramError ("attempt to difference pixel buffers of different formats.");
1906
1907 return 0.0;
1908
1909 }
1910
1911 /*****************************************************************************/
1912