1/*****************************************************************************/ 2// Copyright 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_opcodes.cpp#1 $ */ 10/* $DateTime: 2012/05/30 13:28:51 $ */ 11/* $Change: 832332 $ */ 12/* $Author: tknoll $ */ 13 14/*****************************************************************************/ 15 16#include "dng_opcodes.h" 17 18#include "dng_bottlenecks.h" 19#include "dng_exceptions.h" 20#include "dng_filter_task.h" 21#include "dng_globals.h" 22#include "dng_host.h" 23#include "dng_image.h" 24#include "dng_negative.h" 25#include "dng_parse_utils.h" 26#include "dng_stream.h" 27#include "dng_tag_values.h" 28 29/*****************************************************************************/ 30 31dng_opcode::dng_opcode (uint32 opcodeID, 32 uint32 minVersion, 33 uint32 flags) 34 35 : fOpcodeID (opcodeID) 36 , fMinVersion (minVersion) 37 , fFlags (flags) 38 , fWasReadFromStream (false) 39 , fStage (0) 40 41 { 42 43 } 44 45/*****************************************************************************/ 46 47dng_opcode::dng_opcode (uint32 opcodeID, 48 dng_stream &stream, 49 const char *name) 50 51 : fOpcodeID (opcodeID) 52 , fMinVersion (0) 53 , fFlags (0) 54 , fWasReadFromStream (true) 55 , fStage (0) 56 57 { 58 59 fMinVersion = stream.Get_uint32 (); 60 fFlags = stream.Get_uint32 (); 61 62 #if qDNGValidate 63 64 if (gVerbose) 65 { 66 67 printf ("\nOpcode: "); 68 69 if (name) 70 { 71 printf ("%s", name); 72 } 73 else 74 { 75 printf ("Unknown (%u)", (unsigned) opcodeID); 76 } 77 78 printf (", minVersion = %u.%u.%u.%u", 79 (unsigned) ((fMinVersion >> 24) & 0x0FF), 80 (unsigned) ((fMinVersion >> 16) & 0x0FF), 81 (unsigned) ((fMinVersion >> 8) & 0x0FF), 82 (unsigned) ((fMinVersion ) & 0x0FF)); 83 84 printf (", flags = %u\n", (unsigned) fFlags); 85 86 } 87 88 #else 89 90 (void) name; 91 92 #endif 93 94 } 95 96/*****************************************************************************/ 97 98dng_opcode::~dng_opcode () 99 { 100 101 } 102 103/*****************************************************************************/ 104 105void dng_opcode::PutData (dng_stream &stream) const 106 { 107 108 // No data by default 109 110 stream.Put_uint32 (0); 111 112 } 113 114/*****************************************************************************/ 115 116bool dng_opcode::AboutToApply (dng_host &host, 117 dng_negative &negative) 118 { 119 120 if (SkipIfPreview () && host.ForPreview ()) 121 { 122 123 negative.SetIsPreview (true); 124 125 } 126 127 else if (MinVersion () > dngVersion_Current && 128 WasReadFromStream ()) 129 { 130 131 if (!Optional ()) 132 { 133 134 // Somebody screwed up computing the DNGBackwardVersion... 135 136 ThrowBadFormat (); 137 138 } 139 140 } 141 142 else if (!IsValidForNegative (negative)) 143 { 144 145 ThrowBadFormat (); 146 147 } 148 149 else if (!IsNOP ()) 150 { 151 152 return true; 153 154 } 155 156 return false; 157 158 } 159 160/*****************************************************************************/ 161 162dng_opcode_Unknown::dng_opcode_Unknown (dng_host &host, 163 uint32 opcodeID, 164 dng_stream &stream) 165 166 : dng_opcode (opcodeID, 167 stream, 168 NULL) 169 170 , fData () 171 172 { 173 174 uint32 size = stream.Get_uint32 (); 175 176 if (size) 177 { 178 179 fData.Reset (host.Allocate (size)); 180 181 stream.Get (fData->Buffer (), 182 fData->LogicalSize ()); 183 184 #if qDNGValidate 185 186 if (gVerbose) 187 { 188 189 DumpHexAscii (fData->Buffer_uint8 (), 190 fData->LogicalSize ()); 191 192 } 193 194 #endif 195 196 } 197 198 } 199 200/*****************************************************************************/ 201 202void dng_opcode_Unknown::PutData (dng_stream &stream) const 203 { 204 205 if (fData.Get ()) 206 { 207 208 stream.Put_uint32 (fData->LogicalSize ()); 209 210 stream.Put (fData->Buffer (), 211 fData->LogicalSize ()); 212 213 } 214 215 else 216 { 217 218 stream.Put_uint32 (0); 219 220 } 221 222 } 223 224/*****************************************************************************/ 225 226void dng_opcode_Unknown::Apply (dng_host & /* host */, 227 dng_negative & /* negative */, 228 AutoPtr<dng_image> & /* image */) 229 { 230 231 // We should never need to apply an unknown opcode. 232 233 if (!Optional ()) 234 { 235 236 ThrowBadFormat (); 237 238 } 239 240 } 241 242/*****************************************************************************/ 243 244class dng_filter_opcode_task: public dng_filter_task 245 { 246 247 private: 248 249 dng_filter_opcode &fOpcode; 250 251 dng_negative &fNegative; 252 253 public: 254 255 dng_filter_opcode_task (dng_filter_opcode &opcode, 256 dng_negative &negative, 257 const dng_image &srcImage, 258 dng_image &dstImage) 259 260 : dng_filter_task (srcImage, 261 dstImage) 262 263 , fOpcode (opcode) 264 , fNegative (negative) 265 266 { 267 268 fSrcPixelType = fOpcode.BufferPixelType (srcImage.PixelType ()); 269 270 fDstPixelType = fSrcPixelType; 271 272 fSrcRepeat = opcode.SrcRepeat (); 273 274 } 275 276 virtual dng_rect SrcArea (const dng_rect &dstArea) 277 { 278 279 return fOpcode.SrcArea (dstArea, 280 fDstImage.Bounds ()); 281 282 } 283 284 virtual dng_point SrcTileSize (const dng_point &dstTileSize) 285 { 286 287 return fOpcode.SrcTileSize (dstTileSize, 288 fDstImage.Bounds ()); 289 290 } 291 292 virtual void ProcessArea (uint32 threadIndex, 293 dng_pixel_buffer &srcBuffer, 294 dng_pixel_buffer &dstBuffer) 295 { 296 297 fOpcode.ProcessArea (fNegative, 298 threadIndex, 299 srcBuffer, 300 dstBuffer, 301 dstBuffer.Area (), 302 fDstImage.Bounds ()); 303 304 } 305 306 virtual void Start (uint32 threadCount, 307 const dng_point &tileSize, 308 dng_memory_allocator *allocator, 309 dng_abort_sniffer *sniffer) 310 { 311 312 dng_filter_task::Start (threadCount, 313 tileSize, 314 allocator, 315 sniffer); 316 317 fOpcode.Prepare (fNegative, 318 threadCount, 319 tileSize, 320 fDstImage.Bounds (), 321 fDstImage.Planes (), 322 fDstPixelType, 323 *allocator); 324 325 } 326 327 }; 328 329/*****************************************************************************/ 330 331dng_filter_opcode::dng_filter_opcode (uint32 opcodeID, 332 uint32 minVersion, 333 uint32 flags) 334 335 : dng_opcode (opcodeID, 336 minVersion, 337 flags) 338 339 { 340 341 } 342 343/*****************************************************************************/ 344 345dng_filter_opcode::dng_filter_opcode (uint32 opcodeID, 346 dng_stream &stream, 347 const char *name) 348 349 : dng_opcode (opcodeID, 350 stream, 351 name) 352 353 { 354 355 } 356 357/*****************************************************************************/ 358 359void dng_filter_opcode::Apply (dng_host &host, 360 dng_negative &negative, 361 AutoPtr<dng_image> &image) 362 { 363 364 dng_rect modifiedBounds = ModifiedBounds (image->Bounds ()); 365 366 if (modifiedBounds.NotEmpty ()) 367 { 368 369 // Allocate destination image. 370 371 AutoPtr<dng_image> dstImage; 372 373 // If we are processing the entire image, allocate an 374 // undefined image. 375 376 if (modifiedBounds == image->Bounds ()) 377 { 378 379 dstImage.Reset (host.Make_dng_image (image->Bounds (), 380 image->Planes (), 381 image->PixelType ())); 382 383 } 384 385 // Else start with a clone of the existing image. 386 387 else 388 { 389 390 dstImage.Reset (image->Clone ()); 391 392 } 393 394 // Filter the image. 395 396 dng_filter_opcode_task task (*this, 397 negative, 398 *image, 399 *dstImage); 400 401 host.PerformAreaTask (task, 402 modifiedBounds); 403 404 // Return the new image. 405 406 image.Reset (dstImage.Release ()); 407 408 } 409 410 } 411 412/*****************************************************************************/ 413 414class dng_inplace_opcode_task: public dng_area_task 415 { 416 417 private: 418 419 dng_inplace_opcode &fOpcode; 420 421 dng_negative &fNegative; 422 423 dng_image &fImage; 424 425 uint32 fPixelType; 426 427 AutoPtr<dng_memory_block> fBuffer [kMaxMPThreads]; 428 429 public: 430 431 dng_inplace_opcode_task (dng_inplace_opcode &opcode, 432 dng_negative &negative, 433 dng_image &image) 434 435 : dng_area_task () 436 437 , fOpcode (opcode) 438 , fNegative (negative) 439 , fImage (image) 440 , fPixelType (opcode.BufferPixelType (image.PixelType ())) 441 442 { 443 444 } 445 446 virtual void Start (uint32 threadCount, 447 const dng_point &tileSize, 448 dng_memory_allocator *allocator, 449 dng_abort_sniffer * /* sniffer */) 450 { 451 452 uint32 bufferSize = ComputeBufferSize(fPixelType, tileSize, 453 fImage.Planes(), pad16Bytes); 454 455 for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++) 456 { 457 458 fBuffer [threadIndex] . Reset (allocator->Allocate (bufferSize)); 459 460 } 461 462 fOpcode.Prepare (fNegative, 463 threadCount, 464 tileSize, 465 fImage.Bounds (), 466 fImage.Planes (), 467 fPixelType, 468 *allocator); 469 470 } 471 472 virtual void Process (uint32 threadIndex, 473 const dng_rect &tile, 474 dng_abort_sniffer * /* sniffer */) 475 { 476 477 // Setup buffer. 478 479 dng_pixel_buffer buffer(tile, 0, fImage.Planes (), fPixelType, 480 pcRowInterleavedAlign16, 481 fBuffer [threadIndex]->Buffer ()); 482 483 // Get source pixels. 484 485 fImage.Get (buffer); 486 487 // Process area. 488 489 fOpcode.ProcessArea (fNegative, 490 threadIndex, 491 buffer, 492 tile, 493 fImage.Bounds ()); 494 495 // Save result pixels. 496 497 fImage.Put (buffer); 498 499 } 500 501 }; 502 503/*****************************************************************************/ 504 505dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID, 506 uint32 minVersion, 507 uint32 flags) 508 509 : dng_opcode (opcodeID, 510 minVersion, 511 flags) 512 513 { 514 515 } 516 517/*****************************************************************************/ 518 519dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID, 520 dng_stream &stream, 521 const char *name) 522 523 : dng_opcode (opcodeID, 524 stream, 525 name) 526 527 { 528 529 } 530 531/*****************************************************************************/ 532 533void dng_inplace_opcode::Apply (dng_host &host, 534 dng_negative &negative, 535 AutoPtr<dng_image> &image) 536 { 537 538 dng_rect modifiedBounds = ModifiedBounds (image->Bounds ()); 539 540 if (modifiedBounds.NotEmpty ()) 541 { 542 543 dng_inplace_opcode_task task (*this, 544 negative, 545 *image); 546 547 host.PerformAreaTask (task, 548 modifiedBounds); 549 550 } 551 552 } 553 554/*****************************************************************************/ 555