The RTI Image File Format

C. Furlong
WPI-ME/CHSLT


Overview

RTI images are non-standard bitmap based format used in the 16/32-bit data images generated by WPI-ME/CHSLT's opto-electronic holography systems.  RTI images are written in binary format and consisting of: Data stored in the 16-bit images is of the short int type (2 bytes) and data stored in the 32-bit images is of the float type (4-bytes).  The header of an RTI image can be read by defining the following C structures:
 
struct TimeCode
{
  short int scene;   /* 0-999       */
  short int hour;    /* 0- 23       */
  short int minute;  /* 0- 59       */
  short int second;  /* 0- 59       */
  short int frame;   /* 0- 29       */
  short int field;   /* 1-  2  Note: -1 indicated non-valid field */
};

typedef struct _FileHeaderData {
  char signiture[4];
  char suffix[4];
  char dataSize;
  char camNum;                     /* Added for holograms */
  short int space1;
  short int saveMethod;
  short int formatRevision;
  short int xMin;
  short int yMin;
  short int xMax;
  short int yMax;
  long annotationOffset;
  long dataOffset;
  char comment[80];
  double xScale;
  double yScale;
  double zScale;
  double xOrig;
  double yOrig;
  double zOrig;
  char pUnits[20];
  char iUnits[20];
  struct TimeCode timeCode;
  short int fileType;
} FileHeaderData;
 

First example:

Reads RTI file (16/32-bit) and extracts values on area of interest (AOI) defined by image coordinates (x1, y1)-(x2,y2).  Extracted data can be subsampled with delta increments: Delta_x and Delta_y.
Extracted data is written to output file in ASCII format.
 

/*                                                                                                       */
/* This program reads RTI 16 and 32 bit image files and         */
/* writes an output file with data number, pixel coordinates, */
/* and corresponding assigned values.                                     */
/*                                                                                                      */
/* Cosme Furlong                                                                          */
/* WPI-ME/Laser Laboratory                                                      */
/*                                                                                                      */

#include <stdlib.h> 
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include "rtiheader.h"

#define HOLO_SIGN  "RTI"
#define PI     (3.141592654)

