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