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