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
28namespace {
29
30bool 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
40void 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
277void 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
311void 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
345dng_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
364dng_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
442dng_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
461dng_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
482dng_pixel_buffer::~dng_pixel_buffer ()
483	{
484
485	}
486
487/*****************************************************************************/
488
489#if qDebugPixelType
490
491void 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
507uint32 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
542void 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
668void 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
710void 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
1243dng_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
1277void 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
1373void 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
1422void 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
1478void dng_pixel_buffer::FlipH ()
1479	{
1480
1481	fData = InternalPixel (fArea.t, fArea.r - 1);
1482
1483	fColStep = -fColStep;
1484
1485	}
1486
1487/*****************************************************************************/
1488
1489void dng_pixel_buffer::FlipV ()
1490	{
1491
1492	fData = InternalPixel (fArea.b - 1, fArea.l);
1493
1494	fRowStep = -fRowStep;
1495
1496	}
1497
1498/*****************************************************************************/
1499
1500void dng_pixel_buffer::FlipZ ()
1501	{
1502
1503	fData = InternalPixel (fArea.t, fArea.l, fPlanes - 1);
1504
1505	fPlaneStep = -fPlaneStep;
1506
1507	}
1508
1509/*****************************************************************************/
1510
1511bool 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
1628namespace
1629	{
1630
1631	template <typename T>
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>
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
1739real64 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