1 /*****************************************************************************/
2 // Copyright 2006-2019 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 #include "dng_host.h"
10
11 #include "dng_abort_sniffer.h"
12 #include "dng_area_task.h"
13 #include "dng_bad_pixels.h"
14 #include "dng_exceptions.h"
15 #include "dng_exif.h"
16 #include "dng_gain_map.h"
17 #include "dng_ifd.h"
18 #include "dng_lens_correction.h"
19 #include "dng_memory.h"
20 #include "dng_misc_opcodes.h"
21 #include "dng_negative.h"
22 #include "dng_resample.h"
23 #include "dng_shared.h"
24 #include "dng_simple_image.h"
25 #include "dng_xmp.h"
26
27 /*****************************************************************************/
28
dng_host(dng_memory_allocator * allocator,dng_abort_sniffer * sniffer)29 dng_host::dng_host (dng_memory_allocator *allocator,
30 dng_abort_sniffer *sniffer)
31
32 : fAllocator (allocator)
33 , fSniffer (sniffer)
34
35 , fNeedsMeta (true)
36 , fNeedsImage (true)
37 , fForPreview (false)
38 , fMinimumSize (0)
39 , fPreferredSize (0)
40 , fMaximumSize (0)
41 , fCropFactor (1.0)
42 , fSaveDNGVersion (dngVersion_None)
43 , fSaveLinearDNG (false)
44 , fKeepOriginalFile (false)
45 , fForFastSaveToDNG (false)
46 , fFastSaveToDNGSize (0)
47 , fPreserveStage2 (false)
48
49 {
50
51 }
52
53 /*****************************************************************************/
54
~dng_host()55 dng_host::~dng_host ()
56 {
57
58 }
59
60 /*****************************************************************************/
61
Allocator()62 dng_memory_allocator & dng_host::Allocator ()
63 {
64
65 if (fAllocator)
66 {
67
68 return *fAllocator;
69
70 }
71
72 else
73 {
74
75 return gDefaultDNGMemoryAllocator;
76
77 }
78
79 }
80
81 /*****************************************************************************/
82
Allocate(uint32 logicalSize)83 dng_memory_block * dng_host::Allocate (uint32 logicalSize)
84 {
85
86 return Allocator ().Allocate (logicalSize);
87
88 }
89
90 /*****************************************************************************/
91
SniffForAbort()92 void dng_host::SniffForAbort ()
93 {
94
95 dng_abort_sniffer::SniffForAbort (Sniffer ());
96
97 }
98
99 /*****************************************************************************/
100
ValidateSizes()101 void dng_host::ValidateSizes ()
102 {
103
104 // The maximum size limits the other two sizes.
105
106 if (MaximumSize ())
107 {
108 SetMinimumSize (Min_uint32 (MinimumSize (), MaximumSize ()));
109 SetPreferredSize (Min_uint32 (PreferredSize (), MaximumSize ()));
110 }
111
112 // If we have a preferred size, it limits the minimum size.
113
114 if (PreferredSize ())
115 {
116 SetMinimumSize (Min_uint32 (MinimumSize (), PreferredSize ()));
117 }
118
119 // Else find default value for preferred size.
120
121 else
122 {
123
124 // If preferred size is zero, then we want the maximim
125 // size image.
126
127 if (MaximumSize ())
128 {
129 SetPreferredSize (MaximumSize ());
130 }
131
132 }
133
134 // If we don't have a minimum size, find default.
135
136 if (!MinimumSize ())
137 {
138
139 // A common size for embedded thumbnails is 120 by 160 pixels,
140 // So allow 120 by 160 pixels to be used for thumbnails when the
141 // preferred size is 256 pixel.
142
143 if (PreferredSize () >= 160 && PreferredSize () <= 256)
144 {
145 SetMinimumSize (160);
146 }
147
148 // Many sensors are near a multiple of 1024 pixels in size, but after
149 // the default crop, they are a just under. We can get an extra factor
150 // of size reduction if we allow a slight undershoot in the final size
151 // when computing large previews.
152
153 else if (PreferredSize () >= 490 && PreferredSize () <= 512)
154 {
155 SetMinimumSize (490);
156 }
157
158 else if (PreferredSize () >= 980 && PreferredSize () <= 1024)
159 {
160 SetMinimumSize (980);
161 }
162
163 else if (PreferredSize () >= 1470 && PreferredSize () <= 1536)
164 {
165 SetMinimumSize (1470);
166 }
167
168 else if (PreferredSize () >= 1960 && PreferredSize () <= 2048)
169 {
170 SetMinimumSize (1960);
171 }
172
173 else if (PreferredSize () >= 2400 && PreferredSize () <= 2560)
174 {
175 SetMinimumSize (2400);
176 }
177
178 // The following resolutions are typically on HiDPI displays where a
179 // greater degree of upsampling remains visually ok for previews. The
180 // following ratios are all based on 20% upsampling in a linear
181 // dimension.
182
183 else if (PreferredSize () >= 2448 && PreferredSize () <= 2880)
184 {
185 SetMinimumSize (2448);
186 }
187
188 // 1st-generation Surface Book.
189
190 else if (PreferredSize () >= 2560 && PreferredSize () <= 3000)
191 {
192 SetMinimumSize (2560);
193 }
194
195 // 4K (actually 3840).
196
197 else if (PreferredSize () >= 3480 && PreferredSize () <= 4096)
198 {
199 SetMinimumSize (3480);
200 }
201
202 // Surface Studio.
203
204 else if (PreferredSize () >= 3824 && PreferredSize () <= 4500)
205 {
206 SetMinimumSize (3824);
207 }
208
209 // 5K.
210
211 else if (PreferredSize () >= 4352 && PreferredSize () <= 5120)
212 {
213 SetMinimumSize (4352);
214 }
215
216 // 8K.
217
218 else if (PreferredSize () >= 6528 && PreferredSize () <= 7680)
219 {
220 SetMinimumSize (6528);
221 }
222
223 // Else minimum size is same as preferred size.
224
225 else
226 {
227 SetMinimumSize (PreferredSize ());
228 }
229
230 }
231
232 }
233
234 /*****************************************************************************/
235
SaveDNGVersion() const236 uint32 dng_host::SaveDNGVersion () const
237 {
238
239 return fSaveDNGVersion;
240
241 }
242
243 /*****************************************************************************/
244
SaveLinearDNG(const dng_negative &) const245 bool dng_host::SaveLinearDNG (const dng_negative & /* negative */) const
246 {
247
248 return fSaveLinearDNG;
249
250 }
251
252 /*****************************************************************************/
253
IsTransientError(dng_error_code code)254 bool dng_host::IsTransientError (dng_error_code code)
255 {
256
257 switch (code)
258 {
259
260 case dng_error_memory:
261 case dng_error_user_canceled:
262 {
263 return true;
264 }
265
266 default:
267 break;
268
269 }
270
271 return false;
272
273 }
274
275 /*****************************************************************************/
276
PerformAreaTask(dng_area_task & task,const dng_rect & area,dng_area_task_progress * progress)277 void dng_host::PerformAreaTask (dng_area_task &task,
278 const dng_rect &area,
279 dng_area_task_progress *progress)
280 {
281
282 dng_area_task::Perform (task,
283 area,
284 &Allocator (),
285 Sniffer (),
286 progress);
287
288 }
289
290 /*****************************************************************************/
291
PerformAreaTaskThreads()292 uint32 dng_host::PerformAreaTaskThreads ()
293 {
294
295 return 1;
296
297 }
298
299 /*****************************************************************************/
300
Make_dng_exif()301 dng_exif * dng_host::Make_dng_exif ()
302 {
303
304 dng_exif *result = new dng_exif ();
305
306 if (!result)
307 {
308
309 ThrowMemoryFull ();
310
311 }
312
313 return result;
314
315 }
316
317 /*****************************************************************************/
318
Make_dng_xmp()319 dng_xmp * dng_host::Make_dng_xmp ()
320 {
321
322 dng_xmp *result = new dng_xmp (Allocator ());
323
324 if (!result)
325 {
326
327 ThrowMemoryFull ();
328
329 }
330
331 return result;
332
333 }
334
335 /*****************************************************************************/
336
Make_dng_shared()337 dng_shared * dng_host::Make_dng_shared ()
338 {
339
340 dng_shared *result = new dng_shared ();
341
342 if (!result)
343 {
344
345 ThrowMemoryFull ();
346
347 }
348
349 return result;
350
351 }
352
353 /*****************************************************************************/
354
Make_dng_ifd()355 dng_ifd * dng_host::Make_dng_ifd ()
356 {
357
358 dng_ifd *result = new dng_ifd ();
359
360 if (!result)
361 {
362
363 ThrowMemoryFull ();
364
365 }
366
367 return result;
368
369 }
370
371 /*****************************************************************************/
372
Make_dng_negative()373 dng_negative * dng_host::Make_dng_negative ()
374 {
375
376 return dng_negative::Make (*this);
377
378 }
379
380 /*****************************************************************************/
381
Make_dng_image(const dng_rect & bounds,uint32 planes,uint32 pixelType)382 dng_image * dng_host::Make_dng_image (const dng_rect &bounds,
383 uint32 planes,
384 uint32 pixelType)
385 {
386
387 dng_image *result = new dng_simple_image (bounds,
388 planes,
389 pixelType,
390 Allocator ());
391
392 if (!result)
393 {
394
395 ThrowMemoryFull ();
396
397 }
398
399 return result;
400
401 }
402
403 /*****************************************************************************/
404
Make_dng_opcode(uint32 opcodeID,dng_stream & stream)405 dng_opcode * dng_host::Make_dng_opcode (uint32 opcodeID,
406 dng_stream &stream)
407 {
408
409 dng_opcode *result = NULL;
410
411 switch (opcodeID)
412 {
413
414 case dngOpcode_WarpRectilinear:
415 {
416
417 result = new dng_opcode_WarpRectilinear (stream);
418
419 break;
420
421 }
422
423 case dngOpcode_WarpFisheye:
424 {
425
426 result = new dng_opcode_WarpFisheye (stream);
427
428 break;
429
430 }
431
432 case dngOpcode_FixVignetteRadial:
433 {
434
435 result = new dng_opcode_FixVignetteRadial (stream);
436
437 break;
438
439 }
440
441 case dngOpcode_FixBadPixelsConstant:
442 {
443
444 result = new dng_opcode_FixBadPixelsConstant (stream);
445
446 break;
447
448 }
449
450 case dngOpcode_FixBadPixelsList:
451 {
452
453 result = new dng_opcode_FixBadPixelsList (stream);
454
455 break;
456
457 }
458
459 case dngOpcode_TrimBounds:
460 {
461
462 result = new dng_opcode_TrimBounds (stream);
463
464 break;
465
466 }
467
468 case dngOpcode_MapTable:
469 {
470
471 result = new dng_opcode_MapTable (*this,
472 stream);
473
474 break;
475
476 }
477
478 case dngOpcode_MapPolynomial:
479 {
480
481 result = new dng_opcode_MapPolynomial (stream);
482
483 break;
484
485 }
486
487 case dngOpcode_GainMap:
488 {
489
490 result = new dng_opcode_GainMap (*this,
491 stream);
492
493 break;
494
495 }
496
497 case dngOpcode_DeltaPerRow:
498 {
499
500 result = new dng_opcode_DeltaPerRow (*this,
501 stream);
502
503 break;
504
505 }
506
507 case dngOpcode_DeltaPerColumn:
508 {
509
510 result = new dng_opcode_DeltaPerColumn (*this,
511 stream);
512
513 break;
514
515 }
516
517 case dngOpcode_ScalePerRow:
518 {
519
520 result = new dng_opcode_ScalePerRow (*this,
521 stream);
522
523 break;
524
525 }
526
527 case dngOpcode_ScalePerColumn:
528 {
529
530 result = new dng_opcode_ScalePerColumn (*this,
531 stream);
532
533 break;
534
535 }
536
537 default:
538 {
539
540 result = new dng_opcode_Unknown (*this,
541 opcodeID,
542 stream);
543
544 }
545
546 }
547
548 if (!result)
549 {
550
551 ThrowMemoryFull ();
552
553 }
554
555 return result;
556
557 }
558
559 /*****************************************************************************/
560
ApplyOpcodeList(dng_opcode_list & list,dng_negative & negative,AutoPtr<dng_image> & image)561 void dng_host::ApplyOpcodeList (dng_opcode_list &list,
562 dng_negative &negative,
563 AutoPtr<dng_image> &image)
564 {
565
566 list.Apply (*this,
567 negative,
568 image);
569
570 }
571
572 /*****************************************************************************/
573
ResampleImage(const dng_image & srcImage,dng_image & dstImage)574 void dng_host::ResampleImage (const dng_image &srcImage,
575 dng_image &dstImage)
576 {
577
578 ::ResampleImage (*this,
579 srcImage,
580 dstImage,
581 srcImage.Bounds (),
582 dstImage.Bounds (),
583 dng_resample_bicubic::Get ());
584
585 }
586
587 /*****************************************************************************/
588