Coverage Report

Created: 2025-02-07 06:10

/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/PluginRAW.cpp
Line
Count
Source (jump to first uncovered line)
1
// ==========================================================
2
// RAW camera image loader
3
//
4
// Design and implementation by 
5
// - Hervé Drolon (drolon@infonie.fr)
6
//
7
// This file is part of FreeImage 3
8
//
9
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
10
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
11
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
12
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
13
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
14
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
15
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
16
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
17
// THIS DISCLAIMER.
18
//
19
// Use at your own risk!
20
// ==========================================================
21
22
#include "../LibRawLite/libraw/libraw.h"
23
24
#include "FreeImage.h"
25
#include "Utilities.h"
26
#include "../Metadata/FreeImageTag.h"
27
28
// ==========================================================
29
// Plugin Interface
30
// ==========================================================
31
32
static int s_format_id;
33
34
// ==========================================================
35
// Internal functions
36
// ==========================================================
37
38
// ----------------------------------------------------------
39
//   FreeImage datastream wrapper
40
// ----------------------------------------------------------
41
42
class LibRaw_freeimage_datastream : public LibRaw_abstract_datastream {
43
private: 
44
  FreeImageIO *_io;
45
  fi_handle _handle;
46
  long _eof;
47
  INT64 _fsize;
48
49
public:
50
22.7k
  LibRaw_freeimage_datastream(FreeImageIO *io, fi_handle handle) : _io(io), _handle(handle) {
51
22.7k
    long start_pos = io->tell_proc(handle);
52
22.7k
    io->seek_proc(handle, 0, SEEK_END);
53
22.7k
    _eof = io->tell_proc(handle);
54
22.7k
    _fsize = _eof - start_pos;
55
22.7k
    io->seek_proc(handle, start_pos, SEEK_SET);
56
22.7k
  }
57
58
0
  ~LibRaw_freeimage_datastream() {
59
0
  }
60
61
22.7k
    int valid() { 
62
22.7k
    return (_io && _handle) ? 1 : 0;
63
22.7k
  }
64
65
427M
    int read(void *buffer, size_t size, size_t count) { 
66
427M
    return _io->read_proc(buffer, (unsigned)size, (unsigned)count, _handle);
67
427M
  }
68
69
201M
    int seek(INT64 offset, int origin) { 
70
201M
    return _io->seek_proc(_handle, (long)offset, origin);
71
201M
  }
72
73
288M
    INT64 tell() { 
74
288M
        return _io->tell_proc(_handle);
75
288M
    }
76
  
77
95.9M
  INT64 size() {
78
95.9M
    return _fsize;
79
95.9M
  }
80
81
51.7M
    int get_char() { 
82
51.7M
    int c = 0;
83
51.7M
    if (!_io->read_proc(&c, 1, 1, _handle)) {
84
50.5M
      return -1;
85
50.5M
    }
86
1.15M
    return c;
87
51.7M
   }
88
  
89
119k
  char* gets(char *buffer, int length) { 
90
119k
    memset(buffer, 0, length);
91
6.69M
    for(int i = 0; i < length; i++) {
92
6.59M
      if (!_io->read_proc(&buffer[i], 1, 1, _handle)) {
93
825
        return NULL;
94
825
      }
95
6.59M
      if (buffer[i] == 0x0A) {
96
21.9k
        break;
97
21.9k
      }
98
6.59M
    }
99
118k
    return buffer;
100
119k
  }
101
102
9.24k
  int scanf_one(const char *fmt, void* val) {
103
9.24k
    std::string buffer;
104
9.24k
    char element = 0;
105
9.24k
    bool bDone = false;
106
347k
    do {
107
347k
      if(_io->read_proc(&element, 1, 1, _handle) == 1) {
108
346k
        switch(element) {
109
1.60k
          case '0':
110
2.66k
          case '\n':
111
4.30k
          case ' ':
112
7.80k
          case '\t':
113
7.80k
            bDone = true;
114
7.80k
            break;
115
338k
          default:
116
338k
            break;
117
346k
        }
118
346k
        buffer.append(&element, 1);
119
346k
      } else {
120
1.44k
        return 0;
121
1.44k
      }
122
347k
    } while(!bDone);
123
124
7.80k
    return sscanf(buffer.c_str(), fmt, val);
125
9.24k
  }
126
127
747k
  int eof() { 
128
747k
        return (_io->tell_proc(_handle) >= _eof);
129
747k
    }
130
131
0
  void * make_jas_stream() {
132
0
    return NULL;
133
0
  }
134
};
135
136
// ----------------------------------------------------------
137
138
/**
139
Convert a processed raw data array to a FIBITMAP
140
@param RawProcessor LibRaw handle containing the processed raw image
141
@return Returns the converted dib if successfull, returns NULL otherwise
142
*/
143
static FIBITMAP * 
144
0
libraw_ConvertProcessedRawToDib(LibRaw *RawProcessor) {
145
0
  FIBITMAP *dib = NULL;
146
0
    int width, height, colors, bpp;
147
148
0
  try {
149
0
    int bgr = 0;  // pixel copy order: RGB if (bgr == 0) and BGR otherwise
150
151
    // get image info
152
0
    RawProcessor->get_mem_image_format(&width, &height, &colors, &bpp);
153
154
    // only 3-color images supported...
155
0
    if(colors != 3) {
156
0
      throw "LibRaw : only 3-color images supported";
157
0
    }
158
159
0
    if(bpp == 16) {
160
      // allocate output dib
161
0
      dib = FreeImage_AllocateT(FIT_RGB16, width, height);
162
0
      if(!dib) {
163
0
        throw FI_MSG_ERROR_DIB_MEMORY;
164
0
      }
165
166
0
    } else if(bpp == 8) {
167
0
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
168
0
      bgr = 1;  // only useful for FIT_BITMAP types
169
0
#endif
170
171
      // allocate output dib
172
0
      dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
173
0
      if(!dib) {
174
0
        throw FI_MSG_ERROR_DIB_MEMORY;
175
0
      }
176
0
    }
177
178
    // copy post-processed bitmap data into FIBITMAP buffer
179
0
    if(RawProcessor->copy_mem_image(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), bgr) != LIBRAW_SUCCESS) {
180
0
      throw "LibRaw : failed to copy data into dib";
181
0
    }
182
183
    // flip vertically
184
0
    FreeImage_FlipVertical(dib);
185
186
0
    return dib;
187
188
0
  } catch(const char *text) {
189
0
    FreeImage_Unload(dib);
190
0
    FreeImage_OutputMessageProc(s_format_id, text);
191
0
    return NULL;
192
0
  }
