|
Packit Service |
6754ca |
The IlmImfUtil Library
|
|
Packit Service |
6754ca |
----------------------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
The IlmImfUtil library implements an in-memory image data structure, as
|
|
Packit Service |
6754ca |
well as simple function calls for saving images in OpenEXR files, and for
|
|
Packit Service |
6754ca |
constructing images from the contents of existing OpenEXR files.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
The OpenEXR file format has a fairly large number of options for on-file
|
|
Packit Service |
6754ca |
image storage, including arbitrary sets of channels, per-channel pixel
|
|
Packit Service |
6754ca |
format selection, sub-sampled channels, multi-resolution images, deep
|
|
Packit Service |
6754ca |
images, or storing images as tiles or scan lines. While reading a simple
|
|
Packit Service |
6754ca |
RGBA image does not require a lot of code, reading the contents of an
|
|
Packit Service |
6754ca |
arbitrary OpenEXR file, and representing those contents in main memory
|
|
Packit Service |
6754ca |
is not trivial. The IlmImfUtil library simplifies those tasks.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Image, Image Level, Image Channel
|
|
Packit Service |
6754ca |
---------------------------------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
An image (class Image) is a container for a set of image levels (class
|
|
Packit Service |
6754ca |
ImageLevel), and an image level is a container for a set of image channels
|
|
Packit Service |
6754ca |
(class ImageChannel). An image channel contains an array of pixel values.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
For example:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
image --+-- level 0,0 --+-- channel "R" --- pixel data
|
|
Packit Service |
6754ca |
| |
|
|
Packit Service |
6754ca |
| +-- channel "G" --- pixel data
|
|
Packit Service |
6754ca |
| |
|
|
Packit Service |
6754ca |
| +-- channel "B" --- pixel data
|
|
Packit Service |
6754ca |
|
|
|
Packit Service |
6754ca |
+-- level 1,1 --+-- channel "R" --- pixel data
|
|
Packit Service |
6754ca |
| |
|
|
Packit Service |
6754ca |
| +-- channel "G" --- pixel data
|
|
Packit Service |
6754ca |
| |
|
|
Packit Service |
6754ca |
| +-- channel "B" --- pixel data
|
|
Packit Service |
6754ca |
|
|
|
Packit Service |
6754ca |
+-- level 2,2 --+-- channel "R" --- pixel data
|
|
Packit Service |
6754ca |
|
|
|
Packit Service |
6754ca |
+-- channel "G" --- pixel data
|
|
Packit Service |
6754ca |
|
|
|
Packit Service |
6754ca |
+-- channel "B" --- pixel data
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
An image has a level mode (enum LevelMode), which can be ONE_LEVEL,
|
|
Packit Service |
6754ca |
MIPMAP_LEVELS or RIPMAP_LEVELS. A ONE_LEVEL image contains only a single
|
|
Packit Service |
6754ca |
level, but a multi-resolution image, that is, one with level mode set to
|
|
Packit Service |
6754ca |
MIPMAP_LEVELS or RIPMAP_LEVELS, contains multiple levels. The levels are
|
|
Packit Service |
6754ca |
analogous to the levels in an OpenEXR file, as described in the "Technical
|
|
Packit Service |
6754ca |
Introduction to OpenEXR" document.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Levels are indexed by a pairs of level numbers. Level (0,0) contains the
|
|
Packit Service |
6754ca |
highest-resolution version of the image; level (lx,ly) contains an image
|
|
Packit Service |
6754ca |
whose resolution is reduced in x and y by a factor of 2^lx and 2^ly
|
|
Packit Service |
6754ca |
respectively. The level has a data window that indicates the range of
|
|
Packit Service |
6754ca |
x and y for which pixel data are stored in the level.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
All levels in an image have the same set of image channels.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
An image channel has a name (e.g. "R", "Z", or "xVelocity"), a type (HALF,
|
|
Packit Service |
6754ca |
FLOAT or UINT) and x and y sampling rates. A channel stores samples for
|
|
Packit Service |
6754ca |
a pixel if the pixel is inside the data window of the level to which the
|
|
Packit Service |
6754ca |
channel belongs, and the x and y coordinates of the pixel are divisible by
|
|
Packit Service |
6754ca |
the x and y sampling rates of the channel.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
An image can be either flat or deep. In a flat image each channel in each
|
|
Packit Service |
6754ca |
level stores at most one value per pixel. In a deep image each channel in
|
|
Packit Service |
6754ca |
each level stores an arbitrary number of values per pixel. As an exception,
|
|
Packit Service |
6754ca |
each level of a deep image has a sample count channel with a single value
|
|
Packit Service |
6754ca |
per pixel; this value determines how many values each of the other channels
|
|
Packit Service |
6754ca |
in the same level has at the same pixel location.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
The Image, ImageLevel and ImageChannel classes are abstact base classes.
|
|
Packit Service |
6754ca |
Two sets of classes, one for flat images and one for deep images, are
|
|
Packit Service |
6754ca |
derived from the base classes. The FlatImageChannel and DeepImageChannel
|
|
Packit Service |
6754ca |
classes, derived from ImageChannel, are themselves base classes for the
|
|
Packit Service |
6754ca |
templates TypedFlatImageChannel<T> and TypedDeepImageChannel<T>:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Image -> FlatImage
|
|
Packit Service |
6754ca |
-> DeepImage
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
ImageLevel -> FlatImageLevel
|
|
Packit Service |
6754ca |
-> DeepImageLevel
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
ImageChannel -> FlatImageChannel -> TypedFlatImageChannel<T>
|
|
Packit Service |
6754ca |
-> DeepImageChannel -> TypedDeepImageChannel<T>
|
|
Packit Service |
6754ca |
-> SampleCountChannel
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Channel objects of type TypedFlatImageChannel<T> and TypedDeepImageChannel<T>
|
|
Packit Service |
6754ca |
contain pixel values of type T, where T is either half, float or unsigned int.
|
|
Packit Service |
6754ca |
For convenience, the following typedefs are provided:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
typedef TypedFlatImageChannel<half> FlatHalfChannel;
|
|
Packit Service |
6754ca |
typedef TypedFlatImageChannel<float> FlatFloatChannel;
|
|
Packit Service |
6754ca |
typedef TypedFlatImageChannel<unsigned int> FlatUIntChannel;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
typedef TypedDeepImageChannel<half> DeepHalfChannel;
|
|
Packit Service |
6754ca |
typedef TypedDeepImageChannel<float> DeepFloatChannel;
|
|
Packit Service |
6754ca |
typedef TypedDeepImageChannel<unsigned int> DeepUIntChannel;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
File I/O
|
|
Packit Service |
6754ca |
--------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
An Image object can be saved in an OpenEXR file with a single function call:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
saveImage ("foo.exr", myImage);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
The saveImage() function automatically creates a flat or a deep image file,
|
|
Packit Service |
6754ca |
depending on the type of the image. All channels and all image levels will
|
|
Packit Service |
6754ca |
be saved in the file.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Optionally an OpenEXR Header object can be passed to the saveImage() function;
|
|
Packit Service |
6754ca |
this allows application code save custom attributes in the file, and to control
|
|
Packit Service |
6754ca |
how the file will be compressed:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Header myHeader;
|
|
Packit Service |
6754ca |
myHeader.compression() = PIZ_COMPRESSION;
|
|
Packit Service |
6754ca |
myHeader.pixelAspectRatio() = 1.5;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
saveImage ("foo.exr", myHeader, myImage);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Loading an image from an OpenEXR file also requires only one function call,
|
|
Packit Service |
6754ca |
either
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Image* myImage = loadImage ("foo.exr");
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
or
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Header myHeader;
|
|
Packit Service |
6754ca |
Image* myImage = loadImage ("foo.exr", myHeader);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
The application owns the image that is returned by the loadImage() call.
|
|
Packit Service |
6754ca |
It is the application's responsibility to delete the Image object.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
The IlmImfUtil library also provides versions of the saveImage() and
|
|
Packit Service |
6754ca |
loadImage() functions that work only on flat images or only on deep images:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
saveFlatImage()
|
|
Packit Service |
6754ca |
saveFlatScanLineImage()
|
|
Packit Service |
6754ca |
saveFlatTiledImage()
|
|
Packit Service |
6754ca |
saveDeepImage()
|
|
Packit Service |
6754ca |
saveDeepScanLineImage()
|
|
Packit Service |
6754ca |
saveDeepTiledImage()
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
For details the the ImfFlatImageIO.h and ImfDeepImageIO.h header files.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Manipulating Images in Memory
|
|
Packit Service |
6754ca |
-----------------------------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Creating a mip-mapped flat image with two channels:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
FlatImage fimg (Box2i (V2i (0, 0), V2i (255, 255)), // data window
|
|
Packit Service |
6754ca |
MIPMAP_LEVELS); // level mode
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
fimg.insertChannel ("R", HALF);
|
|
Packit Service |
6754ca |
fimg.insertChannel ("Z", FLOAT);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Creating a single-level deep image:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
DeepImage dimg (Box2i (V2i (0, 0), V2i (255, 255)), // data window
|
|
Packit Service |
6754ca |
ONE_LEVEL); // level mode
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
dimg.insertChannel ("R", HALF);
|
|
Packit Service |
6754ca |
dimg.insertChannel ("Z", FLOAT);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Reading and writing pixels in level (2,2) of the mip-mapped flat image
|
|
Packit Service |
6754ca |
(note: a mip-mapped image contains only levels where the x and y level
|
|
Packit Service |
6754ca |
numbers are equal. For convenience, mip-map levels can be addressed
|
|
Packit Service |
6754ca |
using a single level number):
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
FlatImageLevel &level = fimg.level (2);
|
|
Packit Service |
6754ca |
FlatHalfChannel &R = level.typedChannel<half> ("R);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
half r1 = R.at (20, 15); // read pixel (20,15), with bounds checking
|
|
Packit Service |
6754ca |
// (exception for access outside data window)
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
half r2 = R (17, 4); // read pixel (17,4) without bounds checking
|
|
Packit Service |
6754ca |
// faster, but crashes for access outside
|
|
Packit Service |
6754ca |
// data window
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
R.at (20, 15) = 2 * r1; // change pixel value, with and
|
|
Packit Service |
6754ca |
R (17, 4) = 2 * r2; // without bounds checking
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Reading and writing pixels in the single-level deep image:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
DeepImageLevel &level = dimg.level();
|
|
Packit Service |
6754ca |
DeepHalfChannel &R = level.typedChannel<half> ("R);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
// with bounds checking
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
unsigned int n1 = R.sampleCounts().at (20, 15);
|
|
Packit Service |
6754ca |
half r1;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
if (n1 > 0)
|
|
Packit Service |
6754ca |
r1 = R.at(20, 15)[n1 - 1]; // read the last sample in pixel (20,15)
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
// without bounds checking
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
unsigned int n2 = R.sampleCounts()(20, 15);
|
|
Packit Service |
6754ca |
half r2;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
if (n > 0)
|
|
Packit Service |
6754ca |
r2 = R(17, 4)[n2 - 1]; // read the last sample in pixel (17,4)
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
// change the value of an existing sample
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
if (n1 > 0)
|
|
Packit Service |
6754ca |
R(20,15)[n1 - 1] = r1 * 2;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
// append a new sample to a pixel and set the sample to 3.0
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
R.sampleCounts().set (20, 15, n1 + 1);
|
|
Packit Service |
6754ca |
R.(20, 15)[n1] = 3.0;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
In addition to functions for reading and writing individual pixels, there
|
|
Packit Service |
6754ca |
are functions for accessing a whole row of pixels with a single function
|
|
Packit Service |
6754ca |
call. For details see the ImfFlatImageChannel.h, ImfDeepImageChannel.h
|
|
Packit Service |
6754ca |
and ImfSampleCountChannel.h header files in the IlmImf library:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
T* TypedFlatImageChannel<T>::row (int r);
|
|
Packit Service |
6754ca |
const T* TypedFlatImageChannel<T>::row (int r) const;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
T * const * TypedDeepImageChannel<T>::row (int r);
|
|
Packit Service |
6754ca |
const T * const * TypedDeepImageChannel<T>::row (int r) const;
|
|
Packit Service |
6754ca |
const unsigned int * SampleCountChannel::row (int r) const;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
To change the number of samples in all pixels in one row of a deep image
|
|
Packit Service |
6754ca |
level, use:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
void SampleCountChannel::set (int r, unsigned int newNumSamples[]);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Use an Edit object to temporarily make all sample counts in a deep image
|
|
Packit Service |
6754ca |
level editable:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
class SampleCountChannel::Edit;
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Miscellaneous Functions:
|
|
Packit Service |
6754ca |
------------------------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Change the data window and the level mode of an image (pixel data are not
|
|
Packit Service |
6754ca |
preserved across the call):
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
void Image::resize (const Box2i &dataWindow, LevelMode levelMode);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Shift the data window in x and y; shift the pixels along with the data window:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
void Image::shiftPixels (int dx, int dy);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Erase a channel, rename a channel, rename multiple channels at the same time:
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
void Image::eraseChannel (const string &name);
|
|
Packit Service |
6754ca |
void Image::renameChannel (const string &oldName, const string &newName);
|
|
Packit Service |
6754ca |
void Image::renameChannels (const RenamingMap &oldToNewNames);
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Missing Functionality:
|
|
Packit Service |
6754ca |
----------------------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
At this point, the IlmImfUtil library cannot read or write multi-part
|
|
Packit Service |
6754ca |
files. A future version of the library should probably define a new class
|
|
Packit Service |
6754ca |
MultiPartImage that contains a set of regular images. The library should
|
|
Packit Service |
6754ca |
also define corresponding loadMultiPartImage() and saveMultiPartImage()
|
|
Packit Service |
6754ca |
functions.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
Sample Code
|
|
Packit Service |
6754ca |
-----------
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
See the exrsave, exrmakescanlines, exrclip utilities.
|
|
Packit Service |
6754ca |
|
|
Packit Service |
6754ca |
|