Home | History | Annotate | Download | only in source
      1 /*****************************************************************************/
      2 // Copyright 2006-2011 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_linearization_info.cpp#1 $ */
     10 /* $DateTime: 2012/05/30 13:28:51 $ */
     11 /* $Change: 832332 $ */
     12 /* $Author: tknoll $ */
     13 
     14 /*****************************************************************************/
     15 
     16 #include "dng_linearization_info.h"
     17 
     18 #include "dng_area_task.h"
     19 #include "dng_exceptions.h"
     20 #include "dng_host.h"
     21 #include "dng_image.h"
     22 #include "dng_info.h"
     23 #include "dng_negative.h"
     24 #include "dng_pixel_buffer.h"
     25 #include "dng_safe_arithmetic.h"
     26 #include "dng_tag_types.h"
     27 #include "dng_tile_iterator.h"
     28 #include "dng_utils.h"
     29 
     30 /*****************************************************************************/
     31 
     32 class dng_linearize_plane
     33 	{
     34 
     35 	private:
     36 
     37 		const dng_image & fSrcImage;
     38 		      dng_image & fDstImage;
     39 
     40 		uint32 fPlane;
     41 
     42 		dng_rect fActiveArea;
     43 
     44 		uint32 fSrcPixelType;
     45 		uint32 fDstPixelType;
     46 
     47 		bool fReal32;
     48 
     49 		real32 fScale;
     50 
     51 		AutoPtr<dng_memory_block> fScale_buffer;
     52 
     53 		uint32 fBlack_2D_rows;
     54 		uint32 fBlack_2D_cols;
     55 
     56 		AutoPtr<dng_memory_block> fBlack_2D_buffer;
     57 
     58 		uint32 fBlack_1D_rows;
     59 
     60 		AutoPtr<dng_memory_block> fBlack_1D_buffer;
     61 
     62 	public:
     63 
     64 		dng_linearize_plane (dng_host &host,
     65 							 dng_linearization_info &info,
     66 							 const dng_image &srcImage,
     67 							 dng_image &dstImage,
     68 							 uint32 plane);
     69 
     70 		~dng_linearize_plane ();
     71 
     72 		void Process (const dng_rect &tile);
     73 
     74 	};
     75 
     76 /*****************************************************************************/
     77 
     78 dng_linearize_plane::dng_linearize_plane (dng_host &host,
     79 										  dng_linearization_info &info,
     80 										  const dng_image &srcImage,
     81 										  dng_image &dstImage,
     82 										  uint32 plane)
     83 
     84 	:	fSrcImage (srcImage)
     85 	,	fDstImage (dstImage)
     86 	,	fPlane (plane)
     87 	,	fActiveArea (info.fActiveArea)
     88 	,	fSrcPixelType (srcImage.PixelType ())
     89 	,	fDstPixelType (dstImage.PixelType ())
     90 	,	fReal32 (false)
     91 	,	fScale (0.0f)
     92 	,	fScale_buffer ()
     93 	,	fBlack_2D_rows (0)
     94 	,	fBlack_2D_cols (0)
     95 	,	fBlack_2D_buffer ()
     96 	,	fBlack_1D_rows (0)
     97 	,	fBlack_1D_buffer ()
     98 
     99 	{
    100 
    101 	uint32 j;
    102 	uint32 k;
    103 
    104 	// Make sure the source pixel type is supported.
    105 
    106 	if (fSrcPixelType != ttByte  &&
    107 		fSrcPixelType != ttShort &&
    108 		fSrcPixelType != ttLong  &&
    109 		fSrcPixelType != ttFloat)
    110 		{
    111 
    112 		DNG_REPORT ("Unsupported source pixel type");
    113 
    114 		ThrowProgramError ();
    115 
    116 		}
    117 
    118 	if (fDstPixelType != ttShort &&
    119 		fDstPixelType != ttFloat)
    120 		{
    121 
    122 		DNG_REPORT ("Unsupported destination pixel type");
    123 
    124 		ThrowProgramError ();
    125 
    126 		}
    127 
    128 	if (fSrcPixelType == ttFloat &&
    129 		fDstPixelType != ttFloat)
    130 		{
    131 
    132 		DNG_REPORT ("Cannot convert floating point stage1 to non-floating stage2");
    133 
    134 		ThrowProgramError ();
    135 
    136 		}
    137 
    138 	// Are we using floating point math?
    139 
    140 	fReal32 = (fSrcPixelType == ttLong ||
    141 			   fDstPixelType == ttFloat);
    142 
    143 	// Find the scale for this plane.
    144 
    145 	real64 maxBlack = info.MaxBlackLevel (plane);
    146 
    147 	real64 minRange = info.fWhiteLevel [plane] - maxBlack;
    148 
    149 	if (minRange <= 0.0)
    150 		{
    151 		ThrowBadFormat ();
    152 		}
    153 
    154 	real64 scale = 1.0 / minRange;
    155 
    156 	fScale = (real32) scale;
    157 
    158 	// Calculate two-dimensional black pattern, if any.
    159 
    160 	if (info.fBlackDeltaH.Get ())
    161 		{
    162 
    163 		fBlack_2D_rows = info.fBlackLevelRepeatRows;
    164 		fBlack_2D_cols = info.fActiveArea.W ();
    165 
    166 		}
    167 
    168 	else if (info.fBlackLevelRepeatCols > 1)
    169 		{
    170 
    171 		fBlack_2D_rows = info.fBlackLevelRepeatRows;
    172 		fBlack_2D_cols = info.fBlackLevelRepeatCols;
    173 
    174 		}
    175 
    176 	if (fBlack_2D_rows)
    177 		{
    178 
    179 		fBlack_2D_buffer.Reset (host.Allocate (
    180 			SafeUint32Mult (fBlack_2D_rows, fBlack_2D_cols, 4)));
    181 
    182 		for (j = 0; j < fBlack_2D_rows; j++)
    183 			{
    184 
    185 			for (k = 0;  k < fBlack_2D_cols; k++)
    186 				{
    187 
    188 				real64 x = info.fBlackLevel [j]
    189 											[k % info.fBlackLevelRepeatCols]
    190 											[plane];
    191 
    192 				if (info.fBlackDeltaH.Get ())
    193 					{
    194 
    195 					x += info.fBlackDeltaH->Buffer_real64 () [k];
    196 
    197 					}
    198 
    199 				x *= scale;
    200 
    201 				uint32 index = j * fBlack_2D_cols + k;
    202 
    203 				if (fReal32)
    204 					{
    205 
    206 					fBlack_2D_buffer->Buffer_real32 () [index] = (real32) x;
    207 
    208 					}
    209 
    210 				else
    211 					{
    212 
    213 					x *= 0x0FFFF * 256.0;
    214 
    215 					int32 y = Round_int32 (x);
    216 
    217 					fBlack_2D_buffer->Buffer_int32 () [index] = y;
    218 
    219 					}
    220 
    221 				}
    222 
    223 			}
    224 
    225 		}
    226 
    227 	// Calculate one-dimensional (per row) black pattern, if any.
    228 
    229 	if (info.fBlackDeltaV.Get ())
    230 		{
    231 
    232 		fBlack_1D_rows = info.fActiveArea.H ();
    233 
    234 		}
    235 
    236 	else if (fBlack_2D_rows == 0 &&
    237 			 (info.fBlackLevelRepeatRows > 1 || fSrcPixelType != ttShort))
    238 		{
    239 
    240 		fBlack_1D_rows = info.fBlackLevelRepeatRows;
    241 
    242 		}
    243 
    244 	if (fBlack_1D_rows)
    245 		{
    246 
    247 		fBlack_1D_buffer.Reset (host.Allocate (
    248 			SafeUint32Mult(fBlack_1D_rows, 4)));
    249 
    250 		bool allZero = true;
    251 
    252 		for (j = 0; j < fBlack_1D_rows; j++)
    253 			{
    254 
    255 			real64 x = 0.0;
    256 
    257 			if (fBlack_2D_rows == 0)
    258 				{
    259 
    260 				x = info.fBlackLevel [j % info.fBlackLevelRepeatRows]
    261 									 [0]
    262 									 [plane];
    263 
    264 				}
    265 
    266 			if (info.fBlackDeltaV.Get ())
    267 				{
    268 
    269 				x += info.fBlackDeltaV->Buffer_real64 () [j];
    270 
    271 				}
    272 
    273 			allZero = allZero && (x == 0.0);
    274 
    275 			x *= scale;
    276 
    277 			if (fReal32)
    278 				{
    279 
    280 				fBlack_1D_buffer->Buffer_real32 () [j] = (real32) x;
    281 
    282 				}
    283 
    284 			else
    285 				{
    286 
    287 				x *= 0x0FFFF * 256.0;
    288 
    289 				int32 y = Round_int32 (x);
    290 
    291 				fBlack_1D_buffer->Buffer_int32 () [j] = y;
    292 
    293 				}
    294 
    295 			}
    296 
    297 		if (allZero)
    298 			{
    299 
    300 			fBlack_1D_rows = 0;
    301 
    302 			fBlack_1D_buffer.Reset ();
    303 
    304 			}
    305 
    306 		}
    307 
    308 	// Calculate scale table, if any.
    309 
    310 	if (fSrcPixelType != ttLong &&
    311 		fSrcPixelType != ttFloat)
    312 		{
    313 
    314 		// Find linearization table, if any.
    315 
    316 		uint16 *lut = NULL;
    317 
    318 		uint32 lutEntries = 0;
    319 
    320 		if (info.fLinearizationTable.Get ())
    321 			{
    322 
    323 			lut = info.fLinearizationTable->Buffer_uint16 ();
    324 
    325 			lutEntries = info.fLinearizationTable->LogicalSize () >> 1;
    326 
    327 			}
    328 
    329 		// If the black level does not vary from pixel to pixel, then
    330 		// the entire process can be a single LUT.
    331 
    332 		if (fBlack_1D_rows == 0 &&
    333 		    fBlack_2D_rows == 0)
    334 			{
    335 
    336 			fScale_buffer.Reset (host.Allocate (0x10000 *
    337 											    TagTypeSize (fDstPixelType)));
    338 
    339 			for (j = 0; j < 0x10000; j++)
    340 				{
    341 
    342 				uint32 x = j;
    343 
    344 				// Apply linearization table, if any.
    345 
    346 				if (lut)
    347 					{
    348 
    349 					x = Min_uint32 (x, lutEntries - 1);
    350 
    351 					x = lut [x];
    352 
    353 					}
    354 
    355 				// Subtract constant black level.
    356 
    357 				real64 y = x - info.fBlackLevel [0] [0] [plane];
    358 
    359 				// Apply scale.
    360 
    361 				y *= scale;
    362 
    363 				// We can burn in the clipping also.
    364 
    365 				y = Pin_real64 (0.0, y, 1.0);
    366 
    367 				// Store output value in table.
    368 
    369 				if (fDstPixelType == ttShort)
    370 					{
    371 
    372 					uint16 z = (uint16) Round_uint32 (y * 0x0FFFF);
    373 
    374 					fScale_buffer->Buffer_uint16 () [j] = z;
    375 
    376 					}
    377 
    378 				else
    379 					{
    380 
    381 					fScale_buffer->Buffer_real32 () [j] = (real32) y;
    382 
    383 					}
    384 
    385 				}
    386 
    387 			}
    388 
    389 		// Else we only do the scaling operation in the scale table.
    390 
    391 		else
    392 			{
    393 
    394 			fScale_buffer.Reset (host.Allocate (0x10000 * 4));
    395 
    396 			for (j = 0; j < 0x10000; j++)
    397 				{
    398 
    399 				uint32 x = j;
    400 
    401 				// Apply linearization table, if any.
    402 
    403 				if (lut)
    404 					{
    405 
    406 					x = Min_uint32 (x, lutEntries - 1);
    407 
    408 					x = lut [x];
    409 
    410 					}
    411 
    412 				// Apply scale.
    413 
    414 				real64 y = x * scale;
    415 
    416 				// Store output value in table.
    417 
    418 				if (fReal32)
    419 					{
    420 
    421 					fScale_buffer->Buffer_real32 () [j] = (real32) y;
    422 
    423 					}
    424 
    425 				else
    426 					{
    427 
    428 					int32 z = Round_int32 (y * 0x0FFFF * 256.0);
    429 
    430 					fScale_buffer->Buffer_int32 () [j] = z;
    431 
    432 					}
    433 
    434 				}
    435 
    436 			}
    437 
    438 		}
    439 
    440 	}
    441 
    442 /*****************************************************************************/
    443 
    444 dng_linearize_plane::~dng_linearize_plane ()
    445 	{
    446 
    447 	}
    448 
    449 /*****************************************************************************/
    450 
    451 void dng_linearize_plane::Process (const dng_rect &srcTile)
    452 	{
    453 
    454 	// Process tile.
    455 
    456 	dng_rect dstTile = srcTile - fActiveArea.TL ();
    457 
    458 	dng_const_tile_buffer srcBuffer (fSrcImage, srcTile);
    459 	dng_dirty_tile_buffer dstBuffer (fDstImage, dstTile);
    460 
    461 	int32 sStep = srcBuffer.fColStep;
    462 	int32 dStep = dstBuffer.fColStep;
    463 
    464 	uint32 count = srcTile.W ();
    465 
    466 	uint32 dstCol = dstTile.l;
    467 
    468 	uint32 rows = srcTile.H ();
    469 
    470 	for (uint32 row = 0; row < rows; row++)
    471 		{
    472 
    473 		uint32 dstRow = dstTile.t + row;
    474 
    475 		const void *sPtr = srcBuffer.ConstPixel (srcTile.t + row,
    476 											     srcTile.l,
    477 											     fPlane);
    478 
    479 		void *dPtr = dstBuffer.DirtyPixel (dstRow,
    480 										   dstCol,
    481 										   fPlane);
    482 
    483 		// Floating point source case.
    484 
    485 		if (fSrcPixelType == ttFloat)
    486 			{
    487 
    488 			real32 scale = fScale;
    489 
    490 			const real32 *srcPtr = (const real32 *) sPtr;
    491 
    492 			real32 *dstPtr = (real32 *) dPtr;
    493 
    494 			// Optimize scale only case, which is the most common.
    495 
    496 			if (fBlack_1D_rows == 0 &&
    497 				fBlack_2D_cols == 0)
    498 				{
    499 
    500 				for (uint32 j = 0; j < count; j++)
    501 					{
    502 
    503 					*dstPtr = (*srcPtr) * scale;
    504 
    505 					srcPtr += sStep;
    506 					dstPtr += dStep;
    507 
    508 					}
    509 
    510 				}
    511 
    512 			else
    513 				{
    514 
    515 				real32 b1 = 0.0f;
    516 
    517 				if (fBlack_1D_rows)
    518 					{
    519 					b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows];
    520 					}
    521 
    522 				const real32 *b2 = NULL;
    523 
    524 				uint32 b2_count = fBlack_2D_cols;
    525 				uint32 b2_phase = 0;
    526 
    527 				if (b2_count)
    528 					{
    529 
    530 					b2 = fBlack_2D_buffer->Buffer_real32 () +
    531 						 b2_count * (dstRow % fBlack_2D_rows);
    532 
    533 					b2_phase = dstCol % b2_count;
    534 
    535 					}
    536 
    537 				for (uint32 j = 0; j < count; j++)
    538 					{
    539 
    540 					real32 x = (*srcPtr) * scale - b1;
    541 
    542 					if (b2_count)
    543 						{
    544 
    545 						x -= b2 [b2_phase];
    546 
    547 						if (++b2_phase == b2_count)
    548 							{
    549 							b2_phase = 0;
    550 							}
    551 
    552 						}
    553 
    554 					*dstPtr = x;
    555 
    556 					srcPtr += sStep;
    557 					dstPtr += dStep;
    558 
    559 					}
    560 
    561 				}
    562 
    563 			}
    564 
    565 		// Simple LUT case.
    566 
    567 		else if (fBlack_1D_rows == 0 &&
    568 				 fBlack_2D_rows == 0 && fSrcPixelType != ttLong)
    569 			{
    570 
    571 			if (fDstPixelType == ttShort)
    572 				{
    573 
    574 				const uint16 *lut = fScale_buffer->Buffer_uint16 ();
    575 
    576 				uint16 *dstPtr = (uint16 *) dPtr;
    577 
    578 				if (fSrcPixelType == ttByte)
    579 					{
    580 
    581 					const uint8 *srcPtr = (const uint8 *) sPtr;
    582 
    583 					for (uint32 j = 0; j < count; j++)
    584 						{
    585 
    586 						*dstPtr = lut [*srcPtr];
    587 
    588 						srcPtr += sStep;
    589 						dstPtr += dStep;
    590 
    591 						}
    592 
    593 					}
    594 
    595 				else
    596 					{
    597 
    598 					const uint16 *srcPtr = (const uint16 *) sPtr;
    599 
    600 					for (uint32 j = 0; j < count; j++)
    601 						{
    602 
    603 						*dstPtr = lut [*srcPtr];
    604 
    605 						srcPtr += sStep;
    606 						dstPtr += dStep;
    607 
    608 						}
    609 
    610 					}
    611 
    612 				}
    613 
    614 			else
    615 				{
    616 
    617 				const real32 *lut = fScale_buffer->Buffer_real32 ();
    618 
    619 				real32 *dstPtr = (real32 *) dPtr;
    620 
    621 				if (fSrcPixelType == ttByte)
    622 					{
    623 
    624 					const uint8 *srcPtr = (const uint8 *) sPtr;
    625 
    626 					for (uint32 j = 0; j < count; j++)
    627 						{
    628 
    629 						*dstPtr = lut [*srcPtr];
    630 
    631 						srcPtr += sStep;
    632 						dstPtr += dStep;
    633 
    634 						}
    635 
    636 					}
    637 
    638 				else
    639 					{
    640 
    641 					const uint16 *srcPtr = (const uint16 *) sPtr;
    642 
    643 					for (uint32 j = 0; j < count; j++)
    644 						{
    645 
    646 						*dstPtr = lut [*srcPtr];
    647 
    648 						srcPtr += sStep;
    649 						dstPtr += dStep;
    650 
    651 						}
    652 
    653 					}
    654 
    655 				}
    656 
    657 			}
    658 
    659 		// Integer math case.
    660 
    661 		else if (!fReal32)
    662 			{
    663 
    664 			const int32 *lut = fScale_buffer->Buffer_int32 ();
    665 
    666 			int32 b1 = 0;
    667 
    668 			if (fBlack_1D_rows)
    669 				{
    670 				b1 = fBlack_1D_buffer->Buffer_int32 () [dstRow % fBlack_1D_rows];
    671 				}
    672 
    673 			const int32 *b2 = NULL;
    674 
    675 			uint32 b2_count = fBlack_2D_cols;
    676 			uint32 b2_phase = 0;
    677 
    678 			if (b2_count)
    679 				{
    680 
    681 				b2 = fBlack_2D_buffer->Buffer_int32 () +
    682 					 b2_count * (dstRow % fBlack_2D_rows);
    683 
    684 				b2_phase = dstCol % b2_count;
    685 
    686 				}
    687 
    688 			uint16 *dstPtr = (uint16 *) dPtr;
    689 
    690 			b1 -= 128;		// Rounding for 8 bit shift
    691 
    692 			if (fSrcPixelType == ttByte)
    693 				{
    694 
    695 				const uint8 *srcPtr = (const uint8 *) sPtr;
    696 
    697 				for (uint32 j = 0; j < count; j++)
    698 					{
    699 
    700 					int32 x = lut [*srcPtr] - b1;
    701 
    702 					if (b2_count)
    703 						{
    704 
    705 						x -= b2 [b2_phase];
    706 
    707 						if (++b2_phase == b2_count)
    708 							{
    709 							b2_phase = 0;
    710 							}
    711 
    712 						}
    713 
    714 					x >>= 8;
    715 
    716 					*dstPtr = Pin_uint16 (x);
    717 
    718 					srcPtr += sStep;
    719 					dstPtr += dStep;
    720 
    721 					}
    722 
    723 				}
    724 
    725 			else
    726 				{
    727 
    728 				const uint16 *srcPtr = (const uint16 *) sPtr;
    729 
    730 				for (uint32 j = 0; j < count; j++)
    731 					{
    732 
    733 					int32 x = lut [*srcPtr] - b1;
    734 
    735 					if (b2_count)
    736 						{
    737 
    738 						x -= b2 [b2_phase];
    739 
    740 						if (++b2_phase == b2_count)
    741 							{
    742 							b2_phase = 0;
    743 							}
    744 
    745 						}
    746 
    747 					x >>= 8;
    748 
    749 					*dstPtr = Pin_uint16 (x);
    750 
    751 					srcPtr += sStep;
    752 					dstPtr += dStep;
    753 
    754 					}
    755 
    756 				}
    757 
    758 			}
    759 
    760 		// Floating point math cases.
    761 
    762 		else
    763 			{
    764 
    765 			real32 b1 = 0.0f;
    766 
    767 			if (fBlack_1D_rows)
    768 				{
    769 				b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows];
    770 				}
    771 
    772 			const real32 *b2 = NULL;
    773 
    774 			uint32 b2_count = fBlack_2D_cols;
    775 			uint32 b2_phase = 0;
    776 
    777 			if (b2_count)
    778 				{
    779 
    780 				b2 = fBlack_2D_buffer->Buffer_real32 () +
    781 					 b2_count * (dstRow % fBlack_2D_rows);
    782 
    783 				b2_phase = dstCol % b2_count;
    784 
    785 				}
    786 
    787 			// Case 1: uint8/uint16 -> real32
    788 
    789 			if (fSrcPixelType != ttLong)
    790 				{
    791 
    792 				const real32 *lut = fScale_buffer->Buffer_real32 ();
    793 
    794 				real32 *dstPtr = (real32 *) dPtr;
    795 
    796 				if (fSrcPixelType == ttByte)
    797 					{
    798 
    799 					const uint8 *srcPtr = (const uint8 *) sPtr;
    800 
    801 					for (uint32 j = 0; j < count; j++)
    802 						{
    803 
    804 						real32 x = lut [*srcPtr] - b1;
    805 
    806 						if (b2_count)
    807 							{
    808 
    809 							x -= b2 [b2_phase];
    810 
    811 							if (++b2_phase == b2_count)
    812 								{
    813 								b2_phase = 0;
    814 								}
    815 
    816 							}
    817 
    818 						x = Pin_real32 (0.0f, x, 1.0f);
    819 
    820 						*dstPtr = x;
    821 
    822 						srcPtr += sStep;
    823 						dstPtr += dStep;
    824 
    825 						}
    826 
    827 					}
    828 
    829 				else
    830 					{
    831 
    832 					const uint16 *srcPtr = (const uint16 *) sPtr;
    833 
    834 					for (uint32 j = 0; j < count; j++)
    835 						{
    836 
    837 						real32 x = lut [*srcPtr] - b1;
    838 
    839 						if (b2_count)
    840 							{
    841 
    842 							x -= b2 [b2_phase];
    843 
    844 							if (++b2_phase == b2_count)
    845 								{
    846 								b2_phase = 0;
    847 								}
    848 
    849 							}
    850 
    851 						x = Pin_real32 (0.0f, x, 1.0f);
    852 
    853 						*dstPtr = x;
    854 
    855 						srcPtr += sStep;
    856 						dstPtr += dStep;
    857 
    858 						}
    859 
    860 					}
    861 
    862 				}
    863 
    864 			// Otherwise source is uint32
    865 
    866 			else
    867 				{
    868 
    869 				real32 scale = fScale;
    870 
    871 				const uint32 *srcPtr = (const uint32 *) sPtr;
    872 
    873 				// Case 2: uint32 -> real32
    874 
    875 				if (fDstPixelType == ttFloat)
    876 					{
    877 
    878 					real32 *dstPtr = (real32 *) dPtr;
    879 
    880 					for (uint32 j = 0; j < count; j++)
    881 						{
    882 
    883 						real32 x = ((real32) *srcPtr) * scale - b1;
    884 
    885 						if (b2_count)
    886 							{
    887 
    888 							x -= b2 [b2_phase];
    889 
    890 							if (++b2_phase == b2_count)
    891 								{
    892 								b2_phase = 0;
    893 								}
    894 
    895 							}
    896 
    897 						x = Pin_real32 (0.0f, x, 1.0f);
    898 
    899 						*dstPtr = x;
    900 
    901 						srcPtr += sStep;
    902 						dstPtr += dStep;
    903 
    904 						}
    905 
    906 					}
    907 
    908 				// Case 3: uint32 -> uint16
    909 
    910 				else
    911 					{
    912 
    913 					uint16 *dstPtr = (uint16 *) dPtr;
    914 
    915 					real32 dstScale = (real32) 0x0FFFF;
    916 
    917 					for (uint32 j = 0; j < count; j++)
    918 						{
    919 
    920 						real32 x = ((real32) *srcPtr) * scale - b1;
    921 
    922 						if (b2_count)
    923 							{
    924 
    925 							x -= b2 [b2_phase];
    926 
    927 							if (++b2_phase == b2_count)
    928 								{
    929 								b2_phase = 0;
    930 								}
    931 
    932 							}
    933 
    934 						x = Pin_real32 (0.0f, x, 1.0f);
    935 
    936 						*dstPtr = (uint16) (x * dstScale + 0.5f);
    937 
    938 						srcPtr += sStep;
    939 						dstPtr += dStep;
    940 
    941 						}
    942 
    943 					}
    944 
    945 				}
    946 
    947 			}
    948 
    949 		}
    950 
    951 	}
    952 
    953 /*****************************************************************************/
    954 
    955 class dng_linearize_image: public dng_area_task
    956 	{
    957 
    958 	private:
    959 
    960 		const dng_image & fSrcImage;
    961 		      dng_image & fDstImage;
    962 
    963 		dng_rect fActiveArea;
    964 
    965 		AutoPtr<dng_linearize_plane> fPlaneTask [kMaxColorPlanes];
    966 
    967 	public:
    968 
    969 		dng_linearize_image (dng_host &host,
    970 							 dng_linearization_info &info,
    971 							 const dng_image &srcImage,
    972 							 dng_image &dstImage);
    973 
    974 		virtual ~dng_linearize_image ();
    975 
    976 		virtual dng_rect RepeatingTile1 () const;
    977 
    978 		virtual dng_rect RepeatingTile2 () const;
    979 
    980 		virtual void Process (uint32 threadIndex,
    981 							  const dng_rect &tile,
    982 							  dng_abort_sniffer *sniffer);
    983 
    984 	};
    985 
    986 /*****************************************************************************/
    987 
    988 dng_linearize_image::dng_linearize_image (dng_host &host,
    989 										  dng_linearization_info &info,
    990 										  const dng_image &srcImage,
    991 										  dng_image &dstImage)
    992 
    993 	:	fSrcImage   (srcImage)
    994 	,	fDstImage   (dstImage)
    995 	,	fActiveArea (info.fActiveArea)
    996 
    997 	{
    998 
    999 	// Build linearization table for each plane.
   1000 
   1001 	for (uint32 plane = 0; plane < srcImage.Planes (); plane++)
   1002 		{
   1003 
   1004 		fPlaneTask [plane].Reset (new dng_linearize_plane (host,
   1005 														   info,
   1006 														   srcImage,
   1007 														   dstImage,
   1008 														   plane));
   1009 
   1010 		}
   1011 
   1012 	// Adjust maximum tile size.
   1013 
   1014 	fMaxTileSize = dng_point (1024, 1024);
   1015 
   1016 	}
   1017 
   1018 /*****************************************************************************/
   1019 
   1020 dng_linearize_image::~dng_linearize_image ()
   1021 	{
   1022 
   1023 	}
   1024 
   1025 /*****************************************************************************/
   1026 
   1027 dng_rect dng_linearize_image::RepeatingTile1 () const
   1028 	{
   1029 
   1030 	return fSrcImage.RepeatingTile ();
   1031 
   1032 	}
   1033 
   1034 /*****************************************************************************/
   1035 
   1036 dng_rect dng_linearize_image::RepeatingTile2 () const
   1037 	{
   1038 
   1039 	return fDstImage.RepeatingTile () + fActiveArea.TL ();
   1040 
   1041 	}
   1042 
   1043 /*****************************************************************************/
   1044 
   1045 void dng_linearize_image::Process (uint32 /* threadIndex */,
   1046 							  	   const dng_rect &srcTile,
   1047 							  	   dng_abort_sniffer * /* sniffer */)
   1048 	{
   1049 
   1050 	// Process each plane.
   1051 
   1052 	for (uint32 plane = 0; plane < fSrcImage.Planes (); plane++)
   1053 		{
   1054 
   1055 		fPlaneTask [plane]->Process (srcTile);
   1056 
   1057 		}
   1058 
   1059 	}
   1060 
   1061 /*****************************************************************************/
   1062 
   1063 dng_linearization_info::dng_linearization_info ()
   1064 
   1065 	:	fActiveArea ()
   1066 	,	fMaskedAreaCount (0)
   1067 	,	fLinearizationTable ()
   1068 	,	fBlackLevelRepeatRows (1)
   1069 	,	fBlackLevelRepeatCols (1)
   1070 	,	fBlackDeltaH ()
   1071 	,	fBlackDeltaV ()
   1072 	,	fBlackDenom (256)
   1073 
   1074 	{
   1075 
   1076 	uint32 j;
   1077 	uint32 k;
   1078 	uint32 n;
   1079 
   1080 	for (j = 0; j < kMaxBlackPattern; j++)
   1081 		for (k = 0; k < kMaxBlackPattern; k++)
   1082 			for (n = 0; n < kMaxSamplesPerPixel; n++)
   1083 				{
   1084 				fBlackLevel [j] [k] [n] = 0.0;
   1085 				}
   1086 
   1087 	for (n = 0; n < kMaxSamplesPerPixel; n++)
   1088 		{
   1089 		fWhiteLevel [n] = 65535.0;
   1090 		}
   1091 
   1092 	}
   1093 
   1094 /*****************************************************************************/
   1095 
   1096 dng_linearization_info::~dng_linearization_info ()
   1097 	{
   1098 
   1099 	}
   1100 
   1101 /*****************************************************************************/
   1102 
   1103 void dng_linearization_info::RoundBlacks ()
   1104 	{
   1105 
   1106 	uint32 j;
   1107 	uint32 k;
   1108 	uint32 n;
   1109 
   1110 	real64 maxAbs = 0.0;
   1111 
   1112 	for (j = 0; j < fBlackLevelRepeatRows; j++)
   1113 		for (k = 0; k < fBlackLevelRepeatCols; k++)
   1114 			for (n = 0; n < kMaxSamplesPerPixel; n++)
   1115 				{
   1116 
   1117 				maxAbs = Max_real64 (maxAbs,
   1118 									 Abs_real64 (fBlackLevel [j] [k] [n]));
   1119 
   1120 				}
   1121 
   1122 	uint32 count = RowBlackCount ();
   1123 
   1124 	for (j = 0; j < count; j++)
   1125 		{
   1126 
   1127 		maxAbs = Max_real64 (maxAbs,
   1128 							 Abs_real64 (fBlackDeltaV->Buffer_real64 () [j]));
   1129 
   1130 		}
   1131 
   1132 	count = ColumnBlackCount ();
   1133 
   1134 	for (j = 0; j < count; j++)
   1135 		{
   1136 
   1137 		maxAbs = Max_real64 (maxAbs,
   1138 							 Abs_real64 (fBlackDeltaH->Buffer_real64 () [j]));
   1139 
   1140 
   1141 		}
   1142 
   1143 	fBlackDenom = 256;
   1144 
   1145 	while (fBlackDenom > 1 && (maxAbs * fBlackDenom) >= 30000.0 * 65536.0)
   1146 		{
   1147 		fBlackDenom >>= 1;
   1148 		}
   1149 
   1150 	for (j = 0; j < fBlackLevelRepeatRows; j++)
   1151 		for (k = 0; k < fBlackLevelRepeatCols; k++)
   1152 			for (n = 0; n < kMaxSamplesPerPixel; n++)
   1153 				{
   1154 
   1155 				fBlackLevel [j] [k] [n] = BlackLevel (j, k, n).As_real64 ();
   1156 
   1157 				}
   1158 
   1159 	count = RowBlackCount ();
   1160 
   1161 	for (j = 0; j < count; j++)
   1162 		{
   1163 
   1164 		fBlackDeltaV->Buffer_real64 () [j] = RowBlack (j).As_real64 ();
   1165 
   1166 		}
   1167 
   1168 	count = ColumnBlackCount ();
   1169 
   1170 	for (j = 0; j < count; j++)
   1171 		{
   1172 
   1173 		fBlackDeltaH->Buffer_real64 () [j] = ColumnBlack (j).As_real64 ();
   1174 
   1175 		}
   1176 
   1177 	}
   1178 
   1179 /*****************************************************************************/
   1180 
   1181 void dng_linearization_info::Parse (dng_host &host,
   1182 								    dng_stream &stream,
   1183 								    dng_info &info)
   1184 	{
   1185 
   1186 	uint32 j;
   1187 	uint32 k;
   1188 	uint32 n;
   1189 
   1190 	// Find main image IFD.
   1191 
   1192 	dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
   1193 
   1194 	// Copy active area.
   1195 
   1196 	fActiveArea = rawIFD.fActiveArea;
   1197 
   1198 	// Copy masked areas.
   1199 
   1200 	fMaskedAreaCount = rawIFD.fMaskedAreaCount;
   1201 
   1202 	for (j = 0; j < fMaskedAreaCount; j++)
   1203 		{
   1204 		fMaskedArea [j] = rawIFD.fMaskedArea [j];
   1205 		}
   1206 
   1207 	// Read linearization LUT.
   1208 
   1209 	if (rawIFD.fLinearizationTableCount)
   1210 		{
   1211 
   1212 		uint32 size = SafeUint32Mult (rawIFD.fLinearizationTableCount,
   1213 									  static_cast<uint32> (sizeof (uint16)));
   1214 
   1215 		fLinearizationTable.Reset (host.Allocate (size));
   1216 
   1217 		uint16 *table = fLinearizationTable->Buffer_uint16 ();
   1218 
   1219 		stream.SetReadPosition (rawIFD.fLinearizationTableOffset);
   1220 
   1221 		for (j = 0; j < rawIFD.fLinearizationTableCount; j++)
   1222 			{
   1223 			table [j] = stream.Get_uint16 ();
   1224 			}
   1225 
   1226 		}
   1227 
   1228 	// Copy black level pattern.
   1229 
   1230 	fBlackLevelRepeatRows = rawIFD.fBlackLevelRepeatRows;
   1231 	fBlackLevelRepeatCols = rawIFD.fBlackLevelRepeatCols;
   1232 
   1233 	for (j = 0; j < kMaxBlackPattern; j++)
   1234 		for (k = 0; k < kMaxBlackPattern; k++)
   1235 			for (n = 0; n < kMaxSamplesPerPixel; n++)
   1236 				{
   1237 				fBlackLevel [j] [k] [n] = rawIFD.fBlackLevel [j] [k] [n];
   1238 				}
   1239 
   1240 	// Read BlackDeltaH.
   1241 
   1242 	if (rawIFD.fBlackLevelDeltaHCount)
   1243 		{
   1244 
   1245 		uint32 size = SafeUint32Mult (rawIFD.fBlackLevelDeltaHCount,
   1246 									  static_cast<uint32> (sizeof (real64)));
   1247 
   1248 		fBlackDeltaH.Reset (host.Allocate (size));
   1249 
   1250 		real64 *blacks = fBlackDeltaH->Buffer_real64 ();
   1251 
   1252 		stream.SetReadPosition (rawIFD.fBlackLevelDeltaHOffset);
   1253 
   1254 		for (j = 0; j < rawIFD.fBlackLevelDeltaHCount; j++)
   1255 			{
   1256 			blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaHType);
   1257 			}
   1258 
   1259 		}
   1260 
   1261 	// Read BlackDeltaV.
   1262 
   1263 	if (rawIFD.fBlackLevelDeltaVCount)
   1264 		{
   1265 
   1266 		uint32 size = SafeUint32Mult (rawIFD.fBlackLevelDeltaVCount,
   1267 									  static_cast<uint32> (sizeof (real64)));
   1268 
   1269 		fBlackDeltaV.Reset (host.Allocate (size));
   1270 
   1271 		real64 *blacks = fBlackDeltaV->Buffer_real64 ();
   1272 
   1273 		stream.SetReadPosition (rawIFD.fBlackLevelDeltaVOffset);
   1274 
   1275 		for (j = 0; j < rawIFD.fBlackLevelDeltaVCount; j++)
   1276 			{
   1277 			blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaVType);
   1278 			}
   1279 
   1280 		}
   1281 
   1282 	// Copy white level.
   1283 
   1284 	for (n = 0; n < kMaxSamplesPerPixel; n++)
   1285 		{
   1286 		fWhiteLevel [n] = rawIFD.fWhiteLevel [n];
   1287 		}
   1288 
   1289 	// Round off black levels.
   1290 
   1291 	RoundBlacks ();
   1292 
   1293 	}
   1294 
   1295 /*****************************************************************************/
   1296 
   1297 void dng_linearization_info::PostParse (dng_host & /* host */,
   1298 										dng_negative &negative)
   1299 	{
   1300 
   1301 	if (fActiveArea.IsEmpty ())
   1302 		{
   1303 
   1304 		fActiveArea = negative.Stage1Image ()->Bounds ();
   1305 
   1306 		}
   1307 
   1308 	}
   1309 
   1310 /*****************************************************************************/
   1311 
   1312 real64 dng_linearization_info::MaxBlackLevel (uint32 plane) const
   1313 	{
   1314 
   1315 	uint32 j;
   1316 	uint32 k;
   1317 
   1318 	// Find maximum value of fBlackDeltaH for each phase of black pattern.
   1319 
   1320 	real64 maxDeltaH [kMaxBlackPattern];
   1321 
   1322 	for (j = 0; j < fBlackLevelRepeatCols; j++)
   1323 		{
   1324 		maxDeltaH [j] = 0.0;
   1325 		}
   1326 
   1327 	if (fBlackDeltaH.Get ())
   1328 		{
   1329 
   1330 		real64 *table = fBlackDeltaH->Buffer_real64 ();
   1331 
   1332 		uint32 entries = fBlackDeltaH->LogicalSize () / (uint32) sizeof (table [0]);
   1333 
   1334 		for (j = 0; j < entries; j++)
   1335 			{
   1336 
   1337 			real64 &entry = maxDeltaH [j % fBlackLevelRepeatCols];
   1338 
   1339 			if (j < fBlackLevelRepeatCols)
   1340 				{
   1341 				entry = table [j];
   1342 				}
   1343 			else
   1344 				{
   1345 				entry = Max_real64 (entry, table [j]);
   1346 				}
   1347 
   1348 			}
   1349 
   1350 		}
   1351 
   1352 	// Find maximum value of fBlackDeltaV for each phase of black pattern.
   1353 
   1354 	real64 maxDeltaV [kMaxBlackPattern];
   1355 
   1356 	for (j = 0; j < fBlackLevelRepeatRows; j++)
   1357 		{
   1358 		maxDeltaV [j] = 0.0;
   1359 		}
   1360 
   1361 	if (fBlackDeltaV.Get ())
   1362 		{
   1363 
   1364 		real64 *table = fBlackDeltaV->Buffer_real64 ();
   1365 
   1366 		uint32 entries = fBlackDeltaV->LogicalSize () / (uint32) sizeof (table [0]);
   1367 
   1368 		for (j = 0; j < entries; j++)
   1369 			{
   1370 
   1371 			real64 &entry = maxDeltaV [j % fBlackLevelRepeatRows];
   1372 
   1373 			if (j < fBlackLevelRepeatRows)
   1374 				{
   1375 				entry = table [j];
   1376 				}
   1377 			else
   1378 				{
   1379 				entry = Max_real64 (entry, table [j]);
   1380 				}
   1381 
   1382 			}
   1383 
   1384 		}
   1385 
   1386 	// Now scan the pattern and find the maximum value after row and column
   1387 	// deltas.
   1388 
   1389 	real64 maxBlack = 0.0;
   1390 
   1391 	for (j = 0; j < fBlackLevelRepeatRows; j++)
   1392 		{
   1393 
   1394 		for (k = 0; k < fBlackLevelRepeatCols; k++)
   1395 			{
   1396 
   1397 			real64 black = fBlackLevel [j] [k] [plane];
   1398 
   1399 			black += maxDeltaH [k];
   1400 			black += maxDeltaV [j];
   1401 
   1402 			if (j == 0 && k == 0)
   1403 				{
   1404 				maxBlack = black;
   1405 				}
   1406 			else
   1407 				{
   1408 				maxBlack = Max_real64 (maxBlack, black);
   1409 				}
   1410 
   1411 			}
   1412 
   1413 		}
   1414 
   1415 	return maxBlack;
   1416 
   1417 	}
   1418 
   1419 /*****************************************************************************/
   1420 
   1421 void dng_linearization_info::Linearize (dng_host &host,
   1422 										const dng_image &srcImage,
   1423 										dng_image &dstImage)
   1424 	{
   1425 
   1426 	dng_linearize_image processor (host,
   1427 								   *this,
   1428 								   srcImage,
   1429 								   dstImage);
   1430 
   1431 	host.PerformAreaTask (processor,
   1432 						  fActiveArea);
   1433 
   1434 	}
   1435 
   1436 /*****************************************************************************/
   1437 
   1438 dng_urational dng_linearization_info::BlackLevel (uint32 row,
   1439 												  uint32 col,
   1440 												  uint32 plane) const
   1441 	{
   1442 
   1443 	dng_urational r;
   1444 
   1445 	r.Set_real64 (fBlackLevel [row] [col] [plane], fBlackDenom);
   1446 
   1447 	return r;
   1448 
   1449 	}
   1450 
   1451 /*****************************************************************************/
   1452 
   1453 uint32 dng_linearization_info::RowBlackCount () const
   1454 	{
   1455 
   1456 	if (fBlackDeltaV.Get ())
   1457 		{
   1458 
   1459 		return fBlackDeltaV->LogicalSize () >> 3;
   1460 
   1461 		}
   1462 
   1463 	return 0;
   1464 
   1465 	}
   1466 
   1467 /*****************************************************************************/
   1468 
   1469 dng_srational dng_linearization_info::RowBlack (uint32 row) const
   1470 	{
   1471 
   1472 	if (fBlackDeltaV.Get ())
   1473 		{
   1474 
   1475 		dng_srational r;
   1476 
   1477 		r.Set_real64 (fBlackDeltaV->Buffer_real64 () [row], fBlackDenom);
   1478 
   1479 		return r;
   1480 
   1481 		}
   1482 
   1483 	return dng_srational (0, 1);
   1484 
   1485 	}
   1486 
   1487 /*****************************************************************************/
   1488 
   1489 uint32 dng_linearization_info::ColumnBlackCount () const
   1490 	{
   1491 
   1492 	if (fBlackDeltaH.Get ())
   1493 		{
   1494 
   1495 		return fBlackDeltaH->LogicalSize () >> 3;
   1496 
   1497 		}
   1498 
   1499 	return 0;
   1500 
   1501 	}
   1502 
   1503 /*****************************************************************************/
   1504 
   1505 dng_srational dng_linearization_info::ColumnBlack (uint32 col) const
   1506 	{
   1507 
   1508 	if (fBlackDeltaH.Get ())
   1509 		{
   1510 
   1511 		dng_srational r;
   1512 
   1513 		r.Set_real64 (fBlackDeltaH->Buffer_real64 () [col], fBlackDenom);
   1514 
   1515 		return r;
   1516 
   1517 		}
   1518 
   1519 	return dng_srational (0, 1);
   1520 
   1521 	}
   1522 
   1523 /*****************************************************************************/
   1524