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
32class 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
78dng_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
444dng_linearize_plane::~dng_linearize_plane ()
445	{
446
447	}
448
449/*****************************************************************************/
450
451void 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
955class 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
988dng_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
1020dng_linearize_image::~dng_linearize_image ()
1021	{
1022
1023	}
1024
1025/*****************************************************************************/
1026
1027dng_rect dng_linearize_image::RepeatingTile1 () const
1028	{
1029
1030	return fSrcImage.RepeatingTile ();
1031
1032	}
1033
1034/*****************************************************************************/
1035
1036dng_rect dng_linearize_image::RepeatingTile2 () const
1037	{
1038
1039	return fDstImage.RepeatingTile () + fActiveArea.TL ();
1040
1041	}
1042
1043/*****************************************************************************/
1044
1045void 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
1063dng_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
1096dng_linearization_info::~dng_linearization_info ()
1097	{
1098
1099	}
1100
1101/*****************************************************************************/
1102
1103void 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
1181void 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
1297void 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
1312real64 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
1421void 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
1438dng_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
1453uint32 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
1469dng_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
1489uint32 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
1505dng_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