1 /*****************************************************************************/
2 // Copyright 2006-2008 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_image.cpp#1 $ */
10 /* $DateTime: 2012/05/30 13:28:51 $ */
11 /* $Change: 832332 $ */
12 /* $Author: tknoll $ */
13 
14 /*****************************************************************************/
15 
16 #include "dng_image.h"
17 
18 #include "dng_assertions.h"
19 #include "dng_exceptions.h"
20 #include "dng_orientation.h"
21 #include "dng_pixel_buffer.h"
22 #include "dng_tag_types.h"
23 #include "dng_tile_iterator.h"
24 #include "dng_utils.h"
25 
26 /*****************************************************************************/
27 
dng_tile_buffer(const dng_image & image,const dng_rect & tile,bool dirty)28 dng_tile_buffer::dng_tile_buffer (const dng_image &image,
29 						 		  const dng_rect &tile,
30 						 		  bool dirty)
31 
32 	:	fImage   (image)
33 	,	fRefData (NULL)
34 
35 	{
36 
37 	fImage.AcquireTileBuffer (*this,
38 							  tile,
39 							  dirty);
40 
41 	}
42 
43 /*****************************************************************************/
44 
~dng_tile_buffer()45 dng_tile_buffer::~dng_tile_buffer ()
46 	{
47 
48 	fImage.ReleaseTileBuffer (*this);
49 
50 	}
51 
52 /*****************************************************************************/
53 
dng_const_tile_buffer(const dng_image & image,const dng_rect & tile)54 dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image,
55 						 		  			  const dng_rect &tile)
56 
57 	: 	dng_tile_buffer (image, tile, false)
58 
59 	{
60 
61 	}
62 
63 /*****************************************************************************/
64 
~dng_const_tile_buffer()65 dng_const_tile_buffer::~dng_const_tile_buffer ()
66 	{
67 
68 	}
69 
70 /*****************************************************************************/
71 
dng_dirty_tile_buffer(dng_image & image,const dng_rect & tile)72 dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image,
73 						 		  			  const dng_rect &tile)
74 
75 	: 	dng_tile_buffer (image, tile, true)
76 
77 	{
78 
79 	}
80 
81 /*****************************************************************************/
82 
~dng_dirty_tile_buffer()83 dng_dirty_tile_buffer::~dng_dirty_tile_buffer ()
84 	{
85 
86 	}
87 
88 /*****************************************************************************/
89 
dng_image(const dng_rect & bounds,uint32 planes,uint32 pixelType)90 dng_image::dng_image (const dng_rect &bounds,
91 				      uint32 planes,
92 				      uint32 pixelType)
93 
94 	: 	fBounds    (bounds)
95 	,	fPlanes    (planes)
96 	,	fPixelType (pixelType)
97 
98 	{
99 
100 	if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0)
101 		{
102 
103 		#if qDNGValidate
104 
105 		ReportError ("Fuzz: Attempt to create zero size image");
106 
107 		#endif
108 
109 		ThrowBadFormat ();
110 
111 		}
112 
113 	}
114 
115 /*****************************************************************************/
116 
~dng_image()117 dng_image::~dng_image ()
118 	{
119 
120 	}
121 
122 /*****************************************************************************/
123 
Clone() const124 dng_image * dng_image::Clone () const
125 	{
126 
127 	ThrowProgramError ("Clone is not supported by this dng_image subclass");
128 
129 	return NULL;
130 
131 	}
132 
133 /*****************************************************************************/
134 
SetPixelType(uint32 pixelType)135 void dng_image::SetPixelType (uint32 pixelType)
136 	{
137 
138 	if (TagTypeSize (pixelType) != PixelSize ())
139 		{
140 
141 		ThrowProgramError ("Cannot change pixel size for existing image");
142 
143 		}
144 
145 	fPixelType = pixelType;
146 
147 	}
148 
149 /*****************************************************************************/
150 
PixelSize() const151 uint32 dng_image::PixelSize () const
152 	{
153 
154 	return TagTypeSize (PixelType ());
155 
156 	}
157 
158 /*****************************************************************************/
159 
PixelRange() const160 uint32 dng_image::PixelRange () const
161 	{
162 
163 	switch (fPixelType)
164 		{
165 
166 		case ttByte:
167 		case ttSByte:
168 			{
169 			return 0x0FF;
170 			}
171 
172 		case ttShort:
173 		case ttSShort:
174 			{
175 			return 0x0FFFF;
176 			}
177 
178 		case ttLong:
179 		case ttSLong:
180 			{
181 			return 0xFFFFFFFF;
182 			}
183 
184 		default:
185 			break;
186 
187 		}
188 
189 	return 0;
190 
191 	}
192 
193 /*****************************************************************************/
194 
RepeatingTile() const195 dng_rect dng_image::RepeatingTile () const
196 	{
197 
198 	return fBounds;
199 
200 	}
201 
202 /*****************************************************************************/
203 
AcquireTileBuffer(dng_tile_buffer &,const dng_rect &,bool) const204 void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */,
205 								   const dng_rect & /* area */,
206 								   bool /* dirty */) const
207 	{
208 
209 	ThrowProgramError ();
210 
211 	}
212 
213 /*****************************************************************************/
214 
ReleaseTileBuffer(dng_tile_buffer &) const215 void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const
216 	{
217 
218 	}
219 
220 /*****************************************************************************/
221 
DoGet(dng_pixel_buffer & buffer) const222 void dng_image::DoGet (dng_pixel_buffer &buffer) const
223 	{
224 
225 	dng_rect tile;
226 
227 	dng_tile_iterator iter (*this, buffer.fArea);
228 
229 	while (iter.GetOneTile (tile))
230 		{
231 
232 		dng_const_tile_buffer tileBuffer (*this, tile);
233 
234 		buffer.CopyArea (tileBuffer,
235 				  		 tile,
236 				  		 buffer.fPlane,
237 				  		 buffer.fPlanes);
238 
239 		}
240 
241 	}
242 
243 /*****************************************************************************/
244 
DoPut(const dng_pixel_buffer & buffer)245 void dng_image::DoPut (const dng_pixel_buffer &buffer)
246 	{
247 
248 	dng_rect tile;
249 
250 	dng_tile_iterator iter (*this, buffer.fArea);
251 
252 	while (iter.GetOneTile (tile))
253 		{
254 
255 		dng_dirty_tile_buffer tileBuffer (*this, tile);
256 
257 		tileBuffer.CopyArea (buffer,
258 				  		     tile,
259 				  		     buffer.fPlane,
260 				  		     buffer.fPlanes);
261 
262 		}
263 
264 	}
265 
266 /*****************************************************************************/
267 
GetRepeat(dng_pixel_buffer & buffer,const dng_rect & srcArea,const dng_rect & dstArea) const268 void dng_image::GetRepeat (dng_pixel_buffer &buffer,
269 				           const dng_rect &srcArea,
270 				           const dng_rect &dstArea) const
271 	{
272 
273 	// If we already have the entire srcArea in the
274 	// buffer, we can just repeat that.
275 
276 	if ((srcArea & buffer.fArea) == srcArea)
277 		{
278 
279 		buffer.RepeatArea (srcArea,
280 						   dstArea);
281 
282 		}
283 
284 	// Else we first need to get the srcArea into the buffer area.
285 
286 	else
287 		{
288 
289 		// Find repeating pattern size.
290 
291 		dng_point repeat = srcArea.Size ();
292 
293 		// Find pattern phase at top-left corner of destination area.
294 
295 		dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea,
296 													     dstArea);
297 
298 		// Find new source area at top-left of dstArea.
299 
300 		dng_rect newArea = srcArea + (dstArea.TL () -
301 								      srcArea.TL ());
302 
303 		// Find quadrant split coordinates.
304 
305 		int32 splitV = newArea.t + repeat.v - phase.v;
306 		int32 splitH = newArea.l + repeat.h - phase.h;
307 
308 		// Top-left quadrant.
309 
310 		dng_rect dst1 (dng_rect (newArea.t,
311 					   			 newArea.l,
312 					   			 splitV,
313 					   			 splitH) & dstArea);
314 
315 		if (dst1.NotEmpty ())
316 			{
317 
318 			dng_pixel_buffer temp (buffer);
319 
320 			temp.fArea = dst1 + (srcArea.TL () -
321 								 dstArea.TL () +
322 								 dng_point (phase.v, phase.h));
323 
324 			temp.fData = buffer.DirtyPixel (dst1.t,
325 									        dst1.l,
326 									        buffer.fPlane);
327 
328 			DoGet (temp);
329 
330 			}
331 
332 		// Top-right quadrant.
333 
334 		dng_rect dst2 (dng_rect (newArea.t,
335 								 splitH,
336 								 splitV,
337 								 newArea.r) & dstArea);
338 
339 		if (dst2.NotEmpty ())
340 			{
341 
342 			dng_pixel_buffer temp (buffer);
343 
344 			temp.fArea = dst2 + (srcArea.TL () -
345 								 dstArea.TL () +
346 								 dng_point (phase.v, -phase.h));
347 
348 			temp.fData = buffer.DirtyPixel (dst2.t,
349 									        dst2.l,
350 									        buffer.fPlane);
351 
352 			DoGet (temp);
353 
354 			}
355 
356 		// Bottom-left quadrant.
357 
358 		dng_rect dst3 (dng_rect (splitV,
359 								 newArea.l,
360 								 newArea.b,
361 								 splitH) & dstArea);
362 
363 		if (dst3.NotEmpty ())
364 			{
365 
366 			dng_pixel_buffer temp (buffer);
367 
368 			temp.fArea = dst3 + (srcArea.TL () -
369 								 dstArea.TL () +
370 								 dng_point (-phase.v, phase.h));
371 
372 			temp.fData = buffer.DirtyPixel (dst3.t,
373 									        dst3.l,
374 									        buffer.fPlane);
375 
376 			DoGet (temp);
377 
378 			}
379 
380 		// Bottom-right quadrant.
381 
382 		dng_rect dst4 (dng_rect (splitV,
383 								 splitH,
384 								 newArea.b,
385 								 newArea.r) & dstArea);
386 
387 		if (dst4.NotEmpty ())
388 			{
389 
390 			dng_pixel_buffer temp (buffer);
391 
392 			temp.fArea = dst4 + (srcArea.TL () -
393 								 dstArea.TL () +
394 								 dng_point (-phase.v, -phase.h));
395 
396 			temp.fData = buffer.DirtyPixel (dst4.t,
397 									        dst4.l,
398 									        buffer.fPlane);
399 
400 			DoGet (temp);
401 
402 			}
403 
404 		// Replicate this new source area.
405 
406 		buffer.RepeatArea (newArea,
407 						   dstArea);
408 
409 		}
410 
411 	}
412 
413 /*****************************************************************************/
414 
GetEdge(dng_pixel_buffer & buffer,edge_option edgeOption,const dng_rect & srcArea,const dng_rect & dstArea) const415 void dng_image::GetEdge (dng_pixel_buffer &buffer,
416 					     edge_option edgeOption,
417 				         const dng_rect &srcArea,
418 				         const dng_rect &dstArea) const
419 	{
420 
421 	switch (edgeOption)
422 		{
423 
424 		case edge_zero:
425 			{
426 
427 			buffer.SetZero (dstArea,
428 							buffer.fPlane,
429 							buffer.fPlanes);
430 
431 			break;
432 
433 			}
434 
435 		case edge_repeat:
436 			{
437 
438 			GetRepeat (buffer,
439 					   srcArea,
440 					   dstArea);
441 
442 			break;
443 
444 			}
445 
446 		case edge_repeat_zero_last:
447 			{
448 
449 			if (buffer.fPlanes > 1)
450 				{
451 
452 				dng_pixel_buffer buffer1 (buffer);
453 
454 				buffer1.fPlanes--;
455 
456 				GetEdge (buffer1,
457 						 edge_repeat,
458 						 srcArea,
459 						 dstArea);
460 
461 				}
462 
463 			dng_pixel_buffer buffer2 (buffer);
464 
465 			buffer2.fPlane  = buffer.fPlanes - 1;
466 			buffer2.fPlanes = 1;
467 
468 			buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t,
469 										  	   buffer2.fArea.l,
470 										  	   buffer2.fPlane);
471 
472 			GetEdge (buffer2,
473 					 edge_zero,
474 					 srcArea,
475 					 dstArea);
476 
477 			break;
478 
479 			}
480 
481 		default:
482 			{
483 
484 			ThrowProgramError ();
485 
486 			}
487 
488 		}
489 
490 	}
491 
492 /*****************************************************************************/
493 
Get(dng_pixel_buffer & buffer,edge_option edgeOption,uint32 repeatV,uint32 repeatH) const494 void dng_image::Get (dng_pixel_buffer &buffer,
495 					 edge_option edgeOption,
496 				     uint32 repeatV,
497 				     uint32 repeatH) const
498 	{
499 
500 	// Find the overlap with the image bounds.
501 
502 	dng_rect overlap = buffer.fArea & fBounds;
503 
504 	// Move the overlapping pixels.
505 
506 	if (overlap.NotEmpty ())
507 		{
508 
509 		dng_pixel_buffer temp (buffer);
510 
511 		temp.fArea = overlap;
512 
513 		temp.fData = buffer.DirtyPixel (overlap.t,
514 								   		overlap.l,
515 								   		buffer.fPlane);
516 
517 		DoGet (temp);
518 
519 		}
520 
521 	// See if we need to pad the edge values.
522 
523 	if ((edgeOption != edge_none) && (overlap != buffer.fArea))
524 		{
525 
526 		dng_rect areaT (buffer.fArea);
527 		dng_rect areaL (buffer.fArea);
528 		dng_rect areaB (buffer.fArea);
529 		dng_rect areaR (buffer.fArea);
530 
531 		areaT.b = Min_int32 (areaT.b, fBounds.t);
532 		areaL.r = Min_int32 (areaL.r, fBounds.l);
533 		areaB.t = Max_int32 (areaB.t, fBounds.b);
534 		areaR.l = Max_int32 (areaR.l, fBounds.r);
535 
536 		dng_rect areaH (buffer.fArea);
537 		dng_rect areaV (buffer.fArea);
538 
539 		areaH.l = Max_int32 (areaH.l, fBounds.l);
540 		areaH.r = Min_int32 (areaH.r, fBounds.r);
541 
542 		areaV.t = Max_int32 (areaV.t, fBounds.t);
543 		areaV.b = Min_int32 (areaV.b, fBounds.b);
544 
545 		// Top left.
546 
547 		dng_rect areaTL = areaT & areaL;
548 
549 		if (areaTL.NotEmpty ())
550 			{
551 
552 			GetEdge (buffer,
553 					 edgeOption,
554 					 dng_rect (fBounds.t,
555 					 		   fBounds.l,
556 					 		   fBounds.t + repeatV,
557 					 		   fBounds.l + repeatH),
558 					 areaTL);
559 
560 			}
561 
562 		// Top middle.
563 
564 		dng_rect areaTM = areaT & areaH;
565 
566 		if (areaTM.NotEmpty ())
567 			{
568 
569 			GetEdge (buffer,
570 					 edgeOption,
571 					 dng_rect (fBounds.t,
572 					 		   areaTM.l,
573 					 		   fBounds.t + repeatV,
574 					 		   areaTM.r),
575 					 areaTM);
576 
577 			}
578 
579 		// Top right.
580 
581 		dng_rect areaTR = areaT & areaR;
582 
583 		if (areaTR.NotEmpty ())
584 			{
585 
586 			GetEdge (buffer,
587 					 edgeOption,
588 					 dng_rect (fBounds.t,
589 					 		   fBounds.r - repeatH,
590 					 		   fBounds.t + repeatV,
591 					 		   fBounds.r),
592 					 areaTR);
593 
594 			}
595 
596 		// Left middle.
597 
598 		dng_rect areaLM = areaL & areaV;
599 
600 		if (areaLM.NotEmpty ())
601 			{
602 
603 			GetEdge (buffer,
604 					 edgeOption,
605 					 dng_rect (areaLM.t,
606 					 		   fBounds.l,
607 					 		   areaLM.b,
608 					 		   fBounds.l + repeatH),
609 					 areaLM);
610 
611 			}
612 
613 		// Right middle.
614 
615 		dng_rect areaRM = areaR & areaV;
616 
617 		if (areaRM.NotEmpty ())
618 			{
619 
620 			GetEdge (buffer,
621 					 edgeOption,
622 					 dng_rect (areaRM.t,
623 					 		   fBounds.r - repeatH,
624 					 		   areaRM.b,
625 					 		   fBounds.r),
626 					 areaRM);
627 
628 			}
629 
630 		// Bottom left.
631 
632 		dng_rect areaBL = areaB & areaL;
633 
634 		if (areaBL.NotEmpty ())
635 			{
636 
637 			GetEdge (buffer,
638 					 edgeOption,
639 					 dng_rect (fBounds.b - repeatV,
640 					 		   fBounds.l,
641 					 		   fBounds.b,
642 					 		   fBounds.l + repeatH),
643 					 areaBL);
644 
645 			}
646 
647 		// Bottom middle.
648 
649 		dng_rect areaBM = areaB & areaH;
650 
651 		if (areaBM.NotEmpty ())
652 			{
653 
654 			GetEdge (buffer,
655 					 edgeOption,
656 					 dng_rect (fBounds.b - repeatV,
657 					 		   areaBM.l,
658 					 		   fBounds.b,
659 					 		   areaBM.r),
660 					 areaBM);
661 
662 			}
663 
664 		// Bottom right.
665 
666 		dng_rect areaBR = areaB & areaR;
667 
668 		if (areaBR.NotEmpty ())
669 			{
670 
671 			GetEdge (buffer,
672 					 edgeOption,
673 					 dng_rect (fBounds.b - repeatV,
674 					 		   fBounds.r - repeatH,
675 					 		   fBounds.b,
676 					 		   fBounds.r),
677 					 areaBR);
678 
679 			}
680 
681 		}
682 
683 	}
684 
685 /*****************************************************************************/
686 
Put(const dng_pixel_buffer & buffer)687 void dng_image::Put (const dng_pixel_buffer &buffer)
688 	{
689 
690 	// Move the overlapping pixels.
691 
692 	dng_rect overlap = buffer.fArea & fBounds;
693 
694 	if (overlap.NotEmpty ())
695 		{
696 
697 		dng_pixel_buffer temp (buffer);
698 
699 		temp.fArea = overlap;
700 
701 		temp.fData = (void *) buffer.ConstPixel (overlap.t,
702 								   		 		 overlap.l,
703 								   		 		 buffer.fPlane);
704 
705 		// Move the overlapping planes.
706 
707 		if (temp.fPlane < Planes ())
708 			{
709 
710 			temp.fPlanes = Min_uint32 (temp.fPlanes,
711 									   Planes () - temp.fPlane);
712 
713 			DoPut (temp);
714 
715 			}
716 
717 		}
718 
719 	}
720 
721 /*****************************************************************************/
722 
Trim(const dng_rect & r)723 void dng_image::Trim (const dng_rect &r)
724 	{
725 
726 	if (r != Bounds ())
727 		{
728 
729 		ThrowProgramError ("Trim is not support by this dng_image subclass");
730 
731 		}
732 
733 	}
734 
735 /*****************************************************************************/
736 
Rotate(const dng_orientation & orientation)737 void dng_image::Rotate (const dng_orientation &orientation)
738 	{
739 
740 	if (orientation != dng_orientation::Normal ())
741 		{
742 
743 		ThrowProgramError ("Rotate is not support by this dng_image subclass");
744 
745 		}
746 
747 	}
748 
749 /*****************************************************************************/
750 
CopyArea(const dng_image & src,const dng_rect & area,uint32 srcPlane,uint32 dstPlane,uint32 planes)751 void dng_image::CopyArea (const dng_image &src,
752 						  const dng_rect &area,
753 						  uint32 srcPlane,
754 						  uint32 dstPlane,
755 						  uint32 planes)
756 	{
757 
758 	if (&src == this)
759 		return;
760 
761 	dng_tile_iterator destIter(*this, area);
762 	dng_rect destTileArea;
763 
764 	while (destIter.GetOneTile(destTileArea))
765 		{
766 		dng_tile_iterator srcIter(src, destTileArea);
767 		dng_rect srcTileArea;
768 
769 		while (srcIter.GetOneTile(srcTileArea))
770 			{
771 
772 			dng_dirty_tile_buffer destTile(*this, srcTileArea);
773 			dng_const_tile_buffer srcTile(src, srcTileArea);
774 
775 			destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes);
776 
777 			}
778 
779 		}
780 
781 	}
782 
783 /*****************************************************************************/
784 
EqualArea(const dng_image & src,const dng_rect & area,uint32 plane,uint32 planes) const785 bool dng_image::EqualArea (const dng_image &src,
786 						   const dng_rect &area,
787 						   uint32 plane,
788 						   uint32 planes) const
789 	{
790 
791 	if (&src == this)
792 		return true;
793 
794 	dng_tile_iterator destIter (*this, area);
795 
796 	dng_rect destTileArea;
797 
798 	while (destIter.GetOneTile (destTileArea))
799 		{
800 
801 		dng_tile_iterator srcIter (src, destTileArea);
802 
803 		dng_rect srcTileArea;
804 
805 		while (srcIter.GetOneTile (srcTileArea))
806 			{
807 
808 			dng_const_tile_buffer destTile (*this, srcTileArea);
809 			dng_const_tile_buffer srcTile  (src  , srcTileArea);
810 
811 			if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes))
812 				{
813 				return false;
814 				}
815 
816 			}
817 
818 		}
819 
820 	return true;
821 
822 	}
823 
824 /*****************************************************************************/
825 
SetConstant(uint32 value,const dng_rect & area)826 void dng_image::SetConstant (uint32 value,
827 							 const dng_rect &area)
828 	{
829 
830 	dng_tile_iterator iter (*this, area);
831 
832 	dng_rect tileArea;
833 
834 	while (iter.GetOneTile (tileArea))
835 		{
836 
837 		dng_dirty_tile_buffer buffer (*this, tileArea);
838 
839 		buffer.SetConstant (tileArea,
840 							0,
841 							fPlanes,
842 							value);
843 
844 		}
845 
846 	}
847 
848 /*****************************************************************************/
849