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 
dng_opcode(uint32 opcodeID,uint32 minVersion,uint32 flags)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 
dng_opcode(uint32 opcodeID,dng_stream & stream,const char * name)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 
~dng_opcode()98 dng_opcode::~dng_opcode ()
99 	{
100 
101 	}
102 
103 /*****************************************************************************/
104 
PutData(dng_stream & stream) const105 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 
AboutToApply(dng_host & host,dng_negative & negative)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 
dng_opcode_Unknown(dng_host & host,uint32 opcodeID,dng_stream & stream)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 
PutData(dng_stream & stream) const202 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 
Apply(dng_host &,dng_negative &,AutoPtr<dng_image> &)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 
dng_filter_opcode_task(dng_filter_opcode & opcode,dng_negative & negative,const dng_image & srcImage,dng_image & dstImage)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 
SrcArea(const dng_rect & dstArea)276 		virtual dng_rect SrcArea (const dng_rect &dstArea)
277 			{
278 
279 			return fOpcode.SrcArea (dstArea,
280 									fDstImage.Bounds ());
281 
282 			}
283 
SrcTileSize(const dng_point & dstTileSize)284 		virtual dng_point SrcTileSize (const dng_point &dstTileSize)
285 			{
286 
287 			return fOpcode.SrcTileSize (dstTileSize,
288 										fDstImage.Bounds ());
289 
290 			}
291 
ProcessArea(uint32 threadIndex,dng_pixel_buffer & srcBuffer,dng_pixel_buffer & dstBuffer)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 
Start(uint32 threadCount,const dng_point & tileSize,dng_memory_allocator * allocator,dng_abort_sniffer * sniffer)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 
dng_filter_opcode(uint32 opcodeID,uint32 minVersion,uint32 flags)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 
dng_filter_opcode(uint32 opcodeID,dng_stream & stream,const char * name)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 
Apply(dng_host & host,dng_negative & negative,AutoPtr<dng_image> & image)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 
dng_inplace_opcode_task(dng_inplace_opcode & opcode,dng_negative & negative,dng_image & image)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 
Start(uint32 threadCount,const dng_point & tileSize,dng_memory_allocator * allocator,dng_abort_sniffer *)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 
Process(uint32 threadIndex,const dng_rect & tile,dng_abort_sniffer *)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 
dng_inplace_opcode(uint32 opcodeID,uint32 minVersion,uint32 flags)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 
dng_inplace_opcode(uint32 opcodeID,dng_stream & stream,const char * name)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 
Apply(dng_host & host,dng_negative & negative,AutoPtr<dng_image> & image)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