This HTML automatically generated with rman for NEMO
Table of Contents


image - binary format for 2D and 3D image/cube "ccd" files


#include <stdinc.h>
#include <filestruct.h>
#include <image.h>


image implement a rectangular 2-dimensional matrix or 3-dimensional cube in a filestruct(5NEMO) datafile. The current implementation restricts images to well known 2- and 3-dimensional cases, as well as the restriction that the whole image must be in memory. See mdarray(3NEMO) for a more general multi-dimensional array interface (though there is no special I/O interface for this data structure). The coordinate transformation to world coordinates is by no means restricted to a simple linear equation of the form:
        x.w.c. = SCALE * i + OFFSET
where i runs from 0 to N-1, the dimension of the matrix in any of its coordinates.

Image files are used in 2D and 3D images, i.e. a matrix of values of any kind (intensity, velocity etc.). The output format of image(3NEMO) files is the general binary structured fileformat as described in filestruct(3NEMO) .

The data is stored on disk in Fortran (column-major) or C (row-major) fashion, as in Data(row,column,plane) depending on a compile switch or #define in the image.h module, which must be included in every program using images. The default compilation is using the FORDEF, i.e. x coordinate running fastest in memory (compatibility with existing contour and FITS routines).

There is some experimental code in image.c to compile with -DUSE_IARRAY (Iliffe vectors).


For no good reason NEMO grew names different from FITS, so here’s the dictionary between them
     NAXISi     nx,ny,nz
     CRVALi     xmin,ymin,zmin
     CDELTi     dx,dy,dz
     CRPIXi     xref,yref,xref
     CTYPEi     namex,namey,namez
     CUNITi     unitx,unity,unitz
     BUNIT      unit
     BMAJ       beamx
     BMIN       beamy


typedef struct {
    real   *frame;     /* pointer to datablock */
    real   **matrix;     /* 2D special case: pointers to pointers */
    real   ***cube;      /* 3D special case: ptr to ptr to ptr’s  */
    int    axis;         /* axis type (0=old, no ref pixel; 1=with Xref
    int    nx;         /* number of pixels along x-axis NAXIS1 */
    int    ny;         /* number of pixels along y-axis NAXIS2 */
    int    nz;           /* number of pixels along z-axis NAXIS3 */
    real   xmin;     /* x-value belonging to reference x-pixel CRVAL1 */
    real   ymin;     /* y-value belonging to reference y-pixel CRVAL2 */
    real   zmin;     /* z-value belonging to reference z-pixel CRVAL3 */
    real   dx;         /* step in x-pixel CDELT1 */
    real   dy;         /* step in y_pixel CDELT2 */
    real   dz;         /* step in z_pixel CDELT3 */
    real   xref;         /* reference pixel in X (0 the first) CRPIX1 */
    real   yref;         /* reference pixel in Y CRPIX2 */
    real   zref;         /* reference pixel in Z CRPIX3 */
    real   map_min;      /* minimum map value */
    real   map_max;      /* maximum map value */
    int    beamtype;        /* type of beam used for beam smoothing */
    real   beamx;        /* beamwidth along x (if used) */
    real   beamy;        /* beamwidth along y (if used) */
    real   beamz;        /* beamwidth along z (if used) */
    string namex;        /* pointer to x-axis name string CTYPE1 */
    string namey;        /* pointer to y-axis name string CTYPE2 */
    string namez;        /* pointer to z-axis name string CTYPE3 */
    string unitx;        /* pointer to x-axis unit string CUNIT1 */
    string unity;        /* pointer to y-axis unit string CUNIT2 */
    string unitz;        /* pointer to z-axis unit string CUNIT3 */
    string unit;                /* BUNIT */
    real   time;
    string storage;        /* pointer to storage fashion string */
} image, *imageptr;


