Coverage Report

Created: 2026-06-07 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/dng.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                            DDDD   N   N   GGGG                              %
7
%                            D   D  NN  N  GS                                 %
8
%                            D   D  N N N  G  GG                              %
9
%                            D   D  N  NN  G   G                              %
10
%                            DDDD   N   N   GGGG                              %
11
%                                                                             %
12
%                                                                             %
13
%                  Read the Digital Negative Image Format                     %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1999                                   %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
21
%  dedicated to making software imaging solutions freely available.           %
22
%                                                                             %
23
%  You may not use this file except in compliance with the License.  You may  %
24
%  obtain a copy of the License at                                            %
25
%                                                                             %
26
%    https://imagemagick.org/license/                                         %
27
%                                                                             %
28
%  Unless required by applicable law or agreed to in writing, software        %
29
%  distributed under the License is distributed on an "AS IS" BASIS,          %
30
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31
%  See the License for the specific language governing permissions and        %
32
%  limitations under the License.                                             %
33
%                                                                             %
34
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
%
36
%
37
*/
38

39
/*
40
  Include declarations.
41
*/
42
#include "MagickCore/studio.h"
43
#include "MagickCore/blob.h"
44
#include "MagickCore/blob-private.h"
45
#include "MagickCore/constitute.h"
46
#include "MagickCore/delegate.h"
47
#include "MagickCore/exception.h"
48
#include "MagickCore/exception-private.h"
49
#include "MagickCore/geometry.h"
50
#include "MagickCore/image.h"
51
#include "MagickCore/image-private.h"
52
#include "MagickCore/layer.h"
53
#include "MagickCore/list.h"
54
#include "MagickCore/log.h"
55
#include "MagickCore/magick.h"
56
#include "MagickCore/memory_.h"
57
#include "MagickCore/monitor.h"
58
#include "MagickCore/monitor-private.h"
59
#include "MagickCore/opencl.h"
60
#include "MagickCore/option.h"
61
#include "MagickCore/pixel-accessor.h"
62
#include "MagickCore/profile-private.h"
63
#include "MagickCore/property.h"
64
#include "MagickCore/quantum-private.h"
65
#include "MagickCore/resource_.h"
66
#include "MagickCore/static.h"
67
#include "MagickCore/string_.h"
68
#include "MagickCore/string-private.h"
69
#include "MagickCore/module.h"
70
#include "MagickCore/transform.h"
71
#include "MagickCore/utility.h"
72
#include "MagickCore/utility-private.h"
73
#include "MagickCore/xml-tree.h"
74
#include "MagickCore/xml-tree-private.h"
75
#if defined(MAGICKCORE_RAW_R_DELEGATE)
76
#include <libraw.h>
77
#endif
78

79
/*
80
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81
%                                                                             %
82
%                                                                             %
83
%                                                                             %
84
%   R e a d D N G I m a g e                                                   %
85
%                                                                             %
86
%                                                                             %
87
%                                                                             %
88
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89
%
90
%  ReadDNGImage() reads an binary file in the Digital Negative format and
91
%  returns it.  It allocates the memory necessary for the new Image structure
92
%  and returns a pointer to the new image.
93
%
94
%  The format of the ReadDNGImage method is:
95
%
96
%      Image *ReadDNGImage(const ImageInfo *image_info,
97
%        ExceptionInfo *exception)
98
%
99
%  A description of each parameter follows:
100
%
101
%    o image_info: the image info.
102
%
103
%    o exception: return any errors or warnings in this structure.
104
%
105
*/
106
107
#if defined(MAGICKCORE_WINDOWS_SUPPORT) && defined(MAGICKCORE_OPENCL_SUPPORT)
108
static void InitializeDcrawOpenCL(ExceptionInfo *exception)
109
{
110
  MagickCLDevice
111
    *devices;
112
113
  size_t
114
    length;
115
116
  ssize_t
117
    i;
118
119
  (void) SetEnvironmentVariable("DCR_CL_PLATFORM",NULL);
120
  (void) SetEnvironmentVariable("DCR_CL_DEVICE",NULL);
121
  (void) SetEnvironmentVariable("DCR_CL_DISABLED",NULL);
122
  if (GetOpenCLEnabled() == MagickFalse)
123
    {
124
      (void) SetEnvironmentVariable("DCR_CL_DISABLED","1");
125
      return;
126
    }
127
  devices=GetOpenCLDevices(&length,exception);
128
  if (devices == (MagickCLDevice *) NULL)
129
    return;
130
  for (i=0; i < (ssize_t) length; i++)
131
  {
132
    const char
133
      *name;
134
135
    MagickCLDevice
136
      device;
137
138
    device=devices[i];
139
    if (GetOpenCLDeviceEnabled(device) == MagickFalse)
140
      continue;
141
    name=GetOpenCLDeviceVendorName(device);
142
    if (name != (const char *) NULL)
143
      (void) SetEnvironmentVariable("DCR_CL_PLATFORM",name);
144
    name=GetOpenCLDeviceName(device);
145
    if (name != (const char *) NULL)
146
      (void) SetEnvironmentVariable("DCR_CL_DEVICE",name);
147
    return;
148
  }
149
}
150
#else
151
static void InitializeDcrawOpenCL(ExceptionInfo *magick_unused(exception))
152
5
{
153
5
  magick_unreferenced(exception);
154
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
155
  (void) SetEnvironmentVariable("DCR_CL_DISABLED","1");
156
#endif
157
5
}
158
#endif
159
160
#if defined(MAGICKCORE_RAW_R_DELEGATE)
161
static void SetDNGProperties(Image *image,const libraw_data_t *raw_info,
162
  ExceptionInfo *exception)
