Home | History | Annotate | Download | only in source
      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 
     31 dng_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 
     47 dng_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 
     98 dng_opcode::~dng_opcode ()
     99 	{
    100 
    101 	}
    102 
    103 /*****************************************************************************/
    104 
    105 void 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 
    116 bool 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 
    162 dng_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 
    202 void 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 
    226 void 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 
    244 class 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 
    331 dng_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 
    345 dng_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 
    359 void 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 
    414 class 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 
    505 dng_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 
    519 dng_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 
    533 void 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