Accessing the individual structure components can be done through some pre-define macros (in image.h):
#define Frame(iptr)    ((iptr)->frame)
#define Nx(iptr)    ((iptr)->nx)
#define Ny(iptr)    ((iptr)->ny)
#define Nz(iptr)    ((iptr)->nz)
#define Axis(iptr)    ((iptr)->axis)
#define Xmin(iptr)     ((iptr)->xmin)
#define Ymin(iptr)     ((iptr)->ymin)
#define Zmin(iptr)     ((iptr)->zmin)
#define Dx(iptr)    ((iptr)->dx)
#define Dy(iptr)    ((iptr)->dy)
#define Dz(iptr)    ((iptr)->dz)
#define Xref(iptr)     ((iptr)->xref)
#define Yref(iptr)     ((iptr)->yref)
#define Zref(iptr)     ((iptr)->zref)
#define MapMin(iptr)    ((iptr)->map_min)
#define MapMax(iptr)    ((iptr)->map_max)
#define BeamType(iptr)    ((iptr)->beamtype)
#define Beamx(iptr)    ((iptr)->beamx)
#define Beamy(iptr)    ((iptr)->beamy)
#define Beamz(iptr)    ((iptr)->beamz)
#define Namex(iptr)    ((iptr)->namex)
#define Namey(iptr)    ((iptr)->namey)
#define Namez(iptr)    ((iptr)->namez)
#define Unit(iptr)      ((iptr)->unit)
#define Storage(iptr)   ((iptr)->storage)
/* row major */
#if defined(CDEF)
#define MapValue(iptr,ix,iy)    (*( (iptr)->frame + iy + ix*Ny(iptr) ))
#define CubeValue(iptr,ix,iy,iz)    (*( (iptr)->frame + iz + Nz(iptr)*(iy + Ny(iptr)*ix)))
/* column major */
#if defined(FORDEF)
#define MapValue(iptr,ix,iy)     (*( (iptr)->frame + ix + Nx(iptr)*iy) )
#define CubeValue(iptr,ix,iy,iz)    (*( (iptr)->frame + ix + Nx(iptr)*(iy+Ny(iptr)*iz)))

Array Notation

The MapValue and CubeValue macros are sometimes cumbersome typography, and using two image library routines, map2_image and map3_image these can be converted to the commonly used array syntax:
    image *iptr = open_image(....);
    real **a = map2_image(iptr);
    for (i=0; i<nx; i++)
        for (j=0; j<nx; j++)
            a[i][j] = 0.0;

The following example creates a simple cube by which you can test the row-major and column-major implementations.

In CDef mode:

    % ccdmath "" cube0 "%x+10*%y+100*%z" 4,3,2
    % tsf cube0
    double MapValues[4][3][2] 0.00000 100.000 10.0000 110.000 20.0000 120.000
...  123.000
In ForDef mode:
    % tsf cube0
    double MapValues[4][3][2] 0.00000 1.00000 2.00000 3.00000 10.0000 11.0000
... 123.000


The current default images (axis=0) have their origin at the first (lower-left = 0,0) pixel. In FITS parlance, there is no freedom in the location of the reference pixel, it’s (0,0). For axis=1 (most programs now support it, notably ccdfits(1NEMO) and fitsccd(1NEMO) ) this limitation will go away, but only simple cartesian coordinate systems are supported. There is no astronomical WCS support, other than labeling it. Perhaps this will be for a future axis=2.

Future Expansions

Code could be modified to use dynamem(3NEMO) . Allows more flexable use by addressing image[i][j] instead of slower (?) macros MapValue(iptr,i,j)

See Also

snapshot(5NEMO) , image(3NEMO) , tsf(1NEMO) , mdarray(3NEMO)


Peter Teuben


~/src/pjt/image       image.c image.h image.3 image.5

Update History

29-Jun-87    V1.0: Original created    PJT
30-Jun-87    V2.0: use struct as interface    PJT
22-May-88    comment to use dynamem(3NEMO)    PJT
23-dec-88    V2.3: velocity added to header    PJT
18-jan-89    V3.0: 3D added PJT
1-feb-89    V4.0: compile switch for FORDEF and CDEF matrix storage    PJT
21-feb-00    A[i][j] usage            PJT
19-may-03    improved documentation    PJT
8-may-04    V5.0: added reference pixel for axis type 1    PJT
7-may-13    added benchmark example
27-jan-2021    noted axis=1 now becoming standard    PJT

Table of Contents