163
4.44k
{
164
4.44k
  char
165
4.44k
    timestamp[MagickTimeExtent];
166
167
4.44k
  (void) SetImageProperty(image,"dng:make",raw_info->idata.make,exception);
168
4.44k
  (void) SetImageProperty(image,"dng:camera.model.name",raw_info->idata.model,
169
4.44k
    exception);
170
4.44k
  (void) FormatMagickTime(raw_info->other.timestamp,sizeof(timestamp),
171
4.44k
    timestamp);
172
4.44k
  (void) SetImageProperty(image,"dng:create.date",timestamp,exception);
173
4.44k
  (void) FormatImageProperty(image,"dng:iso.setting","%.0g",
174
4.44k
    (double) raw_info->other.iso_speed);
175
4.44k
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,18)
176
4.44k
  (void) SetImageProperty(image,"dng:software",raw_info->idata.software,
177
4.44k
    exception);
178
4.44k
  if (*raw_info->shootinginfo.BodySerial != '\0')
179
223
    (void) SetImageProperty(image,"dng:serial.number",
180
223
      raw_info->shootinginfo.BodySerial,exception);
181
4.44k
  (void) FormatImageProperty(image,"dng:exposure.time","1/%.0g",
182
4.44k
    (double) MagickSafeReciprocal(raw_info->other.shutter));
183
4.44k
  (void) FormatImageProperty(image,"dng:f.number","%0.1g",
184
4.44k
    (double) raw_info->other.aperture);
185
4.44k
  (void) FormatImageProperty(image,"dng:max.aperture.value","%0.1g",
186
4.44k
    (double) raw_info->lens.EXIF_MaxAp);
187
4.44k
  (void) FormatImageProperty(image,"dng:focal.length","%0.1g mm",
188
4.44k
    (double) raw_info->other.focal_len);
189
4.44k
  (void) FormatImageProperty(image,"dng:wb.rb.levels","%g %g %g %g",
190
4.44k
    (double) raw_info->color.cam_mul[0],(double) raw_info->color.cam_mul[2],
191
4.44k
    (double) raw_info->color.cam_mul[1],(double) raw_info->color.cam_mul[3]);
192
4.44k
  (void) SetImageProperty(image,"dng:lens.type",
193
4.44k
    raw_info->lens.makernotes.LensFeatures_suf,exception);
194
4.44k
  (void) FormatImageProperty(image,"dng:lens","%0.1g-%0.1gmm f/%0.1g-%0.1g",
195
4.44k
    (double) raw_info->lens.makernotes.MinFocal,
196
4.44k
    (double) raw_info->lens.makernotes.MaxFocal,
197
4.44k
    (double) raw_info->lens.makernotes.MaxAp4MinFocal,
198
4.44k
    (double) raw_info->lens.makernotes.MaxAp4MaxFocal);
199
4.44k
  (void) FormatImageProperty(image,"dng:lens.f.stops","%0.2f",
200
4.44k
    (double) raw_info->lens.makernotes.LensFStops);
201
4.44k
  (void) FormatImageProperty(image,"dng:min.focal.length","%0.1f mm",
202
4.44k
    (double) raw_info->lens.makernotes.MinFocal);
203
4.44k
  (void) FormatImageProperty(image,"dng:max.focal.length","%0.1g mm",
204
4.44k
    (double) raw_info->lens.makernotes.MaxFocal);
