Re: [Openexr-devel] OpenEXR Data Channel Configurations
From:
Paul Schneider
Subject:
Re: [Openexr-devel] OpenEXR Data Channel Configurations
Date:
Fri, 19 Nov 2004 16:22:50 -0800
In case people are still interested, here's a very simple program that reads in all of the channels of an OpenEXR file. Once the channels are in memory, you could do just about anything with them; this program just writes them out to a new file. You can use "diff" or similar to verify that the new file is identical to the old one, and therefore all of the file's contents must have been read (I reuse the header from the input file to preserve attributes and compression type).
Note that the "SliceAndStorage" class is just a very simple class for managing pixel storage, that reuses much of the OpenEXR code. In a real application, you would almost certainly manage your pixel storage in a more sophisticated way.
- Paul
//-----------------------------------------------------------------------------
// deepexample.cpp
//
// A simple example program that demonstrates how to read OpenEXR files
// with arbitrary channels and channel types. This example does not
// demonstrate use of the tiled API.
//
// Written by Paul Schneider - 11/15/2004
//-----------------------------------------------------------------------------
// To build on a unix-like system:
// CC deepexample.cpp -o deepexample -I/usr/local/include/OpenEXR -L/usr/local/lib -lHalf -lIex -lImath -lIlmImf -lz
using std::cout;
using std::cerr;
using std::endl;
//-----------------------------------------------------------------------------
// SliceAndStorage
//-----------------------------------------------------------------------------
// The simplest example of an image "slice". This class manages storage
// for the pixels in the slice; pixels are stored tightly packed.
class SliceAndStorage
{
public:
SliceAndStorage (PixelType type, int w, int h, int size,
int xSampling, int ySampling);
~SliceAndStorage ();
//-----------------------------------------------------------------------------
// SliceAndStorage
//-----------------------------------------------------------------------------
// allocate enough storage for the pixels in this slice, and construct
// an Imf::Slice that points to the storage.
SliceAndStorage::SliceAndStorage (PixelType type, int w, int h, int size,
int xSampling, int ySampling)
:
_storage (new char [w * h * size]), // pixel storage
_slice (type, // type
_storage, // base
size, // x stride
w * size, // y stride
xSampling, // x sampling
ySampling) // y sampling
{
// nothing
}
//-----------------------------------------------------------------------------
// ~SliceAndStorage
//-----------------------------------------------------------------------------
// delete the pixel storage
//-----------------------------------------------------------------------------
// SliceAndStorage::slice
//-----------------------------------------------------------------------------
// access to the Imf::slice
//-----------------------------------------------------------------------------
// pixelTypeSize
//-----------------------------------------------------------------------------
// return the size, in bytes, of a pixel of type pixelType
static int
pixelTypeSize (PixelType pixelType)
{
switch (pixelType)
{
case HALF: return 2; break;
case FLOAT: return 4; break;
case UINT: return 4; break;
}
//-----------------------------------------------------------------------------
// processFile
//-----------------------------------------------------------------------------
// Basic strategy:
//
// - examine the given OpenEXR file
// - construct slices for each channel
// - read all of the channels into the storage
// - write the pixels back out to a new file
//
// the original file and the new file can be compared using "diff"
// or a similar utility to ensure that the pixels were read
// and written correctly.
// for each channel in the input file, insert a "slice" into the
// framebuffer to store that channel's pixels.
for (ChannelList::ConstIterator i = channelList.begin();
i != channelList.end(); ++i)
{
const Channel& c = i.channel(); // channel
int s = pixelTypeSize (c.type); // size of a pixel in bytes
int w = (dw.max.x - dw.min.x + 1); // width of the slice
int h = (dw.max.y - dw.min.y + 1); // height of the slice
// take subsampling into account - we only need storage for
// the pixels for which we have samples
w /= c.xSampling;
h /= c.ySampling;
// store this slice so we can properly dispose of it when we're done
slices.push_back (new SliceAndStorage (c.type, w, h, s, c.xSampling, c.ySampling));
// add the slice to our framebuffer
fb.insert (i.name(), slices.back()->slice());
}
// tell the input file to read pixels into our framebuffer
for (int i = 0; i < slices.size(); ++i)
{
delete slices[i];
}
}
//-----------------------------------------------------------------------------
// main
//-----------------------------------------------------------------------------
// process specified OpenEXR files