Hugh Macdonald wrote:
> Hi all,
>
> I'm kinda new to OpenEXR development - I've been trying a few things
> in the past couple of days, but am a little stuck on one thing at the
> moment...
>
> I need to look at each pixel in an image, so I'm reading the image
> into an Array2D<Rgba> using:
>
> -----------------------------------------------------
> const Box2i dataWindow = inFileHeader.dataWindow();
>
> int dataWidth = dataWindow.max.x - dataWindow.min.x + 1;
> int dataHeight = dataWindow.max.y - dataWindow.min.y + 1;
>
> Array2D<Rgba> pixels (dataHeight, dataWidth);
> inFile.setFrameBuffer (&pixels[0][0] - dataWindow.min.x -
> dataWindow.min.y * dataWidth, 1, dataWidth);
> inFile.readPixels (dataWindow.min.y, dataWindow.max.y);
> -----------------------------------------------------
As far as I can tell the code above is correct. It causes the
pixels to be stored in row-major order; each horizontal row of
pixels is contiguous in memory.
>
> I then (and I think that this is where I'm getting confused) look
> through the pixels with:
>
> -----------------------------------------------------
> for(x = 0; x < pixelsWidth; x++)
> {
> for(y = 0; y < pixelsHeight; y++)
> {
> int pixelAddr = y + (x * pixelsHeight);
> const Rgba *thisPixel = pixels[pixelAddr];
> cout << "At: " << x << "," << y << " (addr: " << pixelAddr << ")
> : "
> << thisPixel->r << "," << thisPixel->g << "," << thisPixel->b << ","
> << thisPixel->a << endl;
> }
> }
> -----------------------------------------------------
This part of the code is probably wrong. Assuming that pixelsWidth
and pixelsHeight are the same as dataWidth and dataHeight above,
the loop should look something like this:
for(x = 0; x < pixelsWidth; x++)
{
for(y = 0; y < pixelsHeight; y++)
{
const Rgba &thisPixel = pixels[y][x];
cout << thisPixel.r << ...
}
}
Or, if "pixels" in this loop is not the same Array2D as in the
file reading code above, but instead a pointer to the pixel in the
upper left corner of the dataWindow, then you may want to try this:
for(x = 0; x < pixelsWidth; x++)
{
for(y = 0; y < pixelsHeight; y++)
{
const Rgba *thisPixel = pixels + y * pixelsWidth + x;
cout << thisPixel->r << ...
}
}
Your loop traverses the image in column-major order. If you are
concerned about speed, you may want to switch to traversing in
row-major order by nesting the "for x" loop inside the "for y"
loop. Row-major order is potentially faster because you get
better cache coherence.
>
> The image I'm testing this on is a grad, and looking at the printout
> of the colour values, I can tell that the addressing is going in y,
> starting from the top left. However, when it gets to the bottom left
> of the image, I get some erroneous pixel values before the whole
> program seg faults.
>
> Any ideas? Please tell me I'm being an idiot somewhere along the line....
>
> Any suggestions more than welcome!
>