205
4.44k
  (void) FormatImageProperty(image,"dng:max.aperture.at.min.focal","%0.1g",
206
4.44k
    (double) raw_info->lens.makernotes.MaxAp4MinFocal);
207
4.44k
  (void) FormatImageProperty(image,"dng:max.aperture.at.max.focal","%0.1g",
208
4.44k
    (double) raw_info->lens.makernotes.MaxAp4MaxFocal);
209
4.44k
  (void) FormatImageProperty(image,"dng:focal.length.in.35mm.format","%d mm",
210
4.44k
    raw_info->lens.FocalLengthIn35mmFormat);
211
4.44k
#endif
212
4.44k
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,20)
213
4.44k
  (void) FormatImageProperty(image,"dng:gps.latitude",
214
4.44k
    "%.0g deg %.0g' %.2g\" N",
215
4.44k
    (double) raw_info->other.parsed_gps.latitude[0],
216
4.44k
    (double) raw_info->other.parsed_gps.latitude[1],
217
4.44k
    (double) raw_info->other.parsed_gps.latitude[2]);
218
4.44k
  (void) FormatImageProperty(image,"dng:gps.longitude",
219
4.44k
    "%.0g deg %.0g' %.2g\" W",
220
4.44k
    (double) raw_info->other.parsed_gps.longitude[0],
221
4.44k
    (double) raw_info->other.parsed_gps.longitude[1],
222
4.44k
    (double) raw_info->other.parsed_gps.longitude[2]);
223
4.44k
  (void) FormatImageProperty(image,"dng:gps.altitude","%.1g m",
224
4.44k
    (double) raw_info->other.parsed_gps.altitude);
225
4.44k
#endif
226
4.44k
}
227
#endif
228
229
static Image *InvokeDNGDelegate(const ImageInfo *image_info,Image *image,
230
  ExceptionInfo *exception)
231
5
{
232
5
  ExceptionInfo
233
5
    *sans_exception;
234
235
5
  ImageInfo
236
5
    *read_info;
237
238
5
  MagickBooleanType
239
5
    status;
240
241
  /*
242
    Convert DNG to TIFF with delegate program.
243
  */
244
5
  (void) DestroyImageList(image);
245
5
  InitializeDcrawOpenCL(exception);
246
5
  image=AcquireImage(image_info,exception);
247
5
  read_info=CloneImageInfo(image_info);
248
5
  SetImageInfoBlob(read_info,(void *) NULL,0);
249
5
  status=InvokeDelegate(read_info,image,"dng:decode",(char *) NULL,exception);
250
5
  image=DestroyImage(image);
251
5
  if (status == MagickFalse)
252
5
    {
253
5
      read_info=DestroyImageInfo(read_info);
254
5
      return(image);
255
5
    }
256
0
  *read_info->magick='\0';
257
0
  (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s.tif",
258
0
    read_info->unique);
259
0
  sans_exception=AcquireExceptionInfo();
260
0
  image=ReadImage(read_info,sans_exception);
261
0
  sans_exception=DestroyExceptionInfo(sans_exception);
262
0
  if (image != (Image *) NULL)
263
0
    (void) CopyMagickString(image->magick,read_info->magick,MagickPathExtent);
264
0
  (void) RelinquishUniqueFileResource(read_info->filename);
265
0
  read_info=DestroyImageInfo(read_info);
266
0
  return(image);
267
5
}
268
269
#if defined(MAGICKCORE_RAW_R_DELEGATE)
270
static void SetLibRawParams(const ImageInfo *image_info,Image *image,
271
  libraw_data_t *raw_info)
272
2.02k
{
273
2.02k
  const char
274
2.02k
    *option;
275
276
2.02k
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,20)
277
2.02k
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,21)
278
2.02k
  raw_info->rawparams.max_raw_memory_mb=8192;
279
#else
280
  raw_info->params.max_raw_memory_mb=8192;
281
#endif
282
2.02k
  option=GetImageOption(image_info,"dng:max-raw-memory");
283
2.02k
  if (option != (const char *) NULL)
284
0
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,21)
285
0
    raw_info->rawparams.max_raw_memory_mb=(unsigned int)
286
0
      StringToInteger(option);
287
#else
288
   raw_info->params.max_raw_memory_mb=(unsigned int) StringToInteger(option);
289
#endif
290
2.02k
#endif
291
2.02k
  raw_info->params.user_flip=0;
292
2.02k
  raw_info->params.output_bps=16;
293
2.02k
  raw_info->params.use_camera_wb=1;
