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 /*****************************************************************************/