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