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