193
0
}
194
195
196
/**
197
Convert a processed raw image to a FIBITMAP
198
@param image Processed raw image
199
@return Returns the converted dib if successfull, returns NULL otherwise
200
@see libraw_LoadEmbeddedPreview
201
*/
202
static FIBITMAP * 
203
0
libraw_ConvertProcessedImageToDib(libraw_processed_image_t *image) {
204
0
  FIBITMAP *dib = NULL;
205
206
0
  try {
207
0
    unsigned width = image->width;
208
0
    unsigned height = image->height;
209
0
    unsigned bpp = image->bits;
210
0
    if(bpp == 16) {
211
      // allocate output dib
212
0
      dib = FreeImage_AllocateT(FIT_RGB16, width, height);
213
0
      if(!dib) {
214
0
        throw FI_MSG_ERROR_DIB_MEMORY;
215
0
      }
216
      // write data
217
0
      WORD *raw_data = (WORD*)image->data;
218
0
      for(unsigned y = 0; y < height; y++) {
219
0
        FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
220
0
        for(unsigned x = 0; x < width; x++) {
221
0
          output[x].red   = raw_data[0];
222
0
          output[x].green = raw_data[1];
223
0
          output[x].blue  = raw_data[2];
224
0
          raw_data += 3;
225
0
        }
226
0
      }
227
0
    } else if(bpp == 8) {
228
      // allocate output dib
229
0
      dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
230
0
      if(!dib) {
231
0
        throw FI_MSG_ERROR_DIB_MEMORY;
232
0
      }
233
      // write data
234
0
      BYTE *raw_data = (BYTE*)image->data;
235
0
      for(unsigned y = 0; y < height; y++) {
236
0
        RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y);
237
0
        for(unsigned x = 0; x < width; x++) {
238
0
          output[x].rgbtRed   = raw_data[0];
239
0
          output[x].rgbtGreen = raw_data[1];
240
0
          output[x].rgbtBlue  = raw_data[2];
241
0
          raw_data += 3;
242
0
        }
243
0
      }
244
0
    }
245
    
246
0
    return dib;
247
248
0
  } catch(const char *text) {
249
0
    FreeImage_Unload(dib);
250
0
    FreeImage_OutputMessageProc(s_format_id, text);
251
0
    return NULL;
252
0
  }