294
2.02k
  option=GetImageOption(image_info,"dng:use-camera-wb");
295
2.02k
  if (option == (const char *) NULL)
296
2.02k
    option=GetImageOption(image_info,"dng:use_camera_wb");
297
2.02k
  if (option != (const char *) NULL)
298
0
    raw_info->params.use_camera_wb=IsStringTrue(option) != MagickFalse ? 1 : 0;
299
2.02k
  option=GetImageOption(image_info,"dng:use-auto-wb");
300
2.02k
  if (option == (const char *) NULL)
301
2.02k
    option=GetImageOption(image_info,"dng:use_auto_wb");
302
2.02k
  if (option != (const char *) NULL)
303
0
    raw_info->params.use_auto_wb=IsStringTrue(option) != MagickFalse ? 1 : 0;
304
2.02k
  option=GetImageOption(image_info,"dng:no-auto-bright");
305
2.02k
  if (option == (const char *) NULL)
306
2.02k
    option=GetImageOption(image_info,"dng:no_auto_bright");
307
2.02k
  if (option != (const char *) NULL)
308
0
    raw_info->params.no_auto_bright=IsStringTrue(option) != MagickFalse ? 1 : 0;
309
2.02k
  option=GetImageOption(image_info,"dng:output-color");
310
2.02k
  if (option == (const char *) NULL)
311
2.02k
    option=GetImageOption(image_info,"dng:output_color");
312
2.02k
  if (option != (const char *) NULL)
313
0
    {
314
0
      raw_info->params.output_color=StringToInteger(option);
315
0
      if (raw_info->params.output_color == 5)
316
0
        image->colorspace=XYZColorspace;
317
0
    }
318
2.02k
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,21)
319
2.02k
  option=GetImageOption(image_info,"dng:interpolation-quality");
320
2.02k
  if (option != (const char *) NULL)
321
0
    {
322
0
      int
323
0
        value;
324
325
0
      value=StringToInteger(option);
326
0
      if (value == -1)
327
0
        raw_info->params.no_interpolation=1;
328
0
      else
329
0
        raw_info->params.user_qual=value;
330
0
    }
331
2.02k
#endif
332
2.02k
}
333
334
static void LibRawDataError(void *data,const char *magick_unused(file),
335
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,22)
336
  const INT64 offset)
337
#else
338
  const int offset)
339
#endif
340
2.29k
{
341
2.29k
  magick_unreferenced(file);
342
2.29k
  if (offset >= 0)
343
1.16k
    {
344
1.16k
      ExceptionInfo
345
1.16k
        *exception;
346
347
      /*
348
        Value below zero is an EOF and an exception is raised instead.
349
      */
350
1.16k
      exception=(ExceptionInfo *) data;
351
1.16k
      (void) ThrowMagickException(exception,GetMagickModule(),
352
1.16k
        CorruptImageWarning,"Data corrupted at","`%d'",(int) offset);
353
1.16k
  }
354
2.29k
}
355
356
static void ReadLibRawThumbnail(const ImageInfo *image_info,Image *image,
357
  libraw_data_t *raw_info,ExceptionInfo *exception)
