summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginRAW.cpp')
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginRAW.cpp223
1 files changed, 159 insertions, 64 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp b/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
index 4611824f4d..bf5d82169c 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
@@ -44,56 +44,63 @@ private:
FreeImageIO *_io;
fi_handle _handle;
long _eof;
+ INT64 _fsize;
public:
LibRaw_freeimage_datastream(FreeImageIO *io, fi_handle handle) : _io(io), _handle(handle) {
long start_pos = io->tell_proc(handle);
io->seek_proc(handle, 0, SEEK_END);
_eof = io->tell_proc(handle);
+ _fsize = _eof - start_pos;
io->seek_proc(handle, start_pos, SEEK_SET);
}
+
~LibRaw_freeimage_datastream() {
}
- virtual void * make_jas_stream() {
- return NULL;
- }
- virtual int valid() {
+
+ int valid() {
return (_io && _handle);
}
- virtual int read(void *buffer, size_t size, size_t count) {
+
+ int read(void *buffer, size_t size, size_t count) {
if(substream) return substream->read(buffer, size, count);
return _io->read_proc(buffer, (unsigned)size, (unsigned)count, _handle);
- }
- virtual int eof() {
- if(substream) return substream->eof();
- return (_io->tell_proc(_handle) >= _eof);
- }
- virtual int seek(INT64 offset, int origin) {
+ }
+
+ int seek(INT64 offset, int origin) {
if(substream) return substream->seek(offset, origin);
return _io->seek_proc(_handle, (long)offset, origin);
- }
- virtual INT64 tell() {
+ }
+
+ INT64 tell() {
if(substream) return substream->tell();
return _io->tell_proc(_handle);
}
- virtual int get_char() {
+
+ INT64 size() {
+ return _fsize;
+ }
+
+ int get_char() {
int c = 0;
if(substream) return substream->get_char();
- if (!_io->read_proc(&c, 1, 1, _handle)) return -1;
+ if(!_io->read_proc(&c, 1, 1, _handle)) return -1;
return c;
}
- virtual char* gets(char *buffer, int length) {
+
+ char* gets(char *buffer, int length) {
if (substream) return substream->gets(buffer, length);
memset(buffer, 0, length);
for(int i = 0; i < length; i++) {
- if (!_io->read_proc(&buffer[i], 1, 1, _handle))
+ if(!_io->read_proc(&buffer[i], 1, 1, _handle))
return NULL;
if(buffer[i] == 0x0A)
break;
}
return buffer;
}
- virtual int scanf_one(const char *fmt, void* val) {
+
+ int scanf_one(const char *fmt, void* val) {
std::string buffer;
char element = 0;
bool bDone = false;
@@ -118,6 +125,15 @@ public:
return sscanf(buffer.c_str(), fmt, val);
}
+
+ int eof() {
+ if(substream) return substream->eof();
+ return (_io->tell_proc(_handle) >= _eof);
+ }
+
+ void * make_jas_stream() {
+ return NULL;
+ }
};
// ----------------------------------------------------------
@@ -137,7 +153,7 @@ libraw_ConvertToDib(libraw_processed_image_t *image) {
if(bpp == 16) {
// allocate output dib
dib = FreeImage_AllocateT(FIT_RGB16, width, height);
- if (!dib) {
+ if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// write data
@@ -154,7 +170,7 @@ libraw_ConvertToDib(libraw_processed_image_t *image) {
} else if(bpp == 8) {
// allocate output dib
dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
- if (!dib) {
+ if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// write data
@@ -184,20 +200,20 @@ Get the embedded JPEG preview image from RAW picture with included Exif Data.
@return Returns the loaded dib if successfull, returns NULL otherwise
*/
static FIBITMAP *
-libraw_LoadEmbeddedPreview(LibRaw& RawProcessor, int flags) {
+libraw_LoadEmbeddedPreview(LibRaw *RawProcessor, int flags) {
FIBITMAP *dib = NULL;
libraw_processed_image_t *thumb_image = NULL;
try {
// unpack data
- if(RawProcessor.unpack_thumb() != LIBRAW_SUCCESS) {
+ if(RawProcessor->unpack_thumb() != LIBRAW_SUCCESS) {
// run silently "LibRaw : failed to run unpack_thumb"
return NULL;
}
// retrieve thumb image
int error_code = 0;
- thumb_image = RawProcessor.dcraw_make_mem_thumb(&error_code);
+ thumb_image = RawProcessor->dcraw_make_mem_thumb(&error_code);
if(thumb_image) {
if(thumb_image->type != LIBRAW_IMAGE_BITMAP) {
// attach the binary data to a memory stream
@@ -221,14 +237,14 @@ libraw_LoadEmbeddedPreview(LibRaw& RawProcessor, int flags) {
}
// clean-up and return
- RawProcessor.dcraw_clear_mem(thumb_image);
+ RawProcessor->dcraw_clear_mem(thumb_image);
return dib;
} catch(const char *text) {
// clean-up and return
if(thumb_image) {
- RawProcessor.dcraw_clear_mem(thumb_image);
+ RawProcessor->dcraw_clear_mem(thumb_image);
}
if(text != NULL) {
FreeImage_OutputMessageProc(s_format_id, text);
@@ -244,7 +260,7 @@ Load raw data and convert to FIBITMAP
@return Returns the loaded dib if successfull, returns NULL otherwise
*/
static FIBITMAP *
-libraw_LoadRawData(LibRaw& RawProcessor, int bitspersample) {
+libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) {
FIBITMAP *dib = NULL;
libraw_processed_image_t *processed_image = NULL;
@@ -253,39 +269,39 @@ libraw_LoadRawData(LibRaw& RawProcessor, int bitspersample) {
// -----------------------
// (-6) 16-bit or 8-bit
- RawProcessor.imgdata.params.output_bps = bitspersample;
+ RawProcessor->imgdata.params.output_bps = bitspersample;
// (-g power toe_slope)
if(bitspersample == 16) {
// set -g 1 1 for linear curve
- RawProcessor.imgdata.params.gamm[0] = 1;
- RawProcessor.imgdata.params.gamm[1] = 1;
+ RawProcessor->imgdata.params.gamm[0] = 1;
+ RawProcessor->imgdata.params.gamm[1] = 1;
} else if(bitspersample == 8) {
// by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5
- RawProcessor.imgdata.params.gamm[0] = 1/2.222;
- RawProcessor.imgdata.params.gamm[1] = 4.5;
+ RawProcessor->imgdata.params.gamm[0] = 1/2.222;
+ RawProcessor->imgdata.params.gamm[1] = 4.5;
}
// (-W) Don't use automatic increase of brightness by histogram
- RawProcessor.imgdata.params.no_auto_bright = 1;
+ RawProcessor->imgdata.params.no_auto_bright = 1;
// (-a) Use automatic white balance obtained after averaging over the entire image
- RawProcessor.imgdata.params.use_auto_wb = 1;
+ RawProcessor->imgdata.params.use_auto_wb = 1;
// (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD)
- RawProcessor.imgdata.params.user_qual = 3;
+ RawProcessor->imgdata.params.user_qual = 3;
// -----------------------
// unpack data
- if(RawProcessor.unpack() != LIBRAW_SUCCESS) {
+ if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
throw "LibRaw : failed to unpack data";
}
// process data (... most consuming task ...)
- if(RawProcessor.dcraw_process() != LIBRAW_SUCCESS) {
+ if(RawProcessor->dcraw_process() != LIBRAW_SUCCESS) {
throw "LibRaw : failed to process data";
}
// retrieve processed image
int error_code = 0;
- processed_image = RawProcessor.dcraw_make_mem_image(&error_code);
+ processed_image = RawProcessor->dcraw_make_mem_image(&error_code);
if(processed_image) {
// type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
if(processed_image->type != LIBRAW_IMAGE_BITMAP) {
@@ -303,14 +319,14 @@ libraw_LoadRawData(LibRaw& RawProcessor, int bitspersample) {
dib = libraw_ConvertToDib(processed_image);
// clean-up and return
- RawProcessor.dcraw_clear_mem(processed_image);
+ RawProcessor->dcraw_clear_mem(processed_image);
return dib;
} catch(const char *text) {
// clean-up and return
if(processed_image) {
- RawProcessor.dcraw_clear_mem(processed_image);
+ RawProcessor->dcraw_clear_mem(processed_image);
}
FreeImage_OutputMessageProc(s_format_id, text);
}
@@ -396,23 +412,92 @@ MimeType() {
return "image/x-dcraw";
}
+static BOOL
+HasMagicHeader(FreeImageIO *io, fi_handle handle) {
+ const unsigned signature_size = 32;
+ BYTE signature[signature_size] = { 0 };
+
+ // Canon (CR2), Intel byte order
+ const BYTE CR2_II[] = { 0x49, 0x49, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 };
+ // Canon (CR2), Motorola byte order
+ const BYTE CR2_MM[] = { 0x4D, 0x4D, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 };
+ // Canon (CRW), Intel byte order
+ const BYTE CRW_II[] = { 0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45, 0x41, 0x50, 0x43, 0x43, 0x44, 0x52, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ // Minolta (MRW)
+ const BYTE MRW[] = { 0x00, 0x4D, 0x52, 0x4D, 0x00 };
+ // Olympus (ORF), Intel byte order
+ const BYTE ORF_IIRS[] = { 0x49, 0x49, 0x52, 0x53, 0x08, 0x00, 0x00, 0x00 };
+ const BYTE ORF_IIRO[] = { 0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00 };
+ // Olympus (ORF), Motorola byte order
+ const BYTE ORF_MMOR[] = { 0x4D, 0x4D, 0x4F, 0x52, 0x00, 0x00, 0x00, 0x08 };
+ // Fujifilm (RAF)
+ const BYTE RAF[] = { 0x46, 0x55, 0x4A, 0x49, 0x46, 0x49, 0x4C, 0x4D, 0x43, 0x43, 0x44, 0x2D, 0x52, 0x41, 0x57, 0x20, 0x30, 0x32, 0x30, 0x31 };
+ // Panasonic (RW2) or Leica (RWL)
+ const BYTE RW2_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 };
+
+ if(io->read_proc(signature, 1, signature_size, handle) != signature_size) {
+ return FALSE;
+ }
+ if(memcmp(CR2_II, signature, 12) == 0)
+ return TRUE;
+ if(memcmp(CR2_MM, signature, 12) == 0)
+ return TRUE;
+ if(memcmp(CRW_II, signature, 26) == 0)
+ return TRUE;
+ if(memcmp(MRW, signature, 5) == 0)
+ return TRUE;
+ if(memcmp(ORF_IIRS, signature, 8) == 0)
+ return TRUE;
+ if(memcmp(ORF_IIRO, signature, 8) == 0)
+ return TRUE;
+ if(memcmp(ORF_MMOR, signature, 8) == 0)
+ return TRUE;
+ if(memcmp(RAF, signature, 20) == 0)
+ return TRUE;
+ if(memcmp(RW2_II, signature, 24) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
- LibRaw RawProcessor;
- BOOL bSuccess = TRUE;
-
- // wrap the input datastream
- LibRaw_freeimage_datastream datastream(io, handle);
-
- // open the datastream
- if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
- bSuccess = FALSE; // LibRaw : failed to open input stream (unknown format)
+ // some RAW files have a magic signature (most of them have a TIFF signature)
+ // try to check this in order to speed up the file identification
+ {
+ long tell = io->tell_proc(handle);
+ if( HasMagicHeader(io, handle) ) {
+ return TRUE;
+ } else {
+ io->seek_proc(handle, tell, SEEK_SET);
+ }
}
- // clean-up internal memory allocations
- RawProcessor.recycle();
+ // no magic signature : we need to open the file (it will take more time to identify it)
+ // do not declare RawProcessor on the stack as it may be huge (300 KB)
+ {
+ LibRaw *RawProcessor = new(std::nothrow) LibRaw;
+
+ if(RawProcessor) {
+ BOOL bSuccess = TRUE;
+
+ // wrap the input datastream
+ LibRaw_freeimage_datastream datastream(io, handle);
- return bSuccess;
+ // open the datastream
+ if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) {
+ bSuccess = FALSE; // LibRaw : failed to open input stream (unknown format)
+ }
+
+ // clean-up internal memory allocations
+ RawProcessor->recycle();
+ delete RawProcessor;
+
+ return bSuccess;
+ }
+ }
+
+ return FALSE;
}
static BOOL DLL_CALLCONV
@@ -440,11 +525,17 @@ SupportsNoPixels() {
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
FIBITMAP *dib = NULL;
- LibRaw RawProcessor;
+ LibRaw *RawProcessor = NULL;
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
try {
+ // do not declare RawProcessor on the stack as it may be huge (300 KB)
+ RawProcessor = new(std::nothrow) LibRaw;
+ if(!RawProcessor) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
// wrap the input datastream
LibRaw_freeimage_datastream datastream(io, handle);
@@ -453,30 +544,30 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// --------------------------------------------
// (-s [0..N-1]) Select one raw image from input file
- RawProcessor.imgdata.params.shot_select = 0;
+ RawProcessor->imgdata.params.shot_select = 0;
// (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb)
- RawProcessor.imgdata.params.use_camera_wb = 1;
+ RawProcessor->imgdata.params.use_camera_wb = 1;
// (-h) outputs the image in 50% size
- RawProcessor.imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
+ RawProcessor->imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
// open the datastream
- if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
+ if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) {
throw "LibRaw : failed to open input stream (unknown format)";
}
if(header_only) {
// header only mode
- dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor.imgdata.sizes.width, RawProcessor.imgdata.sizes.height);
+ dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor->imgdata.sizes.width, RawProcessor->imgdata.sizes.height);
}
- else if ((flags & RAW_PREVIEW) == RAW_PREVIEW) {
+ else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
// try to get the embedded JPEG
dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
- if (!dib) {
+ if(!dib) {
// no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit)
dib = libraw_LoadRawData(RawProcessor, 8);
}
}
- else if ((flags & RAW_DISPLAY) == RAW_DISPLAY) {
+ else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
// load raw data as 8-bit/sample (i.e. RGB 24-bit)
dib = libraw_LoadRawData(RawProcessor, 8);
}
@@ -486,8 +577,8 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
}
// save ICC profile if present
- if(dib && (NULL != RawProcessor.imgdata.color.profile)) {
- FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length);
+ if(dib && (NULL != RawProcessor->imgdata.color.profile)) {
+ FreeImage_CreateICCProfile(dib, RawProcessor->imgdata.color.profile, RawProcessor->imgdata.color.profile_length);
}
// try to get JPEG embedded Exif metadata
@@ -500,15 +591,19 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
}
// clean-up internal memory allocations
- RawProcessor.recycle();
+ RawProcessor->recycle();
+ delete RawProcessor;
return dib;
} catch(const char *text) {
+ if(RawProcessor) {
+ RawProcessor->recycle();
+ delete RawProcessor;
+ }
if(dib) {
FreeImage_Unload(dib);
}
- RawProcessor.recycle();
FreeImage_OutputMessageProc(s_format_id, text);
}