253
0
}
254
255
/** 
256
Get the embedded JPEG preview image from RAW picture with included Exif Data. 
257
@param RawProcessor Libraw handle
258
@param flags JPEG load flags
259
@return Returns the loaded dib if successfull, returns NULL otherwise
260
*/
261
static FIBITMAP * 
262
0
libraw_LoadEmbeddedPreview(LibRaw *RawProcessor, int flags) {
263
0
  FIBITMAP *dib = NULL;
264
0
  libraw_processed_image_t *thumb_image = NULL;
265
  
266
0
  try {
267
    // unpack data
268
0
    if(RawProcessor->unpack_thumb() != LIBRAW_SUCCESS) {
269
      // run silently "LibRaw : failed to run unpack_thumb"
270
0
      return NULL;
271
0
    }
272
273
    // retrieve thumb image
274
0
    int error_code = 0;
275
0
    thumb_image = RawProcessor->dcraw_make_mem_thumb(&error_code);
276
0
    if(thumb_image) {
277
0
      if(thumb_image->type != LIBRAW_IMAGE_BITMAP) {
278
        // attach the binary data to a memory stream
279
0
        FIMEMORY *hmem = FreeImage_OpenMemory((BYTE*)thumb_image->data, (DWORD)thumb_image->data_size);
280
        // get the file type
281
0
        FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
282
0
        if(fif == FIF_JPEG) {
283
          // rotate according to Exif orientation
284
0
          flags |= JPEG_EXIFROTATE;
285
0
        }
286
        // load an image from the memory stream
287
0
        dib = FreeImage_LoadFromMemory(fif, hmem, flags);
288
        // close the stream
289
0
        FreeImage_CloseMemory(hmem);
290
0
      } else if((flags & FIF_LOAD_NOPIXELS) != FIF_LOAD_NOPIXELS) {
291
        // convert processed data to output dib
292
0
        dib = libraw_ConvertProcessedImageToDib(thumb_image);
293
0
      }
294
0
    } else {
295
0
      throw "LibRaw : failed to run dcraw_make_mem_thumb";
296
0
    }
297
298
    // clean-up and return
299
0
    RawProcessor->dcraw_clear_mem(thumb_image);
300
301
0
    return dib;
302
303
0
  } catch(const char *text) {
304
    // clean-up and return
305
0
    if(thumb_image) {
306
0
      RawProcessor->dcraw_clear_mem(thumb_image);
307
0
    }
308
0
    if(text != NULL) {
309
0
      FreeImage_OutputMessageProc(s_format_id, text);
310
0
    }
311
0
  }
312
313
0
  return NULL;
314
0
}
315
/**
316
Load raw data and convert to FIBITMAP
317
@param RawProcessor Libraw handle
318
@param bitspersample Output bitdepth (8- or 16-bit)
319
@return Returns the loaded dib if successfull, returns NULL otherwise
320
*/
321
static FIBITMAP * 
322
0
libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) {
323
0
  FIBITMAP *dib = NULL;
324
325
0
  try {
326
    // set decoding parameters
327
    // -----------------------
328
    
329
    // (-6) 16-bit or 8-bit
330
0
    RawProcessor->imgdata.params.output_bps = bitspersample;
331
    // (-g power toe_slope)
332
0
    if(bitspersample == 16) {
333
      // set -g 1 1 for linear curve
334
0
      RawProcessor->imgdata.params.gamm[0] = 1;
335
0
      RawProcessor->imgdata.params.gamm[1] = 1;
336
0
    } else if(bitspersample == 8) {
337
      // by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5
338
0
      RawProcessor->imgdata.params.gamm[0] = 1/2.222;
339
0
      RawProcessor->imgdata.params.gamm[1] = 4.5;
340
0
    }
341
    // (-W) Don't use automatic increase of brightness by histogram
342
0
    RawProcessor->imgdata.params.no_auto_bright = 1;
343
    // (-a) Use automatic white balance obtained after averaging over the entire image
344
0
    RawProcessor->imgdata.params.use_auto_wb = 1;
345
    // (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD)
346
0
    RawProcessor->imgdata.params.user_qual = 3;
347
348
    // -----------------------
349
350
    // unpack data
351
0
    if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
352
0
      throw "LibRaw : failed to unpack data";
353
0
    }
354
355
    // process data (... most consuming task ...)
356
0
    if(RawProcessor->dcraw_process() != LIBRAW_SUCCESS) {
357
0
      throw "LibRaw : failed to process data";
358
0
    }
359
360
    // retrieve processed image
361
0
    dib = libraw_ConvertProcessedRawToDib(RawProcessor);
362
  
363
0
    return dib;
364
365
0
  } catch(const char *text) {
366
0
    FreeImage_OutputMessageProc(s_format_id, text);
367
0
    return NULL;
368
0
  }
