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