/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 | } |