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