369
0
}
370
371
/**
372
Load the Bayer matrix (unprocessed raw data) as a FIT_UINT16 image. 
373
Note that some formats don't have a Bayer matrix (e.g. Foveon, Canon sRAW, demosaiced DNG files). 
374
@param RawProcessor Libraw handle
375
@return Returns the loaded dib if successfull, returns NULL otherwise
376
*/
377
static FIBITMAP * 
378
0
libraw_LoadUnprocessedData(LibRaw *RawProcessor) {
379
0
  FIBITMAP *dib = NULL;
380
381
0
  try {
382
    // unpack data
383
0
    if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
384
0
      throw "LibRaw : failed to unpack data";
385
0
    }
386
387
    // check for a supported Bayer format
388
0
    if(!(RawProcessor->imgdata.idata.filters || RawProcessor->imgdata.idata.colors == 1)) {
389
0
      throw "LibRaw : only Bayer-pattern RAW files are supported";
390
0
    }
391
392
    // allocate output dib
393
0
    const unsigned width = RawProcessor->imgdata.sizes.raw_width;
394
0
    const unsigned height = RawProcessor->imgdata.sizes.raw_height;
395
0
    const size_t line_size = width * sizeof(WORD);
396
0
    const WORD *src_bits = (WORD*)RawProcessor->imgdata.rawdata.raw_image;
397
398
0
    if(src_bits) {
399
0
      dib = FreeImage_AllocateT(FIT_UINT16, width, height);
400
0
    }
401
0
    if(!dib) {
402
0
      throw FI_MSG_ERROR_DIB_MEMORY;
403
0
    }
404
405
    // retrieve the raw image
406
0
    for(unsigned y = 0; y < height; y++) {
407
0
      WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
408
0
      memcpy(dst_bits, src_bits, line_size);
409
0
      src_bits += width;
410
0
    }
411
412
    // store metadata needed for post-processing
413
0
    {
414
0
      char value[512];
415
416
0
      const libraw_image_sizes_t *sizes = &RawProcessor->imgdata.sizes;
417
418
      // image output width & height
419
0
      {
420
0
        sprintf(value, "%d", sizes->iwidth);
421
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Width", value);
422
        
423
0
        sprintf(value, "%d", sizes->iheight);
424
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Height", value);
425
0
      }
426
427
      // image output frame
428
0
      {
429
0
        const unsigned f_left = sizes->left_margin;
430
0
        const unsigned f_top = sizes->top_margin;
431
0
        const unsigned f_width = sizes->width;
432
0
        const unsigned f_height = sizes->height;
433
        
434
0
        sprintf(value, "%d", f_left);
435
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Left", value);
436
437
0
        sprintf(value, "%d", f_top);
438
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Top", value);
439
440
0
        sprintf(value, "%d", f_width);
441
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Width", value);
442
443
0
        sprintf(value, "%d", f_height);
444
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Height", value);
445
0
      }
446
447
      // Bayer pattern
448
      // Mask describing the order of color pixels in the matrix. 
449
      // This field describe 16 pixels (8 rows with two pixels in each, from left to right and from top to bottom). 
450
451
0
      if(RawProcessor->imgdata.idata.filters) {
452
        // description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG)
453
0
        char *cdesc = RawProcessor->imgdata.idata.cdesc;
454
0
        if(!cdesc[3]) {
455
0
          cdesc[3] = 'G';
456
0
        }
457
0
        char *pattern = &value[0];
458
0
        for(int i = 0; i < 16; i++) {
459
0
          pattern[i] = cdesc[ RawProcessor->fcol(i >> 1, i & 1) ];
460
0
        }
461
0
        pattern[16] = 0;
462
463
0
        FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.BayerPattern", value);
464
0
      }
465
0
    }
466
  
467
0
    return dib;
468
469
0
  } catch(const char *text) {
470
0
    FreeImage_Unload(dib);
471
0
    FreeImage_OutputMessageProc(s_format_id, text);
472
0
    return NULL;
473
0
  }
