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