Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginRAW.cpp view on Meta::CPAN
}
int get_char() {
int c = 0;
if(substream) return substream->get_char();
if(!_io->read_proc(&c, 1, 1, _handle)) return -1;
return c;
}
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))
return NULL;
if(buffer[i] == 0x0A)
break;
}
return buffer;
}
int scanf_one(const char *fmt, void* val) {
std::string buffer;
char element = 0;
bool bDone = false;
if(substream) return substream->scanf_one(fmt,val);
do {
if(_io->read_proc(&element, 1, 1, _handle) == 1) {
switch(element) {
case '0':
case '\n':
case ' ':
case '\t':
bDone = true;
break;
default:
break;
}
buffer.append(&element, 1);
} else {
return 0;
}
} while(!bDone);
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;
}
};
// ----------------------------------------------------------
/**
Convert a processed raw data array to a FIBITMAP
@param RawProcessor LibRaw handle containing the processed raw image
@return Returns the converted dib if successfull, returns NULL otherwise
*/
static FIBITMAP *
libraw_ConvertProcessedRawToDib(LibRaw *RawProcessor) {
FIBITMAP *dib = NULL;
int width, height, colors, bpp;
try {
int bgr = 0; // pixel copy order: RGB if (bgr == 0) and BGR otherwise
// get image info
RawProcessor->get_mem_image_format(&width, &height, &colors, &bpp);
// only 3-color images supported...
if(colors != 3) {
throw "LibRaw : only 3-color images supported";
}
if(bpp == 16) {
// allocate output dib
dib = FreeImage_AllocateT(FIT_RGB16, width, height);
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
} else if(bpp == 8) {
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
bgr = 1; // only useful for FIT_BITMAP types
#endif
// allocate output dib
dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
}
// copy post-processed bitmap data into FIBITMAP buffer
if(RawProcessor->copy_mem_image(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), bgr) != LIBRAW_SUCCESS) {
throw "LibRaw : failed to copy data into dib";
}
// flip vertically
FreeImage_FlipVertical(dib);
return dib;
} catch(const char *text) {
FreeImage_Unload(dib);
FreeImage_OutputMessageProc(s_format_id, text);
return NULL;
}
}
/**
Convert a processed raw image to a FIBITMAP
@param image Processed raw image
@return Returns the converted dib if successfull, returns NULL otherwise
@see libraw_LoadEmbeddedPreview
*/
static FIBITMAP *
libraw_ConvertProcessedImageToDib(libraw_processed_image_t *image) {
FIBITMAP *dib = NULL;
try {
unsigned width = image->width;
unsigned height = image->height;
unsigned bpp = image->bits;
if(bpp == 16) {
// allocate output dib
dib = FreeImage_AllocateT(FIT_RGB16, width, height);
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// write data
WORD *raw_data = (WORD*)image->data;
for(unsigned y = 0; y < height; y++) {
FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
for(unsigned x = 0; x < width; x++) {
output[x].red = raw_data[0];
output[x].green = raw_data[1];
output[x].blue = raw_data[2];
raw_data += 3;
}
}
} else if(bpp == 8) {
// allocate output dib
dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// write data
BYTE *raw_data = (BYTE*)image->data;
for(unsigned y = 0; y < height; y++) {
RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y);
for(unsigned x = 0; x < width; x++) {
output[x].rgbtRed = raw_data[0];
output[x].rgbtGreen = raw_data[1];
output[x].rgbtBlue = raw_data[2];
raw_data += 3;
}
}
}
return dib;
} catch(const char *text) {
FreeImage_Unload(dib);
FreeImage_OutputMessageProc(s_format_id, text);
return NULL;
}
}
/**
Get the embedded JPEG preview image from RAW picture with included Exif Data.
@param RawProcessor Libraw handle
@param flags JPEG load flags
@return Returns the loaded dib if successfull, returns NULL otherwise
*/
static FIBITMAP *
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) {
// 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);
if(thumb_image) {
if(thumb_image->type != LIBRAW_IMAGE_BITMAP) {
// attach the binary data to a memory stream
FIMEMORY *hmem = FreeImage_OpenMemory((BYTE*)thumb_image->data, (DWORD)thumb_image->data_size);
// get the file type
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
if(fif == FIF_JPEG) {
// rotate according to Exif orientation
flags |= JPEG_EXIFROTATE;
}
// load an image from the memory stream
dib = FreeImage_LoadFromMemory(fif, hmem, flags);
// close the stream
FreeImage_CloseMemory(hmem);
} else if((flags & FIF_LOAD_NOPIXELS) != FIF_LOAD_NOPIXELS) {
// convert processed data to output dib
dib = libraw_ConvertProcessedImageToDib(thumb_image);
}
} else {
throw "LibRaw : failed to run dcraw_make_mem_thumb";
}
// clean-up and return
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);
}
if(text != NULL) {
FreeImage_OutputMessageProc(s_format_id, text);
}
}
return NULL;
}
/**
Load raw data and convert to FIBITMAP
@param RawProcessor Libraw handle
@param bitspersample Output bitdepth (8- or 16-bit)
@return Returns the loaded dib if successfull, returns NULL otherwise
*/
static FIBITMAP *
libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) {
FIBITMAP *dib = NULL;
try {
// set decoding parameters
// -----------------------
// (-6) 16-bit or 8-bit
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;
} 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;
}
// (-W) Don't use automatic increase of brightness by histogram
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;
// (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD)
RawProcessor->imgdata.params.user_qual = 3;
// -----------------------
// unpack data
if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
throw "LibRaw : failed to unpack data";
}
// process data (... most consuming task ...)
if(RawProcessor->dcraw_process() != LIBRAW_SUCCESS) {
throw "LibRaw : failed to process data";
}
// retrieve processed image
dib = libraw_ConvertProcessedRawToDib(RawProcessor);
return dib;
} catch(const char *text) {
FreeImage_OutputMessageProc(s_format_id, text);
return NULL;
}
}
/**
Load the Bayer matrix (unprocessed raw data) as a FIT_UINT16 image.
Note that some formats don't have a Bayer matrix (e.g. Foveon, Canon sRAW, demosaiced DNG files).
@param RawProcessor Libraw handle
@return Returns the loaded dib if successfull, returns NULL otherwise
*/
static FIBITMAP *
libraw_LoadUnprocessedData(LibRaw *RawProcessor) {
FIBITMAP *dib = NULL;
try {
// unpack data
if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
throw "LibRaw : failed to unpack data";
}
// check for a supported Bayer format
if(!(RawProcessor->imgdata.idata.filters || RawProcessor->imgdata.idata.colors == 1)) {
throw "LibRaw : only Bayer-pattern RAW files are supported";
}
// allocate output dib
const unsigned width = RawProcessor->imgdata.sizes.raw_width;
const unsigned height = RawProcessor->imgdata.sizes.raw_height;
const size_t line_size = width * sizeof(WORD);
const WORD *src_bits = (WORD*)RawProcessor->imgdata.rawdata.raw_image;
if(src_bits) {
dib = FreeImage_AllocateT(FIT_UINT16, width, height);
}
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// retrieve the raw image
for(unsigned y = 0; y < height; y++) {
WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
memcpy(dst_bits, src_bits, line_size);
src_bits += width;
}
// store metadata needed for post-processing
{
char value[512];
const libraw_image_sizes_t *sizes = &RawProcessor->imgdata.sizes;
// image output width & height
{
sprintf(value, "%d", sizes->iwidth);
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Width", value);
sprintf(value, "%d", sizes->iheight);
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Height", value);
}
// image output frame
{
const unsigned f_left = sizes->left_margin;
const unsigned f_top = sizes->top_margin;
const unsigned f_width = sizes->width;
const unsigned f_height = sizes->height;
sprintf(value, "%d", f_left);
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Left", value);
sprintf(value, "%d", f_top);
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Top", value);
sprintf(value, "%d", f_width);
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Width", value);
sprintf(value, "%d", f_height);
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Height", value);
}
// Bayer pattern
// Mask describing the order of color pixels in the matrix.
// This field describe 16 pixels (8 rows with two pixels in each, from left to right and from top to bottom).
if(RawProcessor->imgdata.idata.filters) {
// description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG)
char *cdesc = RawProcessor->imgdata.idata.cdesc;
if(!cdesc[3]) {
cdesc[3] = 'G';
}
char *pattern = &value[0];
for(int i = 0; i < 16; i++) {
pattern[i] = cdesc[ RawProcessor->fcol(i >> 1, i & 1) ];
}
pattern[16] = 0;
FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.BayerPattern", value);
}
}
return dib;
} catch(const char *text) {
FreeImage_Unload(dib);
FreeImage_OutputMessageProc(s_format_id, text);
return NULL;
src/Source/FreeImage/PluginRAW.cpp view on Meta::CPAN
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsICCProfiles() {
return TRUE;
}
static BOOL DLL_CALLCONV
SupportsNoPixels() {
return TRUE;
}
// ----------------------------------------------------------
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
FIBITMAP *dib = NULL;
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);
// set decoding parameters
// the following parameters affect data reading
// --------------------------------------------
// (-s [0..N-1]) Select one raw image from input file
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;
// (-M) Use any color matrix from the camera metadata. This option only affects Olympus, Leaf, and Phase One cameras.
RawProcessor->imgdata.params.use_camera_matrix = 1;
// (-h) outputs the image in 50% size
RawProcessor->imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
// open the datastream
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);
}
else if((flags & RAW_UNPROCESSED) == RAW_UNPROCESSED) {
// load raw data without post-processing (i.e. as a Bayer matrix)
dib = libraw_LoadUnprocessedData(RawProcessor);
}
else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
// try to get the embedded JPEG
dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
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) {
// load raw data as 8-bit/sample (i.e. RGB 24-bit)
dib = libraw_LoadRawData(RawProcessor, 8);
}
else {
// default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit)
dib = libraw_LoadRawData(RawProcessor, 16);
}
// save ICC profile if present
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
if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) {
FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
if(metadata_dib) {
FreeImage_CloneMetadata(dib, metadata_dib);
FreeImage_Unload(metadata_dib);
}
}
// clean-up internal memory allocations
RawProcessor->recycle();
delete RawProcessor;
return dib;
} catch(const char *text) {
if(RawProcessor) {
RawProcessor->recycle();
delete RawProcessor;
}
if(dib) {
FreeImage_Unload(dib);
}
FreeImage_OutputMessageProc(s_format_id, text);
}
return NULL;
}
// ==========================================================
// Init
// ==========================================================
void DLL_CALLCONV
InitRAW(Plugin *plugin, int format_id) {
s_format_id = format_id;
( run in 0.452 second using v1.01-cache-2.11-cpan-ceb78f64989 )