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
30dng_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
44dng_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
88void 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
102void 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
118void 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
186void 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
204dng_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
245dng_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
277dng_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
345void 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
361void 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
381uint32 dng_opcode_MapTable::BufferPixelType (uint32 /* imagePixelType */)
382	{
383
384	return ttShort;
385
386	}
387
388/*****************************************************************************/
389
390dng_rect dng_opcode_MapTable::ModifiedBounds (const dng_rect &imageBounds)
391	{
392
393	return fAreaSpec.Overlap (imageBounds);
394
395	}
396
397/*****************************************************************************/
398
399void 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
434dng_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
473dng_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
532void 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
550uint32 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
609dng_rect dng_opcode_MapPolynomial::ModifiedBounds (const dng_rect &imageBounds)
610	{
611
612	return fAreaSpec.Overlap (imageBounds);
613
614	}
615
616/*****************************************************************************/
617
618void 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
828dng_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
847dng_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
912void 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
935uint32 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
971dng_rect dng_opcode_DeltaPerRow::ModifiedBounds (const dng_rect &imageBounds)
972	{
973
974	return fAreaSpec.Overlap (imageBounds);
975
976	}
977
978/*****************************************************************************/
979
980void 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
1034dng_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
1053dng_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
1118void 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
1141uint32 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
1177dng_rect dng_opcode_DeltaPerColumn::ModifiedBounds (const dng_rect &imageBounds)
1178	{
1179
1180	return fAreaSpec.Overlap (imageBounds);
1181
1182	}
1183
1184/*****************************************************************************/
1185
1186void 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
1243dng_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
1261dng_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
1325void 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
1348uint32 dng_opcode_ScalePerRow::BufferPixelType (uint32 /* imagePixelType */)
1349	{
1350
1351	return ttFloat;
1352
1353	}
1354
1355/*****************************************************************************/
1356
1357dng_rect dng_opcode_ScalePerRow::ModifiedBounds (const dng_rect &imageBounds)
1358	{
1359
1360	return fAreaSpec.Overlap (imageBounds);
1361
1362	}
1363
1364/*****************************************************************************/
1365
1366void 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
1420dng_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
1438dng_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
1502void 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
1525uint32 dng_opcode_ScalePerColumn::BufferPixelType (uint32 /* imagePixelType */)
1526	{
1527
1528	return ttFloat;
1529
1530	}
1531
1532/*****************************************************************************/
1533
1534dng_rect dng_opcode_ScalePerColumn::ModifiedBounds (const dng_rect &imageBounds)
1535	{
1536
1537	return fAreaSpec.Overlap (imageBounds);
1538
1539	}
1540
1541/*****************************************************************************/
1542
1543void 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