Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginEXR.cpp view on Meta::CPAN
dst_line -= dstPitch;
}
FreeImage_SetThumbnail(dib, thumbnail);
FreeImage_Unload(thumbnail);
}
}
if(header_only) {
// header only mode
return dib;
}
// load pixels
// --------------------------------------------------------------
const BYTE *bits = FreeImage_GetBits(dib); // pointer to our pixel buffer
const size_t bytespp = sizeof(float) * components; // size of our pixel in bytes
const unsigned pitch = FreeImage_GetPitch(dib); // size of our yStride in bytes
Imf::PixelType pixelType = Imf::FLOAT; // load as float data type;
if(bUseRgbaInterface) {
// use the RGBA interface (used when loading RY BY Y images )
const int chunk_size = 16;
BYTE *scanline = (BYTE*)bits;
// re-open using the RGBA interface
io->seek_proc(handle, stream_start, SEEK_SET);
Imf::RgbaInputFile rgbaFile(istream);
// read the file in chunks
Imath::Box2i dw = dataWindow;
Imf::Array2D<Imf::Rgba> chunk(chunk_size, width);
while (dw.min.y <= dw.max.y) {
// read a chunk
rgbaFile.setFrameBuffer (&chunk[0][0] - dw.min.x - dw.min.y * width, 1, width);
rgbaFile.readPixels (dw.min.y, MIN(dw.min.y + chunk_size - 1, dw.max.y));
// fill the dib
const int y_max = ((dw.max.y - dw.min.y) <= chunk_size) ? (dw.max.y - dw.min.y) : chunk_size;
for(int y = 0; y < y_max; y++) {
FIRGBF *pixel = (FIRGBF*)scanline;
const Imf::Rgba *half_rgba = chunk[y];
for(int x = 0; x < width; x++) {
// convert from half to float
pixel[x].red = half_rgba[x].r;
pixel[x].green = half_rgba[x].g;
pixel[x].blue = half_rgba[x].b;
}
// next line
scanline += pitch;
}
// next chunk
dw.min.y += chunk_size;
}
} else {
// use the low level interface
// build a frame buffer (i.e. what we want on output)
Imf::FrameBuffer frameBuffer;
// allow dataWindow with minimal bounds different form zero
size_t offset = - dataWindow.min.x * bytespp - dataWindow.min.y * pitch;
if(components == 1) {
frameBuffer.insert ("Y", // name
Imf::Slice (pixelType, // type
(char*)(bits + offset), // base
bytespp, // xStride
pitch, // yStride
1, 1, // x/y sampling
0.0)); // fillValue
} else if((components == 3) || (components == 4)) {
const char *channel_name[4] = { "R", "G", "B", "A" };
for(int c = 0; c < components; c++) {
frameBuffer.insert (
channel_name[c], // name
Imf::Slice (pixelType, // type
(char*)(bits + c * sizeof(float) + offset), // base
bytespp, // xStride
pitch, // yStride
1, 1, // x/y sampling
0.0)); // fillValue
}
}
// read the file
file.setFrameBuffer(frameBuffer);
file.readPixels(dataWindow.min.y, dataWindow.max.y);
}
// lastly, flip dib lines
FreeImage_FlipVertical(dib);
}
catch(Iex::BaseExc & e) {
if(dib != NULL) {
FreeImage_Unload(dib);
}
FreeImage_OutputMessageProc(s_format_id, e.what());
return NULL;
}
return dib;
}
/**
Set the preview image using the dib embedded thumbnail
*/
static BOOL
SetPreviewImage(FIBITMAP *dib, Imf::Header& header) {
if(!FreeImage_GetThumbnail(dib)) {
return FALSE;
}
FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib);
if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 32)) {
// invalid thumbnail - ignore it
FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL);
} else {
const unsigned thWidth = FreeImage_GetWidth(thumbnail);
const unsigned thHeight = FreeImage_GetHeight(thumbnail);
Imf::PreviewImage preview(thWidth, thHeight);
// copy thumbnail to 32-bit RGBA preview image
const BYTE* src_line = FreeImage_GetScanLine(thumbnail, thHeight - 1);
Imf::PreviewRgba* dst_line = preview.pixels();
const unsigned srcPitch = FreeImage_GetPitch(thumbnail);
for (unsigned y = 0; y < thHeight; y++) {
const RGBQUAD* src_pixel = (RGBQUAD*)src_line;
Imf::PreviewRgba* dst_pixel = dst_line;
for(unsigned x = 0; x < thWidth; x++) {
dst_pixel->r = src_pixel->rgbRed;
dst_pixel->g = src_pixel->rgbGreen;
dst_pixel->b = src_pixel->rgbBlue;
dst_pixel->a = src_pixel->rgbReserved;
src_pixel++;
dst_pixel++;
}
src_line -= srcPitch;
dst_line += thWidth;
}
src/Source/FreeImage/PluginEXR.cpp view on Meta::CPAN
// default value
compress = Imf::PIZ_COMPRESSION;
}
// create the header
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
int dx = 0, dy = 0;
Imath::Box2i dataWindow (Imath::V2i (0, 0), Imath::V2i (width - 1, height - 1));
Imath::Box2i displayWindow (Imath::V2i (-dx, -dy), Imath::V2i (width - dx - 1, height - dy - 1));
Imf::Header header = Imf::Header(displayWindow, dataWindow, 1,
Imath::V2f(0,0), 1,
Imf::INCREASING_Y, compress);
// handle thumbnail
SetPreviewImage(dib, header);
// check for EXR_LC compression
if((flags & EXR_LC) == EXR_LC) {
return SaveAsEXR_LC(ostream, dib, header, width, height);
}
// output pixel type
Imf::PixelType pixelType;
if((flags & EXR_FLOAT) == EXR_FLOAT) {
pixelType = Imf::FLOAT; // save as float data type
} else {
// default value
pixelType = Imf::HALF; // save as half data type
}
// check the data type and number of channels
int components = 0;
FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
switch(image_type) {
case FIT_FLOAT:
components = 1;
// insert luminance channel
header.channels().insert ("Y", Imf::Channel(pixelType));
break;
case FIT_RGBF:
components = 3;
for(int c = 0; c < components; c++) {
// insert R, G and B channels
header.channels().insert (channel_name[c], Imf::Channel(pixelType));
}
break;
case FIT_RGBAF:
components = 4;
for(int c = 0; c < components; c++) {
// insert R, G, B and A channels
header.channels().insert (channel_name[c], Imf::Channel(pixelType));
}
break;
default:
THROW (Iex::ArgExc, "Cannot save: invalid data type.\nConvert the image to float before saving as OpenEXR.");
}
// build a frame buffer (i.e. what we have on input)
Imf::FrameBuffer frameBuffer;
BYTE *bits = NULL; // pointer to our pixel buffer
size_t bytespp = 0; // size of our pixel in bytes
size_t bytespc = 0; // size of our pixel component in bytes
unsigned pitch = 0; // size of our yStride in bytes
if(pixelType == Imf::HALF) {
// convert from float to half
halfData = new(std::nothrow) half[width * height * components];
if(!halfData) {
THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);
}
for(int y = 0; y < height; y++) {
float *src_bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
half *dst_bits = halfData + y * width * components;
for(int x = 0; x < width; x++) {
for(int c = 0; c < components; c++) {
dst_bits[c] = src_bits[c];
}
src_bits += components;
dst_bits += components;
}
}
bits = (BYTE*)halfData;
bytespc = sizeof(half);
bytespp = sizeof(half) * components;
pitch = sizeof(half) * width * components;
} else if(pixelType == Imf::FLOAT) {
// invert dib scanlines
bIsFlipped = FreeImage_FlipVertical(dib);
bits = FreeImage_GetBits(dib);
bytespc = sizeof(float);
bytespp = sizeof(float) * components;
pitch = FreeImage_GetPitch(dib);
}
if(image_type == FIT_FLOAT) {
frameBuffer.insert ("Y", // name
Imf::Slice (pixelType, // type
(char*)(bits), // base
bytespp, // xStride
pitch)); // yStride
} else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) {
for(int c = 0; c < components; c++) {
char *channel_base = (char*)(bits) + c*bytespc;
frameBuffer.insert (channel_name[c],// name
Imf::Slice (pixelType, // type
channel_base, // base
bytespp, // xStride
pitch)); // yStride
}
}
// write the data
Imf::OutputFile file (ostream, header);
file.setFrameBuffer (frameBuffer);
file.writePixels (height);
if(halfData != NULL) {
delete[] halfData;
}
if(bIsFlipped) {
// invert dib scanlines
FreeImage_FlipVertical(dib);
}
return TRUE;
} catch(Iex::BaseExc & e) {
if(halfData != NULL) {
delete[] halfData;
}
if(bIsFlipped) {
// invert dib scanlines
FreeImage_FlipVertical(dib);
}
FreeImage_OutputMessageProc(s_format_id, e.what());
return FALSE;
}
}
// ==========================================================
// Init
// ==========================================================
void DLL_CALLCONV
InitEXR(Plugin *plugin, int format_id) {
s_format_id = format_id;
// initialize the OpenEXR library
// note that this OpenEXR function produce so called "false memory leaks"
// see http://lists.nongnu.org/archive/html/openexr-devel/2013-11/msg00000.html
Imf::staticInitialize();
plugin->format_proc = Format;
plugin->description_proc = Description;
plugin->extension_proc = Extension;
plugin->regexpr_proc = RegExpr;
plugin->open_proc = NULL;
plugin->close_proc = NULL;
plugin->pagecount_proc = NULL;
plugin->pagecapability_proc = NULL;
plugin->load_proc = Load;
plugin->save_proc = Save;
plugin->validate_proc = Validate;
plugin->mime_proc = MimeType;
plugin->supports_export_bpp_proc = SupportsExportDepth;
plugin->supports_export_type_proc = SupportsExportType;
plugin->supports_icc_profiles_proc = NULL;
plugin->supports_no_pixels_proc = SupportsNoPixels;
}
( run in 0.723 second using v1.01-cache-2.11-cpan-df04353d9ac )