image (lx_image.hpp)

From The Foundry MODO SDK wiki
Jump to: navigation, search
There are security restrictions on this page


Contents

Images

This module defines COM interfaces for dealing with pixel-map images. Greyscale, color and alpha mapped images can be read, written, loaded and saved using these interfaces. All images present consistent features regardless of their internal representation.

Pixel Formats

Images are defined by their pixel format which consists of a datatype and vector size. There are two data types. The BYTE type is an 8 bit integer in the range is 0 to 255. The FLOAT type is a 32-bit floating point number in the nominal range of 0.0 to 1.0. Operations on integer pixel values are clamped so the results are always in the valid range. Floating point colors are not clamped, so the images can represent superbright and superdark pixels.

(1) SDK: Declarations
 #define LXiIMD_BYTE     0x00
 #define LXiIMD_FLOAT    0x08
 #define LXfIMD_MASK     0x08
 
 #define LXxIMD_TYPE(t)  (t & LXfIMD_MASK)

The vector sizes are GREY which is one monochrome component; RGB which is a vector of three color components; or RGBA which is a vector of three color components and alpha. The alpha channel is represented by 0 for transparent, 255 for opaque if in byte format, and 1.0 for opaque if floating point format.

(2) SDK: Declarations
 #define LXiIMV_GREY     0x01
 #define LXiIMV_RGB      0x03
 #define LXiIMV_RGBA     0x04
 #define LXfIMV_MASK     0x07
 
 #define LXxIMV_TYPE(v)  (v & LXfIMV_MASK)

Index images use the index flag.

(3) SDK: Declarations
 #define LXiIMT_INDEX    0x100
 #define LXiIMT_MASK     0x100

Image pixel types are just the mask values combined together. Here are all six of the possible combinations in more convenient form. The color bits of an index mask can be acquired separately as well.

(4) SDK: Declarations
 #define LXiIMP_GREY8    (LXiIMD_BYTE  | LXiIMV_GREY)
 #define LXiIMP_GREYFP   (LXiIMD_FLOAT | LXiIMV_GREY)
 #define LXiIMP_RGB24    (LXiIMD_BYTE  | LXiIMV_RGB)
 #define LXiIMP_RGBFP    (LXiIMD_FLOAT | LXiIMV_RGB)
 #define LXiIMP_RGBA32   (LXiIMD_BYTE  | LXiIMV_RGBA)
 #define LXiIMP_RGBAFP   (LXiIMD_FLOAT | LXiIMV_RGBA)
 
 #define LXiIMP_IGREY8   (LXiIMD_BYTE  | LXiIMV_GREY | LXiIMT_INDEX)
 #define LXiIMP_IRGB24   (LXiIMD_BYTE  | LXiIMV_RGB  | LXiIMT_INDEX)
 #define LXiIMP_IRGBA32  (LXiIMD_BYTE  | LXiIMV_RGBA | LXiIMT_INDEX)
 
 // macro to check for greyscale pixel types explicitly, as LXiIMV_RGB masks LXiIMV_GREY
 #define LXi_IMP_ISGREY(x) ((x == LXiIMP_GREY8) || (x == LXiIMP_GREYFP) || (x == LXiIMP_IGREY8))

(5) SDK: Declarations

(6) SDK: Types
 typedef unsigned int     LXtPixelFormat;
 typedef unsigned int     LXtProcessHint;
 typedef unsigned char    LXtImageByte;
 typedef float            LXtImageFloat;
 typedef unsigned int     LXtImageIndex;
 typedef LXtImageFloat    LXtColorRGBA[4];

Color components in stored in vector type pixels are always in RGBA order. Use these indices to access components in a more abstract way.

(7) SDK: Declarations
 #define LXiIMC_RED      0
 #define LXiIMC_GREEN    1
 #define LXiIMC_BLUE     2
 #define LXiIMC_ALPHA    3

Image Interfaces

There are several image interfaces, but they all start with the following two methods. The first gets the width and height of the image in pixels. The second returns the pixel format closest to the native storage format for the image data. Both must always return reasonable values, so there are no error conditions.

(8) Common Image Methods
         LXxMETHOD( void,
 Size) (
         LXtObjectID              self,
         unsigned int            *w,
         unsigned int            *h);
 
         LXxMETHOD( LXtPixelFormat,
 Format) (
         LXtObjectID              self);

There are also common user class extensions to allow reading the width and height independently, and to query attributes of the format.

(9) User Size Methods
         unsigned
 Width () const
 {
         unsigned                 w, h;
 
         Size (&w, &h);
         return w;
 }
 
         unsigned
 Height () const
 {
         unsigned                 w, h;
 
         Size (&w, &h);
         return h;
 }

(10) User Format Methods
         bool
 IsFloat () const
 {
         return LXxIMD_TYPE (Format ()) == LXiIMD_FLOAT;
 }
 
         unsigned
 Components () const
 {
         return LXxIMV_TYPE (Format ());
 }

