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