in my application I have the need to read EXR files and split them up into layers and channels.
I'm currently using OpenExr-1.6.1 on Linux (64 bit).
Therefore I open the file, read the header (dimensions and channels) and iterate over all channels mentioned there. For each channel I create a memory area where the data should be put upon reading the content. This memory area is added to the framebuffer.
These two make the application crash. It seems that memory gets heavily corrupted.
#include "Iex.h"
#include "ImfInputFile.h"
#include "ImfHeader.h"
#include "ImfChannelList.h"
#include "ImfFrameBuffer.h"
#include <stdexcept>
#include <vector>
namespace {
/*!
* \brief Determines the number of bytes we need to store a pixel of type \c n_type
*
* \return 0 on error, a value > 0 otherwise
*/
unsigned char getPixelSize(Imf::PixelType n_type) {
switch (n_type) {
case Imf::UINT:
return sizeof(unsigned int);
case Imf::HALF:
return 2; // per definition, a Half is a 16 bit float value
case Imf::FLOAT:
return sizeof(float);
}
return 0;
}
}
int main(int argc, char** argv) {
Imf::InputFile f(argv[1]);
if (!f.isComplete()) {
throw std::runtime_error("File not complete");
}
const Imf::Header& hdr = f.header();
Imath::Box2i sz = hdr.dataWindow();
size_t width = sz.max.x - sz.min.x + 1;
size_t height = sz.max.y - sz.min.y + 1;
std::vector<char*> buffers; // to free them later
Imf::FrameBuffer frameBuffer;
const Imf::ChannelList& channels(hdr.channels()); // all the channels
// get all the channels, allocate data for the buffer and create a slice within the FrameBuffer
for (Imf::ChannelList::ConstIterator channel = channels.begin(); channel != channels.end(); ++channel) {
// XXX: use an auto_ptr here and put it into a Boost Pointer Container
char *tmpBuf = new char[width * height * getPixelSize(channel.channel().type) * 2];
buffers.push_back(tmpBuf);
// calculate the address of pixel (0,0)
char *base = tmpBuf + (getPixelSize(channel.channel().type) * (sz.min.x - sz.min.y * width));
// create a Slice in the Framebuffer
Imf::Slice(
channel.channel().type,
base,
getPixelSize(channel.channel().type),
getPixelSize(channel.channel().type) * width, channel.channel().xSampling, channel.channel().ySampling, 0.0));
}
f.setFrameBuffer(frameBuffer);
f.readPixels(sz.min.y, sz.max.y);
for (std::vector<char*>::iterator i = buffers.begin(); i != buffers.end(); ++i) {
std::cerr << "Free buffer at: " << (void*) *i << std::endl;
delete *i;
}
return 0;
}