(11) Python Image methods
 def IsFloat(self):
     return (self.Format() & lx.symbol.fIMD_MASK) == lx.symbol.iIMD_FLOAT
 
 def Components(self):
     return self.Format() & lx.symbol.fIMV_MASK

Adding Image Attributes

Arbitrary attributes may be added to writeable image objects. These can be read and set using the image ILxAttributes interface.

This function allows a client to add an attribute to an ILxImageWrite object by providing an attribute name and an exotype name. If the attribute has been added successfully, its index will be returned.

(12) Common Image Write Methods
         LXxMETHOD(  LxResult,
 AddAttribute) (
         LXtObjectID              self,
         const char              *name,
         const char              *type,
         unsigned                *index);

Standard Image Attributes

Some name and types are defined for common attributes that are read or set by the application.

DPI
Dots per Inch, which is the number of pixels in the image that will fit vertically in each inch of the printed image. To know the horizontal DPI you have to take pixel aspect into account.
PIXASPECT
This is the aspect ratio of a single pixel in the image, computed as width/height. If the pixel height is one, then the pixel width is the same as the pixel aspect.
REGX0, REGX1, REGY0, REGY1
Pixel coordinates of the borders of the rendered region of the image. X and Y start at zero at the left and top of the image.
GAMMA
Gamma is an exponent applied to unity-normalized color values in the image before saving. To get the "real" values for pixels in the image, the inverse gamma needs to be applied.
COMMENT
Everyone's got something to say, right?

(13) SDK: Declarations
 #define LXsIATTRNAME_CAM_TRANS                  "cameraTransform"
 #define LXsIATTRTYPE_CAM_TRANS          LXsTYPE_STRING
 
 #define LXsIATTRNAME_WORLD_TO_CAM               "worldToCamera"
 #define LXsIATTRTYPE_WORLD_TO_CAM               LXsTYPE_STRING
 
 #define LXsIATTRNAME_ISO                        "ISO"
 #define LXsIATTRTYPE_ISO                        LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_EXPTIME                    "exposureTime"
 #define LXsIATTRTYPE_EXPTIME                    LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_DPI                    "DPI"
 #define LXsIATTRTYPE_DPI                    LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_APERATUREX     "aperatureX"
 #define LXsIATTRTYPE_APERATUREX     LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_APERATUREY     "aperatureY"
 #define LXsIATTRTYPE_APERATUREY     LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_CLIP_DIST      "clipDist"
 #define LXsIATTRTYPE_CLIP_DIST      LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_FOC_LENGTH     "focalLength"
 #define LXsIATTRTYPE_FOC_LENGTH     LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_PIXASPECT          "pixelAspect"
 #define LXsIATTRTYPE_PIXASPECT          LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_REGX0                  "regionX0"
 #define LXsIATTRTYPE_REGX0                  LXsTYPE_INTEGER
 
 #define LXsIATTRNAME_REGX1                  "regionX1"
 #define LXsIATTRTYPE_REGX1                  LXsTYPE_INTEGER
 
 #define LXsIATTRNAME_REGY0                  "regionY0"
 #define LXsIATTRTYPE_REGY0                  LXsTYPE_INTEGER
 
 #define LXsIATTRNAME_REGY1                  "regionY1"
 #define LXsIATTRTYPE_REGY1                  LXsTYPE_INTEGER
 
 #define LXsIATTRNAME_GAMMA                  "gamma"
 #define LXsIATTRTYPE_GAMMA                  LXsTYPE_FLOAT
 
 #define LXsIATTRNAME_COMMENT                "comment"
 #define LXsIATTRTYPE_COMMENT                LXsTYPE_STRING
 
 #define LXsIATTRNAME_APPLY_DISPLAY_LUT      "applyDisplayLUT"
 #define LXsIATTRTYPE_APPLY_DISPLAY_LUT      LXsTYPE_INTEGER
 
 #define LXsSAV_OUTPUT_PIXEL_FORMAT          "outputPixelFormat"
 #define LXsSAV_OUTPUT_KNOWN_COLOR_SPACE     "knownColorSpace"
 
 // Certain image formats have a particular color space which
 // can't be inferred from their pixel format (e.g. .hdr is 8-bit but linear)
 // Image IO Plugins can set the 'colorspace' field of the LXtImageTarget1
 // structure to LXsKNOWN_COLORSPACE_LINEAR in order to specify
 // that the colorspace of this image is linear.
 
 #define LXsKNOWN_COLORSPACE_LINEAR          "linear"
 
 #define LXsDEFAULT_COLORSPACE_8BIT          "8bit"
 #define LXsDEFAULT_COLORSPACE_16BIT         "16bit"
 #define LXsDEFAULT_COLORSPACE_FLOAT         "float"
 #define LXsDEFAULT_COLORSPACE_GREY          "grey"
 
 // Image IO Plugins can set the 'depth' field of the LXtImageTarget1
 // structure to any of the below values.
 // Modo will choose a default colorspace for the image based on this setting.
 // If 'None' is specified, no default colorspace conversion will occur.
 //
 // But users can override this choice on a per-clip basis, by setting the
 // clip's colorspace channel.
 //
 #define LXiDEFAULT_COLORSPACE_NONE      0
 #define LXiDEFAULT_COLORSPACE_8BIT      1
 #define LXiDEFAULT_COLORSPACE_16BIT     2
 #define LXiDEFAULT_COLORSPACE_FLOAT     3
 #define LXiDEFAULT_COLORSPACE_GREY      4

