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