358
4.44k
{
359
4.44k
  const char
360
4.44k
    *option;
361
362
4.44k
  int
363
4.44k
    errcode;
364
365
4.44k
  libraw_processed_image_t
366
4.44k
    *thumbnail;
367
368
4.44k
  option=GetImageOption(image_info,"dng:read-thumbnail");
369
4.44k
  if (IsStringTrue(option) == MagickFalse)
370
4.44k
    return;
371
0
  errcode=libraw_unpack_thumb(raw_info);
372
0
  if (errcode != LIBRAW_SUCCESS)
373
0
    return;
374
0
  thumbnail=libraw_dcraw_make_mem_thumb(raw_info,&errcode);
375
0
  if (errcode == LIBRAW_SUCCESS)
376
0
    {
377
0
      StringInfo
378
0
        *profile;
379
380
0
      if (thumbnail->type == LIBRAW_IMAGE_JPEG)
381
0
        SetImageProperty(image,"dng:thumbnail.type","jpeg",exception);
382
0
      else if (thumbnail->type == LIBRAW_IMAGE_BITMAP)
383
0
        {
384
0
          char
385
0
            value[15];
386
387
0
          SetImageProperty(image,"dng:thumbnail.type","bitmap",exception);
388
0
          (void) FormatLocaleString(value,sizeof(value),"%hu",thumbnail->bits);
389
0
          SetImageProperty(image,"dng:thumbnail.bits",value,exception);
390
0
          (void) FormatLocaleString(value,sizeof(value),"%hu",
391
0
            thumbnail->colors);
392
0
          SetImageProperty(image,"dng:thumbnail.colors",value,exception);
393
0
          (void) FormatLocaleString(value,sizeof(value),"%hux%hu",
394
0
            thumbnail->width,thumbnail->height);
395
0
          SetImageProperty(image,"dng:thumbnail.geometry",value,exception);
396
0
        }
397
0
      profile=BlobToProfileStringInfo("dng:thumbnail",thumbnail->data,
398
0
        thumbnail->data_size,exception);
399
0
      (void) SetImageProfilePrivate(image,profile,exception);
400
0
    }
401
0
  if (thumbnail != (libraw_processed_image_t *) NULL)
402
0
    libraw_dcraw_clear_mem(thumbnail);
403
0
}
404
405
static OrientationType LibRawFlipToOrientation(int flip)
406
4.44k
{
407
4.44k
  switch(flip)
408
4.44k
  {
409
111
    case 5:
410
111
    {
411
111
      return(LeftBottomOrientation);
412
0
    }
413
0
    case 8:
414
0
    {
415
0
      return(LeftTopOrientation);
416
0
    }
417
4.33k
    default:
418
4.33k
    {
419
4.33k
      return((OrientationType) flip);
420
0
    }
421
4.44k
  }
422
4.44k
}
423
424
#endif
425
426
static Image *ReadDNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
427
29.9k
{
428
29.9k
  Image
429
29.9k
    *image;
430
431
29.9k
  MagickBooleanType
432
29.9k
    status;
433
434
  /*
435
    Open image file.
436
  */
437
29.9k
  assert(image_info != (const ImageInfo *) NULL);
438
29.9k
  assert(image_info->signature == MagickCoreSignature);
439
29.9k
  assert(exception != (ExceptionInfo *) NULL);
440
29.9k
  assert(exception->signature == MagickCoreSignature);
441
29.9k
  if (IsEventLogging() != MagickFalse)
442
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
443
0
      image_info->filename);
444
29.9k
  image=AcquireImage(image_info,exception);
445
29.9k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
446
29.9k
  if (status == MagickFalse)
447
0
    {
448
0
      image=DestroyImageList(image);
449
0
      return((Image *) NULL);
450
0
    }
451
29.9k
  (void) CloseBlob(image);
452
29.9k
  if (LocaleCompare(image_info->magick,"DCRAW") == 0)
453
5
    return(InvokeDNGDelegate(image_info,image,exception));
454
29.9k
#if defined(MAGICKCORE_RAW_R_DELEGATE)
455
29.9k
  {
456
29.9k
    int
457
29.9k
      errcode;
458
459
29.9k
    libraw_data_t
460
29.9k
      *raw_info;
461
462
29.9k
    libraw_processed_image_t
463
29.9k
      *raw_image;
464
465
29.9k
    ssize_t
466
29.9k
      y;
467
468
29.9k
    StringInfo
469
29.9k
      *profile;
470
471
29.9k
    unsigned int
472
29.9k
      flags;
473
474
29.9k
    unsigned short
475
29.9k
      *p;
476
477
29.9k
    errcode=LIBRAW_UNSPECIFIED_ERROR;
478
29.9k
    flags=LIBRAW_OPIONS_NO_DATAERR_CALLBACK;
479
#if LIBRAW_SHLIB_CURRENT < 23
480
    flags|=LIBRAW_OPIONS_NO_MEMERR_CALLBACK;
481
#endif
482
29.9k
    raw_info=libraw_init(flags);
483
29.9k
    if (raw_info == (libraw_data_t *) NULL)
484
0
      {
485
0
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
486
0
          libraw_strerror(errcode),"`%s'",image->filename);
487
0
        libraw_close(raw_info);
488
0
        return(DestroyImageList(image));
489
0
      }
490
29.9k
    libraw_set_dataerror_handler(raw_info,LibRawDataError,exception);
491
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
492
    {
493
      wchar_t
494
        *path;
495
496
      path=NTCreateWidePath(image->filename);
497
      if (path != (wchar_t *) NULL)
498
        {
499
          errcode=libraw_open_wfile(raw_info,path);
500
          path=(wchar_t *) RelinquishMagickMemory(path);
501
        }
502
    }
503
#else
504
29.9k
    errcode=libraw_open_file(raw_info,image->filename);
505
29.9k
#endif
506
29.9k
    if (errcode != LIBRAW_SUCCESS)