HDR Image Attributes

The OpenEXR file specification suggests some common metadata appropriate for HDR or physically accurate images.

LUMA
The luminance of a white pixel with r=g=b=1.0. The units, candela/m^2, match the 'whiteLuminance' OpenEXR standard attribute.
FOCDIST
The focus distance for the camera.
APERTURE
the aperture is given in f-stops, (focal length of the lens divided by the diameter of the iris opening).

(14) SDK: Declarations

Color Image

The basic image interface allows clients to read colored pixels or entire lines. When reading pixels the client should always ask for an RGBA format, but for lines the full range of format conversions is possible.

(15) SDK: ILxImage interface
 ''[[#C8|Common Image Methods]]''
 
         LXxMETHOD( LxResult,
 GetPixel) (
         LXtObjectID              self,
         unsigned int             x,
         unsigned int             y,
         LXtPixelFormat           type,
         void                    *pixel);
 
         LXxMETHOD( const void *,
 GetLine) (
         LXtObjectID              self,
         unsigned int             y,
         LXtPixelFormat           type,
         void                    *buf);

This is the primary interface for image objects, and so this the GUID specified when attempting to load or save images.

(16) SDK: Declarations
 #define LXu_IMAGE       "469AFBB8-E6A2-4d88-9C39-5430CA72E404"
 #define LXa_IMAGE       "image"
 #define LXa_IMAGE_FLOAT "image_float"
 #define LXsSAV_IMAGE_FLOAT "saver.imageFloat"

(17) User Class: Image method
 ''[[#C9|User Size Methods]]''
 ''[[#C10|User Format Methods]]''

(18) PY: Image method
 ''[[#C11|Python Image methods]]''

An image segment is a sub-range of pixels within a scanline, which is always read in FP RGBA format, and written in any given format.

(19) SDK: ILxImageSegment interface
         LXxMETHOD( LxResult,
 GetSegment) (
         LXtObjectID              self,
         unsigned int             y,
         unsigned int             left,
         unsigned int             right,
         LXtImageFloat           *rgba);
 
         LXxMETHOD( LxResult,
 SetSegment) (
         LXtObjectID              self,
         unsigned int             y,
         unsigned int             left,
         unsigned int             right,
         LXtPixelFormat           type,
         const void              *line);

Empty ImageSegment Python user class.

(20) PY: ImageSegment method
 pass

(21) SDK: Declarations
 #define LXu_IMAGESEGMENT        "370ABB2F-119E-4EEC-98F8-03388ABE7D2C"
 #define LXa_IMAGESEGMENT        "imagesegment"

Writing to an image requires a different interface. This provides methods for assigning color values to pixels or lines. Not all images will be writable.

(22) SDK: ILxImageWrite interface
 ''[[#C8|Common Image Methods]]''
 ''[[#C12|Common Image Write Methods]]''
 
         LXxMETHOD( LxResult,
 SetPixel) (
         LXtObjectID              self,
         unsigned int             x,
         unsigned int             y,
         LXtPixelFormat           type,
         const void              *pixel);
 
         LXxMETHOD( LxResult,
 SetLine) (
         LXtObjectID              self,
         unsigned int             y,
         LXtPixelFormat           type,
         const void              *line);

(23) SDK: Declarations
 #define LXu_IMAGEWRITE  "8F9CF293-B6F9-498e-A124-6704E2C24662"
 #define LXa_IMAGEWRITE  "imagewrite"

(24) User Class: ImageWrite method
         LxResult
 AddAttribute (
         const std::string       &name,
         const std::string       &type,
         unsigned                &index)
 {
         return CLxLoc_ImageWrite::AddAttribute (name.c_str (), type.c_str (), &index);
 }
 
 ''[[#C9|User Size Methods]]''
 ''[[#C10|User Format Methods]]''

(25) PY: ImageWrite method
 ''[[#C11|Python Image methods]]''

Index Image

An index image is one that stores index values at the pixel locations and uses a lookup table to get the color. While the ILxImage interface gets the color values at each pixel, this interface allows access to the underlying index and color map.

(26) SDK: ILxIndexImage interface
 ''[[#C8|Common Image Methods]]''
 
         LXxMETHOD( LxResult,
 MapSize) (
         LXtObjectID              self,
         unsigned                *numColors);
 
         LXxMETHOD( LxResult,
 GetIndex) (
         LXtObjectID              self,
         unsigned int             x,
         unsigned int             y,
         LXtImageIndex           *index);
 
         LXxMETHOD( LxResult,
 GetMap) (
         LXtObjectID              self,
         LXtImageIndex            index,
         LXtPixelFormat           type,
         void                    *pixel);

(27) SDK: Declarations
 #define LXu_INDEXIMAGE          "08CAE3BC-ED69-4EC4-9D7D-BBDBE4E35343"

(28) User Class: IndexImage method
 ''[[#C9|User Size Methods]]''
 ''[[#C10|User Format Methods]]''

(29) PY: IndexImage method
 ''[[#C11|Python Image methods]]''

Writing to an index image can only be done with one of these interfaces.

(30) SDK: ILxIndexImageWrite interface
 ''[[#C8|Common Image Methods]]''
 
 ''[[#C12|Common Image Write Methods]]''
 
         LXxMETHOD( LxResult,
 SetIndex) (
         LXtObjectID              self,
         unsigned int             x,
         unsigned int             y,
         LXtImageIndex            index);
 
         LXxMETHOD( LxResult,
 SetMap) (
         LXtObjectID              self,
         LXtImageIndex            index,
         LXtPixelFormat           type,
         const void              *pixel);

(31) SDK: Declarations
 #define LXu_INDEXIMAGEWRITE     "D59C5E09-779E-445b-B317-282630CB6BD5"

(32) User Class: IndexImageWrite method
         LxResult
 AddAttribute (
         const std::string       &name,
         const std::string       &type,
         unsigned                &index)
 {
         return CLxLoc_IndexImageWrite::AddAttribute (name.c_str (), type.c_str (), &index);
 }
 
 ''[[#C9|User Size Methods]]''
 ''[[#C10|User Format Methods]]''

(33) PY: IndexImageWrite method
 ''[[#C11|Python Image methods]]''

Layered Images

In many cases it is useful to add channels to images beyond the basic R, G, B, and A. In other cases, it is useful to preserve multiple sub-images in a composition. These requirements can be met with a layered image object, consisting of a list of named, independent sub-images, each with their own dimensions, offset, and pixel type. Interlayer blending information is also associated with each layer, Photoshop style.

Size
This returns the bounds of the image composition. While the combination of layer sizes and offsets makes it possible that some layers' pixels will not all be in bounds, the entire composition will be cropped at (0,0) to (w,h).

(34) SDK: ILxLayeredImage interface
         LXxMETHOD( LxResult,
 Size) (
         LXtObjectID              self,
         unsigned int            *w,
         unsigned int            *h);

Adding a standard format() method here would allow this object to masquerade as an ILxImage object... probably more confusing than useful.

Count
return number of layers.
Image
return ILxImage for layer at 'index'.
Name
return name for layer at 'index'.
Type
return type string and flags for layer at 'index'.

(35) SDK: ILxLayeredImage interface
         LXxMETHOD( unsigned int,
 Count) (
         LXtObjectID              self);
 
         LXxMETHOD( LxResult,
 Image) (
         LXtObjectID              self,
         unsigned int             index,
         void                   **ppvObj);
 
         LXxMETHOD( LxResult,
 Name) (
         LXtObjectID              self,
         unsigned int             index,
         const char             **name);
 
         LXxMETHOD( LxResult,
 Type) (
         LXtObjectID              self,
         unsigned int             index,
         unsigned int            *flags,
         const char             **type);

Offset
return pixel offset for layer at 'index' relative to complete layered image composition..
Blend
returns the opacity and the image blend mode for layer at 'index'. The image blend mode is one of the LXi_IBM_ modes.

(36) SDK: ILxLayeredImage interface
         LXxMETHOD( LxResult,
 Offset) (
         LXtObjectID              self,
         unsigned int             index,
         int                     *x,
         int                     *y);
 
         LXxMETHOD( LxResult,
 Blend) (
         LXtObjectID              self,
         unsigned int             index,
         float                   *opacity,
         unsigned int            *mode);

ChannelName
Pass back the name of the channel at the given layer and channel index, which may be overridden by the user by inserting semicolon delimiters in between each channel name in the Shader Tree.

(37) SDK: ILxLayeredImage interface
         LXxMETHOD( LxResult,
 ChannelName) (
         LXtObjectID              self,
         unsigned                 layerIndex,
         unsigned                 channelIndex,
         const char              **name);

Parent
Returns the parent layer index, or -1 if there is no parent
IsGroup
Returns true if the layer is a group layer

(38) SDK: ILxLayeredImage interface
         LXxMETHOD( LxResult,
 Parent) (
         LXtObjectID              self,
         unsigned                 layerIndex,
         int                     *parentIndex);
 
         LXxMETHOD( LxResult,
 IsGroup) (
         LXtObjectID              self,
         unsigned                 layerIndex,
         unsigned int            *isGroup);

(39) SDK: Declarations
 #define LXu_LAYEREDIMAGE        "8523ECC4-B8B3-4C6E-8F14-A1D2D01E8038"
 #define LXa_LAYEREDIMAGE        "layeredimage"

(40) User Class: LayeredImage method
 
 ''[[#C9|User Size Methods]]''
 
         bool
 GetImage (
         unsigned int             index,
         CLxLoc_Image            &img)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (Image (index, &obj)))
                 return false;
 
         return img.take (obj);
 }

Empty LayeredImage Python user class.

(41) PY: LayeredImage method
 pass

Writing Layered Images

Layered image objects will provide an ILxLayeredImageWrite interface for writing.

AddLayer
This is the way a layered image is actually created, adding layers by passing in ILxImage objects. The image object will be locked and released by the layered image, so clients may release the image after setting the layer.
SetType
Layer type and flags can be set using this function.
SetOffset
Pixel offsets for a layer are set with this function.
SetBlending
The blending parameter (or opacity) and the blending mode are set with this function. A list of modes should appear here shortly...

(42) SDK: ILxLayeredImageWrite interface
         LXxMETHOD( LxResult,
 AddLayer) (
         LXtObjectID              self,
         LXtObjectID              image,
         const char              *name,
         const char              **channelNames);
 
         LXxMETHOD( LxResult,
 SetType) (
         LXtObjectID              self,
         unsigned int             index,
         int                      flags,
         const char              *type);
 
         LXxMETHOD( LxResult,
 SetOffset) (
         LXtObjectID              self,
         unsigned int             index,
         int                      x,
         int                      y);
 
         LXxMETHOD( LxResult,
 SetBlending) (
         LXtObjectID              self,
         unsigned int             index,
         float                    blend,
         const char              *mode);
 
         LXxMETHOD(  LxResult,
 AddAttribute) (
         LXtObjectID              self,
         const char              *name,
         const char              *type,
         int                     *index);

(43) SDK: Declarations
 #define LXu_LAYEREDIMAGEWRITE   "79D28886-9652-4A76-9AA7-1B1E4D553DCD"

(44) User Class: LayeredImageWrite method

Empty LayeredImageWrite Python user class.

(45) PY: LayeredImageWrite method
 pass

Tile Image Interface

The tiled image interface provides a way for clients to implement images using tile trees. Tiles will themselves simply be images, so we can manage a global cache of them internally rather than depending on each implementation to manage an internal cache.

A tile tree is a collection of "levels", which are intended to be images of decreasing size. Each image level is broken into tiles, which allows us to only work on small portions of the image instead of loading an entire image. Typically, the image levels decrease in size by power of two.

For example, one dimension of a normal tile tree of an image with size 1024x1024, and tiles of size 256x256, would look like this:

Level 2 _ Level 1 _ _ Level 0 _ _ _ _

Where each _ represents a tile.

One thing to note is that the meaning of "level" is reverse from ImageLevelSample; level 0 is the base of the tile tree, where each tile is the original size, and the highest value of level will have a single tile.

Implementations of the TileImage interface are only required to be able to get the tiles at level 0; they may require the clients to generate tiles above level 0 by resizing the tiles below them.

LevelCount
LevelCount returns the number of levels in the tile tree.

(46) SDK: ILxTileImage interface
         LXxMETHOD( unsigned,
 LevelCount) (
         LXtObjectID              self);

GetTile
GetTile is the direct way of getting a tile from the tile image. In general, this will be loaded directly from the file off disk. Tiles will simply be an ILxImageID. These should be created by the implementation, and the client will release them.

It should return LXe_OK if it's okay, but LXe_OUTOFBOUNDS if the tile isn't in the image.

(47) SDK: ILxTileImage interface
         LXxMETHOD( LxResult,
 GetTile) (
         LXtObjectID               self,
         unsigned int              level,
         unsigned int              tileX,
         unsigned int              tileY,
         void                    **ppvObj);

GetTileSize
GetTileSize will determine the width and height of a given tile, and place it in *width and *height. For a given TileImage, these will usually be constant and equal except for boundary tiles.

It should return LXe_OK if it's okay, but LXe_OUTOFBOUNDS if the tile isn't in the image.

(48) SDK: ILxTileImage interface
         LXxMETHOD( LxResult,
 GetTileSize) (
         LXtObjectID              self,
         unsigned int             level,
         unsigned int             tileX,
         unsigned int             tileY,
         unsigned int            *width,
         unsigned int            *height);

GetLevelSize
GetLevelSize will determine the size of an entire level both in pixel counts and tile counts. It will place the former in *width and *height, and the latter in *tilesWidth and *tilesHeight.

Any of the pointers should be able to be NULL, if the caller only wants to get the tile dimensions, for instance. It should return LXe_OUTOFBOUNDS if the level isn't in the image.

(49) SDK: ILxTileImage interface
         LXxMETHOD( LxResult,
 GetLevelSize) (
         LXtObjectID              self,
         unsigned int             level,
         unsigned int            *width,
         unsigned int            *height,
         unsigned int            *tilesWidth,
         unsigned int            *tilesHeight);

DetermineTile
DetermineTile will determine which tile contains a given pixel at a given level, and place it in *tileX and *tileY.

It should return LXe_OK normally, but LXe_OUTOFBOUNDS if the pixel isn't on that level.

(50) SDK: ILxTileImage interface
         LXxMETHOD( LxResult,
 DetermineTile) (
         LXtObjectID              self,
         unsigned int             level,
         unsigned int             x,
         unsigned int             y,
         unsigned int            *tileX,
         unsigned int            *tileY);

DeterminePixel
DeterminePixel will take in a pixel position X and Y for a given level, and put in *adjX and *adjY the position of the pixel within the tile that contains it.

It should return LXe_OK normally, but LXe_OUTOFBOUNDS if the pixel isn't on that level.

(51) SDK: ILxTileImage interface
         LXxMETHOD( LxResult,
 DeterminePixel) (
         LXtObjectID              self,
         unsigned int             level,
         unsigned int             x,
         unsigned int             y,
         unsigned int            *adjX,
         unsigned int            *adjY);

(52) SDK: Declarations
 #define LXu_TILEIMAGE   "BD12D6C3-C08F-4AD1-A080-399F958D28C0"
 #define LXa_TILEIMAGE   "tileImage"

(53) User Class: TileImage method

Empty TileImage Python user class.

(54) PY: TileImage method
 pass

Image I/O

Images can be loaded and saved with appropriate servers of the loader and saver class. Loading can be opaque for disk-based access, although most loaders are currently direct, so a format, type, size and number of colors must be specified by the recognition method to allow the host to create a suitable image object to receive the data. This is done using a target interface.

(55) SDK: ILxImageLoaderTarget1 interface
         LXxMETHOD( LxResult,
 SetSize) (
         LXtObjectID              self,
         LXtPixelFormat           type,
         unsigned                 width,
         unsigned                 height);
 
         LXxMETHOD( LxResult,
 SetMap) (
         LXtObjectID              self,
         unsigned                 ncolor);

(56) SDK: Declarations
 #define LXu_IMAGELOADERTARGET1  "9F124A7B-DFC7-42E6-977B-71AE2E33B017"

(57) User Class: ImageLoaderTarget1 method

Legacy struct, still provided for older image loaders.

(58) SDK: LXtImageTarget1 struct
 LXtPixelFormat           type;
 unsigned int             w, h, ncolor;

The latest image loader target interface. This has two additional methods. * SetColorspaceDepth * SetColorspace

These can be used to specify more accurately which colorspaces to use for the given type.

(59) SDK: ILxImageLoaderTarget interface
         LXxMETHOD( LxResult,
 SetSize) (
         LXtObjectID              self,
         LXtPixelFormat           type,
         unsigned                 width,
         unsigned                 height);
 
         LXxMETHOD( LxResult,
 SetMap) (
         LXtObjectID              self,
         unsigned                 ncolor);
 
         LXxMETHOD( LxResult,
 SetColorspaceDepth) (
         LXtObjectID              self,
         unsigned                 depth);
 
         LXxMETHOD( LxResult,
 SetColorspace) (
         LXtObjectID              self,
         const char              *colorspace);

(60) SDK: Declarations
 #define LXu_IMAGELOADERTARGET   "1034861C-78C4-4BEC-9588-F1D3C0B0401A"

(61) User Class: ImageLoaderTarget method

Empty ImageLoaderTarget Python user class.

(62) PY: ImageLoaderTarget method
 pass

Image Level Access

Images can present an alternate interface that allows them to be accessed as a set of levels. The levels are filtered versions of the image at different scales, and typically are arranged in power-law series. The underlying implementation may be tiled, enabling access to images that are larger than the available memory, since the image server only needs sufficient memory for a single tile. Levels can be used directly when rendering so that the only levels used are those approximating the visual scale of the image in the rendered scene.

The count returns the number of different levels in the image.

(63) SDK: ILxImageLevelSample interface
         LXxMETHOD( unsigned,
 Count) (
         LXtObjectID              self);

Each resolution level should be twice the size of the previous level, starting at 1x1 pixels for level zero, although the tiled image load can pass back slightly different dimensions for each resolution level, according to the needs of the tiled format. The image may or may not provide the full image as a level, although the full image must be accessible through the required ILxImage interface.

(64) SDK: ILxImageLevelSample interface
         LXxMETHOD( LxResult,
 GetLevelSize) (
         LXtObjectID              self,
         unsigned                 level,
         unsigned                *width,
         unsigned                *height);

Sampling of a level is done using an array of structures, each with a pixel position in the level and a location to receive the RGBA data in floating point format.

(65) SDK: LXtImageSample struct
 unsigned                 x;
 unsigned                 y;
 LXtImageFloat           *rgba;

Level images provide image data at a given resolution level, for an array of image samples.

(66) SDK: ILxImageLevelSample interface
         LXxMETHOD( LxResult,
 SampleLevel) (
         LXtObjectID              self,
         unsigned                 level,
         LXtImageSample          *pixel,
         unsigned                 num);

Pixels can be directly accessed from a given level, in either integer or floating-point RGBA format, using an x- and y-coordinate in the local coordinate system of the specified level.

(67) SDK: ILxImageLevelSample interface
         LXxMETHOD( LxResult,
 GetPixel) (
         LXtObjectID              self,
         unsigned                 level,
         unsigned int             x,
         unsigned int             y,
         LXtPixelFormat           type,
         void                    *pixel);

Levels also support line-by-line access through a modified version of the GetLine() method, which uses a y-coordinate in the local coordinate system of the specified level. The data returned is always RGBA in floating point.

(68) SDK: ILxImageLevelSample interface
         LXxMETHOD( const LXtImageFloat *,
 GetLine) (
         LXtObjectID              self,
         unsigned                 level,
         unsigned                 y,
         LXtImageFloat           *buf);

Empty ImageLevelSample Python user class.

(69) PY: ImageLevelSample method
 pass

(70) SDK: Declarations
 #define LXu_IMAGELEVELSAMPLE    "79A6EA0E-9589-4D03-880C-C06A6EC6CF7D"
 #define LXa_IMAGELEVELSAMPLE    "imageLevelSample"

Global Service

Image facilities can be accessed through the SDK using a global service interface.

(71) SDK: ILxImageService interface
         LXxMETHOD(  LxResult,
 ScriptQuery) (
         LXtObjectID              self,
         void                   **ppvObj);
 
         LXxMETHOD(  LxResult,
 Create) (
         LXtObjectID              self,
         unsigned int             width,
         unsigned int             height,
         LXtPixelFormat           type,
         unsigned int             maxIndex,
         void                   **ppvObj);
 
         LXxMETHOD(  LxResult,
 Duplicate) (
         LXtObjectID              self,
         LXtObjectID              source,
         LXtPixelFormat           type,
         void                   **ppvObj);
 
         LXxMETHOD(  LxResult,
 Load) (
         LXtObjectID              self,
         const char              *filePath,
         void                   **ppvObj);
 
         LXxMETHOD(  LxResult,
 Save) (
         LXtObjectID              self,
         LXtObjectID              image,
         const char              *filePath,
         const char              *format,
         LXtObjectID              monitor);
 
         LXxMETHOD(  LxResult,
 Resample) (
         LXtObjectID              self,
         LXtObjectID              dest,
         LXtObjectID              source,
         LXtProcessHint           hint);
 
         LXxMETHOD(  LxResult,
 Composite) (
         LXtObjectID              self,
         LXtObjectID              dest,
         LXtObjectID              source,
         const LXtFVector2        pos);
 
         LXxMETHOD(  LxResult,
 DrawLine) (
         LXtObjectID              self,
         LXtObjectID              image,
         const LXtFVector2        p0,
         const LXtFVector2        p1,
         const LXtFVector         color);
 
         LXxMETHOD(  LxResult,
 Kelvin2RGB) (
         LXtObjectID              self,
         float                    kelvin,
         LXtFVector               rgbColor);
 
         LXxMETHOD(  LxResult,
 RGB2Kelvin) (
         LXtObjectID              self,
         const LXtFVector         rgbColor,
         float                   *kelvin);
 
         LXxMETHOD(  LxResult,
 CreateCrop) (
         LXtObjectID              self,
         LXtObjectID              sourceImage,
         double                   x,
         double                   y,
         double                   w,
         double                   h,
         void                   **ppvObj);

This reads the entire image into a single buffer given the pixel format. This is just like Image::GetLine() except that it does all the lines at once.

(72) SDK: ILxImageService interface
         LXxMETHOD(  LxResult,
 ImageGetBuffer) (
         LXtObjectID              self,
         LXtObjectID              sourceImage,
         LXtPixelFormat           type,
         void                    *buf);

Nexus 801

LaodNoCache() is the same as Load(), but the image is not added to the intenral cache. This is useful when the image is only needed once (say, because it is being loaded and resized).

(73) SDK: ILxImageService interface
         LXxMETHOD(  LxResult,
 LoadNoCache) (
         LXtObjectID              self,
         const char              *filePath,
         void                   **ppvObj);

(74) SDK: Declarations
 #define LXu_IMAGESERVICE        "03A7D258-397C-4D92-B3AF-695AD676FCF9"

Create a new image and fill in the user's user object.

(75) User Service Class: ImageService method
         bool
 New (
         CLxUser_Image           &image,
         unsigned int             w,
         unsigned int             h,
         LXtPixelFormat           type,
         unsigned int             maxIndex = 0)
 {
         LXtObjectID              obj;
         bool                     created = false;
 
         image.clear ();
         if (LXx_OK (Create (w, h, type, maxIndex, &obj))) {
                 image.take (obj);
                 created = true;
         }
 
         return created;
 }
 
         bool
 NewCrop (
         CLxUser_Image           &image,
         CLxUser_Image           &sourceImage,
         double                   x,
         double                   y,
         double                   w,
         double                   h)
 {
         LXtObjectID              obj;
         bool                     created = false;
 
         image.clear ();
         if (LXx_OK (CLxLoc_ImageService::CreateCrop (sourceImage, x, y, w, h, &obj))) {
                 image.take (obj);
                 created = true;
         }
 
         return created;
 }
 
         bool
 Load (
         CLxUser_Image           &image,
         const std::string       &filePath)
 {
         LXtObjectID              obj;
         bool                     found = false;
 
         image.clear ();
         if (LXx_OK (CLxLoc_ImageService::Load (filePath.c_str (), &obj))) {
                 image.take (obj);
                 found = true;
         }
 
         return found;
 }
 
         bool
 LoadNoCache (
         CLxUser_Image           &image,
         const std::string       &filePath)
 {
         LXtObjectID              obj;
         bool                     found = false;
 
         image.clear ();
         if (LXx_OK (CLxLoc_ImageService::LoadNoCache (filePath.c_str (), &obj))) {
                 image.take (obj);
                 found = true;
         }
 
         return found;
 }
 
         LxResult
 Save (
         CLxUser_Image           &image,
         const std::string       &filePath,
         const std::string       &format,
         ILxUnknownID             monitor = 0)
 {
         return CLxLoc_ImageService::Save (image, filePath.c_str (), format.c_str (), monitor);
 }
 
         LxResult
 Resample (
         CLxUser_Image           &destImage,
         CLxUser_Image           &sourceImage,
         LXtProcessHint           hint)
 {
         return CLxLoc_ImageService::Resample (destImage, sourceImage, hint);
 }
 
         LxResult
 Composite (
         CLxUser_Image           &destImage,
         CLxUser_Image           &sourceImage,
         const LXtFVector2        pos)
 {
         return CLxLoc_ImageService::Composite (destImage, sourceImage, pos);
 }
 
         LxResult
 DrawLine (
         CLxUser_Image           &image,
         const LXtFVector2        p0,
         const LXtFVector2        p1,
         LXtFVector               color)
 {
         return CLxLoc_ImageService::DrawLine (image, p0, p1, color);
 }

Empty Image service Python user class.

(76) PY: ImageService method
 pass

Image Compression

Image block codec interfaces allow an image to be compressed into a block of data which can then be included in other files, such as for thumbnails. Compress() allocates and returns a block encoding the image. Free() frees the block when the client is done. Decompress() creates an image from a block.

(77) SDK: ILxImageBlockCodec interface
         LXxMETHOD(  LxResult,
 Compress) (
         LXtObjectID              self,
         LXtObjectID              image,
         unsigned char          **buf,
         int                     *size);
 
         LXxMETHOD(  void,
 Free) (
         LXtObjectID              self,
         unsigned char           *buf,
         int                      size);
 
         LXxMETHOD(  LxResult,
 Decompress) (
         LXtObjectID              self,
         unsigned char           *buf,
         int                      size,
         void                   **ppvObj);

(78) SDK: Declarations
 #define LXu_IMAGEBLOCKCODEC     "7960B5BA-70D3-4FAD-8CA1-BD30A7938554"
 #define LXa_IMAGEBLOCKCODEC     "imageBlockCodec"

Animation Creation

Since there's really no better place for this we'll put the simple animation interface here. This is a very simple API for creating animations.

The LXsMOVIE_OPTIONSCOMMAND tag identifies a command that should be executed to set options for the movie saver. It is commonly called when the user has chosen the movie saver from a file dialog, and in any other situation where the user needs to be presented with saver options before actually saving the movie.

(79) SDK: Declarations
 #define LXu_MOVIE               "B7BD9F49-9400-45F1-ADEE-BFE82A1C4A65"
 #define LXa_MOVIE               "movie" 
 #define LXsMOVIE_SAVESTEREO     "movie.stereoscopic"
 #define LXsMOVIE_OPTIONSCOMMAND "optionsCommand"

Movie creation API is pretty simple - you begin a movie, add a bunch of images in sequence, and then end it. The movie itself lives on disk at the path specified. There are currently no flags defined, but there may be in the future. Default format is MP4 and default framerate is 15 fps.

(80) SDK: ILxMovie interface
         LXxMETHOD(  LxResult,
 BeginMovie) (
         LXtObjectID              self,
         const char              *fname,
         int                      w,
         int                      h,
         int                      flags);

Before adding any frames, you can change the framerate from the default of 15 with following method.

(81) SDK: ILxMovie interface
         LXxMETHOD(  LxResult,
 SetFramerate) (
         LXtObjectID              self,
         int                      frate);

Adding an image is straightforward. Do this in sequence.

(82) SDK: ILxMovie interface
         LXxMETHOD(  LxResult,
 AddImage) (
         LXtObjectID              self,
         LXtObjectID              image);

When done adding images, call this to finalize the movie and write it to disk.

(83) SDK: ILxMovie interface
         LXxMETHOD(  LxResult,
 EndMovie) (
         LXtObjectID              self);

Adding an audio track. This must be called after adding all images before EndMove.

(84) SDK: ILxMovie interface
         LXxMETHOD(  LxResult,
 AddAudio) (
         LXtObjectID              self,
         LXtObjectID              audio);