Home | History | Annotate | Download | only in source
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    482 dng_pixel_buffer::~dng_pixel_buffer ()
    483 	{
    484 
    485 	}
    486 
    487 /*****************************************************************************/
    488 
    489 #if qDebugPixelType
    490 
    491 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 
    507 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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1511 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>
   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 
   1739 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