I have having difficult working out the correct stride logic to write one scanline at a time to an OpenEXR file.
The example code shows write the entire array in memory but I only have access to a single scanline at a time.
I want to minimize the memory usage by not storing the entire image before writing.
Here is the code.
Thanks in advance.
#include <stdio.h>
#include <string>
#include <OpenEXR/ImfOutputFile.h>
#include <OpenEXR/ImfArray.h>
#include <OpenEXR/ImfCompression.h>
#include <OpenEXR/ImfChannelList.h>
#include <OpenEXR/ImfRgba.h>
// This is currently NOT working but would be a useful example to have
void writeIncrementalScanline (const std::string& fileName,
int width,
int height)
{
float pixelAspectRatio = 1;
const Imath::V2f screenWindowCenter = Imath::V2f (0, 0);
float screenWindowWidth = 1;
Imf::LineOrder lineOrder = Imf::INCREASING_Y;
Imf::Compression compression = Imf::ZIPS_COMPRESSION;
Imf::Header header(width, height,
pixelAspectRatio,
screenWindowCenter,
screenWindowWidth,
lineOrder,
compression);
header.channels().insert("rgba.R",Imf::Channel(Imf::HALF));
header.channels().insert("rgba.G",Imf::Channel(Imf::HALF));
header.channels().insert("rgba.B",Imf::Channel(Imf::HALF));
header.channels().insert("rgba.A",Imf::Channel(Imf::HALF));
Imf::OutputFile file (fileName.c_str(), header);
Imf::FrameBuffer framebuffer;
Imf::Array2D<half> redBuffer(width,1);
Imf::Array2D<half> greenBuffer(width,1);
Imf::Array2D<half> blueBuffer(width,1);
Imf::Array2D<half> alphaBuffer(width,1);
half colorChannelGreyScaleDelta = 1.0f/float(height-1);
std::cout << "colorChannelGreyScaleDelta = " << colorChannelGreyScaleDelta << std::endl;
std::cout << "height * colorChannelGreyScaleDelta = " << height * colorChannelGreyScaleDelta << std::endl;
size_t xStride = sizeof(half) * 1;
size_t yStride = width;
const half *redPixels = &redBuffer[0][0];
const half *greenPixels = &greenBuffer[0][0];
const half *bluePixels = &blueBuffer[0][0];
const half *alphaPixels = &alphaBuffer[0][0];
framebuffer.insert("rgba.R",
Imf::Slice(Imf::HALF,
(char *)redPixels,
xStride,
yStride));
framebuffer.insert("rgba.G",
Imf::Slice(Imf::HALF,
(char *)greenPixels,
xStride,
yStride));
framebuffer.insert("rgba.B",
Imf::Slice(Imf::HALF,
(char *)bluePixels,
xStride,
yStride));
framebuffer.insert("rgba.A",
Imf::Slice(Imf::HALF,
(char *)alphaPixels,
xStride,
yStride));
for (int h=0;h<height;h++)
{
half grey_scale_value = colorChannelGreyScaleDelta * h;
for (int w=0;w<width;w++)
{
redBuffer[w][0] = 1.;//grey_scale_value;
greenBuffer[w][0] = 1.;//grey_scale_value;
blueBuffer[w][0] = 1.;//grey_scale_value;
alphaBuffer[w][0] = 1.;
}
file.setFrameBuffer(framebuffer);
file.writePixels();
}
}
int main()
{
const std::string fileName("IncrementalScanline.exr");
const int width = 256;
const int height = 512;
writeIncrementalScanline (fileName, width, height);
return 0;
}