474
0
}
475
476
// ==========================================================
477
// Plugin Implementation
478
// ==========================================================
479
480
static const char * DLL_CALLCONV
481
2
Format() {
482
2
  return "RAW";
483
2
}
484
485
static const char * DLL_CALLCONV
486
0
Description() {
487
0
  return "RAW camera image";
488
0
}
489
490
static const char * DLL_CALLCONV
491
0
Extension() {
492
  /**
493
  Below are known RAW file extensions that you can check using FreeImage_GetFIFFromFormat. 
494
  If a file extension is not listed, that doesn't mean that you cannot load it. 
495
  Using FreeImage_GetFileType is the best way to know if a RAW file format is supported. 
496
  */
497
0
  static const char *raw_extensions = 
498
0
    "3fr,"   // Hasselblad Digital Camera Raw Image Format.
499
0
    "arw,"   // Sony Digital Camera Raw Image Format for Alpha devices.
500
0
    "bay,"   // Casio Digital Camera Raw File Format.
501
0
    "bmq,"   // NuCore Raw Image File.
502
0
    "cap,"   // Phase One Digital Camera Raw Image Format.
503
0
    "cine,"  // Phantom Software Raw Image File.
504
0
    "cr2,"   // Canon Digital Camera RAW Image Format version 2.0. These images are based on the TIFF image standard.
505
0
    "crw,"   // Canon Digital Camera RAW Image Format version 1.0. 
506
0
    "cs1,"   // Sinar Capture Shop Raw Image File.
507
0
    "dc2,"   // Kodak DC25 Digital Camera File.
508
0
    "dcr,"   // Kodak Digital Camera Raw Image Format for these models: Kodak DSC Pro SLR/c, Kodak DSC Pro SLR/n, Kodak DSC Pro 14N, Kodak DSC PRO 14nx.
509
0
    "drf,"   // Kodak Digital Camera Raw Image Format.
510
0
    "dsc,"   // Kodak Digital Camera Raw Image Format.
511
0
    "dng,"   // Adobe Digital Negative: DNG is publicly available archival format for the raw files generated by digital cameras. By addressing the lack of an open standard for the raw files created by individual camera models, DNG helps ensure that photographers will be able to access their files in the future. 
512
0
    "erf,"   // Epson Digital Camera Raw Image Format.
513
0
    "fff,"   // Imacon Digital Camera Raw Image Format.
514
0
    "ia,"    // Sinar Raw Image File.
515
0
    "iiq,"   // Phase One Digital Camera Raw Image Format.
516
0
    "k25,"   // Kodak DC25 Digital Camera Raw Image Format.
517
0
    "kc2,"   // Kodak DCS200 Digital Camera Raw Image Format.
518
0
    "kdc,"   // Kodak Digital Camera Raw Image Format.
519
0
    "mdc,"   // Minolta RD175 Digital Camera Raw Image Format.
520
0
    "mef,"   // Mamiya Digital Camera Raw Image Format.
521
0
    "mos,"   // Leaf Raw Image File.
522
0
    "mrw,"   // Minolta Dimage Digital Camera Raw Image Format.
523
0
    "nef,"   // Nikon Digital Camera Raw Image Format.
524
0
    "nrw,"   // Nikon Digital Camera Raw Image Format.
525
0
    "orf,"   // Olympus Digital Camera Raw Image Format.
526
0
    "pef,"   // Pentax Digital Camera Raw Image Format.
527
0
    "ptx,"   // Pentax Digital Camera Raw Image Format.
528
0
    "pxn,"   // Logitech Digital Camera Raw Image Format.
529
0
    "qtk,"   // Apple Quicktake 100/150 Digital Camera Raw Image Format.
530
0
    "raf,"   // Fuji Digital Camera Raw Image Format.
531
0
    "raw,"   // Panasonic Digital Camera Image Format.
532
0
    "rdc,"   // Digital Foto Maker Raw Image File.
533
0
    "rw2,"   // Panasonic LX3 Digital Camera Raw Image Format.
534
0
    "rwl,"   // Leica Camera Raw Image Format.
535
0
    "rwz,"   // Rawzor Digital Camera Raw Image Format.
536
0
    "sr2,"   // Sony Digital Camera Raw Image Format.
537
0
    "srf,"   // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1.
538
0
    "srw,"   // Samsung Raw Image Format.
539
0
    "sti,"   // Sinar Capture Shop Raw Image File.
540
0
    "x3f";   // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor.
541
0
  return raw_extensions;
542
0
}
543
544
static const char * DLL_CALLCONV
545
0
RegExpr() {
546
0
  return NULL;
547
0
}
548
549
static const char * DLL_CALLCONV
550
0
MimeType() {
551
0
  return "image/x-dcraw";
552
0
}
553
554
static BOOL 
555
22.7k
HasMagicHeader(FreeImageIO *io, fi_handle handle) {
556
22.7k
  const unsigned signature_size = 32;
557
22.7k
  BYTE signature[signature_size] = { 0 };
558
  /*
559
  note: classic TIFF signature is
560
  { 0x49, 0x49, 0x2A, 0x00 } Classic TIFF, little-endian
561
  { 0x4D, 0x4D, 0x00, 0x2A } Classic TIFF, big-endian
562
  */
563
  // Canon (CR2), little-endian byte order
564
22.7k
  static const BYTE CR2_II[] = { 0x49, 0x49, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 };
565
  // Canon (CRW), little-endian byte order
566
22.7k
  static const BYTE CRW_II[] = { 0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45, 0x41, 0x50, 0x43, 0x43, 0x44, 0x52, 0x02, 0x00 };
567
  // Minolta (MRW)
568
22.7k
  static const BYTE MRW[] = { 0x00, 0x4D, 0x52, 0x4D, 0x00 };
569
  // Olympus (ORF), little-endian byte order
570
22.7k
  static const BYTE ORF_IIRS[] = { 0x49, 0x49, 0x52, 0x53, 0x08, 0x00, 0x00, 0x00 };
571
22.7k
  static const BYTE ORF_IIRO[] = { 0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00 };
572
  // Olympus (ORF), big-endian byte order
573
22.7k
  static  const BYTE ORF_MMOR[] = { 0x4D, 0x4D, 0x4F, 0x52, 0x00, 0x00, 0x00, 0x08 };
574
  // Fujifilm (RAF)
575
22.7k
  static const BYTE RAF[] = { 0x46, 0x55, 0x4A, 0x49, 0x46, 0x49, 0x4C, 0x4D, 0x43, 0x43, 0x44, 0x2D, 0x52, 0x41, 0x57, 0x20 };
576
  // Panasonic (RW2) or Leica (RWL), little-endian byte order
577
22.7k
  static const BYTE RWx_II[] = { 0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8, 0xF8, 0x25, 0x1D, 0x4D, 0x94, 0x7A, 0x6E, 0x77, 0x82, 0x2B, 0x5D, 0x6A };
578
  // Panasonic (RAW) or Leica (RAW), little-endian byte order
579
22.7k
  static const BYTE RAW_II[] = { 0x49, 0x49, 0x55, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00 };
580
  // Foveon (X3F)
581
22.7k
  static const BYTE X3F[] = { 0x46, 0x4F, 0x56, 0x62 };
582
583
22.7k
  if(io->read_proc(signature, 1, signature_size, handle) != signature_size) {
584
0
    return FALSE;
585
0
  }
586
22.7k
  if (memcmp(CR2_II, signature, 12) == 0) {
587
0
    return TRUE;
588
0
  }
589
22.7k
  if (memcmp(CRW_II, signature, 16) == 0) {
590
0
    return TRUE;
591
0
  }
592
22.7k
  if (memcmp(MRW, signature, 5) == 0) {
593
0
    return TRUE;
594
0
  }
595
22.7k
  if (memcmp(ORF_IIRS, signature, 8) == 0) {
596
0
    return TRUE;
597
0
  }
598
22.7k
  if (memcmp(ORF_IIRO, signature, 8) == 0) {
599
1
    return TRUE;
600
1
  }
601
22.7k
  if (memcmp(ORF_MMOR, signature, 8) == 0) {
602
0
    return TRUE;
603
0
  }
604
22.7k
  if (memcmp(RAF, signature, 16) == 0) {
605
1
    return TRUE;
606
1
  }
607
22.7k
  if (memcmp(RWx_II, signature, 24) == 0) {
608
0
    return TRUE;
609
0
  }
610
22.7k
  if (memcmp(RAW_II, signature, 18) == 0) {
611
0
    return TRUE;
612
0
  }
613
22.7k
  if (memcmp(X3F, signature, 4) == 0) {
614
1
    return TRUE;
615
1
  }
616
617
22.7k
  return FALSE;
618
22.7k
}
619
620
static BOOL DLL_CALLCONV
621
22.7k
Validate(FreeImageIO *io, fi_handle handle) {
622
  // some RAW files have a magic signature (most of them have a TIFF signature)
623
  // try to check this in order to speed up the file identification
624
22.7k
  {
625
22.7k
    long tell = io->tell_proc(handle);
626
22.7k
    if( HasMagicHeader(io, handle) ) {
627
3
      return TRUE;
628
22.7k
    } else {
629
22.7k
      io->seek_proc(handle, tell, SEEK_SET);
630
22.7k
    }
631
22.7k
  }
632
633
  // no magic signature : we need to open the file (it will take more time to identify it)
634
  // do not declare RawProcessor on the stack as it may be huge (300 KB)
635
22.7k
  {
636
22.7k
    LibRaw *RawProcessor = new(std::nothrow) LibRaw;
637
638
22.7k
    if(RawProcessor) {
639
22.7k
      BOOL bSuccess = TRUE;
640
641
      // wrap the input datastream
642
22.7k
      LibRaw_freeimage_datastream datastream(io, handle);
643
644
      // open the datastream
645
22.7k
      if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) {
646
22.2k
        bSuccess = FALSE; // LibRaw : failed to open input stream (unknown format)
647
22.2k
      }
648
649
      // clean-up internal memory allocations
650
22.7k
      RawProcessor->recycle();
651
22.7k
      delete RawProcessor;
652
653
22.7k
      return bSuccess;
654
22.7k
    }
655
22.7k
  }
