Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginEXR.cpp view on Meta::CPAN
#include "../OpenEXR/IlmImf/ImfPreviewImage.h"
#include "../OpenEXR/Half/half.h"
// ==========================================================
// Plugin Interface
// ==========================================================
static int s_format_id;
// ----------------------------------------------------------
/**
FreeImage input stream wrapper
@see Imf_2_2::IStream
*/
class C_IStream : public Imf::IStream {
private:
FreeImageIO *_io;
fi_handle _handle;
public:
C_IStream (FreeImageIO *io, fi_handle handle) :
Imf::IStream(""), _io (io), _handle(handle) {
}
virtual bool read (char c[/*n*/], int n) {
return ((unsigned)n != _io->read_proc(c, 1, n, _handle));
}
virtual Imath::Int64 tellg() {
return _io->tell_proc(_handle);
}
virtual void seekg(Imath::Int64 pos) {
_io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
}
virtual void clear() {
}
};
// ----------------------------------------------------------
/**
FreeImage output stream wrapper
@see Imf_2_2::OStream
*/
class C_OStream : public Imf::OStream {
private:
FreeImageIO *_io;
fi_handle _handle;
public:
C_OStream (FreeImageIO *io, fi_handle handle) :
Imf::OStream(""), _io (io), _handle(handle) {
}
virtual void write(const char c[/*n*/], int n) {
if((unsigned)n != _io->write_proc((void*)&c[0], 1, n, _handle)) {
Iex::throwErrnoExc();
}
}
virtual Imath::Int64 tellp() {
return _io->tell_proc(_handle);
}
virtual void seekp(Imath::Int64 pos) {
_io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
}
};
// ----------------------------------------------------------
// ==========================================================
// Plugin Implementation
// ==========================================================
static const char * DLL_CALLCONV
Format() {
return "EXR";
}
static const char * DLL_CALLCONV
Description() {
return "ILM OpenEXR";
}
static const char * DLL_CALLCONV
Extension() {
return "exr";
}
static const char * DLL_CALLCONV
RegExpr() {
return NULL;
}
static const char * DLL_CALLCONV
MimeType() {
return "image/x-exr";
}
static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
BYTE exr_signature[] = { 0x76, 0x2F, 0x31, 0x01 };
BYTE signature[] = { 0, 0, 0, 0 };
io->read_proc(signature, 1, 4, handle);
return (memcmp(exr_signature, signature, 4) == 0);
}
static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
src/Source/FreeImage/PluginEXR.cpp view on Meta::CPAN
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;
( run in 0.758 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )