diff options
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginRAW.cpp')
-rw-r--r-- | plugins/AdvaImg/src/FreeImage/PluginRAW.cpp | 223 |
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); } |