main(argc,argv)
int argc;
char **argv;
{
    char iname[80];
    char head_rti[10];
    int IXSIZE;
    int IYSIZE;
    int datatype;
    int i, Xpo, Ypo;
    int size,count;
    int x1,x2,y1,y2,Del;
    int Off,corrV,nData;
    int Del_x,Del_y;
    FILE *handle_i,*handle_o;
    FileHeaderData hh;
    short value;
    float fval32;
    float maxv;
    void *pdata;

  if ( argc < 8 ) {
   printf("Error %s syntax: inp.rti out.txt x1 y1 x2 y2 del\n",argv[0]);
   exit(-1);
  }

  if ( (handle_i=fopen(argv[1],"r"))==NULL ) {
     printf("Could not open INPUT file!\n");
     exit(1);
  }

  fread(head_rti,10,1,handle_i);

  if (strncmp(head_rti,HOLO_SIGN,strlen(HOLO_SIGN)) == 0) {
     printf("Input file is an RTI file.\n\n");

    } else {

     printf("Input file is NOT an RTI file. Exiting....\n");
     exit(1);
  }

  x1 = atoi(argv[3]);
  y1 = atoi(argv[4]);
  x2 = atoi(argv[5]);
  y2 = atoi(argv[6]);
  Del= atoi(argv[7]);
  Del_x = (x2 - x1);
  Del_y = (y2 - y1);

  printf("Provided coordinates:\n");
  printf("(%d,%d)-(%d,%d)-%d\n\n",x1,y1,x2,y2,Del);

  if ( (x1 > x2) || (y1 > y2) ) {
     printf("Please check input coordinates. Exiting.\n");
     exit(1);
  }

/* Set input file location to first bit */

  fseek(handle_i,0,SEEK_SET);

/* Read 256-bit RTI header   */

  fread(&hh,sizeof(hh),1,handle_i);

/* Shift 256 bits     */

  fseek(handle_i,256,SEEK_SET);

/* Image size    */

  IXSIZE = (hh.xMax - hh.xMin + 1);
  IYSIZE = (hh.yMax - hh.yMin + 1);
  size = IXSIZE*IYSIZE;
  printf("Image size is: %d x %d\n",IXSIZE,IYSIZE);

/* Extract data type   */

  datatype = hh.dataSize;
  printf("RTI file is %d bits.\n",datatype);

  if (datatype == 8) {
     printf("This is not a data file.  Exiting.\n");
     exit(1);
  }

/*      OPEN OUTPUT FILE: ASCII FILE*/

  if ( (handle_o=fopen(argv[2],"w")) == NULL)
    {
     printf("Could not open OUTPUT file!\n");
     exit(1);
  }

/* SWITCH DEPENDING ON DATATYPE  */

    switch(datatype) 
      {
      case(16):

       printf("\n");
       printf("Working....\n\n");

        pdata = malloc(size*2);
        if (fread(pdata,size*2,1,handle_i) < 0) {
           printf("Reading input file error. Exiting.\n");
           exit(1);
        }

/* Find data offset and shift data pointer */

        Off = 512*y1+x1;
        printf("Input file offset: %d\n",Off);
        fseek(handle_i,Off,SEEK_SET);

         nData = 0;
        for (Ypo=0; Ypo <= Del_y; Ypo += Del) {
            for (Xpo=0; Xpo <= Del_x; Xpo += Del) {
               value = ((short*)pdata)[Off+Xpo];

/* Print to output file. Applying correction to Y coordinate.  */

               corrV = 0.8*(y1+Ypo);

               nData++;
              fprintf(handle_o,"%d %d %d %d\n",nData,x1+Xpo,corrV,value);
            }
            Off += (512)*Del;
         }

          printf("Number of data points written: %d\n",nData);

          printf("\n");
          printf("Done!\n\n");

           break;

      case(32):

         printf("\n");
         printf("Working....\n\n");

         pdata = malloc(size*4);
         if (fread(pdata,size*4,1,handle_i) < 0) {
         printf("Reading input file error. Exiting.\n");
         exit(1);
         }

        /* Find data offset and shift data pointer */

        Off = 512*y1+x1;
        printf("Input file offset: %d\n",Off);
        fseek(handle_i,Off,SEEK_SET);

        nData = 0;
        for (Ypo=0; Ypo <= Del_y; Ypo += Del) {
          for (Xpo=0; Xpo <= Del_x; Xpo += Del) {
             fval32 = ((float*)pdata)[Off+Xpo];
             if (fabs(fval32) > 1e20) fval32 = 0;

/*     Write all pixels.  Including bad ones.

             if (fval32) {
*/

/* Print to output file.  Applying correction to Y coordinate.  */

               corrV = 0.8*(y1+Ypo);

               nData ++;
              fprintf(handle_o,"%d %d %d %f\n",nData,x1+Xpo,corrV,fval32);
/*
            }
*/
          }
          Off += (512)*Del;
        }
        printf("Number of data points written: %d\n",nData);

        printf("\n");
        printf("Done!\n\n");

      break;

      default:

           printf("Datatype not supported.  Exiting...\n");
           exit(1);

      } /* End of switch  */

/* CLOSE FILES AND FREE MEMORY */

    fclose(handle_i);
    fclose(handle_o);
    free(pdata);
}



 

Second example:

Reads RTI file (16/32-bit) and writes 8-bit SGI image.

/* Program: rti2sgi.c                   */
/*                                              */
/* This program reads RTI 16/32-bit image files and        */
/* writes out a valid Grayscaled SGI image file (8-bit).      */
/* WPI-ME/Laser Laboratory     */
/* Written in ANSI C by              */
/* C. Furlong                               */
 

#include <stdlib.h> 
#include <stdio.h>
#include <math.h>
#include <unistd.h>

#define HOLO_SIGN   "RTI"
#define PI    (3.141592654)

putbyte(outf,val)
FILE *outf;
unsigned char val;
{
    unsigned char  buf[1];

    buf[0] = val;
    fwrite(buf,1,1,outf);
}

putshort(outf,val)
FILE *outf;
unsigned short val;
{
    unsigned char  buf[2];

    buf[0] = (val>>8);
    buf[1] = (val>>0);
    fwrite(buf,2,1,outf);
}

static int putlong(outf,val)
FILE *outf;
unsigned long val;
{
    unsigned char  buf[4];

    buf[0] = (val>>24);
    buf[1] = (val>>16);
    buf[2] = (val>>8);
    buf[3] = (val>>0);
    return fwrite(buf,4,1,outf);
}

