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 )