Ary - a library for 2D dynamic array manipulation

NAME

makary, makCary, makBary, makSary, makIary, makFary, makDary, makPary, makUSary, makRGBary, makXRGBary, makYUVary, makFRGBary, makRGIary makmemary, consAry, consAry1, destAry, rowsAry, colsAry, startAddrAry, InitialiseBary, InitialiseFary, InitialisePary, InitialiseUSary, WriteAry, ReadAry, printFary, printIary, CopyAry, ScaleMaxFary, ReadP5header, P5pgm2Bary, P4pbm2Bary, P5pgm2Fary, P6ppm2RGBary, MoveP6ppm2RGBary, P6ppm2YUVary, Bary2P5pgm, Bary2P4pbm, RGBary2P6ppm, YUVary2P6ppm, Bary2P5pgmCm, Bary2P4pbmCm, RGBary2P6ppmCm, CutFary2P5pgm, ScaleFary2P5pgm, P5pgmRoi2Fary, P5pgmRoi2Fary1

SYNOPSIS

"#include ''ary.h'' 

ARY*     makary(int fr, int lr, int fc, int lc, int matrix_type); 
void     destAry(ARY * ary);" 
void*    consAry1 
#define  consAry 

"CARY *makCary(int rows, int cols);" 
"BARY *makBary(int rows, int cols);" 
"SARY *makSary(int rows, int cols);" 
"IARY *makIary(int rows, int cols);" 
"FARY *makFary(int rows, int cols);" 
"DARY *makDary(int rows, int cols);" 
"PARY *makPary(int rows, int cols);" 
USARY *makUSary(int rows, int cols); 
RGBARY *makRGBary(int rows, int cols); 
XRGBARY *makXRGBary (int rows, int cols); 
YUVARY *makYUVary (int rows, int cols); 
FRGBARY *makFRGBary (int rows, int cols); 
RGIARY *makRGIary (int rows, int cols) ; 

#define rowsAry(a) 
#define colsAry(a) 
#define startAddrAry(a) 

"void InitialiseBary(  BARY *array, int value  );" 
"void InitialiseFary(  FARY *array, float value );" 
"void InitialisePary(  PARY *array, void * ptr );" 
void InitialiseUSary(  USARY *array, unsigned short int ptr ); 

FILE* ReadP5header(char * filename, int * cols, int * rows); 
BARY* P5pgm2Bary(char * filename);    
BARY* P4pbm2Bary(char * filename);   
FARY* P5pgm2Fary(char * filename); 
RGBARY* P6ppm2RGBary(char * filename); 
RGBARY* MoveP6ppm2RGBary(RGBARY * RGBary, char * filename); 
YUVARY* P6ppm2YUVary(char * filename); 

void* Bary2P5pgm(BARY * image, char * filename); 
void* Bary2P4pbm(BARY * image, char * filename); 
void* RGBary2P6ppm(RGBARY * image,char * filename); 
void* YUVary2P6ppm(YUVARY * image,char * filename); 

void* Bary2P5pgmCm(BARY * image,char * filename,char * comment) ; 
void* Bary2P4pbmCm(BARY * image, char * filename,char * comment); 
void* RGBary2P6ppmCm(RGBARY * image,char * filename,char * comment); 

void CutFary2P5pgm(FARY * image,char * filename); 
void ScaleFary2P5pgm(FARY * image,char * filename) ; 


FARY* P5pgmRoi2Fary(char * filename, int * roi, int fullImage, int extend); 
FARY* P5pgmRoi2Fary1 (FILE * file, int cols, int rows, int * roi, 
                              int fullImage, int extend, void * mem); 

void WriteAry(ARY *ary,char * filename); 
ARY * ReadAry(char *filename); 

"ARY * CopyAry(ARY * ary);" 
"void NormFary(FARY *mask,float value);" 
"void ScaleMaxFary(FARY *ary,int requested_max) ;" 
"BARY *  Fary2Bary(FARY *fary);" 
"BARY *  ScaleFary2Bary(FARY *fary);" 
"" 

t_frgb  Yuv2Frgb(t_yuv p) ; 
t_rgb   Yuv2Rgb(t_yuv p); 
t_rgI   Yuv2Rgi(t_yuv yuv); 