507
25.4k
      {
508
25.4k
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
509
25.4k
          libraw_strerror(errcode),"`%s'",image->filename);
510
25.4k
        libraw_close(raw_info);
511
25.4k
        return(DestroyImageList(image));
512
25.4k
      }
513
4.44k
    image->columns=raw_info->sizes.width;
514
4.44k
    image->rows=raw_info->sizes.height;
515
4.44k
    image->page.width=raw_info->sizes.raw_width;
516
4.44k
    image->page.height=raw_info->sizes.raw_height;
517
4.44k
    image->page.x=raw_info->sizes.left_margin;
518
4.44k
    image->page.y=raw_info->sizes.top_margin;
519
4.44k
    image->orientation=LibRawFlipToOrientation(raw_info->sizes.flip);
520
4.44k
    ReadLibRawThumbnail(image_info,image,raw_info,exception);
521
4.44k
    SetDNGProperties(image,raw_info,exception);
522
4.44k
    if (image_info->ping != MagickFalse)
523
99
      {
524
99
        libraw_close(raw_info);
525
99
        return(image);
526
99
      }
527
4.34k
    status=SetImageExtent(image,image->columns,image->rows,exception);
528
4.34k
    if (status == MagickFalse)
529
459
      {
530
459
        libraw_close(raw_info);
531
459
        return(image);
532
459
      }
533
3.88k
    errcode=libraw_unpack(raw_info);
534
3.88k
    if (errcode != LIBRAW_SUCCESS)
535
1.86k
      {
536
1.86k
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
537
1.86k
          libraw_strerror(errcode),"`%s'",image->filename);
538
1.86k
        libraw_close(raw_info);
539
1.86k
        return(DestroyImageList(image));
540
1.86k
      }
541
2.02k
    SetLibRawParams(image_info,image,raw_info);
542
2.02k
    errcode=libraw_dcraw_process(raw_info);
543
2.02k
    if (errcode != LIBRAW_SUCCESS)
544
60
      {
545
60
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
546
60
          libraw_strerror(errcode),"`%s'",image->filename);
547
60
        libraw_close(raw_info);
548
60
        return(DestroyImageList(image));
549
60
      }
550
1.96k
    raw_image=libraw_dcraw_make_mem_image(raw_info,&errcode);
551
1.96k
    if ((errcode != LIBRAW_SUCCESS) ||
552
1.96k
        (raw_image == (libraw_processed_image_t *) NULL) ||
553
1.96k
        (raw_image->type != LIBRAW_IMAGE_BITMAP) || (raw_image->bits != 16) ||
554
1.96k
        (raw_image->colors < 1) || (raw_image->colors > 4))
555
0
      {
556
0
        if (raw_image != (libraw_processed_image_t *) NULL)
557
0
          libraw_dcraw_clear_mem(raw_image);
558
0
        (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
559
0
          libraw_strerror(errcode),"`%s'",image->filename);
560
0
        libraw_close(raw_info);
561
0
        return(DestroyImageList(image));
562
0
      }
563
1.96k
    if (raw_image->colors < 3)
564
66
      {
565
66
        image->colorspace=GRAYColorspace;
566
66
        image->type=raw_image->colors == 1 ? GrayscaleType : GrayscaleAlphaType;
567
66
      }
568
1.96k
    image->columns=raw_image->width;
569
1.96k
    image->rows=raw_image->height;
570
1.96k
    image->depth=raw_image->bits;
571
1.96k
    status=SetImageExtent(image,image->columns,image->rows,exception);
572
1.96k
    if (status == MagickFalse)
573
15
      {
574
15
        libraw_dcraw_clear_mem(raw_image);
575
15
        libraw_close(raw_info);
576
15
        return(DestroyImageList(image));
577
15
      }
578
1.94k
    p=(unsigned short *) raw_image->data;
579
519k
    for (y=0; y < (ssize_t) image->rows; y++)
580
517k
    {
581
517k
      Quantum
582
517k
        *q;
583
584
517k
      ssize_t
585
517k
        x;
586
587
517k
      q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
588
517k
      if (q == (Quantum *) NULL)
589
0
        break;
590
214M
      for (x=0; x < (ssize_t) image->columns; x++)
591
214M
      {
592
214M
        SetPixelRed(image,ScaleShortToQuantum(*p++),q);
593
214M
        if (raw_image->colors > 2)
594
213M
          {
595
213M
            SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
596
213M
            SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
597
213M
          }
598
214M
        if ((raw_image->colors == 2) || (raw_image->colors > 3))
599
0
          SetPixelAlpha(image,ScaleShortToQuantum(*p++),q);
600
214M
        q+=(ptrdiff_t) GetPixelChannels(image);
601
214M
      }
602
517k
      if (SyncAuthenticPixels(image,exception) == MagickFalse)
603
0
        break;
604
517k
      if (image->previous == (Image *) NULL)
605
517k
        {
606
517k
          status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
607
517k
            image->rows);
608
517k
          if (status == MagickFalse)
609
0
            break;
610
517k
        }
