File indexing completed on 2025-01-19 03:55:00
0001 /*****************************************************************************/ 0002 // Copyright 2006-2019 Adobe Systems Incorporated 0003 // All Rights Reserved. 0004 // 0005 // NOTICE: Adobe permits you to use, modify, and distribute this file in 0006 // accordance with the terms of the Adobe license agreement accompanying it. 0007 /*****************************************************************************/ 0008 0009 #include "dng_image.h" 0010 0011 #include "dng_assertions.h" 0012 #include "dng_exceptions.h" 0013 #include "dng_orientation.h" 0014 #include "dng_pixel_buffer.h" 0015 #include "dng_tag_types.h" 0016 #include "dng_tile_iterator.h" 0017 #include "dng_utils.h" 0018 0019 /*****************************************************************************/ 0020 0021 dng_tile_buffer::dng_tile_buffer (const dng_image &image, 0022 const dng_rect &tile, 0023 bool dirty) 0024 0025 : fImage (image) 0026 , fRefData (NULL) 0027 0028 { 0029 0030 fImage.AcquireTileBuffer (*this, 0031 tile, 0032 dirty); 0033 0034 } 0035 0036 /*****************************************************************************/ 0037 0038 dng_tile_buffer::~dng_tile_buffer () 0039 { 0040 0041 fImage.ReleaseTileBuffer (*this); 0042 0043 } 0044 0045 /*****************************************************************************/ 0046 0047 dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image, 0048 const dng_rect &tile) 0049 0050 : dng_tile_buffer (image, tile, false) 0051 0052 { 0053 0054 } 0055 0056 /*****************************************************************************/ 0057 0058 dng_const_tile_buffer::~dng_const_tile_buffer () 0059 { 0060 0061 } 0062 0063 /*****************************************************************************/ 0064 0065 dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image, 0066 const dng_rect &tile) 0067 0068 : dng_tile_buffer (image, tile, true) 0069 0070 { 0071 0072 } 0073 0074 /*****************************************************************************/ 0075 0076 dng_dirty_tile_buffer::~dng_dirty_tile_buffer () 0077 { 0078 0079 } 0080 0081 /*****************************************************************************/ 0082 0083 dng_image::dng_image (const dng_rect &bounds, 0084 uint32 planes, 0085 uint32 pixelType) 0086 0087 : fBounds (bounds) 0088 , fPlanes (planes) 0089 , fPixelType (pixelType) 0090 0091 { 0092 0093 if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0) 0094 { 0095 0096 #if qDNGValidate 0097 0098 ReportError ("Fuzz: Attempt to create zero size image"); 0099 0100 #endif 0101 0102 ThrowBadFormat (); 0103 0104 } 0105 0106 // Allow up to 2 * kMaxImageSide to deal with intermediate image objects 0107 // (e.g., rotated and padded). 0108 0109 static const uint32 kLimit = 2 * kMaxImageSide; 0110 0111 if (bounds.W () > kLimit || 0112 bounds.H () > kLimit) 0113 { 0114 0115 ThrowBadFormat ("dng_image bounds too large"); 0116 0117 } 0118 0119 } 0120 0121 /*****************************************************************************/ 0122 0123 dng_image::~dng_image () 0124 { 0125 0126 } 0127 0128 /*****************************************************************************/ 0129 0130 dng_image * dng_image::Clone () const 0131 { 0132 0133 ThrowProgramError ("Clone is not supported by this dng_image subclass"); 0134 0135 return NULL; 0136 0137 } 0138 0139 /*****************************************************************************/ 0140 0141 void dng_image::SetPixelType (uint32 pixelType) 0142 { 0143 0144 if (TagTypeSize (pixelType) != PixelSize ()) 0145 { 0146 0147 ThrowProgramError ("Cannot change pixel size for existing image"); 0148 0149 } 0150 0151 fPixelType = pixelType; 0152 0153 } 0154 0155 /*****************************************************************************/ 0156 0157 uint32 dng_image::PixelSize () const 0158 { 0159 0160 return TagTypeSize (PixelType ()); 0161 0162 } 0163 0164 /*****************************************************************************/ 0165 0166 uint32 dng_image::PixelRange () const 0167 { 0168 0169 switch (fPixelType) 0170 { 0171 0172 case ttByte: 0173 case ttSByte: 0174 { 0175 return 0x0FF; 0176 } 0177 0178 case ttShort: 0179 case ttSShort: 0180 { 0181 return 0x0FFFF; 0182 } 0183 0184 case ttLong: 0185 case ttSLong: 0186 { 0187 return 0xFFFFFFFF; 0188 } 0189 0190 default: 0191 break; 0192 0193 } 0194 0195 return 0; 0196 0197 } 0198 0199 /*****************************************************************************/ 0200 0201 dng_rect dng_image::RepeatingTile () const 0202 { 0203 0204 return fBounds; 0205 0206 } 0207 0208 /*****************************************************************************/ 0209 0210 void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */, 0211 const dng_rect & /* area */, 0212 bool /* dirty */) const 0213 { 0214 0215 ThrowProgramError (); 0216 0217 } 0218 0219 /*****************************************************************************/ 0220 0221 void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const 0222 { 0223 0224 } 0225 0226 /*****************************************************************************/ 0227 0228 void dng_image::DoGet (dng_pixel_buffer &buffer) const 0229 { 0230 0231 dng_rect tile; 0232 0233 dng_tile_iterator iter (*this, buffer.fArea); 0234 0235 while (iter.GetOneTile (tile)) 0236 { 0237 0238 dng_const_tile_buffer tileBuffer (*this, tile); 0239 0240 buffer.CopyArea (tileBuffer, 0241 tile, 0242 buffer.fPlane, 0243 buffer.fPlanes); 0244 0245 } 0246 0247 } 0248 0249 /*****************************************************************************/ 0250 0251 void dng_image::DoPut (const dng_pixel_buffer &buffer) 0252 { 0253 0254 dng_rect tile; 0255 0256 dng_tile_iterator iter (*this, buffer.fArea); 0257 0258 while (iter.GetOneTile (tile)) 0259 { 0260 0261 dng_dirty_tile_buffer tileBuffer (*this, tile); 0262 0263 tileBuffer.CopyArea (buffer, 0264 tile, 0265 buffer.fPlane, 0266 buffer.fPlanes); 0267 0268 } 0269 0270 } 0271 0272 /*****************************************************************************/ 0273 0274 void dng_image::GetRepeat (dng_pixel_buffer &buffer, 0275 const dng_rect &srcArea, 0276 const dng_rect &dstArea) const 0277 { 0278 0279 // If we already have the entire srcArea in the 0280 // buffer, we can just repeat that. 0281 0282 if ((srcArea & buffer.fArea) == srcArea) 0283 { 0284 0285 buffer.RepeatArea (srcArea, 0286 dstArea); 0287 0288 } 0289 0290 // Else we first need to get the srcArea into the buffer area. 0291 0292 else 0293 { 0294 0295 // Find repeating pattern size. 0296 0297 dng_point repeat = srcArea.Size (); 0298 0299 // Find pattern phase at top-left corner of destination area. 0300 0301 dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea, 0302 dstArea); 0303 0304 // Find new source area at top-left of dstArea. 0305 0306 dng_rect newArea = srcArea + (dstArea.TL () - 0307 srcArea.TL ()); 0308 0309 // Find quadrant split coordinates. 0310 0311 int32 splitV = newArea.t + repeat.v - phase.v; 0312 int32 splitH = newArea.l + repeat.h - phase.h; 0313 0314 // Top-left quadrant. 0315 0316 dng_rect dst1 (dng_rect (newArea.t, 0317 newArea.l, 0318 splitV, 0319 splitH) & dstArea); 0320 0321 if (dst1.NotEmpty ()) 0322 { 0323 0324 dng_pixel_buffer temp (buffer); 0325 0326 temp.fArea = dst1 + (srcArea.TL () - 0327 dstArea.TL () + 0328 dng_point (phase.v, phase.h)); 0329 0330 temp.fData = buffer.DirtyPixel (dst1.t, 0331 dst1.l, 0332 buffer.fPlane); 0333 0334 DoGet (temp); 0335 0336 } 0337 0338 // Top-right quadrant. 0339 0340 dng_rect dst2 (dng_rect (newArea.t, 0341 splitH, 0342 splitV, 0343 newArea.r) & dstArea); 0344 0345 if (dst2.NotEmpty ()) 0346 { 0347 0348 dng_pixel_buffer temp (buffer); 0349 0350 temp.fArea = dst2 + (srcArea.TL () - 0351 dstArea.TL () + 0352 dng_point (phase.v, -phase.h)); 0353 0354 temp.fData = buffer.DirtyPixel (dst2.t, 0355 dst2.l, 0356 buffer.fPlane); 0357 0358 DoGet (temp); 0359 0360 } 0361 0362 // Bottom-left quadrant. 0363 0364 dng_rect dst3 (dng_rect (splitV, 0365 newArea.l, 0366 newArea.b, 0367 splitH) & dstArea); 0368 0369 if (dst3.NotEmpty ()) 0370 { 0371 0372 dng_pixel_buffer temp (buffer); 0373 0374 temp.fArea = dst3 + (srcArea.TL () - 0375 dstArea.TL () + 0376 dng_point (-phase.v, phase.h)); 0377 0378 temp.fData = buffer.DirtyPixel (dst3.t, 0379 dst3.l, 0380 buffer.fPlane); 0381 0382 DoGet (temp); 0383 0384 } 0385 0386 // Bottom-right quadrant. 0387 0388 dng_rect dst4 (dng_rect (splitV, 0389 splitH, 0390 newArea.b, 0391 newArea.r) & dstArea); 0392 0393 if (dst4.NotEmpty ()) 0394 { 0395 0396 dng_pixel_buffer temp (buffer); 0397 0398 temp.fArea = dst4 + (srcArea.TL () - 0399 dstArea.TL () + 0400 dng_point (-phase.v, -phase.h)); 0401 0402 temp.fData = buffer.DirtyPixel (dst4.t, 0403 dst4.l, 0404 buffer.fPlane); 0405 0406 DoGet (temp); 0407 0408 } 0409 0410 // Replicate this new source area. 0411 0412 buffer.RepeatArea (newArea, 0413 dstArea); 0414 0415 } 0416 0417 } 0418 0419 /*****************************************************************************/ 0420 0421 void dng_image::GetEdge (dng_pixel_buffer &buffer, 0422 edge_option edgeOption, 0423 const dng_rect &srcArea, 0424 const dng_rect &dstArea) const 0425 { 0426 0427 switch (edgeOption) 0428 { 0429 0430 case edge_zero: 0431 { 0432 0433 buffer.SetZero (dstArea, 0434 buffer.fPlane, 0435 buffer.fPlanes); 0436 0437 break; 0438 0439 } 0440 0441 case edge_repeat: 0442 { 0443 0444 GetRepeat (buffer, 0445 srcArea, 0446 dstArea); 0447 0448 break; 0449 0450 } 0451 0452 case edge_repeat_zero_last: 0453 { 0454 0455 if (buffer.fPlanes > 1) 0456 { 0457 0458 dng_pixel_buffer buffer1 (buffer); 0459 0460 buffer1.fPlanes--; 0461 0462 GetEdge (buffer1, 0463 edge_repeat, 0464 srcArea, 0465 dstArea); 0466 0467 } 0468 0469 dng_pixel_buffer buffer2 (buffer); 0470 0471 buffer2.fPlane = buffer.fPlanes - 1; 0472 buffer2.fPlanes = 1; 0473 0474 buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t, 0475 buffer2.fArea.l, 0476 buffer2.fPlane); 0477 0478 GetEdge (buffer2, 0479 edge_zero, 0480 srcArea, 0481 dstArea); 0482 0483 break; 0484 0485 } 0486 0487 default: 0488 { 0489 0490 ThrowProgramError (); 0491 0492 } 0493 0494 } 0495 0496 } 0497 0498 /*****************************************************************************/ 0499 0500 void dng_image::Get (dng_pixel_buffer &buffer, 0501 edge_option edgeOption, 0502 uint32 repeatV, 0503 uint32 repeatH) const 0504 { 0505 0506 // Find the overlap with the image bounds. 0507 0508 dng_rect overlap = buffer.fArea & fBounds; 0509 0510 // Move the overlapping pixels. 0511 0512 if (overlap.NotEmpty ()) 0513 { 0514 0515 dng_pixel_buffer temp (buffer); 0516 0517 temp.fArea = overlap; 0518 0519 temp.fData = buffer.DirtyPixel (overlap.t, 0520 overlap.l, 0521 buffer.fPlane); 0522 0523 DoGet (temp); 0524 0525 } 0526 0527 // See if we need to pad the edge values. 0528 0529 if ((edgeOption != edge_none) && (overlap != buffer.fArea)) 0530 { 0531 0532 dng_rect areaT (buffer.fArea); 0533 dng_rect areaL (buffer.fArea); 0534 dng_rect areaB (buffer.fArea); 0535 dng_rect areaR (buffer.fArea); 0536 0537 areaT.b = Min_int32 (areaT.b, fBounds.t); 0538 areaL.r = Min_int32 (areaL.r, fBounds.l); 0539 areaB.t = Max_int32 (areaB.t, fBounds.b); 0540 areaR.l = Max_int32 (areaR.l, fBounds.r); 0541 0542 dng_rect areaH (buffer.fArea); 0543 dng_rect areaV (buffer.fArea); 0544 0545 areaH.l = Max_int32 (areaH.l, fBounds.l); 0546 areaH.r = Min_int32 (areaH.r, fBounds.r); 0547 0548 areaV.t = Max_int32 (areaV.t, fBounds.t); 0549 areaV.b = Min_int32 (areaV.b, fBounds.b); 0550 0551 // Top left. 0552 0553 dng_rect areaTL = areaT & areaL; 0554 0555 if (areaTL.NotEmpty ()) 0556 { 0557 0558 GetEdge (buffer, 0559 edgeOption, 0560 dng_rect (fBounds.t, 0561 fBounds.l, 0562 fBounds.t + repeatV, 0563 fBounds.l + repeatH), 0564 areaTL); 0565 0566 } 0567 0568 // Top middle. 0569 0570 dng_rect areaTM = areaT & areaH; 0571 0572 if (areaTM.NotEmpty ()) 0573 { 0574 0575 GetEdge (buffer, 0576 edgeOption, 0577 dng_rect (fBounds.t, 0578 areaTM.l, 0579 fBounds.t + repeatV, 0580 areaTM.r), 0581 areaTM); 0582 0583 } 0584 0585 // Top right. 0586 0587 dng_rect areaTR = areaT & areaR; 0588 0589 if (areaTR.NotEmpty ()) 0590 { 0591 0592 GetEdge (buffer, 0593 edgeOption, 0594 dng_rect (fBounds.t, 0595 fBounds.r - repeatH, 0596 fBounds.t + repeatV, 0597 fBounds.r), 0598 areaTR); 0599 0600 } 0601 0602 // Left middle. 0603 0604 dng_rect areaLM = areaL & areaV; 0605 0606 if (areaLM.NotEmpty ()) 0607 { 0608 0609 GetEdge (buffer, 0610 edgeOption, 0611 dng_rect (areaLM.t, 0612 fBounds.l, 0613 areaLM.b, 0614 fBounds.l + repeatH), 0615 areaLM); 0616 0617 } 0618 0619 // Right middle. 0620 0621 dng_rect areaRM = areaR & areaV; 0622 0623 if (areaRM.NotEmpty ()) 0624 { 0625 0626 GetEdge (buffer, 0627 edgeOption, 0628 dng_rect (areaRM.t, 0629 fBounds.r - repeatH, 0630 areaRM.b, 0631 fBounds.r), 0632 areaRM); 0633 0634 } 0635 0636 // Bottom left. 0637 0638 dng_rect areaBL = areaB & areaL; 0639 0640 if (areaBL.NotEmpty ()) 0641 { 0642 0643 GetEdge (buffer, 0644 edgeOption, 0645 dng_rect (fBounds.b - repeatV, 0646 fBounds.l, 0647 fBounds.b, 0648 fBounds.l + repeatH), 0649 areaBL); 0650 0651 } 0652 0653 // Bottom middle. 0654 0655 dng_rect areaBM = areaB & areaH; 0656 0657 if (areaBM.NotEmpty ()) 0658 { 0659 0660 GetEdge (buffer, 0661 edgeOption, 0662 dng_rect (fBounds.b - repeatV, 0663 areaBM.l, 0664 fBounds.b, 0665 areaBM.r), 0666 areaBM); 0667 0668 } 0669 0670 // Bottom right. 0671 0672 dng_rect areaBR = areaB & areaR; 0673 0674 if (areaBR.NotEmpty ()) 0675 { 0676 0677 GetEdge (buffer, 0678 edgeOption, 0679 dng_rect (fBounds.b - repeatV, 0680 fBounds.r - repeatH, 0681 fBounds.b, 0682 fBounds.r), 0683 areaBR); 0684 0685 } 0686 0687 } 0688 0689 } 0690 0691 /*****************************************************************************/ 0692 0693 void dng_image::Put (const dng_pixel_buffer &buffer) 0694 { 0695 0696 // Move the overlapping pixels. 0697 0698 dng_rect overlap = buffer.fArea & fBounds; 0699 0700 if (overlap.NotEmpty ()) 0701 { 0702 0703 dng_pixel_buffer temp (buffer); 0704 0705 temp.fArea = overlap; 0706 0707 temp.fData = (void *) buffer.ConstPixel (overlap.t, 0708 overlap.l, 0709 buffer.fPlane); 0710 0711 // Move the overlapping planes. 0712 0713 if (temp.fPlane < Planes ()) 0714 { 0715 0716 temp.fPlanes = Min_uint32 (temp.fPlanes, 0717 Planes () - temp.fPlane); 0718 0719 DoPut (temp); 0720 0721 } 0722 0723 } 0724 0725 } 0726 0727 /*****************************************************************************/ 0728 0729 void dng_image::Trim (const dng_rect &r) 0730 { 0731 0732 if (r != Bounds ()) 0733 { 0734 0735 ThrowProgramError ("Trim is not support by this dng_image subclass"); 0736 0737 } 0738 0739 } 0740 0741 /*****************************************************************************/ 0742 0743 void dng_image::Rotate (const dng_orientation &orientation) 0744 { 0745 0746 if (orientation != dng_orientation::Normal ()) 0747 { 0748 0749 ThrowProgramError ("Rotate is not support by this dng_image subclass"); 0750 0751 } 0752 0753 } 0754 0755 /*****************************************************************************/ 0756 0757 void dng_image::DoCopyArea (const dng_image &src, 0758 const dng_rect &area, 0759 uint32 srcPlane, 0760 uint32 dstPlane, 0761 uint32 planes) 0762 { 0763 0764 if (&src == this) 0765 return; 0766 0767 dng_tile_iterator destIter(*this, area); 0768 dng_rect destTileArea; 0769 0770 while (destIter.GetOneTile(destTileArea)) 0771 { 0772 dng_tile_iterator srcIter(src, destTileArea); 0773 dng_rect srcTileArea; 0774 0775 while (srcIter.GetOneTile(srcTileArea)) 0776 { 0777 0778 dng_dirty_tile_buffer destTile(*this, srcTileArea); 0779 dng_const_tile_buffer srcTile(src, srcTileArea); 0780 0781 destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes); 0782 0783 } 0784 0785 } 0786 0787 } 0788 0789 /*****************************************************************************/ 0790 0791 bool dng_image::EqualArea (const dng_image &src, 0792 const dng_rect &area, 0793 uint32 plane, 0794 uint32 planes) const 0795 { 0796 0797 if (&src == this) 0798 return true; 0799 0800 dng_tile_iterator destIter (*this, area); 0801 0802 dng_rect destTileArea; 0803 0804 while (destIter.GetOneTile (destTileArea)) 0805 { 0806 0807 dng_tile_iterator srcIter (src, destTileArea); 0808 0809 dng_rect srcTileArea; 0810 0811 while (srcIter.GetOneTile (srcTileArea)) 0812 { 0813 0814 dng_const_tile_buffer destTile (*this, srcTileArea); 0815 dng_const_tile_buffer srcTile (src , srcTileArea); 0816 0817 if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes)) 0818 { 0819 return false; 0820 } 0821 0822 } 0823 0824 } 0825 0826 return true; 0827 0828 } 0829 0830 /*****************************************************************************/ 0831 0832 void dng_image::SetConstant (uint32 value, 0833 const dng_rect &area) 0834 { 0835 0836 dng_tile_iterator iter (*this, area); 0837 0838 dng_rect tileArea; 0839 0840 while (iter.GetOneTile (tileArea)) 0841 { 0842 0843 dng_dirty_tile_buffer buffer (*this, tileArea); 0844 0845 buffer.SetConstant (tileArea, 0846 0, 0847 fPlanes, 0848 value); 0849 0850 } 0851 0852 } 0853 0854 /*****************************************************************************/