/*
*
* Copyrigh (C) 2004 Max-Planck-Institute of Cognitive Neurosience
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*$Id: image.c 52 2004-03-02 15:53:19Z tittge $ */
/*! \file image.c
* \brief basic support for images (the VImage class)
* \author Arthur Pope, UBC Laboratory for Computational Intelligentce
*/
#include "vistaio/vistaio.h"
/*
* Dictionaries for VImage attributes and their values.
*/
/* Keywords for representing band interpretation values: */
VDictEntry VBandInterpDict[] = {
{"complex", VBandInterpComplex}
,
{"gradient", VBandInterpGradient}
,
{"intensity", VBandInterpIntensity}
,
{"orientation", VBandInterpOrientation}
,
{"rgb", VBandInterpRGB}
,
{"stereo_pair", VBandInterpStereoPair}
,
{NULL}
};
/*! \brief Allocates memory for a new image with specified properties.
*
* Returns a pointer to the image if successful, zero otherwise.
*
* \param nbands
* \param nrows
* \param ncolumns
* \param pixel_repn
* \return VImage
*/
EXPORT_VISTA VImage VCreateImage (int nbands, int nrows, int ncolumns,
VRepnKind pixel_repn)
{
size_t row_size = ncolumns * VRepnSize (pixel_repn);
size_t data_size = nbands * nrows * row_size;
size_t row_index_size = nbands * nrows * sizeof (char *);
size_t band_index_size = nbands * sizeof (char **);
size_t pixel_size;
char *p;
VImage image;
int band, row;
#define AlignUp(v, b) ((((v) + (b) - 1) / (b)) * (b))
/* Check parameters: */
if (nbands < 1) {
VWarning ("VCreateImage: Invalid number of bands: %d",
(int)nbands);
return NULL;
}
if (nrows < 1) {
VWarning ("VCreateImage: Invalid number of rows: %d",
(int)nrows);
return NULL;
}
if (ncolumns < 1) {
VWarning ("VCreateImage: Invalid number of columns: %d",
(int)ncolumns);
return NULL;
}
if (pixel_repn != VBitRepn && pixel_repn != VUByteRepn &&
pixel_repn != VSByteRepn && pixel_repn != VShortRepn &&
pixel_repn != VLongRepn && pixel_repn != VFloatRepn
&& pixel_repn != VDoubleRepn) {
VWarning ("VCreateImage: Invalid pixel representation: %d",
(int)pixel_repn);
return NULL;
}
/* Allocate memory for the VImage, its indices, and pixel values, while
padding enough to ensure pixel values are appropriately aligned: */
pixel_size = VRepnSize (pixel_repn);
p = VMalloc (AlignUp (sizeof (VImageRec) + row_index_size +
band_index_size, pixel_size) + data_size);
/* Initialize the VImage: */
image = (VImage) p;
image->nbands = nbands;
image->nrows = nrows;
image->ncolumns = ncolumns;
image->flags = VImageSingleAlloc;
image->pixel_repn = pixel_repn;
image->attributes = VCreateAttrList ();
image->band_index = (VPointer **) (p += sizeof (VImageRec));
image->row_index = (VPointer *) (p += band_index_size);
image->data =
(VPointer) AlignUp ((long)p + row_index_size, pixel_size);
image->nframes = nbands;
image->nviewpoints = image->ncolors = image->ncomponents = 1;
/* Initialize the indices: */
for (band = 0; band < nbands; band++)
image->band_index[band] = image->row_index + band * nrows;
for (row = 0, p = image->data; row < nbands * nrows;
row++, p += row_size)
image->row_index[row] = p;
return image;
#undef AlignUp
}
/*! \brief Create an image with the same properties as an existing one.
*
* \param src
* \return VImage
*/
EXPORT_VISTA VImage VCreateImageLike (VImage src)
{
return VCopyImageAttrs (src, NULL);
}
/*! \brief Frees memory occupied by an image.
*
* \param image
* \return VImage
*/
EXPORT_VISTA void VDestroyImage (VImage image)
{
if (!image)
return;
if (!(image->flags & VImageSingleAlloc)) {
VFree (image->data);
VFree ((VPointer) image->row_index);
VFree ((VPointer) image->band_index);
}
VDestroyAttrList (VImageAttrList (image));
VFree ((VPointer) image);
}
/*! \brief Fetch a pixel value, regardless of type, and return it as a Double.
*
* \param image
* \param band
* \param row
* \param column
* \return VDouble
*/
VDouble VGetPixel (VImage image, int band, int row, int column)
{
VPointer p = VPixelPtr (image, band, row, column);
switch (VPixelRepn (image)) {
case VBitRepn:
return (VDouble) * (VBit *) p;
case VUByteRepn:
return (VDouble) * (VUByte *) p;
case VSByteRepn:
return (VDouble) * (VSByte *) p;
case VShortRepn:
return (VDouble) * (VShort *) p;
case VLongRepn:
return (VDouble) * (VLong *) p;
case VFloatRepn:
return (VDouble) * (VFloat *) p;
case VDoubleRepn:
return (VDouble) * (VDouble *) p;
default:
VError ("VGetPixel: %s images not supported",
VPixelRepnName (image));
}
return 0.0; /* to make lint happy */
}
/*! \brief Set a pixel, regardless of type, and to a value passed as a Double.
*
* \param image
* \param band
* \param row
* \param column
* \param value
*/
void VSetPixel (VImage image, int band, int row, int column,
VDoublePromoted value)
{
VPointer p = VPixelPtr (image, band, row, column);
switch (VPixelRepn (image)) {
case VBitRepn:
*(VBit *) p = (VBit )value;
break;
case VUByteRepn:
*(VUByte *) p = (VUByte )value;
break;
case VSByteRepn:
*(VSByte *) p = (VSByte )value;
break;
case VShortRepn:
*(VShort *) p = (VShort)value;
break;
case VLongRepn:
*(VLong *) p = (VLong)value;
break;
case VFloatRepn:
*(VFloat *) p = (VFloat)value;
break;
case VDoubleRepn:
*(VDouble *) p = value;
break;
default:
VError ("VSetPixel: %s images not supported",
VPixelRepnName (image));
}
}
/*! \brief Copy the pixels and attributes of one image to another.
*
* Returns a pointer to the destination image if successful, zero otherwise.
* The band parameter may be VAllBands, in which case all bands of pixel
* values are copied, or a particular band number, in which case only a
* single band is copied to a 1-band destination image.
*
* \param src
* \param dest
* \param band
* \return Returns a pointer to the destination image if successful, zero
* otherwise
*/
EXPORT_VISTA VImage VCopyImage (VImage src, VImage dest, VBand band)
{
VImage result;
if (src == dest
&& (band == VAllBands || (band == 0 && VImageNBands (src) == 1)))
return src;
if ((result = VCopyImagePixels (src, dest, band)) != 0)
VCopyImageAttrs (src, result);
return result;
}
/*! \brief Give a destination image the same attributes as a source image.
*
* However if the destination image doesn't have the same number of bands
* as the source image, any band interpretation attributes are deleted.
*
* \param src
* \param dest
* \return VImage
*/
EXPORT_VISTA VImage VCopyImageAttrs (VImage src, VImage dest)
{
VAttrList list;
if (src == dest)
return dest;
if (!dest) {
dest = VCreateImage (VImageNBands (src), VImageNRows (src),
VImageNColumns (src), VPixelRepn (src));
if (!dest)
return NULL;
}
/* Clone the source image's attribute list if it isn't empty: */
if (!VAttrListEmpty (VImageAttrList (src))) {
list = VImageAttrList (dest);
VImageAttrList (dest) = VCopyAttrList (VImageAttrList (src));
} else if (!VAttrListEmpty (VImageAttrList (dest))) {
list = VImageAttrList (dest);
VImageAttrList (dest) = VCreateAttrList ();
} else
list = NULL;
if (list)
VDestroyAttrList (list);
/* Preserve band interpretation attributes only if the source and
destination images have the same number of bands: */
if (VImageNBands (src) > 1
&& VImageNBands (dest) == VImageNBands (src)) {
VImageNFrames (dest) = VImageNFrames (src);
VImageNViewpoints (dest) = VImageNViewpoints (src);
VImageNColors (dest) = VImageNColors (src);
VImageNComponents (dest) = VImageNComponents (src);
} else {
VExtractAttr (VImageAttrList (dest), VFrameInterpAttr, NULL,
VBitRepn, NULL, FALSE);
VExtractAttr (VImageAttrList (dest), VViewpointInterpAttr,
NULL, VBitRepn, NULL, FALSE);
VExtractAttr (VImageAttrList (dest), VColorInterpAttr, NULL,
VBitRepn, NULL, FALSE);
VExtractAttr (VImageAttrList (dest), VComponentInterpAttr,
NULL, VBitRepn, NULL, FALSE);
VImageNComponents (dest) = VImageNColors (dest) =
VImageNViewpoints (dest) = 1;
VImageNFrames (dest) = VImageNBands (dest);
}
return dest;
}
/*! \brief Copy the pixels of one image to another.
*
* Returns a pointer to the destination image if successful, zero otherwise.
* The band parameter may be VAllBands, in which case all bands of pixel
* values are copied, or a particular band number, in which case only a
* single band is copied to a 1-band destination image.
*
* \param src
* \param dest
* \param band
* \return Returns a pointer to the destination image if successful,
* zero otherwise.
*/
EXPORT_VISTA VImage VCopyImagePixels (VImage src, VImage dest, VBand band)
{
int npixels;
VPointer src_pixels;
VImage result;
/* Locate the source and destination of the copy: */
if (!VSelectBand
("VCopyImagePixels", src, band, &npixels, &src_pixels))
return NULL;
result = VSelectDestImage ("VCopyImagePixels", dest,
band == VAllBands ? VImageNBands (src) : 1,
VImageNRows (src), VImageNColumns (src),
VPixelRepn (src));
if (!result)
return NULL;
/* Copy pixel values from src to dest: */
memcpy (VImageData (result), src_pixels, npixels * VPixelSize (src));
return result;
}
/*! \brief Copy a band of pixel data from one image to another.
*
* Band src_band of image src is copied to band dest_band of image dest.
* The destination image must exist, having the same pixel representation
* and size as the source image. Either src_band or dst_band may be
* VAllBands, provided they both describe the same number of bands.
*
* \param src
* \param src_band
* \param dest
* \param dest_band
* \return VBoolean
*/
EXPORT_VISTA VBoolean VCopyBand (VImage src, VBand src_band, VImage dest, VBand dest_band)
{
int nbands, src_npixels, dest_npixels;
VPointer src_pixels, dest_pixels;
/* The destination image must exist: */
if (!dest) {
VWarning ("VCopyBand: No destination specified");
return FALSE;
}
/* VAllBands not accepted for destination band: */
if (dest_band < 0 || dest_band >= VImageNBands (dest)) {
VWarning ("VCopyBand: Band %d referenced in image of %d bands", (int)dest_band, (int)VImageNBands (dest));
return FALSE;
}
/* Ensure that the destination image has the appropriate dimensions
and pixel representation: */
nbands = dest_band;
if (src_band == VAllBands)
nbands += VImageNBands (src) - 1;
if (nbands < VImageNBands (dest))
nbands = VImageNBands (dest);
if (!VSelectDestImage ("VCopyBand", dest, nbands, VImageNRows (src),
VImageNColumns (src), VPixelRepn (src)))
return FALSE;
/* Locate the specified source and destination bands: */
if (!VSelectBand
("VCopyBand", src, src_band, &src_npixels, &src_pixels))
return FALSE;
if (!VSelectBand
("VCopyBand", dest, dest_band, &dest_npixels, &dest_pixels))
return FALSE;
/* Copy from the source band to the destination band: */
memcpy (dest_pixels, src_pixels, src_npixels * VPixelSize (src));
return TRUE;
}
/*! \brief Copy a series of bands from various images into a destination image.
*
* nbands is the number of bands to be copied, and the number of elements
* in src_images (a list of images from which to obtain the bands) and
* src_bands (a list of their respective band numbers). The bands are
* copied into the destination image in sequence.
*
* \param nels
* \param src_images
* \param src_bands
* \param dest
* \return VImage
*/
EXPORT_VISTA VImage VCombineBands (int nels, VImage src_images[], VBand src_bands[],
VImage dest)
{
int n, i;
VImage result, src = src_images[0];
/* Count the number of bands needed in the destination image: */
for (i = n = 0; i < nels; i++)
n += (src_bands[i] ==
VAllBands) ? VImageNBands (src_images[i]) : 1;
/* Check or allocate the destination image: */
result = VSelectDestImage ("VCombineBands", dest, n,
VImageNRows (src), VImageNColumns (src),
VPixelRepn (src));
if (!result)
return NULL;
/* Copy each source band into the destination image: */
for (i = n = 0; i < nels; i++) {
if (!VCopyBand (src_images[i], src_bands[i], result, n)) {
if (result != dest)
VDestroyImage (result);
return NULL;
}
n += (src_bands[i] ==
VAllBands) ? VImageNBands (src_images[i]) : 1;
}
return result;
}
/*! \brief A varargs version of VCombineBands.
*
* It is called by:
*
* dest = VCombineBandsVa (dest, src_image1, src_band1, ...,
* (VImage) NULL);
* \param dest
* \return VImage
*/
EXPORT_VISTA VImage VCombineBandsVa (VImage dest, ...)
{
va_list args;
VImage src, result;
int nbands;
VBand src_band, dest_band;
/* Count the number of bands to be combined: */
va_start (args, dest);
for (nbands = 0; (src = va_arg (args, VImage)); nbands +=
(va_arg (args, VBand) == VAllBands) ? VImageNBands (src) : 1);
va_end (args);
/* Check or allocate the destination image: */
va_start (args, dest);
src = va_arg (args, VImage);
va_end (args);
result = VSelectDestImage ("VCombineBandsVa", dest, nbands,
VImageNRows (src), VImageNColumns (src),
VPixelRepn (src));
if (!result)
return NULL;
/* Copy each source band into the destination image: */
va_start (args, dest);
for (dest_band = 0; (src = va_arg (args, VImage));) {
src_band = va_arg (args, VBand);
if (!VCopyBand (src, src_band, result, dest_band)) {
if (result != dest)
VDestroyImage (result);
return NULL;
}
dest_band += (src_band == VAllBands) ? VImageNBands (src) : 1;
}
va_end (args);
return result;
}
/*! \brief Check that a destination image provided for an operation has the
* appropriate number of rows, columns and bands, and a pixel representation.
* Or, if no destination image is provided, create one.
*
* \param routine
* \param dest
* \param nbands
* \param nrows
* \param ncolumns
* \param pixel_repn
* \return VImage
*/
/* There are two ways to use this routine. If an operation is such that
* it can be carried out with a destination image that is the same as
* the source image, one follows this procedure:
*
* VImage result;
*
* result = VSelectDestImage (...);
* if (! result)
* return NULL;
*
* On successful completion:
* VCopyImageAttrs (src, result);
* return result;
*
* On failure:
* if (result != dest)
* VDestroyImage (result);
* return NULL;
*
* And if an operation *cannot* be carried out with a destination image
* that is the same as the source image, one does:
*
* VImage result;
*
* result = VSelectDestImage (...); use or create dest image
* if (! result)
* return NULL;
* if (src == result)
* result = VCreateImage (...); allocate a work image
*
* On successful completion:
* if (src == dest) {
* VCopyImagePixels (result, dest, VAllBands); move work to dest
* VDestroyImage (result);
* return dest;
* } else {
* VCopyImageAttrs (src, result);
* return result;
* }
*
* On failure:
* if (result != dest)
* VDestroyImage (result);
* return NULL;
*/
EXPORT_VISTA VImage VSelectDestImage (VStringConst routine, VImage dest,
int nbands, int nrows, int ncolumns,
VRepnKind pixel_repn)
{
/* If no destination image was specified, allocate one: */
if (!dest)
return VCreateImage (nbands, nrows, ncolumns, pixel_repn);
/* Otherwise check that the destination provided has the appropriate
characteristics: */
if (VImageNBands (dest) != nbands) {
VWarning ("%s: Destination image has %d bands; %d expected",
routine, VImageNBands (dest), nbands);
return NULL;
}
if (VImageNRows (dest) != nrows) {
VWarning ("%s: Destination image has %d rows; %d expected",
routine, VImageNRows (dest), nrows);
return NULL;
}
if (VImageNColumns (dest) != ncolumns) {
VWarning ("%s: Destination image has %d columns; %d expected",
routine, VImageNColumns (dest), ncolumns);
return NULL;
}
if (VPixelRepn (dest) != pixel_repn) {
VWarning ("%s: Destination image has %s pixels; %s expected",
routine, VPixelRepnName (dest),
VRepnName (pixel_repn));
return NULL;
}
return dest;
}
/*! \brief Check a band specification and use it to determine the number and
* address of a block of pixels.
*
* \param routine
* \param image
* \param band
* \param npixels
* \param first_pixel
* \return VBoolean
*/
EXPORT_VISTA VBoolean VSelectBand (VStringConst routine, VImage image, VBand band,
int *npixels, VPointer * first_pixel)
{
if (band == VAllBands) {
if (npixels)
*npixels = VImageNPixels (image);
if (first_pixel)
*first_pixel = VImageData (image);
} else if (band >= 0 && band < VImageNBands (image)) {
if (npixels)
*npixels =
VImageNRows (image) * VImageNColumns (image);
if (first_pixel)
*first_pixel = image->band_index[band][0];
} else {
VWarning ("%s: Band %d referenced in image of %d band(s)",
routine, band, VImageNBands (image));
return FALSE;
}
return TRUE;
}
/*! \brief Routine for accessing an image's band interpretation information.
*
* \param image
* \return VBandInterp
*/
/*
* VImageFrameInterp, VImageViewpointInterp,
* VImageColorInterp, VImageComponentInterp
*
* Routines for accessing an image's band interpretation information.
*
* Each routine returns a VBandInterpXxx constant describing how
* image bands are to be interpreted at a particular level of the band
* hierarchy.
*
* If that level's dimension is 1 and there is no band interpretation
* attribute for the level, VBandInterpNone is returned.
*
* If the dimension is >1 and there is no attribute, VBandInterpOther is
* returned.
*
* If an image's band interpretation information is inconsistent
* (e.g., the color_interp attribute says RGB but ncolors is 2) then
* VWarning is called and VBandInterpOther is returned.
*/
EXPORT_VISTA VBandInterp VImageFrameInterp (VImage image)
{
VLong interp;
VGetAttrResult result;
if (VImageNBands (image) !=
(VImageNFrames (image) * VImageNViewpoints (image) *
VImageNColors (image) * VImageNComponents (image)))
VWarning ("VImageFrameInterp: No. bands (%d) conflicts with no. " "of frames, etc. (%d %d %d %d)", VImageNBands (image), VImageNFrames (image), VImageNViewpoints (image), VImageNColors (image), VImageNComponents (image));
if (!VImageAttrList (image) ||
(result =
VGetAttr (VImageAttrList (image), VFrameInterpAttr,
VBandInterpDict, VLongRepn, &interp)) == VAttrMissing)
return VImageNFrames (image) >
1 ? VBandInterpOther : VBandInterpNone;
if (result == VAttrBadValue)
return VBandInterpOther;
switch (interp) {
}
return VBandInterpOther;
}
/*! \brief Routine for accessing an image's band interpretation information.
*
* \param image
* \return VBandInterp
*/
EXPORT_VISTA VBandInterp VImageViewpointInterp (VImage image)
{
VLong interp;
VGetAttrResult result;
if (VImageNBands (image) !=
(VImageNFrames (image) * VImageNViewpoints (image) *
VImageNColors (image) * VImageNComponents (image)))
VWarning ("VImageViewpointInterp: No. bands (%d) conflicts with no. " "of frames, etc. (%d %d %d %d)", VImageNBands (image), VImageNFrames (image), VImageNViewpoints (image), VImageNColors (image), VImageNComponents (image));
if (!VImageAttrList (image) ||
(result =
VGetAttr (VImageAttrList (image), VViewpointInterpAttr,
VBandInterpDict, VLongRepn, &interp)) == VAttrMissing)
return VImageNViewpoints (image) >
1 ? VBandInterpOther : VBandInterpNone;
if (result == VAttrBadValue)
return VBandInterpOther;
switch (interp) {
case VBandInterpStereoPair:
if (VImageNViewpoints (image) != 2) {
VWarning ("VBandViewpointInterp: "
"Stereo-pair image has %d viewpoint dimension(s)",
VImageNViewpoints (image));
return VBandInterpOther;
}
return VBandInterpStereoPair;
}
return VBandInterpOther;
}
/*! \brief Routine for accessing an image's band interpretation information.
*
* \param image
* \return VBandInterp
*/
EXPORT_VISTA VBandInterp VImageColorInterp (VImage image)
{
VLong interp;
VGetAttrResult result;
if (VImageNBands (image) !=
(VImageNFrames (image) * VImageNViewpoints (image) *
VImageNColors (image) * VImageNComponents (image)))
VWarning ("VImageColorInterp: No. bands (%d) conflicts with no. " "of frames, etc. (%d %d %d %d)", VImageNBands (image), VImageNFrames (image), VImageNViewpoints (image), VImageNColors (image), VImageNComponents (image));
if (!VImageAttrList (image) ||
(result =
VGetAttr (VImageAttrList (image), VColorInterpAttr,
VBandInterpDict, VLongRepn, &interp)) == VAttrMissing)
return VImageNColors (image) >
1 ? VBandInterpOther : VBandInterpNone;
if (result == VAttrBadValue)
return VBandInterpOther;
switch (interp) {
case VBandInterpRGB:
if (VImageNColors (image) != 3) {
VWarning ("VBandColorInterp: RGB image has %d color dimension(s)", VImageNColors (image));
return VBandInterpOther;
}
return VBandInterpRGB;
}
return VBandInterpOther;
}
/*! \brief Routine for accessing an image's band interpretation information.
*
* \param image
* \return VBandInterp
*/
EXPORT_VISTA VBandInterp VImageComponentInterp (VImage image)
{
VLong interp;
VGetAttrResult result;
if (VImageNBands (image) !=
(VImageNFrames (image) * VImageNViewpoints (image) *
VImageNColors (image) * VImageNComponents (image)))
VWarning ("VImageComponentInterp: No. bands (%d) conflicts with no. " "of frames, etc. (%d %d %d %d)", VImageNBands (image), VImageNFrames (image), VImageNViewpoints (image), VImageNColors (image), VImageNComponents (image));
if (!VImageAttrList (image) ||
(result =
VGetAttr (VImageAttrList (image), VComponentInterpAttr,
VBandInterpDict, VLongRepn, &interp)) == VAttrMissing)
return VImageNComponents (image) >
1 ? VBandInterpOther : VBandInterpNone;
if (result == VAttrBadValue)
return VBandInterpOther;
switch (interp) {
case VBandInterpComplex:
if (VImageNComponents (image) != 2) {
VWarning ("VBandColorInterp: Complex image has %d component(s)", VImageNComponents (image));
return VBandInterpOther;
}
return VBandInterpComplex;
case VBandInterpGradient:
if (VImageNComponents (image) > 3) {
VWarning ("VBandColorInterp: Gradient image has %d component(s)", VImageNComponents (image));
return VBandInterpOther;
}
return VBandInterpGradient;
case VBandInterpIntensity:
if (VImageNComponents (image) > 1) {
VWarning ("VBandColorInterp: Intensity image has %d component(s)", VImageNComponents (image));
return VBandInterpOther;
}
return VBandInterpIntensity;
case VBandInterpOrientation:
if (VImageNComponents (image) > 1) {
VWarning ("VBandColorInterp: "
"Orientation image has %d component(s)",
VImageNComponents (image));
return VBandInterpOther;
}
return VBandInterpOrientation;
}
return VBandInterpOther;
}
/*! \brief Set all of an image's standard band interpretation attributes.
*
* \param image
* \param frame_interp
* \param nframes
* \param viewpoint_interp
* \param nviewpoints
* \param color_interp
* \param ncolors
* \param component_interp
* \param ncomponents
* \return VBoolean
*/
EXPORT_VISTA VBoolean VSetBandInterp (VImage image,
VBandInterp frame_interp, int nframes,
VBandInterp viewpoint_interp, int nviewpoints,
VBandInterp color_interp, int ncolors,
VBandInterp component_interp, int ncomponents)
{
VBoolean result = TRUE;
VString str;
if (VImageNBands (image) !=
nframes * nviewpoints * ncolors * ncomponents) {
VWarning ("VSetBandInterp: No. bands (%d) conflicts with no. "
"of frames, etc. (%d %d %d %d)",
VImageNBands (image), nframes, nviewpoints, ncolors,
ncomponents);
result = FALSE;
}
if (frame_interp == VBandInterpNone)
result &=
VExtractAttr (VImageAttrList (image),
VFrameInterpAttr, NULL, VStringRepn,
&str, FALSE);
else
VSetAttr (VImageAttrList (image), VFrameInterpAttr,
VBandInterpDict, VLongRepn, (VLong) frame_interp);
VImageNFrames (image) = nframes;
if (viewpoint_interp == VBandInterpNone)
result &=
VExtractAttr (VImageAttrList (image),
VViewpointInterpAttr, NULL, VStringRepn,
&str, FALSE);
else
VSetAttr (VImageAttrList (image), VViewpointInterpAttr,
VBandInterpDict, VLongRepn,
(VLong) viewpoint_interp);
VImageNViewpoints (image) = nviewpoints;
if (color_interp == VBandInterpNone)
result &=
VExtractAttr (VImageAttrList (image),
VColorInterpAttr, NULL, VStringRepn,
&str, FALSE);
else
VSetAttr (VImageAttrList (image), VColorInterpAttr,
VBandInterpDict, VLongRepn, (VLong) color_interp);
VImageNColors (image) = ncolors;
if (component_interp == VBandInterpNone)
result &=
VExtractAttr (VImageAttrList (image),
VComponentInterpAttr, NULL, VStringRepn,
&str, FALSE);
else
VSetAttr (VImageAttrList (image), VComponentInterpAttr,
VBandInterpDict, VLongRepn,
(VLong) component_interp);
VImageNComponents (image) = ncomponents;
return result;
}
/*! \brief Read a Vista data file, extract the images from it, and return a
* list of them.
*
* \param file
* \param attributes
* \param images
* \return int
*/
EXPORT_VISTA int VReadImages (FILE * file, VAttrList * attributes, VImage ** images)
{
return VReadObjects (file, VImageRepn, attributes,
(VPointer **) images);
}
/*! \brief Write a list of images to a Vista data file.
*
* \param file
* \param attributes
* \param nimages
* \param images
* \return VBoolean
*/
EXPORT_VISTA VBoolean VWriteImages (FILE * file, VAttrList attributes, int nimages,
VImage images[])
{
return VWriteObjects (file, VImageRepn, attributes, nimages,
(VPointer *) images);
}