611
517k
    }
612
1.94k
    libraw_dcraw_clear_mem(raw_image);
613
    /*
614
      Set DNG image metadata.
615
    */
616
1.94k
    if (raw_info->color.profile != NULL)
617
5
      {
618
5
        profile=BlobToProfileStringInfo("icc",raw_info->color.profile,
619
5
          raw_info->color.profile_length,exception);
620
5
        (void) SetImageProfilePrivate(image,profile,exception);
621
5
      }
622
1.94k
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,18)
623
1.94k
    if (raw_info->idata.xmpdata != NULL)
624
1
      {
625
1
        profile=BlobToProfileStringInfo("xmp",raw_info->idata.xmpdata,
626
1
          raw_info->idata.xmplen,exception);
627
1
        (void) SetImageProfilePrivate(image,profile,exception);
628
1
      }
629
1.94k
#endif
630
1.94k
    libraw_close(raw_info);
631
1.94k
    return(image);
632
1.96k
  }
633
#else
634
  return(InvokeDNGDelegate(image_info,image,exception));
635
#endif
636
1.96k
}
637

638
/*
639
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640
%                                                                             %
641
%                                                                             %
642
%                                                                             %
643
%   R e g i s t e r D N G I m a g e                                           %
644
%                                                                             %
645
%                                                                             %
646
%                                                                             %
647
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648
%
649
%  RegisterDNGImage() adds attributes for the DNG image format to
650
%  the list of supported formats.  The attributes include the image format
651
%  tag, a method to read and/or write the format, whether the format
652
%  supports the saving of more than one frame to the same file or blob,
653
%  whether the format supports native in-memory I/O, and a brief
654
%  description of the format.
655
%
656
%  The format of the RegisterDNGImage method is:
657
%
658
%      size_t RegisterDNGImage(void)
659
%
660
*/
661
static inline void RegisterDNGMagickInfo(const char *name,
662
  const char *description,const char *version)
663
434
{
664
434
  MagickInfo
665
434
    *entry;
666
667
434
  entry=AcquireMagickInfo("DNG",name,description);
668
434
  entry->decoder=(DecodeImageHandler *) ReadDNGImage;
669
434
  entry->flags|=CoderDecoderSeekableStreamFlag;
670
434
  entry->flags^=CoderBlobSupportFlag;
671
434
  entry->format_type=ExplicitFormatType;
672
434
  if (*version != '\0')
673
434
    entry->version=ConstantString(version);
674
434
  (void) RegisterMagickInfo(entry);
675
434
}
676
677
ModuleExport size_t RegisterDNGImage(void)
678
14
{
679
14
  char
680
14
    version[MagickPathExtent];
681
682
14
  *version='\0';
683
14
#if defined(MAGICKCORE_RAW_R_DELEGATE)
684
14
  (void) CopyMagickString(version,libraw_version(),MagickPathExtent);
685
14
#endif
686
14
  RegisterDNGMagickInfo("3FR","Hasselblad CFV/H3D39II Raw Format",version);
687
14
  RegisterDNGMagickInfo("ARW","Sony Alpha Raw Format",version);
688
14
  RegisterDNGMagickInfo("CR2","Canon Digital Camera Raw Format",version);
689
14
  RegisterDNGMagickInfo("CR3","Canon Digital Camera Raw Format",version);
690
14
  RegisterDNGMagickInfo("CRW","Canon Digital Camera Raw Format",version);
691
14
  RegisterDNGMagickInfo("DCR","Kodak Digital Camera Raw Format",version);
692
14
  RegisterDNGMagickInfo("DCRAW","Raw Photo Decoder (dcraw)",version);
693
14
  RegisterDNGMagickInfo("DNG","Digital Negative Raw Format",version);
694
14
  RegisterDNGMagickInfo("ERF","Epson Raw Format",version);
695
14
  RegisterDNGMagickInfo("FFF","Hasselblad CFV/H3D39II Raw Format",version);
696
14
  RegisterDNGMagickInfo("IIQ","Phase One Raw Format",version);
697
14
  RegisterDNGMagickInfo("K25","Kodak Digital Camera Raw Format",version);
698
14
  RegisterDNGMagickInfo("KDC","Kodak Digital Camera Raw Format",version);
699
14
  RegisterDNGMagickInfo("MDC","Minolta Digital Camera Raw Format",version);
700
14
  RegisterDNGMagickInfo("MEF","Mamiya Raw Format",version);
701
14
  RegisterDNGMagickInfo("MOS","Aptus Leaf Raw Format",version);
702
14
  RegisterDNGMagickInfo("MRW","Sony (Minolta) Raw Format",version);
703
14
  RegisterDNGMagickInfo("NEF","Nikon Digital SLR Camera Raw Format",version);
704
14
  RegisterDNGMagickInfo("NRW","Nikon Digital SLR Camera Raw Format",version);
705
14
  RegisterDNGMagickInfo("ORF","Olympus Digital Camera Raw Format",version);
706
14
  RegisterDNGMagickInfo("PEF","Pentax Electronic Raw Format",version);
707
14
  RegisterDNGMagickInfo("RAF","Fuji CCD-RAW Graphic Raw Format",version);
708
14
  RegisterDNGMagickInfo("RAW","Raw",version);
709
14
  RegisterDNGMagickInfo("RMF","Raw Media Format",version);
710
14
  RegisterDNGMagickInfo("RW2","Panasonic Lumix Raw Format",version);
711
14
  RegisterDNGMagickInfo("RWL","Leica Raw Format",version);
712
14
  RegisterDNGMagickInfo("SR2","Sony Raw Format 2",version);
713
14
  RegisterDNGMagickInfo("SRF","Sony Raw Format",version);
714
14
  RegisterDNGMagickInfo("SRW","Samsung Raw Format",version);
715
14
  RegisterDNGMagickInfo("STI","Sinar CaptureShop Raw Format",version);
716
14
  RegisterDNGMagickInfo("X3F","Sigma Camera RAW Format",version);
717
14
  return(MagickImageCoderSignature);
718
14
}
719

