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 
dng_linearize_plane(dng_host & host,dng_linearization_info & info,const dng_image & srcImage,dng_image & dstImage,uint32 plane)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 
~dng_linearize_plane()444 dng_linearize_plane::~dng_linearize_plane ()
445 	{
446 
447 	}
448 
449 /*****************************************************************************/
450 
Process(const dng_rect & srcTile)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 
dng_linearize_image(dng_host & host,dng_linearization_info & info,const dng_image & srcImage,dng_image & dstImage)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 
~dng_linearize_image()1020 dng_linearize_image::~dng_linearize_image ()
1021 	{
1022 
1023 	}
1024 
1025 /*****************************************************************************/
1026 
RepeatingTile1() const1027 dng_rect dng_linearize_image::RepeatingTile1 () const
1028 	{
1029 
1030 	return fSrcImage.RepeatingTile ();
1031 
1032 	}
1033 
1034 /*****************************************************************************/
1035 
RepeatingTile2() const1036 dng_rect dng_linearize_image::RepeatingTile2 () const
1037 	{
1038 
1039 	return fDstImage.RepeatingTile () + fActiveArea.TL ();
1040 
1041 	}
1042 
1043 /*****************************************************************************/
1044 
Process(uint32,const dng_rect & srcTile,dng_abort_sniffer *)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 
dng_linearization_info()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 
~dng_linearization_info()1096 dng_linearization_info::~dng_linearization_info ()
1097 	{
1098 
1099 	}
1100 
1101 /*****************************************************************************/
1102 
RoundBlacks()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 
Parse(dng_host & host,dng_stream & stream,dng_info & info)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 
PostParse(dng_host &,dng_negative & negative)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 
MaxBlackLevel(uint32 plane) const1312 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 
Linearize(dng_host & host,const dng_image & srcImage,dng_image & dstImage)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 
BlackLevel(uint32 row,uint32 col,uint32 plane) const1438 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 
RowBlackCount() const1453 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 
RowBlack(uint32 row) const1469 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 
ColumnBlackCount() const1489 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 
ColumnBlack(uint32 col) const1505 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