1 /*****************************************************************************/
2 // Copyright 2008-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_misc_opcodes.h"
10
11 #include "dng_bottlenecks.h"
12 #include "dng_exceptions.h"
13 #include "dng_globals.h"
14 #include "dng_host.h"
15 #include "dng_image.h"
16 #include "dng_negative.h"
17 #include "dng_rect.h"
18 #include "dng_safe_arithmetic.h"
19 #include "dng_stream.h"
20 #include "dng_tag_values.h"
21
22 /*****************************************************************************/
23
dng_opcode_TrimBounds(const dng_rect & bounds)24 dng_opcode_TrimBounds::dng_opcode_TrimBounds (const dng_rect &bounds)
25
26 : dng_opcode (dngOpcode_TrimBounds,
27 dngVersion_1_3_0_0,
28 kFlag_None)
29
30 , fBounds (bounds)
31
32 {
33
34 }
35
36 /*****************************************************************************/
37
dng_opcode_TrimBounds(dng_stream & stream)38 dng_opcode_TrimBounds::dng_opcode_TrimBounds (dng_stream &stream)
39
40 : dng_opcode (dngOpcode_TrimBounds,
41 stream,
42 "TrimBounds")
43
44 , fBounds ()
45
46 {
47
48 if (stream.Get_uint32 () != 16)
49 {
50 ThrowBadFormat ();
51 }
52
53 fBounds.t = stream.Get_int32 ();
54 fBounds.l = stream.Get_int32 ();
55 fBounds.b = stream.Get_int32 ();
56 fBounds.r = stream.Get_int32 ();
57
58 if (fBounds.IsEmpty ())
59 {
60 ThrowBadFormat ();
61 }
62
63 #if qDNGValidate
64
65 if (gVerbose)
66 {
67
68 printf ("Bounds: t=%d, l=%d, b=%d, r=%d\n",
69 (int) fBounds.t,
70 (int) fBounds.l,
71 (int) fBounds.b,
72 (int) fBounds.r);
73
74 }
75
76 #endif
77
78 }
79
80 /*****************************************************************************/
81
PutData(dng_stream & stream) const82 void dng_opcode_TrimBounds::PutData (dng_stream &stream) const
83 {
84
85 stream.Put_uint32 (16);
86
87 stream.Put_int32 (fBounds.t);
88 stream.Put_int32 (fBounds.l);
89 stream.Put_int32 (fBounds.b);
90 stream.Put_int32 (fBounds.r);
91
92 }
93
94 /*****************************************************************************/
95
Apply(dng_host &,dng_negative &,AutoPtr<dng_image> & image)96 void dng_opcode_TrimBounds::Apply (dng_host & /* host */,
97 dng_negative & /* negative */,
98 AutoPtr<dng_image> &image)
99 {
100
101 if (fBounds.IsEmpty () || (fBounds & image->Bounds ()) != fBounds)
102 {
103 ThrowBadFormat ();
104 }
105
106 image->Trim (fBounds);
107
108 }
109
110 /*****************************************************************************/
111
GetData(dng_stream & stream)112 void dng_area_spec::GetData (dng_stream &stream)
113 {
114
115 fArea.t = stream.Get_int32 ();
116 fArea.l = stream.Get_int32 ();
117 fArea.b = stream.Get_int32 ();
118 fArea.r = stream.Get_int32 ();
119
120 fPlane = stream.Get_uint32 ();
121 fPlanes = stream.Get_uint32 ();
122
123 fRowPitch = stream.Get_uint32 ();
124 fColPitch = stream.Get_uint32 ();
125
126 if (fPlanes < 1)
127 {
128 ThrowBadFormat ();
129 }
130
131 if (fRowPitch < 1 || fColPitch < 1)
132 {
133 ThrowBadFormat ();
134 }
135
136 if (fRowPitch >= fArea.H () || fColPitch >= fArea.W ())
137 {
138
139 DNG_REPORT ("Bad rowPitch or colPitch in dng_area_spec::GetData");
140
141 fRowPitch = Min_uint32 (fRowPitch, fArea.H ());
142 fColPitch = Min_uint32 (fColPitch, fArea.W ());
143
144 }
145
146 if (fArea.IsEmpty ())
147 {
148
149 if (fRowPitch != 1 || fColPitch != 1)
150 {
151 ThrowBadFormat ();
152 }
153
154 }
155
156 else
157 {
158
159 int32 width = 0;
160 int32 height = 0;
161
162 if (!SafeInt32Sub (fArea.b, fArea.t, &height) ||
163 !SafeInt32Sub (fArea.r, fArea.l, &width) ||
164 fRowPitch > static_cast<uint32> (height) ||
165 fColPitch > static_cast<uint32> (width))
166 {
167 ThrowBadFormat ();
168 }
169
170 }
171
172 #if qDNGValidate
173
174 if (gVerbose)
175 {
176
177 printf ("AreaSpec: t=%d, l=%d, b=%d, r=%d, p=%u:%u, rp=%u, cp=%u\n",
178 (int) fArea.t,
179 (int) fArea.l,
180 (int) fArea.b,
181 (int) fArea.r,
182 (unsigned) fPlane,
183 (unsigned) fPlanes,
184 (unsigned) fRowPitch,
185 (unsigned) fColPitch);
186
187 }
188
189 #endif
190
191 }
192
193 /*****************************************************************************/
194
PutData(dng_stream & stream) const195 void dng_area_spec::PutData (dng_stream &stream) const
196 {
197
198 stream.Put_int32 (fArea.t);
199 stream.Put_int32 (fArea.l);
200 stream.Put_int32 (fArea.b);
201 stream.Put_int32 (fArea.r);
202
203 stream.Put_uint32 (fPlane);
204 stream.Put_uint32 (fPlanes);
205
206 stream.Put_uint32 (fRowPitch);
207 stream.Put_uint32 (fColPitch);
208
209 }
210
211 /*****************************************************************************/
212
Overlap(const dng_rect & tile) const213 dng_rect dng_area_spec::Overlap (const dng_rect &tile) const
214 {
215
216 // Special case - if the fArea is empty, then dng_area_spec covers
217 // the entire image, no matter how large it is.
218
219 if (fArea.IsEmpty ())
220 {
221 return tile;
222 }
223
224 dng_rect overlap = fArea & tile;
225
226 if (overlap.NotEmpty ())
227 {
228
229 overlap.t = fArea.t + ((overlap.t - fArea.t + fRowPitch - 1) / fRowPitch) * fRowPitch;
230 overlap.l = fArea.l + ((overlap.l - fArea.l + fColPitch - 1) / fColPitch) * fColPitch;
231
232 if (overlap.NotEmpty ())
233 {
234
235 overlap.b = overlap.t + ((overlap.H () - 1) / fRowPitch) * fRowPitch + 1;
236 overlap.r = overlap.l + ((overlap.W () - 1) / fColPitch) * fColPitch + 1;
237
238 return overlap;
239
240 }
241
242 }
243
244 return dng_rect ();
245
246 }
247
248 /*****************************************************************************/
249
dng_opcode_MapTable(dng_host & host,const dng_area_spec & areaSpec,const uint16 * table,uint32 count)250 dng_opcode_MapTable::dng_opcode_MapTable (dng_host &host,
251 const dng_area_spec &areaSpec,
252 const uint16 *table,
253 uint32 count)
254
255 : dng_inplace_opcode (dngOpcode_MapTable,
256 dngVersion_1_3_0_0,
257 kFlag_None)
258
259 , fAreaSpec (areaSpec)
260 , fTable ()
261 , fCount (count)
262
263 , fBlackAdjustedTable ()
264
265 {
266
267 if (count == 0 || count > 0x10000)
268 {
269 ThrowProgramError ();
270 }
271
272 fTable.Reset (host.Allocate (0x10000 * sizeof (uint16)));
273
274 DoCopyBytes (table,
275 fTable->Buffer (),
276 count * (uint32) sizeof (uint16));
277
278 ReplicateLastEntry ();
279
280 }
281
282 /*****************************************************************************/
283
dng_opcode_MapTable(dng_host & host,dng_stream & stream)284 dng_opcode_MapTable::dng_opcode_MapTable (dng_host &host,
285 dng_stream &stream)
286
287 : dng_inplace_opcode (dngOpcode_MapTable,
288 stream,
289 "MapTable")
290
291 , fAreaSpec ()
292 , fTable ()
293 , fCount (0)
294
295 , fBlackAdjustedTable ()
296
297 {
298
299 uint32 dataSize = stream.Get_uint32 ();
300
301 fAreaSpec.GetData (stream);
302
303 fCount = stream.Get_uint32 ();
304
305 if (dataSize != dng_area_spec::kDataSize + 4 + fCount * 2)
306 {
307 ThrowBadFormat ();
308 }
309
310 if (fCount == 0 || fCount > 0x10000)
311 {
312 ThrowBadFormat ();
313 }
314
315 fTable.Reset (host.Allocate (0x10000 * sizeof (uint16)));
316
317 uint16 *table = fTable->Buffer_uint16 ();
318
319 for (uint32 index = 0; index < fCount; index++)
320 {
321 table [index] = stream.Get_uint16 ();
322 }
323
324 ReplicateLastEntry ();
325
326 #if qDNGValidate
327
328 if (gVerbose)
329 {
330
331 printf ("Count: %u\n", (unsigned) fCount);
332
333 for (uint32 j = 0; j < fCount && j < gDumpLineLimit; j++)
334 {
335 printf (" Table [%5u] = %5u\n", (unsigned) j, (unsigned) table [j]);
336 }
337
338 if (fCount > gDumpLineLimit)
339 {
340 printf (" ... %u table entries skipped\n", (unsigned) (fCount - gDumpLineLimit));
341 }
342
343 }
344
345 #endif
346
347 }
348
349 /*****************************************************************************/
350
ReplicateLastEntry()351 void dng_opcode_MapTable::ReplicateLastEntry ()
352 {
353
354 uint16 *table = fTable->Buffer_uint16 ();
355
356 uint16 lastEntry = table [fCount];
357
358 for (uint32 index = fCount; index < 0x10000; index++)
359 {
360 table [index] = lastEntry;
361 }
362
363 }
364
365 /*****************************************************************************/
366
PutData(dng_stream & stream) const367 void dng_opcode_MapTable::PutData (dng_stream &stream) const
368 {
369
370 stream.Put_uint32 (dng_area_spec::kDataSize + 4 + fCount * 2);
371
372 fAreaSpec.PutData (stream);
373
374 stream.Put_uint32 (fCount);
375
376 uint16 *table = fTable->Buffer_uint16 ();
377
378 for (uint32 index = 0; index < fCount; index++)
379 {
380 stream.Put_uint16 (table [index]);
381 }
382
383 }
384
385 /*****************************************************************************/
386
BufferPixelType(uint32)387 uint32 dng_opcode_MapTable::BufferPixelType (uint32 /* imagePixelType */)
388 {
389
390 return ttShort;
391
392 }
393
394 /*****************************************************************************/
395
ModifiedBounds(const dng_rect & imageBounds)396 dng_rect dng_opcode_MapTable::ModifiedBounds (const dng_rect &imageBounds)
397 {
398
399 return fAreaSpec.Overlap (imageBounds);
400
401 }
402
403 /*****************************************************************************/
404
Prepare(dng_negative & negative,uint32,const dng_point &,const dng_rect &,uint32,uint32,dng_memory_allocator & allocator)405 void dng_opcode_MapTable::Prepare (dng_negative &negative,
406 uint32 /* threadCount */,
407 const dng_point & /* tileSize */,
408 const dng_rect & /* imageBounds */,
409 uint32 /* imagePlanes */,
410 uint32 /* bufferPixelType */,
411 dng_memory_allocator &allocator)
412 {
413
414 fBlackAdjustedTable.Reset ();
415
416 int32 blackLevel = negative.Stage3BlackLevel ();
417
418 if (Stage () >= 2 && blackLevel != 0)
419 {
420
421 fBlackAdjustedTable.Reset (allocator.Allocate (0x10000 * sizeof (uint16)));
422
423 const uint16 *srcTable = fTable->Buffer_uint16 ();
424
425 uint16 *dstTable = fBlackAdjustedTable->Buffer_uint16 ();
426
427 real64 srcScale = 65535.0 / (65535.0 - blackLevel);
428
429 real64 dstScale = (65535.0 - blackLevel) / 65535.0;
430
431 for (int32 index = 0; index < 0x10000; index++)
432 {
433
434 real64 x = (index - blackLevel) * srcScale;
435
436 real64 y;
437
438 if (x < 0.0)
439 {
440
441 y = srcTable [0] * 2.0 - (real64) srcTable [Round_uint32 (-x)];
442
443 }
444
445 else
446 {
447
448 y = srcTable [Round_uint32 (x)];
449
450 }
451
452 dstTable [index] = Pin_uint16 (Round_int32 (y * dstScale) + blackLevel);
453
454 }
455
456 }
457
458 }
459
460 /*****************************************************************************/
461
ProcessArea(dng_negative &,uint32,dng_pixel_buffer & buffer,const dng_rect & dstArea,const dng_rect &)462 void dng_opcode_MapTable::ProcessArea (dng_negative & /* negative */,
463 uint32 /* threadIndex */,
464 dng_pixel_buffer &buffer,
465 const dng_rect &dstArea,
466 const dng_rect & /* imageBounds */)
467 {
468
469 dng_rect overlap = fAreaSpec.Overlap (dstArea);
470
471 if (overlap.NotEmpty ())
472 {
473
474 const uint16 *table = fBlackAdjustedTable.Get () ? fBlackAdjustedTable->Buffer_uint16 ()
475 : fTable ->Buffer_uint16 ();
476
477 for (uint32 plane = fAreaSpec.Plane ();
478 plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
479 plane < buffer.Planes ();
480 plane++)
481 {
482
483 DoMapArea16 (buffer.DirtyPixel_uint16 (overlap.t, overlap.l, plane),
484 1,
485 (overlap.H () + fAreaSpec.RowPitch () - 1) / fAreaSpec.RowPitch (),
486 (overlap.W () + fAreaSpec.ColPitch () - 1) / fAreaSpec.ColPitch (),
487 0,
488 fAreaSpec.RowPitch () * buffer.RowStep (),
489 fAreaSpec.ColPitch (),
490 table);
491
492 }
493
494 }
495
496 }
497
498 /*****************************************************************************/
499
dng_opcode_MapPolynomial(const dng_area_spec & areaSpec,uint32 degree,const real64 * coefficient)500 dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (const dng_area_spec &areaSpec,
501 uint32 degree,
502 const real64 *coefficient)
503
504 : dng_inplace_opcode (dngOpcode_MapPolynomial,
505 dngVersion_1_3_0_0,
506 kFlag_None)
507
508 , fAreaSpec (areaSpec)
509 , fDegree (degree)
510
511 {
512
513 for (uint32 j = 0; j <= kMaxDegree; j++)
514 {
515
516 if (j <= fDegree)
517 {
518 fCoefficient [j] = coefficient [j];
519 }
520
521 else
522 {
523 fCoefficient [j] = 0.0;
524 }
525
526 }
527
528 // Reduce degree if possible.
529
530 while (fDegree > 0 && fCoefficient [fDegree] == 0.0)
531 {
532 fDegree--;
533 }
534
535 }
536
537 /*****************************************************************************/
538
dng_opcode_MapPolynomial(dng_stream & stream)539 dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (dng_stream &stream)
540
541 : dng_inplace_opcode (dngOpcode_MapPolynomial,
542 stream,
543 "MapPolynomial")
544
545 , fAreaSpec ()
546 , fDegree (0)
547
548 {
549
550 uint32 dataSize = stream.Get_uint32 ();
551
552 fAreaSpec.GetData (stream);
553
554 fDegree = stream.Get_uint32 ();
555
556 if (dataSize != dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8)
557 {
558 ThrowBadFormat ();
559 }
560
561 if (fDegree > kMaxDegree)
562 {
563 ThrowBadFormat ();
564 }
565
566 for (uint32 j = 0; j <= kMaxDegree; j++)
567 {
568
569 if (j <= fDegree)
570 {
571 fCoefficient [j] = stream.Get_real64 ();
572 }
573 else
574 {
575 fCoefficient [j] = 0.0;
576 }
577
578 }
579
580 #if qDNGValidate
581
582 if (gVerbose)
583 {
584
585 for (uint32 k = 0; k <= fDegree; k++)
586 {
587 printf (" Coefficient [%u] = %f\n", (unsigned) k, fCoefficient [k]);
588 }
589
590 }
591
592 #endif
593
594 }
595
596 /*****************************************************************************/
597
PutData(dng_stream & stream) const598 void dng_opcode_MapPolynomial::PutData (dng_stream &stream) const
599 {
600
601 stream.Put_uint32 (dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8);
602
603 fAreaSpec.PutData (stream);
604
605 stream.Put_uint32 (fDegree);
606
607 for (uint32 j = 0; j <= fDegree; j++)
608 {
609 stream.Put_real64 (fCoefficient [j]);
610 }
611
612 }
613
614 /*****************************************************************************/
615
BufferPixelType(uint32 imagePixelType)616 uint32 dng_opcode_MapPolynomial::BufferPixelType (uint32 imagePixelType)
617 {
618
619 // If we are operating on the stage 1 image, then we need
620 // to adjust the coefficients to convert from the image
621 // values to the 32-bit floating point values that this
622 // opcode operates on.
623
624 // If we are operating on the stage 2 or 3 image, the logical
625 // range of the image is already 0.0 to 1.0, so we don't
626 // need to adjust the values.
627
628 real64 scale32 = 1.0;
629
630 if (Stage () == 1)
631 {
632
633 switch (imagePixelType)
634 {
635
636 case ttFloat:
637 break;
638
639 case ttShort:
640 {
641 scale32 = (real64) 0xFFFF;
642 break;
643 }
644
645 case ttLong:
646 {
647 scale32 = (real64) 0xFFFFFFFF;
648 break;
649 }
650
651 default:
652 ThrowBadFormat ();
653
654 }
655
656 }
657
658 real64 factor32 = 1.0 / scale32;
659
660 for (uint32 j = 0; j <= kMaxDegree; j++)
661 {
662
663 fCoefficient32 [j] = (real32) (fCoefficient [j] * factor32);
664
665 factor32 *= scale32;
666
667 }
668
669 return ttFloat;
670
671 }
672
673 /*****************************************************************************/
674
ModifiedBounds(const dng_rect & imageBounds)675 dng_rect dng_opcode_MapPolynomial::ModifiedBounds (const dng_rect &imageBounds)
676 {
677
678 return fAreaSpec.Overlap (imageBounds);
679
680 }
681
682 /*****************************************************************************/
683
ProcessArea(dng_negative & negative,uint32,dng_pixel_buffer & buffer,const dng_rect & dstArea,const dng_rect &)684 void dng_opcode_MapPolynomial::ProcessArea (dng_negative &negative,
685 uint32 /* threadIndex */,
686 dng_pixel_buffer &buffer,
687 const dng_rect &dstArea,
688 const dng_rect & /* imageBounds */)
689 {
690
691 dng_rect overlap = fAreaSpec.Overlap (dstArea);
692
693 if (overlap.NotEmpty ())
694 {
695
696 uint16 blackLevel = Stage () >= 2 ? negative.Stage3BlackLevel () : 0;
697
698 uint32 rowPitch = fAreaSpec.RowPitch ();
699 uint32 colPitch = fAreaSpec.ColPitch ();
700
701 for (uint32 plane = fAreaSpec.Plane ();
702 plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
703 plane < buffer.Planes ();
704 plane++)
705 {
706
707 DoProcess (buffer,
708 overlap,
709 plane,
710 rowPitch,
711 colPitch,
712 fCoefficient32,
713 fDegree,
714 blackLevel);
715
716 }
717
718 }
719
720 }
721
722 /*****************************************************************************/
723
DoProcess(dng_pixel_buffer & buffer,const dng_rect & area,const uint32 plane,const uint32 rowPitch,const uint32 colPitch,const real32 * coefficients,const uint32 degree,uint16 blackLevel) const724 void dng_opcode_MapPolynomial::DoProcess (dng_pixel_buffer &buffer,
725 const dng_rect &area,
726 const uint32 plane,
727 const uint32 rowPitch,
728 const uint32 colPitch,
729 const real32 *coefficients,
730 const uint32 degree,
731 uint16 blackLevel) const
732 {
733
734 DoBaselineMapPoly32 (buffer.DirtyPixel_real32 (area.t,
735 area.l,
736 plane),
737 buffer.RowStep () * (int32) rowPitch,
738 area.H (),
739 area.W (),
740 rowPitch,
741 colPitch,
742 coefficients,
743 degree,
744 blackLevel);
745
746 }
747
748 /*****************************************************************************/
749
dng_opcode_DeltaPerRow(const dng_area_spec & areaSpec,AutoPtr<dng_memory_block> & table)750 dng_opcode_DeltaPerRow::dng_opcode_DeltaPerRow (const dng_area_spec &areaSpec,
751 AutoPtr<dng_memory_block> &table)
752
753 : dng_inplace_opcode (dngOpcode_DeltaPerRow,
754 dngVersion_1_3_0_0,
755 kFlag_None)
756
757 , fAreaSpec (areaSpec)
758 , fTable ()
759 , fScale (1.0f)
760
761 {
762
763 fTable.Reset (table.Release ());
764
765 }
766
767 /*****************************************************************************/
768
dng_opcode_DeltaPerRow(dng_host & host,dng_stream & stream)769 dng_opcode_DeltaPerRow::dng_opcode_DeltaPerRow (dng_host &host,
770 dng_stream &stream)
771
772 : dng_inplace_opcode (dngOpcode_DeltaPerRow,
773 stream,
774 "DeltaPerRow")
775
776 , fAreaSpec ()
777 , fTable ()
778 , fScale (1.0f)
779
780 {
781
782 uint32 dataSize = stream.Get_uint32 ();
783
784 fAreaSpec.GetData (stream);
785
786 uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().H (),
787 fAreaSpec.RowPitch ());
788
789 if (deltas != stream.Get_uint32 ())
790 {
791 ThrowBadFormat ();
792 }
793
794 if (dataSize != dng_area_spec::kDataSize + 4 + deltas * 4)
795 {
796 ThrowBadFormat ();
797 }
798
799 fTable.Reset (host.Allocate
800 (SafeUint32Mult (deltas,
801 static_cast<uint32> (sizeof (real32)))));
802
803 real32 *table = fTable->Buffer_real32 ();
804
805 for (uint32 j = 0; j < deltas; j++)
806 {
807 table [j] = stream.Get_real32 ();
808 }
809
810 #if qDNGValidate
811
812 if (gVerbose)
813 {
814
815 printf ("Count: %u\n", (unsigned) deltas);
816
817 for (uint32 k = 0; k < deltas && k < gDumpLineLimit; k++)
818 {
819 printf (" Delta [%u] = %f\n", (unsigned) k, table [k]);
820 }
821
822 if (deltas > gDumpLineLimit)
823 {
824 printf (" ... %u deltas skipped\n", (unsigned) (deltas - gDumpLineLimit));
825 }
826
827 }
828
829 #endif
830
831 }
832
833 /*****************************************************************************/
834
PutData(dng_stream & stream) const835 void dng_opcode_DeltaPerRow::PutData (dng_stream &stream) const
836 {
837
838 uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().H (),
839 fAreaSpec.RowPitch ());
840
841 stream.Put_uint32 (dng_area_spec::kDataSize + 4 + deltas * 4);
842
843 fAreaSpec.PutData (stream);
844
845 stream.Put_uint32 (deltas);
846
847 real32 *table = fTable->Buffer_real32 ();
848
849 for (uint32 j = 0; j < deltas; j++)
850 {
851 stream.Put_real32 (table [j]);
852 }
853
854 }
855
856 /*****************************************************************************/
857
BufferPixelType(uint32 imagePixelType)858 uint32 dng_opcode_DeltaPerRow::BufferPixelType (uint32 imagePixelType)
859 {
860
861 real64 scale32 = 1.0;
862
863 switch (imagePixelType)
864 {
865
866 case ttFloat:
867 break;
868
869 case ttShort:
870 {
871 scale32 = (real64) 0xFFFF;
872 break;
873 }
874
875 case ttLong:
876 {
877 scale32 = (real64) 0xFFFFFFFF;
878 break;
879 }
880
881 default:
882 ThrowBadFormat ();
883
884 }
885
886 fScale = (real32) (1.0 / scale32);
887
888 return ttFloat;
889
890 }
891
892 /*****************************************************************************/
893
ModifiedBounds(const dng_rect & imageBounds)894 dng_rect dng_opcode_DeltaPerRow::ModifiedBounds (const dng_rect &imageBounds)
895 {
896
897 return fAreaSpec.Overlap (imageBounds);
898
899 }
900
901 /*****************************************************************************/
902
ProcessArea(dng_negative & negative,uint32,dng_pixel_buffer & buffer,const dng_rect & dstArea,const dng_rect &)903 void dng_opcode_DeltaPerRow::ProcessArea (dng_negative &negative,
904 uint32 /* threadIndex */,
905 dng_pixel_buffer &buffer,
906 const dng_rect &dstArea,
907 const dng_rect & /* imageBounds */)
908 {
909
910 dng_rect overlap = fAreaSpec.Overlap (dstArea);
911
912 if (overlap.NotEmpty ())
913 {
914
915 uint32 cols = overlap.W ();
916
917 uint32 colPitch = fAreaSpec.ColPitch ();
918
919 real32 scale = fScale;
920
921 if (Stage () >= 2 && negative.Stage3BlackLevel () != 0)
922 {
923 scale *= (real32) (1.0 - negative.Stage3BlackLevelNormalized ());
924 }
925
926 for (uint32 plane = fAreaSpec.Plane ();
927 plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
928 plane < buffer.Planes ();
929 plane++)
930 {
931
932 const real32 *table = fTable->Buffer_real32 () +
933 ((overlap.t - fAreaSpec.Area ().t) /
934 fAreaSpec.RowPitch ());
935
936 for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
937 {
938
939 real32 rowDelta = *(table++) * scale;
940
941 real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
942
943 for (uint32 col = 0; col < cols; col += colPitch)
944 {
945
946 real32 x = dPtr [col];
947
948 real32 y = x + rowDelta;
949
950 dPtr [col] = Pin_real32 (-1.0f, y, 1.0f);
951
952 }
953
954 }
955
956 }
957
958 }
959
960 }
961
962 /*****************************************************************************/
963
dng_opcode_DeltaPerColumn(const dng_area_spec & areaSpec,AutoPtr<dng_memory_block> & table)964 dng_opcode_DeltaPerColumn::dng_opcode_DeltaPerColumn (const dng_area_spec &areaSpec,
965 AutoPtr<dng_memory_block> &table)
966
967 : dng_inplace_opcode (dngOpcode_DeltaPerColumn,
968 dngVersion_1_3_0_0,
969 kFlag_None)
970
971 , fAreaSpec (areaSpec)
972 , fTable ()
973 , fScale (1.0f)
974
975 {
976
977 fTable.Reset (table.Release ());
978
979 }
980
981 /*****************************************************************************/
982
dng_opcode_DeltaPerColumn(dng_host & host,dng_stream & stream)983 dng_opcode_DeltaPerColumn::dng_opcode_DeltaPerColumn (dng_host &host,
984 dng_stream &stream)
985
986 : dng_inplace_opcode (dngOpcode_DeltaPerColumn,
987 stream,
988 "DeltaPerColumn")
989
990 , fAreaSpec ()
991 , fTable ()
992 , fScale (1.0f)
993
994 {
995
996 uint32 dataSize = stream.Get_uint32 ();
997
998 fAreaSpec.GetData (stream);
999
1000 uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().W (),
1001 fAreaSpec.ColPitch ());
1002
1003 if (deltas != stream.Get_uint32 ())
1004 {
1005 ThrowBadFormat ();
1006 }
1007
1008 if (dataSize != dng_area_spec::kDataSize + 4 + deltas * 4)
1009 {
1010 ThrowBadFormat ();
1011 }
1012
1013 fTable.Reset (host.Allocate
1014 (SafeUint32Mult (deltas,
1015 static_cast<uint32> (sizeof (real32)))));
1016
1017 real32 *table = fTable->Buffer_real32 ();
1018
1019 for (uint32 j = 0; j < deltas; j++)
1020 {
1021 table [j] = stream.Get_real32 ();
1022 }
1023
1024 #if qDNGValidate
1025
1026 if (gVerbose)
1027 {
1028
1029 printf ("Count: %u\n", (unsigned) deltas);
1030
1031 for (uint32 k = 0; k < deltas && k < gDumpLineLimit; k++)
1032 {
1033 printf (" Delta [%u] = %f\n", (unsigned) k, table [k]);
1034 }
1035
1036 if (deltas > gDumpLineLimit)
1037 {
1038 printf (" ... %u deltas skipped\n", (unsigned) (deltas - gDumpLineLimit));
1039 }
1040
1041 }
1042
1043 #endif
1044
1045 }
1046
1047 /*****************************************************************************/
1048
PutData(dng_stream & stream) const1049 void dng_opcode_DeltaPerColumn::PutData (dng_stream &stream) const
1050 {
1051
1052 uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().W (),
1053 fAreaSpec.ColPitch ());
1054
1055 stream.Put_uint32 (dng_area_spec::kDataSize + 4 + deltas * 4);
1056
1057 fAreaSpec.PutData (stream);
1058
1059 stream.Put_uint32 (deltas);
1060
1061 real32 *table = fTable->Buffer_real32 ();
1062
1063 for (uint32 j = 0; j < deltas; j++)
1064 {
1065 stream.Put_real32 (table [j]);
1066 }
1067
1068 }
1069
1070 /*****************************************************************************/
1071
BufferPixelType(uint32 imagePixelType)1072 uint32 dng_opcode_DeltaPerColumn::BufferPixelType (uint32 imagePixelType)
1073 {
1074
1075 real64 scale32 = 1.0;
1076
1077 switch (imagePixelType)
1078 {
1079
1080 case ttFloat:
1081 break;
1082
1083 case ttShort:
1084 {
1085 scale32 = (real64) 0xFFFF;
1086 break;
1087 }
1088
1089 case ttLong:
1090 {
1091 scale32 = (real64) 0xFFFFFFFF;
1092 break;
1093 }
1094
1095 default:
1096 ThrowBadFormat ();
1097
1098 }
1099
1100 fScale = (real32) (1.0 / scale32);
1101
1102 return ttFloat;
1103
1104 }
1105
1106 /*****************************************************************************/
1107
ModifiedBounds(const dng_rect & imageBounds)1108 dng_rect dng_opcode_DeltaPerColumn::ModifiedBounds (const dng_rect &imageBounds)
1109 {
1110
1111 return fAreaSpec.Overlap (imageBounds);
1112
1113 }
1114
1115 /*****************************************************************************/
1116
ProcessArea(dng_negative & negative,uint32,dng_pixel_buffer & buffer,const dng_rect & dstArea,const dng_rect &)1117 void dng_opcode_DeltaPerColumn::ProcessArea (dng_negative &negative,
1118 uint32 /* threadIndex */,
1119 dng_pixel_buffer &buffer,
1120 const dng_rect &dstArea,
1121 const dng_rect & /* imageBounds */)
1122 {
1123
1124 dng_rect overlap = fAreaSpec.Overlap (dstArea);
1125
1126 if (overlap.NotEmpty ())
1127 {
1128
1129 uint32 rows = (overlap.H () + fAreaSpec.RowPitch () - 1) /
1130 fAreaSpec.RowPitch ();
1131
1132 int32 rowStep = buffer.RowStep () * fAreaSpec.RowPitch ();
1133
1134 real32 scale = fScale;
1135
1136 if (Stage () >= 2 && negative.Stage3BlackLevel () != 0)
1137 {
1138 scale *= (real32) (1.0 - negative.Stage3BlackLevelNormalized ());
1139 }
1140
1141 for (uint32 plane = fAreaSpec.Plane ();
1142 plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
1143 plane < buffer.Planes ();
1144 plane++)
1145 {
1146
1147 const real32 *table = fTable->Buffer_real32 () +
1148 ((overlap.l - fAreaSpec.Area ().l) /
1149 fAreaSpec.ColPitch ());
1150
1151 for (int32 col = overlap.l; col < overlap.r; col += fAreaSpec.ColPitch ())
1152 {
1153
1154 real32 colDelta = *(table++) * scale;
1155
1156 real32 *dPtr = buffer.DirtyPixel_real32 (overlap.t, col, plane);
1157
1158 for (uint32 row = 0; row < rows; row++)
1159 {
1160
1161 real32 x = dPtr [0];
1162
1163 real32 y = x + colDelta;
1164
1165 dPtr [0] = Pin_real32 (-1.0f, y, 1.0f);
1166
1167 dPtr += rowStep;
1168
1169 }
1170
1171 }
1172
1173 }
1174
1175 }
1176
1177 }
1178
1179 /*****************************************************************************/
1180
dng_opcode_ScalePerRow(const dng_area_spec & areaSpec,AutoPtr<dng_memory_block> & table)1181 dng_opcode_ScalePerRow::dng_opcode_ScalePerRow (const dng_area_spec &areaSpec,
1182 AutoPtr<dng_memory_block> &table)
1183
1184 : dng_inplace_opcode (dngOpcode_ScalePerRow,
1185 dngVersion_1_3_0_0,
1186 kFlag_None)
1187
1188 , fAreaSpec (areaSpec)
1189 , fTable ()
1190
1191 {
1192
1193 fTable.Reset (table.Release ());
1194
1195 }
1196
1197 /*****************************************************************************/
1198
dng_opcode_ScalePerRow(dng_host & host,dng_stream & stream)1199 dng_opcode_ScalePerRow::dng_opcode_ScalePerRow (dng_host &host,
1200 dng_stream &stream)
1201
1202 : dng_inplace_opcode (dngOpcode_ScalePerRow,
1203 stream,
1204 "ScalePerRow")
1205
1206 , fAreaSpec ()
1207 , fTable ()
1208
1209 {
1210
1211 uint32 dataSize = stream.Get_uint32 ();
1212
1213 fAreaSpec.GetData (stream);
1214
1215 uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().H (),
1216 fAreaSpec.RowPitch ());
1217
1218 if (scales != stream.Get_uint32 ())
1219 {
1220 ThrowBadFormat ();
1221 }
1222
1223 if (dataSize != dng_area_spec::kDataSize + 4 + scales * 4)
1224 {
1225 ThrowBadFormat ();
1226 }
1227
1228 fTable.Reset (host.Allocate
1229 (SafeUint32Mult (scales,
1230 static_cast<uint32> (sizeof (real32)))));
1231
1232 real32 *table = fTable->Buffer_real32 ();
1233
1234 for (uint32 j = 0; j < scales; j++)
1235 {
1236 table [j] = stream.Get_real32 ();
1237 }
1238
1239 #if qDNGValidate
1240
1241 if (gVerbose)
1242 {
1243
1244 printf ("Count: %u\n", (unsigned) scales);
1245
1246 for (uint32 k = 0; k < scales && k < gDumpLineLimit; k++)
1247 {
1248 printf (" Scale [%u] = %f\n", (unsigned) k, table [k]);
1249 }
1250
1251 if (scales > gDumpLineLimit)
1252 {
1253 printf (" ... %u scales skipped\n", (unsigned) (scales - gDumpLineLimit));
1254 }
1255
1256 }
1257
1258 #endif
1259
1260 }
1261
1262 /*****************************************************************************/
1263
PutData(dng_stream & stream) const1264 void dng_opcode_ScalePerRow::PutData (dng_stream &stream) const
1265 {
1266
1267 uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().H (),
1268 fAreaSpec.RowPitch ());
1269
1270 stream.Put_uint32 (dng_area_spec::kDataSize + 4 + scales * 4);
1271
1272 fAreaSpec.PutData (stream);
1273
1274 stream.Put_uint32 (scales);
1275
1276 real32 *table = fTable->Buffer_real32 ();
1277
1278 for (uint32 j = 0; j < scales; j++)
1279 {
1280 stream.Put_real32 (table [j]);
1281 }
1282
1283 }
1284
1285 /*****************************************************************************/
1286
BufferPixelType(uint32)1287 uint32 dng_opcode_ScalePerRow::BufferPixelType (uint32 /* imagePixelType */)
1288 {
1289
1290 return ttFloat;
1291
1292 }
1293
1294 /*****************************************************************************/
1295
ModifiedBounds(const dng_rect & imageBounds)1296 dng_rect dng_opcode_ScalePerRow::ModifiedBounds (const dng_rect &imageBounds)
1297 {
1298
1299 return fAreaSpec.Overlap (imageBounds);
1300
1301 }
1302
1303 /*****************************************************************************/
1304
ProcessArea(dng_negative & negative,uint32,dng_pixel_buffer & buffer,const dng_rect & dstArea,const dng_rect &)1305 void dng_opcode_ScalePerRow::ProcessArea (dng_negative &negative,
1306 uint32 /* threadIndex */,
1307 dng_pixel_buffer &buffer,
1308 const dng_rect &dstArea,
1309 const dng_rect & /* imageBounds */)
1310 {
1311
1312 dng_rect overlap = fAreaSpec.Overlap (dstArea);
1313
1314 if (overlap.NotEmpty ())
1315 {
1316
1317 uint32 cols = overlap.W ();
1318
1319 uint32 colPitch = fAreaSpec.ColPitch ();
1320
1321 real32 blackOffset = 0.0f;
1322
1323 if (Stage () >= 2 && negative.Stage3BlackLevel () != 0)
1324 {
1325 blackOffset = (real32) negative.Stage3BlackLevelNormalized ();
1326 }
1327
1328 for (uint32 plane = fAreaSpec.Plane ();
1329 plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
1330 plane < buffer.Planes ();
1331 plane++)
1332 {
1333
1334 const real32 *table = fTable->Buffer_real32 () +
1335 ((overlap.t - fAreaSpec.Area ().t) /
1336 fAreaSpec.RowPitch ());
1337
1338 for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
1339 {
1340
1341 real32 rowScale = *(table++);
1342
1343 real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
1344
1345 for (uint32 col = 0; col < cols; col += colPitch)
1346 {
1347
1348 real32 x = dPtr [col];
1349
1350 real32 y = (x - blackOffset) * rowScale + blackOffset;
1351
1352 dPtr [col] = Pin_real32 (-1.0f, y, 1.0f);
1353
1354 }
1355
1356 }
1357
1358 }
1359
1360 }
1361
1362 }
1363
1364 /*****************************************************************************/
1365
dng_opcode_ScalePerColumn(const dng_area_spec & areaSpec,AutoPtr<dng_memory_block> & table)1366 dng_opcode_ScalePerColumn::dng_opcode_ScalePerColumn (const dng_area_spec &areaSpec,
1367 AutoPtr<dng_memory_block> &table)
1368
1369 : dng_inplace_opcode (dngOpcode_ScalePerColumn,
1370 dngVersion_1_3_0_0,
1371 kFlag_None)
1372
1373 , fAreaSpec (areaSpec)
1374 , fTable ()
1375
1376 {
1377
1378 fTable.Reset (table.Release ());
1379
1380 }
1381
1382 /*****************************************************************************/
1383
dng_opcode_ScalePerColumn(dng_host & host,dng_stream & stream)1384 dng_opcode_ScalePerColumn::dng_opcode_ScalePerColumn (dng_host &host,
1385 dng_stream &stream)
1386
1387 : dng_inplace_opcode (dngOpcode_ScalePerColumn,
1388 stream,
1389 "ScalePerColumn")
1390
1391 , fAreaSpec ()
1392 , fTable ()
1393
1394 {
1395
1396 uint32 dataSize = stream.Get_uint32 ();
1397
1398 fAreaSpec.GetData (stream);
1399
1400 uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().W (),
1401 fAreaSpec.ColPitch());
1402
1403 if (scales != stream.Get_uint32 ())
1404 {
1405 ThrowBadFormat ();
1406 }
1407
1408 if (dataSize != dng_area_spec::kDataSize + 4 + scales * 4)
1409 {
1410 ThrowBadFormat ();
1411 }
1412
1413 fTable.Reset (host.Allocate
1414 (SafeUint32Mult (scales,
1415 static_cast<uint32> (sizeof (real32)))));
1416
1417 real32 *table = fTable->Buffer_real32 ();
1418
1419 for (uint32 j = 0; j < scales; j++)
1420 {
1421 table [j] = stream.Get_real32 ();
1422 }
1423
1424 #if qDNGValidate
1425
1426 if (gVerbose)
1427 {
1428
1429 printf ("Count: %u\n", (unsigned) scales);
1430
1431 for (uint32 k = 0; k < scales && k < gDumpLineLimit; k++)
1432 {
1433 printf (" Scale [%u] = %f\n", (unsigned) k, table [k]);
1434 }
1435
1436 if (scales > gDumpLineLimit)
1437 {
1438 printf (" ... %u deltas skipped\n", (unsigned) (scales - gDumpLineLimit));
1439 }
1440
1441 }
1442
1443 #endif
1444
1445 }
1446
1447 /*****************************************************************************/
1448
PutData(dng_stream & stream) const1449 void dng_opcode_ScalePerColumn::PutData (dng_stream &stream) const
1450 {
1451
1452 uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().W (),
1453 fAreaSpec.ColPitch ());
1454
1455 stream.Put_uint32 (dng_area_spec::kDataSize + 4 + scales * 4);
1456
1457 fAreaSpec.PutData (stream);
1458
1459 stream.Put_uint32 (scales);
1460
1461 real32 *table = fTable->Buffer_real32 ();
1462
1463 for (uint32 j = 0; j < scales; j++)
1464 {
1465 stream.Put_real32 (table [j]);
1466 }
1467
1468 }
1469
1470 /*****************************************************************************/
1471
BufferPixelType(uint32)1472 uint32 dng_opcode_ScalePerColumn::BufferPixelType (uint32 /* imagePixelType */)
1473 {
1474
1475 return ttFloat;
1476
1477 }
1478
1479 /*****************************************************************************/
1480
ModifiedBounds(const dng_rect & imageBounds)1481 dng_rect dng_opcode_ScalePerColumn::ModifiedBounds (const dng_rect &imageBounds)
1482 {
1483
1484 return fAreaSpec.Overlap (imageBounds);
1485
1486 }
1487
1488 /*****************************************************************************/
1489
ProcessArea(dng_negative & negative,uint32,dng_pixel_buffer & buffer,const dng_rect & dstArea,const dng_rect &)1490 void dng_opcode_ScalePerColumn::ProcessArea (dng_negative &negative,
1491 uint32 /* threadIndex */,
1492 dng_pixel_buffer &buffer,
1493 const dng_rect &dstArea,
1494 const dng_rect & /* imageBounds */)
1495 {
1496
1497 dng_rect overlap = fAreaSpec.Overlap (dstArea);
1498
1499 if (overlap.NotEmpty ())
1500 {
1501
1502 uint32 rows = (overlap.H () + fAreaSpec.RowPitch () - 1) /
1503 fAreaSpec.RowPitch ();
1504
1505 int32 rowStep = buffer.RowStep () * fAreaSpec.RowPitch ();
1506
1507 real32 blackOffset = 0.0f;
1508
1509 if (Stage () >= 2 && negative.Stage3BlackLevel () != 0)
1510 {
1511 blackOffset = (real32) negative.Stage3BlackLevelNormalized ();
1512 }
1513
1514 for (uint32 plane = fAreaSpec.Plane ();
1515 plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
1516 plane < buffer.Planes ();
1517 plane++)
1518 {
1519
1520 const real32 *table = fTable->Buffer_real32 () +
1521 ((overlap.l - fAreaSpec.Area ().l) /
1522 fAreaSpec.ColPitch ());
1523
1524 for (int32 col = overlap.l; col < overlap.r; col += fAreaSpec.ColPitch ())
1525 {
1526
1527 real32 colScale = *(table++);
1528
1529 real32 *dPtr = buffer.DirtyPixel_real32 (overlap.t, col, plane);
1530
1531 for (uint32 row = 0; row < rows; row++)
1532 {
1533
1534 real32 x = dPtr [0];
1535
1536 real32 y = (x - blackOffset) * colScale + blackOffset;
1537
1538 dPtr [0] = Pin_real32 (-1.0f, y, 1.0f);
1539
1540 dPtr += rowStep;
1541
1542 }
1543
1544 }
1545
1546 }
1547
1548 }
1549
1550 }
1551
1552 /*****************************************************************************/
1553