720
/*
721
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722
%                                                                             %
723
%                                                                             %
724
%                                                                             %
725
%   U n r e g i s t e r D N G I m a g e                                       %
726
%                                                                             %
727
%                                                                             %
728
%                                                                             %
729
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730
%
731
%  UnregisterDNGImage() removes format registrations made by the
732
%  BIM module from the list of supported formats.
733
%
734
%  The format of the UnregisterBIMImage method is:
735
%
736
%      UnregisterDNGImage(void)
737
%
738
*/
739
ModuleExport void UnregisterDNGImage(void)
740
0
{
741
0
  (void) UnregisterMagickInfo("X3F");
742
0
  (void) UnregisterMagickInfo("STI");
743
0
  (void) UnregisterMagickInfo("SRW");
744
0
  (void) UnregisterMagickInfo("SRF");
745
0
  (void) UnregisterMagickInfo("SR2");
746
0
  (void) UnregisterMagickInfo("RWL");
747
0
  (void) UnregisterMagickInfo("RW2");
748
0
  (void) UnregisterMagickInfo("RMF");
749
0
  (void) UnregisterMagickInfo("RAF");
750
0
  (void) UnregisterMagickInfo("PEF");
751
0
  (void) UnregisterMagickInfo("ORF");
752
0
  (void) UnregisterMagickInfo("NRW");
753
0
  (void) UnregisterMagickInfo("NEF");
754
0
  (void) UnregisterMagickInfo("MRW");
755
0
  (void) UnregisterMagickInfo("MOS");
756
0
  (void) UnregisterMagickInfo("MEF");
757
0
  (void) UnregisterMagickInfo("MDC");
758
0
  (void) UnregisterMagickInfo("KDC");
759
0
  (void) UnregisterMagickInfo("K25");
760
0
  (void) UnregisterMagickInfo("IIQ");
761
0
  (void) UnregisterMagickInfo("FFF");
762
0
  (void) UnregisterMagickInfo("ERF");
763
0
  (void) UnregisterMagickInfo("DNG");
764
0
  (void) UnregisterMagickInfo("DCRAW");
765
0
  (void) UnregisterMagickInfo("DCR");
766
0
  (void) UnregisterMagickInfo("CRW");
767
0
  (void) UnregisterMagickInfo("CR3");
768
0
  (void) UnregisterMagickInfo("CR2");
769
0
  (void) UnregisterMagickInfo("ARW");
770
0
  (void) UnregisterMagickInfo("3FR");
771
0
}