t_rgI   Frgb2Rgi(t_frgb frgb); 
t_rgI   Rgb2Rgi(t_rgb rgb); 
t_rgI   Yuv2Rgi(t_yuv yuv); 

t_rgb  Frgb2Rgb(t_frgb frgb); 
t_frgb Rgb2Frgb(t_rgb frgb); 
t_rg   Frgb2Rg(t_frgb frgb); 

RGBARY*  YUVary2RGBary(YUVARY * ary) ; 
FRGBARY* YUVary2FRGBary(YUVARY * ary); 
RGIARY*  YUVary2RGIary(YUVARY * ary) ; 
BARY *    Fary2Bary(FARY *fary); 

BARY *    ScaleFary2Bary(FARY *fary); 
RGBARY *  XRGBary2RGBary(XRGBARY * image) ; 
RGBARY *  XBGRary2RGBary(XRGBARY *xrgb) ; 

SARY *  Bary2Sary(BARY *bary); 
BARY *  Sary2Bary(SARY *sary); 



DESCRIPTION

Introduction

The ary library contains functions for manipulating 2D dynamic arrays; ie. arrays with sizes determined at run time. Moreover, contrary to standard C arrays, both lower and upper bounds can be specified (ie. lower bound need not be 0). The dynamic arrays are expected to represent images (grey-level, color, binary), therefore a number of functions treating ARY's as internal representations of images was added. ARY's can be stored in and read from image files in the pgm/pbm/ppm formats. Array elements for various representations of colour are available together with conversion functions. A simple facility allowing users to define ARY's of any type has been added to the library.

The ARY structure

The basic ARY structure is defined as:
typedef struct { 
   int lb1;            /* first row index */ 
   int ub1;            /* index of last row */ 
   int lb2;            /* index of first column */ 
   int ub2;            /* index of the last column */ 
   int ary_type;       /* the type of the ARY */ 
   ELEMENT_TYPE  **el; /* pointer to a pointer to array element*/ 
} ARY_NAME; 

This version of the ary library supports the following ELEMENT_TYPES: 
ELEMENT_TYPE               ARY_NAME      Constructor 
char                       CARY          makCary(rows,cols) 
unsigned char              BARY          makBary(rows,cols) 
short int                  SARY          makSary(rows,cols) 
int                        IARY          makIary(rows,cols) 
float                      FARY          makFary(rows,cols) 
double                     DARY          makDary(rows,cols) 
void *                     PARY          makPary(rows,cols) 
t_rgb                      RGBARY        makRGBary(rows, cols) 
t_frgb                     FRGBARY       makFRGBary (rows, cols) 
t_xrgb                     XRGBARY       makXRGBary (rows, cols) 
t_yuv                      YUVARY        makYUVary (rows, cols) 
t_rgI                      RGIARY        makRGIary (rows, cols)  


any_ary_type makary (int fr,int lr,int fc,int lc,int type) 
any_ary_type makmemary (int fr,int lr,int fc,int lc,int type,void *addr); 
any          consAry (rows,cols,type) 
any          consAry1 (int fr,int lr,int fc,int lc,int elSize,void * mem); 
The t_rgb, t_frgb, t_xrgb, t_yuv, t_rgI (see ary.h) declare structures that can hold:
      t_rgb        red, green, blue components, each represented as a byte 
      t_frgb       red, green, blue components, each represented as a float 
      t_xrgb       x, red, green, blue compenents as in SUN rasterfile  
      t_yuv        yuv components of a digitized PAL video signal 
      t_rgI        red and gren chromaticity + intensity representation of 
                   colour 
Before using a variable of ARY type, the dynamic ARY structure must be created using a constructor. Preferably the constructor is called when the variable is declared, eg.

BARY * array_of_bytes = makBary(250,16);

This creats a 2D array of unsigned chars (bytes). Individual elements of the array can be accessed using the [] notation:

elem = array_of_bytes->el[7][7];

The lower and upper bounds are stored in the lb1,lb2, ub1,ub2 fields so scanning all array elements would typically look like:



/*--------------------- cut here -----------------------*/ 
int main(void) 
{ 
  BARY * image = makBary(30,30) 


  int i,j; 


  /*--------- initialise all elements to 0  -------------*/ 
  for(i=image->lb1; i<=image->ub1; i++)   
    for(j=image->lb2; j<=image->ub2; j++) 
       image->el[i][j] = 0;        /* could use InitialiseBary*/ 
  
  /* do you processing here */ 


  /*-------- free the memory used by ary ----------------*/ 
  destAry((ARY*)image);                   
  return 0; 
} 
/*--------------------- cut here -----------------------*/ 

Constructors

The ary library provides constructors for ARY varibles of all suported types. These constructors, listed in the previous section, set the lower bounds lb1, lb2 to 0. If non-zero lower bounds are required a more general constructor, makary, must be used, eg.

BARY * bary = makary(1,10,2,10,BYTEMATRIX);

This command allocates a 2D array with lower bounds 1 resp. 2 and both upper bounds 10. The last parameter defines the type of ARY required. The following constants are defined

     Type            Constant 
        CARY            UBYTEMATRIX 
        SARY            SHORTINTMATRIX 
        IARY            INTEGERMATRIX 
        FARY            FLOATMATRIX  
        DARY            DOUBLEMATRIX 
        BARY            BYTEMATRIX      
        PARY            POINTERMATRIX 
        RGBARY          RGBMATRIX 
        XRGBARY         XRGBMATRIX 
        FRGBARY         FRGBMATRIX  
        RGIARY          RGIMATRIX 
        USARY           USHORTINTMATRIX 
        any_other       USER_DEFINED   
The memory used by an ARY variable should be deallocated when a variable goes out of scope by a call to destAry, eg.

destAry((ARY*)bary)

The function destAry is declared to expect a parameter of type ARY. No variables of this type exist; the ARY type is used to indicate and ARY variable of any element type (int, float, etc.). ARYs must not be deallocated by a call to free(), this frees only a small part of the memory allocated for the ARY. Manipulation of ARY's of user-defined types is covered in a separate section (see User-defined types).

Initialisation

After construction through a call to mak____, the contents of an ARY variable is undefined. Functions InitialiseBary, InitialiseFary, InitialisePary could be used to set all elements to the same value passed as a seconde argument to these functions.

Input/Output functions

Functions WriteAry(), ReadAry() can store and retrieve an ary matrix of any type, including int, float and double in the most compact format possible. Files writen out by writeAry conventionally have .ary suffix and are said to be in the ary format. These functions can be used for passing matrices of various types between programs. An ary file can be converted to viff using the arytoviff program. Consequently, even double/int/float matrices can be viewed using KHOROS tools editimage and xprism3. If filename is '-' then the file is read from stdin (written to stdout). Note that the ary format is not portable across architectures/ programming environments that store int/floats/doubles in different formats. This is a penalty for maximum space and time efficiency (the contents of an ary file is a straightforward bit-wise copy of elements). If portability is an isue, convert .ary into VIFF format of the Khoros package.

Pbmplus interface

ARY's can be stored in and read from a file format used in the pbmplus package of Jeff Poskanzer. The package provides a large number of image manipulation routines. Moreover, files in this format are accepted by xv, a sophisticated image viewer written by John Bradley (bradley@cis.upenn.edu). XV is an interactive tool that allows image resizing, cutting, conversion to a number of formats, etc.

The interface is provided by a number of functions with pgm/ppm/pbm in the function name. The functionality of each of the function is coded in the function name. P4pbm and P5pgm refer to the raw bitmap (pbm) and raw greylevel (pgm) image formats respectively. So P5pgm2Bary reads a pgm file into a BARY structure it allocates and returns. Bary2P5pgm writes an ARY to a P5 pgm file.

The family of output functions (write image from ARY) with the Cm suffix inserts a comment into the pbm/pgm/ppm file (in the required format). The Move prefix indicates that the image is read into an already existing ary, which must have the same size as the image read.

Scaling is necessary when a floating point matrix is output into a 256 level pgm image. CutFary2P5pgm replaces all values smaller then 0 by 0 and all values >255 by 255. ScaleFary2P5pgm finds a maximum of all elements which is then output as 255; other values are scaled linearly. A simple bitmap inversion serves as an example:

/*--------------------- cut here -----------------------*/ 
int main() 
{ 
  BARY * image = P4pbm2Bary("-");     /* read P4 from stdin */ 


  int i,j; 


  for(i=image->lb1; i<=image->ub1; i++) 
    for(j=image->lb2; j<=image->ub2; j++) 
       image->el[i][j] = 255 - image->el[i][j];    /* invert */ 


  Bary2P4pbm(image,"-");      /* write as P4 to stdout  */ 


  destAry((ARY*)image); 
  return 0; 
} 


The P5pgmRoi2Fary(char * filename, int * roi, int fullImage, int extend) function reads a rectangular area (a region of interest - ROI) from the matrix (image) stored in the 'filename' file. If the 'fullImage' is set to a non-zero value, the roi parameter will be ignored and the whole matrix (image) will be read in. Ohterwise (ie. if fullImage==0) the roi must point to and array of four integers specifying the region (rectangle) of interest in the following way: roi[0]=x_min (where x denotes the first coordinate of ary); roi[1]=x_max,roi[2]=y_min,roi[3]=y_max. The rectange defined through roi is clipped (intersected) with the matrix (image) read from file if a part of it is not inside the matrix; therefore the ARY returned by P5pgmRoi2Fary need not be of the same size of roi. For typical use the 'extend' parameter should be set to 0 and ignored. The P5pgmRoi2Fary function was written to support convolutions on regions of interest. If convolution is to be performed on the whole ROI, the data read must be 'extended' by half of the convolutin mask size. If the ROI is close to the border of the original image 'mirroring' is applied.

Miscellaneous functions

rowsAry(a) returns the number of rows in a, ie. a->ub1 - a->lb1 + 1. colsAry(a) returns the number of colums in a, ie.i a->ub2 - a->lb2 + 1. startAddrAry(a) returns the address of the first element in a.

CopyAry creates a copy of an ary of any type. NormFary(FARY *fary,float value) normalises FARY so that the summ of its absolute values is 'value'. ScaleMaxFary(FARY *ary,int requested_max) scales a FARY so that it's maximum (positive, not absolute!) is equal to the requested_max value. Fary2Bary convets FARY to BARY by setting all values above 255 to 255, all values bellow 0 to 0 and flooring (not rounding) the remaning values. ScaleFary2Bary scales FARY to BARY so that the maximum element becomes 255 and the others are linearly rescaled.

Conversion between colour representations

Yuv2Frgb, Yuv2Rgb, Yuv2Rgi, Frgb2Rgi, Rgb2Rgi, Yuv2Rgi, Frgb2Rgb, Rgb2Frgb, Frgb2Rg convert colour information stored in various systems. The names of the functions define the functionality (see The ARY structure section for definitions of the various types). YUVary2RGBary, YUVary2FRGBary, YUVary2RGIary convert colour images.

User-defined types

A new ARY type can be defined and used as follows:
  typefef struct{....} myType; 
  DEFINE_ARY(myTypeARY, myType); 


   myTypeARY *ary = consAry(100,100,myType); 


   myType      x =   .... ;  /* initialise your structure */ 
   ary->el[1][1] =  x; 
User-defined ARY's can be constructed using consAry (instead of mak?ary) with lower bounds set to 0. consAry1 allows to specify lower bounds. User-defined ARY's can be copied, written to file, read from a file and destroyed. Individual elements are accessed in the standard way.

SEE ALSO

pbmplus, pgm, pbm, xv, khoros, xprism3, editimage, sun rasterfile

AUTHOR

George Matas, University of Surrey (g.matas@ee.surrey.ac.uk). The original ARY library was written buy Ron Cain of SRI-International at Palo Alto ('The Ary Structure' section contains parts of the original man page). A modified version was obtained by UoS from R. Horaud of LIFIA Grenoble, France.

At UoS the library was ANSI-fied, made portable by changing the internal representation of ARY. Other additions: the structures for aggregate types, possibility to declare ARY of a user-defined type (without modifing the library), the generic I/O (essentially external rep. of ary), interface to the pgm package;a couple of miscelanous functions and macros, conversion functions between colour representations. The pbm/pgm/ppm formats were defined in the pbmplus packages written by Jef Poskanzer (jef@well.sf.ca.us).


23-May-95. Automatically converted by man2html, written by G.Matas (g.matas@ee.surrey.ac.uk)