Home | History | Annotate | Download | only in source
      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 
     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 
     45 dng_tile_buffer::~dng_tile_buffer ()
     46 	{
     47 
     48 	fImage.ReleaseTileBuffer (*this);
     49 
     50 	}
     51 
     52 /*****************************************************************************/
     53 
     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 
     65 dng_const_tile_buffer::~dng_const_tile_buffer ()
     66 	{
     67 
     68 	}
     69 
     70 /*****************************************************************************/
     71 
     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 
     83 dng_dirty_tile_buffer::~dng_dirty_tile_buffer ()
     84 	{
     85 
     86 	}
     87 
     88 /*****************************************************************************/
     89 
     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 
    117 dng_image::~dng_image ()
    118 	{
    119 
    120 	}
    121 
    122 /*****************************************************************************/
    123 
    124 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 
    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 
    151 uint32 dng_image::PixelSize () const
    152 	{
    153 
    154 	return TagTypeSize (PixelType ());
    155 
    156 	}
    157 
    158 /*****************************************************************************/
    159 
    160 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 
    195 dng_rect dng_image::RepeatingTile () const
    196 	{
    197 
    198 	return fBounds;
    199 
    200 	}
    201 
    202 /*****************************************************************************/
    203 
    204 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 
    215 void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const
    216 	{
    217 
    218 	}
    219 
    220 /*****************************************************************************/
    221 
    222 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 
    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 
    268 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 
    415 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 
    494 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 
    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 
    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 
    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 
    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 
    785 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 
    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