OpenDCX

Deep Compositing Extended

OpenDCX 2.2.2 documentation

ImageFormat

class ImageFormat

Image pixel resolution description class containing most of the info required for handling pixel space windows and how they map into & out of common camera projections.

For an explanation of the basic terminology see the OpenEXR TechnicalIntroduction.pdf, pages 4 & 5. Extensions to the OpenEXR basics and reasons why they were required:

apertureWindow:

This rectangle is not in the base OpenEXR definition and is intended to clearly define the extent of the original camera aperture in pixel space before any expansions, and in the same coordinate context (scaling) as the display and data windows. For cg renders the lower-left corner of apertureWindow will be 0,0 allowing the displayWindow to expand the camera aperture into negative coords without losing the alignment of the original aperture as commonly happens in renderers. Using projection matrices to determine the alignment is often impossible due to the inclusion of stereo offsets or other lens related aperture manipulations.

Depending on the usage context of the image (layout/render, composite, delivery, etc) apertureWindow can be thought of as:

  • Shooting camera aperture. i.e. the original, unexpanded camera aperture rectangle in pixel coordinates for a cg render before any filmback expansions.
  • Final delivery rectangle. i.e. what gets shown to a viewer or audience. Often images are worked on with additional padding to allow for stereo repositioning, shake, blur, etc, and this extra padding is typically trimmed off before final delivery. Quite often the final delivery rectangle is the same as the shooting camera aperture.
  • Sub-composition rectangle: ex. a special project might require multiple camera compositions to be combined into a single image - like an old multi-media slide show. Each image could have a different apertureWindow defining that camera composition’s location within the final image.

OpenEXR does provide the attributes ‘screenWindowCenter’ and ‘screenWindowWidth’ as a way of defining the camera aperture but these are inadequate in practice for several reasons:

  1. They are floating-point values and subject to rounding when converted to pixel coordinates. Because OpenEXR does not explicitly define the rounding math each implementation is free to round differently resulting in resolution differences.
  2. Does not fully define camera aperture expansions. While setting screenWindowWidth allows the horizontal aperture expansion to be clearly set, the reliance on pixel aspect ratio to derive screenWindowHeight means that vertical aperture expansions with square pixels are impossible to define. There are plenty of reasons to expand the vertical aperture while not affecting pixel aspect ratio!
  3. Most (all?) applications completely ignore these variables, perhaps because of reasons 1 & 2.
formatReference:
Typically the non-proxy or unscaled format used to determine the current proxy scaling of the format and to support absolute scaling of pixel coords. While the term ‘proxy’ is commonly thought of as a reduction in scale of an image to speed up iterations, it can also be used to scale up an image or completely change the shape of an image, as is often done when producing publicity content or print-res versions of imagery. Managing proxy resolutions is difficult with the current OpenEXR standard as there is no defined or suggested handling methodology. Rather than storing the proxy value as a scalar which is subject to accuracy and rounding issues when applied to inetger pixel rectangles, and is difficult to apply to all image parameters like pixelAspectRatio, the unscaled, original, or ‘reference’ format definition is stored in string form.

Example stereo-window format with negative displayWindow offset:

../_images/image_format_ex01a.jpg

Example stereo-window format with positive apertureWindow offset:

../_images/image_format_ex01b.jpg

Example format with negative xy displayWindow offset:

../_images/image_format_ex02.jpg
enum class FitTarget

Resizing fit modes for reformatting operations

ImageFormat::ImageFormat()

Default ctor leaves name=””, windows=[0,0,-1,-1] and pa=1.

ImageFormat::ImageFormat(const OPENEXR_IMF_NAMESPACE::Header&)

Build from an exr header. This will search for ImageFormat related attributes like formatName, apertureWindow, originalDisplayWindow, etc. If those are missing it assigns intuitive defaults like apertureWindow=displayWindow.

ImageFormat::ImageFormat(const std::string &format_text)

Build from a format definition string. If parsing fails the values are left at defaults [0,0,-1,-1]

ImageFormat::ImageFormat(const std::string &name, const IMATH_NAMESPACE::Box2i &display_window, float pixel_aspect = 1.0f)

Assumes apertureWindow == displayWindow

ImageFormat::ImageFormat(const std::string &name, int display_window[4], float pixel_aspect = 1.0f)

Assumes apertureWindow == displayWindow

ImageFormat::ImageFormat(const std::string &name, const IMATH_NAMESPACE::Box2i &display_window, const IMATH_NAMESPACE::Box2i &aperture_window, float pixel_aspect = 1.0f)

Display win must be >= aperture win so any corners that fall inside aperture will be clamped to it. Int array args are defined as [minX, minY, maxX, maxY]

virtual ImageFormat *ImageFormat::format()

Return the ImageFormat object for subclasses. Subclasses should return ‘this’.

const IMATH_NAMESPACE::Box2i &ImageFormat::displayWindow() const

Pixel-space windows.

displayWindow: ‘Working’ image region. Can include aperture expansions
for stereo offsets, shake, blur, etc.
apertureWindow: Camera aperture region, prior to any expansions. Always
equal to or smaller than displayWindow.
const std::string &ImageFormat::formatReference() const

formatReference string. Typically the non-proxy or unscaled format used to determine the current proxy scaling of the format and to support absolute scaling of pixel coords.

void ImageFormat::setReferenceFormat(const char *format_text, bool update_name = true)

Set the reference display window, optionally updating the format name with a proxy scale appendix. If the name contains an existing appendix it will be replaced with the new proxy scale.

int ImageFormat::displayMinX() const

Display window values.

