File indexing completed on 2025-01-19 03:55:09

0001 /*****************************************************************************/
0002 // Copyright 2008-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_opcodes.h"
0010 
0011 #include "dng_bottlenecks.h"
0012 #include "dng_exceptions.h"
0013 #include "dng_filter_task.h"
0014 #include "dng_globals.h"
0015 #include "dng_host.h"
0016 #include "dng_image.h"
0017 #include "dng_negative.h"
0018 #include "dng_parse_utils.h"
0019 #include "dng_stream.h"
0020 #include "dng_tag_values.h"
0021 
0022 /*****************************************************************************/
0023 
0024 dng_opcode::dng_opcode (uint32 opcodeID,
0025                         uint32 minVersion,
0026                         uint32 flags)
0027 
0028     :   fOpcodeID          (opcodeID)
0029     ,   fMinVersion        (minVersion)
0030     ,   fFlags             (flags)
0031     ,   fWasReadFromStream (false)
0032     ,   fStage             (0)
0033 
0034     {
0035 
0036     }
0037 
0038 /*****************************************************************************/
0039 
0040 dng_opcode::dng_opcode (uint32 opcodeID,
0041                         dng_stream &stream,
0042                         const char *name)
0043 
0044     :   fOpcodeID          (opcodeID)
0045     ,   fMinVersion        (0)
0046     ,   fFlags             (0)
0047     ,   fWasReadFromStream (true)
0048     ,   fStage             (0)
0049 
0050     {
0051 
0052     fMinVersion = stream.Get_uint32 ();
0053     fFlags      = stream.Get_uint32 ();
0054 
0055     #if qDNGValidate
0056 
0057     if (gVerbose)
0058         {
0059 
0060         printf ("\nOpcode: ");
0061 
0062         if (name)
0063             {
0064             printf ("%s", name);
0065             }
0066         else
0067             {
0068             printf ("Unknown (%u)", (unsigned) opcodeID);
0069             }
0070 
0071         printf (", minVersion = %u.%u.%u.%u",
0072                 (unsigned) ((fMinVersion >> 24) & 0x0FF),
0073                 (unsigned) ((fMinVersion >> 16) & 0x0FF),
0074                 (unsigned) ((fMinVersion >>  8) & 0x0FF),
0075                 (unsigned) ((fMinVersion      ) & 0x0FF));
0076 
0077         printf (", flags = %u\n", (unsigned) fFlags);
0078 
0079         }
0080 
0081     #else
0082 
0083     (void) name;
0084 
0085     #endif
0086 
0087     }
0088 
0089 /*****************************************************************************/
0090 
0091 dng_opcode::~dng_opcode ()
0092     {
0093 
0094     }
0095 
0096 /*****************************************************************************/
0097 
0098 void dng_opcode::PutData (dng_stream &stream) const
0099     {
0100 
0101     // No data by default
0102 
0103     stream.Put_uint32 (0);
0104 
0105     }
0106 
0107 /*****************************************************************************/
0108 
0109 bool dng_opcode::AboutToApply (dng_host &host,
0110                                dng_negative &negative,
0111                                const dng_rect &imageBounds,
0112                                uint32 imagePlanes)
0113     {
0114 
0115     if (SkipIfPreview () && host.ForPreview ())
0116         {
0117 
0118         negative.SetIsPreview (true);
0119 
0120         }
0121 
0122     else if (MinVersion () > dngVersion_Current &&
0123              WasReadFromStream ())
0124         {
0125 
0126         if (!Optional ())
0127             {
0128 
0129             // Somebody screwed up computing the DNGBackwardVersion...
0130 
0131             ThrowBadFormat ();
0132 
0133             }
0134 
0135         }
0136 
0137     else if (!IsValidForNegative (negative))
0138         {
0139 
0140         ThrowBadFormat ();
0141 
0142         }
0143 
0144     else if (!IsNOP ())
0145         {
0146 
0147         DoAboutToApply (host,
0148                         negative,
0149                         imageBounds,
0150                         imagePlanes);
0151 
0152         return true;
0153 
0154         }
0155 
0156     return false;
0157 
0158     }
0159 
0160 /*****************************************************************************/
0161 
0162 dng_opcode_Unknown::dng_opcode_Unknown (dng_host &host,
0163                                         uint32 opcodeID,
0164                                         dng_stream &stream)
0165 
0166     :   dng_opcode (opcodeID,
0167                     stream,
0168                     NULL)
0169 
0170     ,   fData ()
0171 
0172     {
0173 
0174     uint32 size = stream.Get_uint32 ();
0175 
0176     if (size)
0177         {
0178 
0179         fData.Reset (host.Allocate (size));
0180 
0181         stream.Get (fData->Buffer      (),
0182                     fData->LogicalSize ());
0183 
0184         #if qDNGValidate
0185 
0186         if (gVerbose)
0187             {
0188 
0189             DumpHexAscii (fData->Buffer_uint8 (),
0190                           fData->LogicalSize  ());
0191 
0192             }
0193 
0194         #endif
0195 
0196         }
0197 
0198     }
0199 
0200 /*****************************************************************************/
0201 
0202 void dng_opcode_Unknown::PutData (dng_stream &stream) const
0203     {
0204 
0205     if (fData.Get ())
0206         {
0207 
0208         stream.Put_uint32 (fData->LogicalSize ());
0209 
0210         stream.Put (fData->Buffer      (),
0211                     fData->LogicalSize ());
0212 
0213         }
0214 
0215     else
0216         {
0217 
0218         stream.Put_uint32 (0);
0219 
0220         }
0221 
0222     }
0223 
0224 /*****************************************************************************/
0225 
0226 void dng_opcode_Unknown::Apply (dng_host & /* host */,
0227                                 dng_negative & /* negative */,
0228                                 AutoPtr<dng_image> & /* image */)
0229     {
0230 
0231     // We should never need to apply an unknown opcode.
0232 
0233     if (!Optional ())
0234         {
0235 
0236         ThrowBadFormat ();
0237 
0238         }
0239 
0240     }
0241 
0242 /*****************************************************************************/
0243 
0244 class dng_filter_opcode_task: public dng_filter_task
0245     {
0246 
0247     private:
0248 
0249         dng_filter_opcode &fOpcode;
0250 
0251         dng_negative &fNegative;
0252 
0253     public:
0254 
0255         dng_filter_opcode_task (dng_filter_opcode &opcode,
0256                                 dng_negative &negative,
0257                                 const dng_image &srcImage,
0258                                 dng_image &dstImage)
0259 
0260             :   dng_filter_task ("dng_filter_opcode_task",
0261                                  srcImage,
0262                                  dstImage)
0263 
0264             ,   fOpcode   (opcode)
0265             ,   fNegative (negative)
0266 
0267             {
0268 
0269             fSrcPixelType = fOpcode.BufferPixelType (srcImage.PixelType ());
0270 
0271             fDstPixelType = fSrcPixelType;
0272 
0273             fSrcRepeat = opcode.SrcRepeat ();
0274 
0275             }
0276 
0277         virtual dng_rect SrcArea (const dng_rect &dstArea)
0278             {
0279 
0280             return fOpcode.SrcArea (dstArea,
0281                                     fDstImage.Bounds ());
0282 
0283             }
0284 
0285         virtual dng_point SrcTileSize (const dng_point &dstTileSize)
0286             {
0287 
0288             return fOpcode.SrcTileSize (dstTileSize,
0289                                         fDstImage.Bounds ());
0290 
0291             }
0292 
0293         virtual void ProcessArea (uint32 threadIndex,
0294                                   dng_pixel_buffer &srcBuffer,
0295                                   dng_pixel_buffer &dstBuffer)
0296             {
0297 
0298             fOpcode.ProcessArea (fNegative,
0299                                  threadIndex,
0300                                  srcBuffer,
0301                                  dstBuffer,
0302                                  dstBuffer.Area (),
0303                                  fDstImage.Bounds ());
0304 
0305             }
0306 
0307         virtual void Start (uint32 threadCount,
0308                             const dng_rect &dstArea,
0309                             const dng_point &tileSize,
0310                             dng_memory_allocator *allocator,
0311                             dng_abort_sniffer *sniffer)
0312             {
0313 
0314             dng_filter_task::Start (threadCount,
0315                                     dstArea,
0316                                     tileSize,
0317                                     allocator,
0318                                     sniffer);
0319 
0320             fOpcode.Prepare (fNegative,
0321                              threadCount,
0322                              tileSize,
0323                              fDstImage.Bounds (),
0324                              fDstImage.Planes (),
0325                              fDstPixelType,
0326                              *allocator);
0327 
0328             }
0329 
0330     };
0331 
0332 /*****************************************************************************/
0333 
0334 dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
0335                                       uint32 minVersion,
0336                                       uint32 flags)
0337 
0338     :   dng_opcode (opcodeID,
0339                     minVersion,
0340                     flags)
0341 
0342     {
0343 
0344     }
0345 
0346 /*****************************************************************************/
0347 
0348 dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
0349                                       dng_stream &stream,
0350                                       const char *name)
0351 
0352     :   dng_opcode (opcodeID,
0353                     stream,
0354                     name)
0355 
0356     {
0357 
0358     }
0359 
0360 /*****************************************************************************/
0361 
0362 void dng_filter_opcode::Apply (dng_host &host,
0363                                dng_negative &negative,
0364                                AutoPtr<dng_image> &image)
0365     {
0366 
0367     dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
0368 
0369     if (modifiedBounds.NotEmpty ())
0370         {
0371 
0372         // Allocate destination image.
0373 
0374         AutoPtr<dng_image> dstImage;
0375 
0376         // If we are processing the entire image, allocate an
0377         // undefined image.
0378 
0379         if (modifiedBounds == image->Bounds ())
0380             {
0381 
0382             dstImage.Reset (host.Make_dng_image (image->Bounds    (),
0383                                                  image->Planes    (),
0384                                                  image->PixelType ()));
0385 
0386             }
0387 
0388         // Else start with a clone of the existing image.
0389 
0390         else
0391             {
0392 
0393             dstImage.Reset (image->Clone ());
0394 
0395             }
0396 
0397         // Filter the image.
0398 
0399         dng_filter_opcode_task task (*this,
0400                                      negative,
0401                                      *image,
0402                                      *dstImage);
0403 
0404         host.PerformAreaTask (task,
0405                               modifiedBounds);
0406 
0407         // Return the new image.
0408 
0409         image.Reset (dstImage.Release ());
0410 
0411         }
0412 
0413     }
0414 
0415 /*****************************************************************************/
0416 
0417 class dng_inplace_opcode_task: public dng_area_task
0418     {
0419 
0420     private:
0421 
0422         dng_inplace_opcode &fOpcode;
0423 
0424         dng_negative &fNegative;
0425 
0426         dng_image &fImage;
0427 
0428         uint32 fPixelType;
0429 
0430         AutoPtr<dng_memory_block> fBuffer [kMaxMPThreads];
0431 
0432     public:
0433 
0434         dng_inplace_opcode_task (dng_inplace_opcode &opcode,
0435                                  dng_negative &negative,
0436                                  dng_image &image)
0437 
0438             :   dng_area_task ("dng_inplace_opcode_task")
0439 
0440             ,   fOpcode    (opcode)
0441             ,   fNegative  (negative)
0442             ,   fImage     (image)
0443             ,   fPixelType (opcode.BufferPixelType (image.PixelType ()))
0444 
0445             {
0446 
0447             }
0448 
0449         virtual void Start (uint32 threadCount,
0450                             const dng_rect & /* dstArea */,
0451                             const dng_point &tileSize,
0452                             dng_memory_allocator *allocator,
0453                             dng_abort_sniffer * /* sniffer */)
0454             {
0455 
0456             uint32 bufferSize = ComputeBufferSize (fPixelType,
0457                                                    tileSize,
0458                                                    fImage.Planes (),
0459                                                    padSIMDBytes);
0460 
0461             for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
0462                 {
0463 
0464                 fBuffer [threadIndex] . Reset (allocator->Allocate (bufferSize));
0465 
0466                 }
0467 
0468             fOpcode.Prepare (fNegative,
0469                              threadCount,
0470                              tileSize,
0471                              fImage.Bounds (),
0472                              fImage.Planes (),
0473                              fPixelType,
0474                              *allocator);
0475 
0476             }
0477 
0478         virtual void Process (uint32 threadIndex,
0479                               const dng_rect &tile,
0480                               dng_abort_sniffer * /* sniffer */)
0481             {
0482 
0483             // Setup buffer.
0484 
0485             dng_pixel_buffer buffer (tile,
0486                                      0,
0487                                      fImage.Planes (),
0488                                      fPixelType,
0489                                      pcRowInterleavedAlignSIMD,
0490                                      fBuffer [threadIndex]->Buffer ());
0491 
0492             // Get source pixels.
0493 
0494             fImage.Get (buffer);
0495 
0496             // Process area.
0497 
0498             fOpcode.ProcessArea (fNegative,
0499                                  threadIndex,
0500                                  buffer,
0501                                  tile,
0502                                  fImage.Bounds ());
0503 
0504             // Save result pixels.
0505 
0506             fImage.Put (buffer);
0507 
0508             }
0509 
0510     };
0511 
0512 /*****************************************************************************/
0513 
0514 dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
0515                                         uint32 minVersion,
0516                                         uint32 flags)
0517 
0518     :   dng_opcode (opcodeID,
0519                     minVersion,
0520                     flags)
0521 
0522     {
0523 
0524     }
0525 
0526 /*****************************************************************************/
0527 
0528 dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
0529                                         dng_stream &stream,
0530                                         const char *name)
0531 
0532     :   dng_opcode (opcodeID,
0533                     stream,
0534                     name)
0535 
0536     {
0537 
0538     }
0539 
0540 /*****************************************************************************/
0541 
0542 void dng_inplace_opcode::Apply (dng_host &host,
0543                                 dng_negative &negative,
0544                                 AutoPtr<dng_image> &image)
0545     {
0546 
0547     dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
0548 
0549     if (modifiedBounds.NotEmpty ())
0550         {
0551 
0552         dng_inplace_opcode_task task (*this,
0553                                       negative,
0554                                       *image);
0555 
0556         host.PerformAreaTask (task,
0557                               modifiedBounds);
0558 
0559         }
0560 
0561     }
0562 
0563 /*****************************************************************************/