The easiest way to load an image file is to open() it, readImages() from it, and then close() the file.
UT_PtrArray<PXL_Raster *> images; IMG_File *file = IMG_File::open("Snail.pic"); if(file) { bool success = file->readImages(images); file->close(); delete file; if(success) { // use rasters in images, and free them when you're done. } }
The following sections describe this process in more detail.
IMG_FileParms allows you to do the following:
By default, the data is interleaved and left at the native raster depth and color model.
// convert the data type (default = use native) void setDataType(IMG_DataType dt); // convert to a standard color model (RGB, RGBA, single). Each plane // will be this color model. void setColorModel(IMG_ColorModel cm); // Determines how to format the data. // IMG_INTERLEAVE_AS_IS - leave it interleaved or non, as in the file. // IMG_INTERLEAVED - always interleave (rgbrgbrgb). Default. // IMG_NON_INTERLEAVED - always non-interleaved (rrrgggbbb) // void setInterleaved(IMG_Interleave i); // If the color model is set to IMG_1CHAN, and the actual color model // is RGB or higher, this method determines how to convert the vector // into a scalar. By default, the luminance is taken. // void setLuminanceFunc(PXL_LumFunction f); // If true, alpha will be read into its own plane, instead of an RGBA // color plane. Color will be read as its own plane as well, RGB. // void readAlphaAsPlane(); // If demoting from a deep raster to an RGB(A) image, these methods // allow you to specify the plane(s) to copy to RGB(A), by name or index. // // Indices are specified from 1 to #planes. // void selectPlane(const UT_IntArray &planeindices); // Selects by numeric pattern, for example "1", "1 3 4", "[1-3] 2" // void selectPlane(const char *pattern); // Selects by plane name pattern, such as "C", "C A Pz" "P? C*" // void selectPlaneName(const char *name);
By default, the native resolution is used.
// scale the image to resolutuion (x,y). (0 = use orginal dimension) void scaleImageTo(int x, int y, UT_FilterType ft=UT_FILTER_BOX); // scale the image by scaling factors (x,y). void scaleImageBy(fpreal x, fpreal y, UT_FilterType ft=UT_FILTER_BOX); // limit the image to a maximum resolution. Scale to this res, preserving // the aspect ratio. void limitImageRes(int x, int y, UT_FilterType ft=UT_FILTER_BOX); // images must be read as powers of two. Does not preserve aspect. void powerTwoOnly();
By default, all file data windows are expanded to fill the entire image.
// normally, a data window is expanded or cropped to the image resolution. // calling this will always read only the data window. // void setDataWindowOnly(); // read the image region in 'area' only (even if we need to crop or expand // the image to fill it) void setWindow(const UT_DimRect &area); // fills the data outside the window with bgcol. If reading, this overrides // any outside behaviour embedded in the file. // void setWindowOutsideColor(fpreal bgcol[4]); // fills the data outside the window by streaking the edges outward to // fill the area. // void setWindowStreak();
By default, the image is read so that the (0,0) pixel is in the bottom left corner of the image.
// options for orienting and flipping the image. Default orienation is // LEFT_FIRST, BOTTOM_FIRST. You can set each to 'none' if you don't care. // void orientImage(IMG_XOrientation x, IMG_YOrientation y); void flipImageVertical(); void flipImageHorizontal(); // rotate the image 90', flopping it on its side. void flopImage();
By default, no color correction is performed.
// apply a lookup table to the data, but only those planes that match the // scope. // void applyLUT(const char *lut, const char *plane_scope = "*"); // Apply gamma to the planes matching the scope. // void applyGamma(fpreal gamma, const char *gamma_scope = "*");
// if set, we're reading or writing tiles with readTile() and writeTile() // instead of readScanline() and writeScanline(). The area of each tile may // vary per call, but no pixel may be written twice for the same plane. void useTileInterface();
IMG_FileParms fparms; fparms.scaleImageTo(100,100); fparms.setInterleaved(IMG_NON_INTERLEAVED); fparms.useTileInterface(); IMG_File *fp = IMG_File::open(filename, &fparms); if(fp) ...
The IMG_FileParms structure is optional in the open() call. If you don't specify it, by default, the file reader is set up to read a full interleaved xres x yres image in its native data format, oriented bottom first.
Note that the object you get back may not be of the type you are expecting - it could be a translator object. If the open() failed, a NULL pointer is returned.
The Data Window has also moved from IMG_File to IMG_Stat. To check the dimensions of the area you will be reading, always call getDataWidth() and getDataHeight(), not getXres() and getYres(). The size of the full scanline (including all planes) and each plane's scanline can be returned through bytesPerScanline() and bytesPerPlaneScan().
To allocate buffer space for any scanline, you can use IMG_File::allocScanlineBuffer(). This will allocate a buffer big enough to handle any plane by itself.
To copy the data into a buffer you are providing, you can call readIntoBuffer() instead (this method returns true for success and false for failure). The buffer must be big enough to fit the scanline, as reported by myStat.bytesPerPlaneScan().
Regardless of where a data window or subregion is in the image, scanlines are always indexed from 0 to getStat().getDataHeight()-1. If you want to read scanlines in random order, you should call randomReadAccessRequired() on the IMG_File object first. Otherwise, you should read the scanlines in ascending order.
If you are reading more than one plane, but you want to read a plane entirely before starting another plane, you must call randomReadAccessRequired() as well.
readImages() method will add one PXL_Raster per plane in the image (usually one image for a normal format, and many rasters for a deep raster format). These PXL_Rasters need to be freed once you are finished using them.
Once you have opened the file, unlike reading, you must write every scanline in the file, for each plane you have defined. If you do not, the planes you did not define will contain garbage data. Unlike reading, you can write scanlines in any order (though it is generally most efficient to write them in ascending order).
freerasters parameter to free the rasters for you once the write has completed.A: The default plane is chosen (C or plane 0).
Q: What happens if I'm writing a deep raster and the format doesn't support different formats for each image?
A: The highest bit depth format is chosen from the planes, so that all planes can be represented properly.
Q: I am writing a file and specified a data window on a format that doesn't support it. What happens?
A: The writer expands the data window to the actual resolution of the image, filling in the outside area with black.
Q: The data type I'm writing doesn't match any of the types that the format supports. What happens?
A: The best data format the file provides is matched to the format you specified, and the data is converted. For example, if you write FP data to an SGI file, which only supports 8 and 16 bit ints, the 16bit int format is chosen and the data clamped at [0,1]. If you wrote 8bit int to a .exr file, it would be converted to 16bit fp.
Q: I don't want the file writer to make automatic decisions about fitting my data. How can I determine what a certain format will support?
A: Call IMG_Format::findFormat(filename) to get the IMG_Format description of that format. You can then query a lot of the this API's features:
virtual IMG_DataType getSupportedTypes() const; virtual IMG_ColorModel getSupportedColorModels() const; virtual void getMaxResolution(unsigned &x,unsigned &y) const; virtual int isReadRandomAccess() const; virtual int isWriteRandomAccess() const; // data orientation. virtual int isTopFirst() const; virtual int isLeftFirst() const; // data organization. virtual bool isDataWindowSupported() const; virtual bool isDeepRasterSupported() const; virtual IMG_DeepRasterColor getDeepRasterRGBASupported() const; virtual bool isDataInterleaved() const; // if true, planes can have different data formats & components. virtual bool canPlaneTypesDiffer() const;
stat(const char *filename, short *xres, short *yres) load(const char *filename, int xres, int yres, ...) save(const char *filename)
The reason that these methods are obsolete is that they only handle 8 and 16 bit color channels. 32b and 16b floating point images will be clipped to 16b fixed color.
On success, the above methods will return 1. If they fail, the return value will be 0.
The load methods will determine the correct format type by looking at the extension of the filename. Any format supported by Houdini may be saved or loaded. If the extension doesn't map to any known suffix, Alias format is used for saving (this does not include an alpha channel).
See the SOP_CopRaster example (SOP/SOP_CopRasterC) for an example of using the IMG_Raster::load method.
1.5.9