656
657
0
  return FALSE;
658
22.7k
}
659
660
static BOOL DLL_CALLCONV
661
0
SupportsExportDepth(int depth) {
662
0
  return FALSE;
663
0
}
664
665
static BOOL DLL_CALLCONV 
666
0
SupportsExportType(FREE_IMAGE_TYPE type) {
667
0
  return FALSE;
668
0
}
669
670
static BOOL DLL_CALLCONV
671
0
SupportsICCProfiles() {
672
0
  return TRUE;
673
0
}
674
675
static BOOL DLL_CALLCONV
676
0
SupportsNoPixels() {
677
0
  return TRUE;
678
0
}
679
680
// ----------------------------------------------------------
681
682
static FIBITMAP * DLL_CALLCONV
683
0
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
684
0
  FIBITMAP *dib = NULL;
685
0
  LibRaw *RawProcessor = NULL;
686
687
0
  BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
688
689
0
  try {
690
    // do not declare RawProcessor on the stack as it may be huge (300 KB)
691
0
    RawProcessor = new(std::nothrow) LibRaw;
692
0
    if(!RawProcessor) {
693
0
      throw FI_MSG_ERROR_MEMORY;
694
0
    }
695
696
    // wrap the input datastream
697
0
    LibRaw_freeimage_datastream datastream(io, handle);
698
699
    // set decoding parameters
700
    // the following parameters affect data reading
701
    // --------------------------------------------
702
703
    // (-s [0..N-1]) Select one raw image from input file
704
0
    RawProcessor->imgdata.rawparams.shot_select = 0;
705
    // (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb)
706
0
    RawProcessor->imgdata.params.use_camera_wb = 1;
707
    // (-M) Use any color matrix from the camera metadata. This option only affects Olympus, Leaf, and Phase One cameras.
708
0
    RawProcessor->imgdata.params.use_camera_matrix = 1;
709
    // (-h) outputs the image in 50% size
710
0
    RawProcessor->imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
711
712
    // open the datastream
713
0
    if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) {
714
0
      throw "LibRaw : failed to open input stream (unknown format)";
715
0
    }