struct TimeCode
{
  short int scene;   /* 0-999       */
  short int hour;    /* 0- 23       */
  short int minute;  /* 0- 59       */
  short int second;  /* 0- 59       */
  short int frame;   /* 0- 29       */
  short int field;   /* 1-  2  Note: -1 indicated non-valid field */
};

typedef struct _FileHeaderData {
  char     signiture[4];
  char     suffix[4];
  char     dataSize;
  char     camNum;    /*         Added for holograms */
  short int    space1;
  short int    saveMethod;
  short int    formatRevision;
  short int    xMin;
  short int    yMin;
  short int    xMax;
  short int    yMax;
  long     annotationOffset;
  long     dataOffset;
  char     comment[80];
  double    xScale;
  double    yScale;
  double    zScale;
  double    xOrig;
  double    yOrig;
  double    zOrig;
  char     pUnits[20];
  char     iUnits[20];
  struct    TimeCode timeCode;
  short int    fileType;
} FileHeaderData;

main(argc,argv)
int argc;
char **argv;
{
    char    iname[80];
    char    head_rti[10];
    unsigned char  outbuf[512];
    unsigned char  bufc[2];
    int     IXSIZE;
    int     IYSIZE;
    int     datatype;
    int     i, Xpo, Ypo;
    int     size,count,count2;
    int     maxi,mini,Diffi;
    FILE    *handle_i,*handle_o;
    FileHeaderData  hh;
    short    value;
    float    fval32;
    float    maxv,minv,Diff;
    void    *pdata;

 if ( argc < 3 ) {
  printf("\nError.  Try: \n");
  printf(">%s input_rti(16/32) output_sgi(8).\n", argv[0]);
 }

 if ( (handle_i=fopen(argv[1],"r"))==NULL ) {
  printf("Could not open INPUT file!\n");
  exit(1);
 }

 fread(head_rti,10,1,handle_i);

 if (strncmp(head_rti,HOLO_SIGN,strlen(HOLO_SIGN)) == 0) {
  printf("Input file is an RTI file.\n");

    } else {

  printf("Input file is NOT an RTI file. Exiting....\n");
  exit(1);
 }

 fseek(handle_i,0,SEEK_SET);
 fread(&hh,sizeof(hh),1,handle_i);
 fseek(handle_i,256,SEEK_SET);

 IXSIZE = (hh.xMax - hh.xMin + 1);
 IYSIZE = (hh.yMax - hh.yMin + 1);

 size = IXSIZE*IYSIZE;

 printf("Image size is: %d x %d\n",IXSIZE,IYSIZE);
 

 datatype = hh.dataSize;
 printf("RTI file is %d bits.\n",datatype);

 printf("Signature: %c\n",hh.signiture[0]);
 printf("Space: %d\n",hh.space1);
 printf("Save method: %d\n",hh.saveMethod);
 printf("Format revision: %d\n",hh.formatRevision);
 printf("xMin: %d\n",hh.xMin);
 printf("yMin: %d\n",hh.yMin);
 printf("xMax: %d\n",hh.xMax);
 printf("yMax: %d\n",hh.yMax);
 printf("Annotation offset: %d\n",hh.annotationOffset);
 printf("Data offset: %d\n",hh.dataOffset);
 printf("xScale: %lf\n",hh.xScale);
 printf("yScale: %lf\n",hh.yScale);
 printf("zScale: %lf\n",hh.zScale);
 printf("xOrig : %lf\n",hh.xOrig);
 printf("yOrig : %lf\n",hh.yOrig);
 printf("zOrig : %lf\n",hh.zOrig);
 printf("pUnits: %c\n",hh.pUnits[3]);
 printf("iUnits: %c\n",hh.iUnits[3]);

/*      OPEN OUTPUT FILE: SGI-IRIS  */

 if ( (handle_o=fopen(argv[2],"w")) == NULL) {
  printf("Could not open OUTPUT file!\n");
  exit(1);
 }

    putshort(handle_o,474);       /* MAGIC                       */
    putbyte(handle_o,0);          /* STORAGE is VERBATIM         */
    putbyte(handle_o,1);          /* BPC is 1                    */
    putshort(handle_o,2);         /* DIMENSION is 2              */
    putshort(handle_o,IXSIZE);    /* XSIZE                       */
    putshort(handle_o,IYSIZE);    /* YSIZE                       */
    putshort(handle_o,1);         /* ZSIZE                       */
    putlong(handle_o,0);          /* PIXMIN is 0                 */
    putlong(handle_o,255);        /* PIXMAX is 255               */

    for(i=0; i<4; i++) {      /* DUMMY 4 bytes       */
        putbyte(handle_o,0);
    }

    strcpy(iname,"WPI-ME/CHSLT");
    fwrite(iname,80,1,handle_o);  /* IMAGENAME           */
    putlong(handle_o,0);          /* COLORMAP is 0       */

    for(i=0; i<404; i++) {     /* DUMMY 404 bytes     */
        putbyte(handle_o,0);
    }

    switch(datatype) 
      {
      case(16):

/* Use the extraction of high and lower byte technique.
 It does not require memory allocation!.

 maxi = 0;
 for(Ypo=0; Ypo<IYSIZE; Ypo++) {
         for(Xpo=0; Xpo<IXSIZE; Xpo++) {
     fread(bufc,2,1,handle_i);
     value = (bufc[0]<<8)+(bufc[1]<<0);

     if (abs(value) > abs(maxi)) maxi = value;

     outbuf[Xpo] = value*8722/256;

     printf("Value(%d,%d): %d\n",Xpo,Ypo,value); 
   }

   fwrite(outbuf,IXSIZE,1,handle_o);
 }
        printf("Maximum pixel value: %d\n",maxi);

*/

  pdata = malloc(size*2);

        if (fread(pdata,size*2,1,handle_i) < 0) {
           printf("Reading input file error. Exiting.\n");
           exit(1);
        }

  mini = maxi = 0;
  for (Xpo=0; Xpo<size; Xpo++) {
     value = ((short*)pdata)[Xpo];
   if ( value >= maxi ) maxi = value;
   if ( value <= mini ) mini = value;
  }
  printf("Max.value(%d bit mode): %d\n",datatype,maxi);
  printf("Min.value(%d bit mode): %d\n",datatype,mini);

  Diffi = maxi-mini;
  if (abs(Diffi) < 1) {
   printf("RTI image contains no modulation. Exiting...\n");
   exit(-1);
  }

  printf("Writing output file...\n\n");
  count = count2 = 0;
  for(Ypo=0; Ypo<IYSIZE; Ypo++) {
        for(Xpo=0; Xpo<IXSIZE; Xpo++) {
    value = ((short*)pdata)[count2+Xpo];
    outbuf[Xpo] = (value-mini)*256/Diffi;
   }
   fwrite(outbuf,IXSIZE,1,handle_o);
   count++;
   count2 = count*IXSIZE;
  }

  break;

  case(32):

  pdata = malloc(size*4);

  if (fread(pdata,size*4,1,handle_i) < 0) {
   printf("Reading input file error. Exiting.\n");
   exit(-1);
  }

  minv  = 0.0;
  maxv  = 0.0;
  for (Xpo=0; Xpo<size; Xpo++) {
   fval32 = ((float*)pdata)[Xpo];
   if (fabs(fval32) >= 1.0e20) fval32 = 0.0;
   if ( fval32 >= maxv ) maxv = fval32;
   if ( fval32 <= minv ) minv = fval32;
  }
        printf("Max.value(%d bit mode): %f*pi\n",datatype,maxv/PI);
        printf("Min.value(%d bit mode): %f*pi\n",datatype,minv/PI);

  Diff = maxv-minv;
  if (fabs(Diff) < 1e-10) {
   printf("RTI image contains no modulation. Exiting...\n");
   exit(-1);
  }

  printf("Writing output file...\n\n");
  count = count2 = 0;
  for(Ypo=0; Ypo<IYSIZE; Ypo++) {
   for(Xpo=0; Xpo<IXSIZE; Xpo++) {
    fval32 = ((float*)pdata)[count2+Xpo];
    if (fabs(fval32) >= 1.0e20) {
     outbuf[Xpo] = 0.0;
    } else {
     outbuf[Xpo] = (fval32-minv)*256/Diff;
    }
   }
   fwrite(outbuf,IXSIZE,1,handle_o);
   count++;
   count2 = count*IXSIZE;
  }

        break;

      default:

  printf("Not a data file - PBM file.  Exiting...\n");
  exit(-1);
 

      } /*  switch  */
 

 printf("\n Done!\n");
 

/* CLOSE FILES AND FREE MEMORY */

    fclose(handle_i);
    fclose(handle_o);
    free(pdata);
}
 


Back to top
Back to ME-593N page


[Main]



[Mechanical Engineering Department]


[CHSLT / NEST Labs]