The question is what happens when an image that has different "data" and
"display" windows is output to an image file type that does not support that
concept. Does it write the pixels (data) as the whole image and lose the
metadata about the display window, or does it consider the display window
sacrosanct and crop and/or pad the pixel data to conform? And at what level of
abstraction should this logic live?
OK, here is what I hope will be the final word on the matter:
I think that high-level classes and apps that deal with the level of
abstraction of entire images (e.g., ImageBuf, oiiotool) ought to provide simple
API commands and facilities that will crop/pad the data to match the display
window. I can accept that this should perhaps be the default behavior when
outputting to a file format that doesn't support the distinction.
But I think that low-level ImageOutput (individual format writers) should write
precisely the pixels they get from the app; no more, no less. I have two
reasons for this:
1. Philosophical: This level of abstraction is meant to hide the details of
individual format library APIs (TIFFfoo() versus JPEGbar() versus ImfBlah()),
but is not supposed to abstract entire images or their semantics. In other
words, an app hands a pile of pixels to an ImageOutput, and expects those
pixels to be written, without being overly clever.
2. Practical: Consider briefly the logistics of handling this automatically in
an ImageOutput. Let's say the display window is (0,0)-(1023,1023), the data
window is (3,3)-(34,34), and the image is tiled with 16x16 tiles. Now, from the
app's point of view, it needs to call write_tile() four times, once for each
tile, which are by definition always aligned to the data window. Upon the
first write_tile() call, what does the ImageOutput do? Well, if it is to pad
automatically, then the output image's tiles start at 0, not at 3, so it needs
to "re-tile" on the fly -- what it really needs to do is split that "app tile"
appropriately to the 4 "output tiles", 3 of which can't be output then, since
they overlap with other app tiles not yet received, so the ImageOutput would
have to buffer those pending tiles, ugh. Basically, it's a nightmare, would
make hard-to-follow (and probably buggy) code, and have a lot of the tricky
bits replicated across many different ImageOutput subclass
es. No way.
So, to recap, the only practicable solution I see is:
a) ImageOutputs write pixels they are sent, as they currently do (no change
needed).
b) But the ImageOutput::supports() method can be extended to allow the app to
query if the image format supports separate display/data windows. Proposed
syntax: supports("displaywindow")
c) Add a simple, single utility function to handle the auto crop/pad:
ImageBufAlgo::FixToDisplayWindow (ImageBuf &img, const std::string
&format)
If the named format does not support display windows (or unconditionally, if
format == ""),
pad and/or crop the image so that its pixel data window exactly fills the
display window.
Padding is black, unless img's ImageSpec contains metadata
"oiio:bordercolor"
(of type float[nchans]) specifying a different border color to use for
pixels beyond the
data window.
d) Change the default behavior of oiiotool and other image-writing utilities to
call this when writing images.
Comments?
-- lg
On Oct 17, 2011, at 9:50 PM, Will Rosecrans wrote:
> On Mon, Oct 17, 2011 at 8:48 PM, Larry Gritz <[email protected]> wrote:
>> The higher-level tools (iconvert, oiiotool) are another story entirely, and
>> I'm willing to bow to common sense, consensus, or precedent of other apps.
>> The two cases we care about are when the input image (a) has a data window
>> smaller than the display window (a crop window) or (b) has a data window
>> larger than the display window (overscan regions), but the output image
>> format does not support these notions at all (e.g. JPEG). What should
>> happen? What do other programs do?
>> Hugh implies that Shake would pad with some black (or some kind of settable
>> background color?), or crop to the display window. Do you agree?
>> Anybody familiar enough with Nuke to know what it does in these
>> circumstances?
>> Jeremy, do you have an opinion on any of this?
>> -- lg
>>
>
> If rendering something in nuke where the internal "data window" is
> smaller than the "display window" to a format the doesn't have such
> concepts, it will render a result that is the size of the "display
> window." which is basically the data surrounded by black. It's
> actually a bit more complicated than that because nuke wants to repeat
> edge pixels, but a crop node defaults to adding a one pixel black
> border around the cropped area (just outside the display window, so
> the resulting so that you edge-repeat the black border in the
> undefined space.) If rendering to EXR, nuke will correctly preserve
> the windows. I don't think nuke has a ngcolor in the sense that Shake
> did.
>
> In nuke-speak, you use a crop node to set the data window, and a
> reformat node to set the display window. You can also reformat in a
> crop node to do both at once. But, if you have the black border
> enabled when you reformat while you crop, the resulting data and
> display windows are not identical. The data window extends one pixel
> past the display window in each direction for the invisible black
> border. (This works fairly well in practice, despite being oddly
> complicated to explain nuke's behavior, you seldom have to think about
> it very explicitly.)
>
> In Shakespeak, the Crop node set the display window, and a setDOD node
> set the data window, basically. It was simpler in Shake.
>
> When rendering an EXR out of nuke where the display window is smaller
> than the data window, Compressor on Mac OS X will try to interpret the
> EXR in terms of the data window. The rule seems to be based on
> 'whichever is bigger.' The result is a QuickTime movie made from an
> EXR sequence that is physically larger than expected, and has
> unexpected stuff visible in it, and a very confused and angry editor.
> I consider the Compressor behavior to be incorrect, and I have never
> desired it.
>
> Basically, if I am making images where the data window matters, I'll
> keep strictly within the realm of tools and formats that maintain the
> distinction. If I need to use a tool that doesn't understand the data
> window, then I'll change my settings in the originating tool to make
> my images unambiguous. Efforts by intermediate tools to care about
> the data window in formats that don't understand it have never turned
> out useful to me. They should just use the display window, IMHO.
> _______________________________________________
> Oiio-dev mailing list
> [email protected]
> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
--
Larry Gritz
[email protected]
_______________________________________________
Oiio-dev mailing list
[email protected]
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org