716
717
0
    if(header_only) {
718
      // header only mode
719
0
      dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor->imgdata.sizes.width, RawProcessor->imgdata.sizes.height);
720
0
    }
721
0
    else if((flags & RAW_UNPROCESSED) == RAW_UNPROCESSED) {
722
      // load raw data without post-processing (i.e. as a Bayer matrix)
723
0
      dib = libraw_LoadUnprocessedData(RawProcessor);
724
0
    }
725
0
    else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
726
      // try to get the embedded JPEG
727
0
      dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
728
0
      if(!dib) {
729
        // no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit)
730
0
        dib = libraw_LoadRawData(RawProcessor, 8);
731
0
      }
732
0
    } 
733
0
    else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
734
      // load raw data as 8-bit/sample (i.e. RGB 24-bit)
735
0
      dib = libraw_LoadRawData(RawProcessor, 8);
736
0
    } 
737
0
    else {
738
      // default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit)
739
0
      dib = libraw_LoadRawData(RawProcessor, 16);
740
0
    }
741
742
    // save ICC profile if present
743
0
    if(dib && (NULL != RawProcessor->imgdata.color.profile)) {
744
0
      FreeImage_CreateICCProfile(dib, RawProcessor->imgdata.color.profile, RawProcessor->imgdata.color.profile_length);
745
0
    }