The displayWindow in OpenEXR is commonly defined as the extent of the working image area, as opposed to the dataWindow which is the region of active pixels. See OpenEXR TechnicalIntroduction.pdf, pages 4 & 5

virtual bool ImageFormat::isValid() const

Returns true if format has been initialized successfully. Formats with zero displayWindow w/h are not considered valid.

int ImageFormat::apertureMinX() const

Aperture window values.

Defines the extent of the original camera aperture in pixel space before any expansions, and is in the same coordinate context (scaling) as the display and data windows. Can also be used to define the final delivery region of an image.

For typical cg renders the lower-left corner of apertureWindow should be 0,0 allowing an expanded displayWindow to shift into negative coords without losing the alignment of the original camera aperture. However in practice most renderers will keep the expanded displayWindow’s lower-left cornder at 0,0 causing the camera aperture to shift up and to the right.

This offset is typically not captured in metadata so it’s difficult or impossible to automatically align images rendered with same camera aperture but with aperture expansions. Using projection matrices to determine the offset is often impossible due to the inclusion of stereo offsets or other lens related aperture manipulations.

See the ImageFormat class notes above for more info.

bool ImageFormat::apertureMatchesDisplay() const

Returns true if apertureWindow == displayWindow

float ImageFormat::pixelAspectRatio() const

Returns the pixel aspect ratio.

IMATH_NAMESPACE::V2f ImageFormat::screenWindowCenter() const

ScreenWindow parameters derived from aperture & display windows scaled to match the OpenEXR spec of [-0.5...+0.5]. screenWindowWidth is always fitted to aperture width while screenWindowHeight includes pixel aspect ratio scaling.

void ImageFormat::pixelToNdc(float x, float y, float &u, float &v) const

Transform a pixel space coordinate to/from NDC [-1.0...+1.0] space.

virtual double ImageFormat::proxyScale() const

Returns the current proxy scale factor of the format as determined by dividing the displayWindow width by the formatReference’s displayWindow width. Subclasses could override this to take another parameter into account.

virtual void ImageFormat::fromHeader(const OPENEXR_IMF_NAMESPACE::Header&)

Get the ImageFormat from an Imf::Header. If header is missing the extra format attributes like ‘apertureWindow’ they are intuitively built using the standard windows.

virtual void ImageFormat::toHeader(OPENEXR_IMF_NAMESPACE::Header&) const

Sets the Imf::Header to the info from the ImageFormat. Sets displayWindow, pixelAspectRatio, and adds the extra format attributes. Does not affect the data window.

virtual bool ImageFormat::fromString(const std::string &format_text, ImageFormat&) const

Update the format parameters from a string. Returns false on parsing error.

virtual void ImageFormat::toString(std::ostream &os, bool brackets = false) const

Serialize the format parameters to a string or output stream. If brackets=true wrap it in ‘[]’

Format name handling

If a format is constructed without being assigned an explicit name an ad-hoc name of the display window’s width x height is constructed. i.e. ‘2048x1556’.

If the format is a proxy scaled version of a ‘full-res’ format then the end of the name may contain a proxy scale factor in parentheses. For example if a format with the name ‘hd_2.35_hvp24’ is proxy scaled by one-third (0.3333...) then the resulting name would be ‘hd_2.35_hvp24(s1/3)’, but if the scale factor is 3.0 then the name is ‘hd_2.35_hvp24(s3)’. This is to avoid floating-point accuracy issues.

Use getScaleFromName() to get the name of the original, full-res format.

const std::string &ImageFormat::name() const

Format’s identifier string.

std::string ImageFormat::buildScaledName(double scale) const

Builds a new format name for this format from the scale value.

static std::string ImageFormat::appendScaleToName(const std::string &name, double scale)

Build a new format name from the provided name & scale value, replacing any existing scale value. Or, strip scale notation off the end of a format name.

static double ImageFormat::getScaleFromName(const std::string &name_with_scale)

Warning - the text name scale notation may not be very accurate - get the scale from proxyScale() which is displayWindow / formatReference.displayWindow.

static std::string ImageFormat::toScaleNotation(double scale)

Scale notation string is of the form ‘s###’ or ‘s1/###’. ex. ‘s2’ ‘s1/2’ ‘s4.23’ ‘s1/3.33’

IMATH_NAMESPACE::Box2f ImageFormat::windowToNdc(const IMATH_NAMESPACE::Box2i &in) const

Transforms a window to ndc coords using the ImageFormat’s aperture.

void ImageFormat::ndcToPixelTransform(IMATH_NAMESPACE::M44d &m) const

Multiply the provided matrix by a transform to project ndc coords to ImageFormat pixel coords. Puts ndc x=-1 at the left edge of the apertureWindow and x=+1 at the right edge. Y is centered vertically within the apertureWindow and pixel aspect ratio applied.

void ImageFormat::pixelToNdcTransform(IMATH_NAMESPACE::M44d &m) const

Multiply the provided matrix by a transform to project ImageFormat pixel coords to ndc coords. Puts the apertureWindow left edge at ndc x=-1 and the right edge at ndc x=+1. The y-center of the apertureWindow is placed at ndc y=0 and pixel aspect ratio removed.

static IMATH_NAMESPACE::Box2i ImageFormat::scaleWindow(const IMATH_NAMESPACE::Box2i &in, double scale, int xpad = 0, int ypad = 0)

Returns a pixel window scaled and optionally padding. Pad amounts are also scaled.

ImageFormat::ImageFormat(const ImageFormat&)

Copy constructor only for subclasses

void ImageFormat::clampDisplayToAperture()

Any display win corners inside aperture win will be moved to the aperture’s edge.

void ImageFormat::clampApertureToDisplay()

Any aperture win corners outside display win will be moved to the displays’s edge.