746
747
    // try to get JPEG embedded Exif metadata
748
0
    if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) {
749
0
      FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
750
0
      if(metadata_dib) {
751
0
        FreeImage_CloneMetadata(dib, metadata_dib);
752
0
        FreeImage_Unload(metadata_dib);
753
0
      }
754
0
    }
755
756
    // clean-up internal memory allocations
757
0
    RawProcessor->recycle();
758
0
    delete RawProcessor;
759
760
0
    return dib;
761
762
0
  } catch(const char *text) {
763
0
    if(RawProcessor) {
764
0
      RawProcessor->recycle();
765
0
      delete RawProcessor;
766
0
    }
767
0
    if(dib) {
768
0
      FreeImage_Unload(dib);
769
0
    }
770
0
    FreeImage_OutputMessageProc(s_format_id, text);
771
0
  }
772
773
0
  return NULL;
774
0
}
775
776
// ==========================================================
777
//   Init
778
// ==========================================================
779
780
void DLL_CALLCONV
781
2
InitRAW(Plugin *plugin, int format_id) {
782
2
  s_format_id = format_id;
783
784
2
  plugin->format_proc = Format;
785
2
  plugin->description_proc = Description;
786
2
  plugin->extension_proc = Extension;
787
2
  plugin->regexpr_proc = RegExpr;
788
2
  plugin->open_proc = NULL;
789
2
  plugin->close_proc = NULL;
790
2
  plugin->pagecount_proc = NULL;
791
2
  plugin->pagecapability_proc = NULL;
792
2
  plugin->load_proc = Load;
793
2
  plugin->save_proc = NULL;
794
2
  plugin->validate_proc = Validate;
795
2
  plugin->mime_proc = MimeType;
796
2
  plugin->supports_export_bpp_proc = SupportsExportDepth;
797
2
  plugin->supports_export_type_proc = SupportsExportType;
798
2
  plugin->supports_icc_profiles_proc = SupportsICCProfiles;
799
2
  plugin->supports_no_pixels_proc = SupportsNoPixels;
800
2
}