home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************/
- /* Copyright (C) 1989, California Institute of Technology */
- /* U. S. Government Sponsorship under NASA Contract */
- /* NAS7-918 is acknowledged. */
- /*************************************************************/
-
- /*** IMDISP module IMAGEIO.C
- Image I/O routines for labeled images
-
- Includes routines for opening images, reading and writing
- image lines, and converting pixel formats.
- ***/
-
- /* * * * INCLUDE files * * * */
-
- #include <ctype.h>
- #include <malloc.h>
- #include <process.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "imdef.h"
- #include "imdisp.h"
- #include "disputil.h"
- #include "fileio.h"
- #include "labutil.h"
- #include "refresh.h"
-
- /* * * * External functions * * * */
-
- /* * * * Function declarations * * * */
-
- int ReadLabel (int ,char *,int ,char *);
- int WriteLabel (int ,char *,unsigned int ,char *);
- int OpenImage (char *,int ,char *,int *,int *,int *,char *);
- int ReadLine (int, char *, int, int, int, char *);
- int CloseImage (int ,char *);
- int CheckStatus (char *);
- int ConvertLine (unsigned char *,unsigned char *,int ,int ,int ,char *);
-
- /* * * * Global Variables * * * */
-
- /* The image control block structure */
- struct ImageBlockType
- {
- long block; /* block # of start of buffer at */
- int blksiz; /* block size in bytes */
- int maxbuf; /* max size of buffer in blocks */
- int bufsiz; /* # of blocks of buffer in use */
- unsigned int lblsiz; /* label size in bytes */
- int pixsiz; /* size of pixels in bits */
- int reclen; /* record length in bytes */
- int nl, ns; /* number of lines and samples */
- int linhed; /* line header length in bytes */
- char access; /* R for read, W for write */
- } IMCB[MaxNumImages];
-
-
- unsigned char *ImageBuffer[MaxNumImages]; /* pointers to image buffers */
- char LabelBuf[LabelBufferLen];
- char LabelFileName[64];
-
- int ReadLabel (int unit, char * LabelBuf, int LabelLength, char * status)
-
- /* ReadLabel reads a buffer full of the beginning of the file and
- copies part of it to the label buffer in uppercase.
- */
-
- {
- int i, * len, length, next = 0;
-
- IMCB[unit].block = 0L;
- ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
- memcpy (LabelBuf, ImageBuffer[unit], LabelLength);
- if (strncmp(LabelBuf+2,"CCSD",4) == 0 ||
- strncmp(LabelBuf+2,"NJPL",4) == 0)
- do
- {
- len = (int *)LabelBuf[next];
- length = *len;
- length += length%2;
- LabelBuf[next] = 13; LabelBuf[next+1] = 10;
- if (strncmp(LabelBuf+next+2,"END",3) == 0 && length < 5)
- break;
- next += length+2;
- } while (next < LabelLength);
-
- for (i = 0; i < LabelLength; i++)
- {
- LabelBuf[i] = toupper(LabelBuf[i]);
- if (LabelBuf[i] == 0) LabelBuf[i] = 32;
- }
- }
-
-
-
-
- int WriteLabel (int unit, char * LabelBuf, unsigned int labelsize,
- char * status)
-
- /* WriteLabel writes the passed label out to the image buffer.
- If the label record is larger than the image buffer then
- the buffer is written to disk.
- */
-
- {
- int movebytes, bytesleft, inptr;
-
- strcpy (status, "");
- memset (ImageBuffer[unit], 0, LabelBufferLen);
-
- IMCB[unit].block = 0L;
- if (labelsize < LabelBufferLen)
- movebytes = labelsize;
- else
- movebytes = LabelBufferLen;
- memcpy (ImageBuffer[unit], LabelBuf, movebytes);
- IMCB[unit].bufsiz = ((movebytes-1) / IMCB[unit].blksiz) + 1;
- bytesleft = labelsize - movebytes;
- inptr = movebytes;
-
- while (bytesleft > 0)
- {
- WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, status);
- if (strlen(status) > 0) return;
- IMCB[unit].block = IMCB[unit].block + IMCB[unit].maxbuf;
- if (bytesleft < LabelBufferLen)
- movebytes = bytesleft;
- else
- movebytes = LabelBufferLen;
- memset (&ImageBuffer[unit][movebytes], 0, ImBufMax-movebytes);
- memcpy (ImageBuffer[unit], &LabelBuf[inptr], movebytes);
- IMCB[unit].bufsiz = ( (movebytes-1) / IMCB[unit].blksiz ) + 1;
- bytesleft = bytesleft - movebytes;
- inptr = inptr + movebytes;
- }
- }
-
- int OpenImage (char * filename, int unit, char * IOmode, int * p_nline,
- int * p_nsamp, int * p_bitsperpix, char * status)
-
- /*** OpenImage opens an image file either for reading or writing. The
- size of the image and pixel format are returned if the file is
- opened for reading. If the file is opened for writing then the
- passed number of lines and samples and pixel format are used for
- the new image. The unit number is used to refer to the file in
- subsequent operations. If the file is opened for input then the
- label processing routines will parse Vicar2 and PDS labels and
- will prompt for user info if the image is unlabeled. PDS detached
- labels and palettes are handled transparently in this routine. If
- the file is for writing then a PDS label will be output. An error
- is returned if there is insufficient room to dynamically allocate
- the image buffer, or if there is a file error. For images with
- pixel sizes less than a byte, each line is assumed to start with a
- new byte.
-
- Parameter Type In/out Description
-
- filename char ptr in Name of image file to open
- unit int in Unit number of image (0,1,2...)
- IOmode char ptr in Access mode of file
- ("r..." for reading, "w..." for writing)
- p_nline int ptr in/out The number of lines in the image
- p_nsamp int ptr in/out The number of samples in the image
- p_bitsperpix int ptr in/out The number of bits in a pixel (pixel format)
- (16 for integer, 8 for byte,
- 4 for nibble, 1 for binary)
- status char ptr out Return string with error message
- (0 length string if no error)
-
- ***/
-
- {
- char LabelBuf[LabelBufferLen];
- int reclen, lineheadbytes, p;
- unsigned int labelsize;
- unsigned int size;
- char accessmode[2], format, DetachedFileName[64], tmpstr[64];
- char DetachedPaletteName[64];
-
-
- if ( (unit < 0) || (unit > MaxNumImages-1) )
- {
- strcpy (status, "Illegal unit number");
- return;
- }
- accessmode[1] = 0;
- accessmode[0] = toupper(IOmode[0]);
- if (accessmode[0] != 'W')
- accessmode[0] = 'R';
-
- OpenFile (filename, unit, accessmode, &IMCB[unit].blksiz, status);
- if (strlen(status) > 0) return;
-
- /* Allocate image buffer on heap */
- /* Only allocate 2048 bytes for output buffer */
- size = (accessmode[0]=='W') ? LabelBufferLen : ImBufMax;
-
- while ( (ImageBuffer[unit] = malloc (size)) == NULL )
- FreeRefresh("imgbuffer");
-
- IMCB[unit].maxbuf = size / IMCB[unit].blksiz; /* MDM 2/3/88*/
-
- if (accessmode[0] == 'R')
- {
- ReadLabel (unit, LabelBuf, LabelBufferLen, status);
- if (strlen(status) > 0) goto CloseUp;
-
- /* patch for microsoft driver */
- /* this checks for dates found in certain positions in the extended
- attr record. These could be found elsewhere, but probably not */
- if (LabelBuf[10] == '1' && LabelBuf[11] == '9' &&
- LabelBuf[26] == '1' && LabelBuf[27] == '9')
- {
- Microsoft = 1; /*read the label again*/
- ReadLabel (unit, LabelBuf, LabelBufferLen, status);
- if (strlen(status) > 0) goto CloseUp;
- }
- else Microsoft = 0;
-
- /* end of patch */
-
- InterpretLabel (LabelBuf, LabelBufferLen,
- &labelsize, p_nline, p_nsamp, p_bitsperpix,
- &reclen, &lineheadbytes, DetachedFileName,
- DetachedPaletteName, unit);
- if (reclen == 0) return(0);
- LabelFileName[0]=NULL;
- if (strlen(DetachedFileName) > 0)
- {
- strcpy(LabelFileName,filename);
- CloseFile (unit, status);
- if ( (strchr(DetachedFileName, '\\') == NULL) &&
- (strchr(DetachedFileName, ':') == NULL) &&
- (strnicmp(filename,"CD:",3) != 0) )
- {
- p = strlen(filename) - 1;
- while ((p > -1) && (filename[p] != '\\')
- && (filename[p] != ':')) p--;
- strcpy (tmpstr, filename);
- tmpstr[p+1] = 0;
- strcat (tmpstr, DetachedFileName);
- strcpy (DetachedFileName, tmpstr);
- }
-
- OpenFile (DetachedFileName, unit, accessmode,
- &IMCB[unit].blksiz, status);
- if (strlen(status) > 0) goto FreeUp;
- IMCB[unit].maxbuf = ImBufMax / IMCB[unit].blksiz;
- IMCB[unit].block = 0L;
- ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
- if (strlen(status) > 0) goto CloseUp;
-
- /* patch for microsoft driver */
- if (ImageBuffer[unit][10] == '1' && ImageBuffer[unit][11] == '9' &&
- ImageBuffer[unit][26] == '1' && ImageBuffer[unit][27] == '9')
- {
- Microsoft = 1; /*read the label again*/
- ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
- if (strlen(status) > 0) goto CloseUp;
- }
- else Microsoft = 0;
-
- }
-
- if ( (strlen(DetachedPaletteName) > 0) || (Palette > 0L) )
- /* Ron Baalke - Added detached */
- { /* palette processing - 07/27/90 */
- LoadPalette(DetachedPaletteName);
- }
-
- }
-
- else
- {
- reclen = ( (long)*p_nsamp* (long)*p_bitsperpix - 1 )/8 + 1;
- MakeLabel (LabelBuf, &labelsize, *p_nline, *p_nsamp,
- *p_bitsperpix, reclen);
- WriteLabel (unit, LabelBuf, labelsize, status);
- if (strlen(status) > 0) goto CloseUp;
- lineheadbytes = 0;
- }
-
- IMCB[unit].lblsiz = labelsize;
- IMCB[unit].reclen = reclen;
- IMCB[unit].nl = *p_nline;
- IMCB[unit].ns = *p_nsamp;
- IMCB[unit].pixsiz = *p_bitsperpix;
- IMCB[unit].linhed = lineheadbytes;
- IMCB[unit].access = accessmode[0];
- return;
-
- CloseUp:
- CloseFile (unit, LabelBuf);
- FreeUp:
- free(ImageBuffer[unit]);
- }
-
-
- int ReadLine (int unit, char * buffer, int line, int ss, int ns, char * status)
-
- /*** ReadLine reads a line of pixels from the image into the user's
- buffer. The reading is completely random access, the lines may be
- read in any order; it is more efficient, however, to read lines
- sequentially. Partial image lines may be read. The output data
- is in the same format as the file (the convert routine may be used
- to convert pixel formats).
-
- Parameter Type In/out Description
-
- unit int in Unit number of image (same as in open)
- buffer char ptr out Buffer to receive pixels
- line int in The number of the image line to read (1 is first)
- ss int in The starting sample in the line
- ns int in The number of samples to read into buffer
- status char ptr out Return string with error message
- (0 length string if no error)
-
- ***/
-
- {
-
- long filebyte, blknum;
- int offset, bufsizebytes, numbytes;
- int movebytes, bytesleft, outptr;
- unsigned char hold, hold1;
- int i,j;
- if (line > IMCB[unit].nl)
- strcpy (status, "Line off image");
- else
- {
- strcpy (status, "");
- /* Calculate the block in the image to start at,
- and read it in if necessary */
- filebyte = IMCB[unit].lblsiz
- + (long)(line-1) * (long)IMCB[unit].reclen
- + ( (long)(ss-1) * (long)IMCB[unit].pixsiz) / 8
- + (long)IMCB[unit].linhed;
- if (GiantLabel > 0)
- filebyte = GiantLabel
- + (long)(line-1) * (long)IMCB[unit].reclen
- + ( (long)(ss-1) * (long)IMCB[unit].pixsiz) / 8
- + (long)IMCB[unit].linhed;
-
- blknum = filebyte/IMCB[unit].blksiz;
- /*
- DisplayOff();
- printf("Gl %ld, fb %ld, bn %ld",GiantLabel,filebyte,blknum);
- exit();
- */
- if ( (blknum < IMCB[unit].block) ||
- (blknum > IMCB[unit].block + IMCB[unit].bufsiz-1) )
- {
- IMCB[unit].block = blknum;
- ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
- if (strlen(status) > 0) return;
- }
-
-
- offset = filebyte - IMCB[unit].blksiz*IMCB[unit].block;
- numbytes = ( (long)ns*IMCB[unit].pixsiz - 1 ) /8 + 1;
-
- /* Transfer the part of the line thats in the image buffer */
- bufsizebytes = IMCB[unit].blksiz*IMCB[unit].bufsiz;
- movebytes = bufsizebytes - offset;
- if (movebytes > numbytes) movebytes = numbytes;
- if (IMCB[unit].pixsiz == 16 && ByteSwap == TRUE)
- swab(&ImageBuffer[unit][offset], buffer, movebytes);
- else
- memcpy (buffer, &ImageBuffer[unit][offset], movebytes);
- bytesleft = numbytes - movebytes;
- outptr = movebytes;
-
- /* Read in more buffer fulls and transfer until done */
- while (bytesleft > 0)
- {
- IMCB[unit].block = IMCB[unit].block + IMCB[unit].bufsiz;
- ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
- if (strlen(status) > 0) return;
- bufsizebytes = IMCB[unit].blksiz*IMCB[unit].bufsiz;
- if (bufsizebytes > bytesleft) movebytes = bytesleft;
- else movebytes = bufsizebytes;
- if (IMCB[unit].pixsiz == 16 && ByteSwap == TRUE)
- swab(ImageBuffer[unit], &buffer[outptr], movebytes);
- else
- memcpy(&buffer[outptr], ImageBuffer[unit], movebytes);
- bytesleft = bytesleft - movebytes;
- outptr = outptr + movebytes;
- }
- /* swap bytes if FITS or other non swapped format */
- /*
- if (IMCB[unit].pixsiz == 16 && ByteSwap == TRUE)
- {
- for (i=0;i<2*ns;i += 2)
- {
- hold = buffer[i+1];
- buffer[i+1] = buffer[i];
- buffer[i] = hold;
- }
- }
- */
-
- /* swap bytes for the 32 bits values. added by AEE, 4-4-89 */
-
- if ((IMCB[unit].pixsiz == 32) && ByteSwap == TRUE)
- {
- for (i=0; i <4*ns; i +=4)
- {
- hold= buffer[i+3];
- hold1= buffer[i+2];
- buffer[i+2]= buffer[i+1];
- buffer[i+3]= buffer[i];
- buffer[i]= hold;
- buffer[i+1]= hold1;
- }
- }
-
-
- }
- }
-
-
-
-
-
- int WriteLine (int unit, unsigned char * buffer, int line, int ss, int ns,
- char * status)
-
- /*** WriteLine writes a line of pixels from the user buffer to the
- image. Although the writing is buffered, completely random access
- will not work; the image lines should be written sequentially.
- Partial image lines may be written. The input data must be in the
- same format as the file (no conversion is performed).
-
- Parameter Type In/out Description
-
- unit int in Unit number of image (same as in open)
- buffer char ptr in Buffer of image pixels
- line int in The number of the image line to write
- ss int in The starting sample in the line
- ns int in The number of samples to write from buffer
- status char ptr out Return string with error message
- (0 length string if no error)
-
- ***/
-
- {
- long filebyte, blknum;
- int offset, bufsizebytes, numbytes;
- int movebytes, bytesleft, inptr;
-
-
- if (line > IMCB[unit].nl)
- strcpy (status, "Line off image");
- else
- {
- strcpy (status, "");
- /* Calculate the block in the image to start at */
- filebyte = IMCB[unit].lblsiz
- + (line-1) * (long)IMCB[unit].reclen
- + ( (ss-1) * (long)IMCB[unit].pixsiz) / 8
- + IMCB[unit].linhed;
- blknum = filebyte/IMCB[unit].blksiz;
- if ( (blknum < IMCB[unit].block) ||
- (blknum > IMCB[unit].block + IMCB[unit].bufsiz-1) )
- {
- WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, status);
- if (strlen(status) > 0) return;
- IMCB[unit].block = blknum;
- memset (ImageBuffer[unit], 0, LabelBufferLen);
- }
-
-
- offset = filebyte - IMCB[unit].blksiz*IMCB[unit].block;
- numbytes = ( (long)ns*IMCB[unit].pixsiz - 1 ) /8 + 1;
-
-
- /* Transfer the part of the line that fits in the image buffer */
- bufsizebytes = LabelBufferLen;
- movebytes = bufsizebytes - offset;
- if (movebytes > numbytes) movebytes = numbytes;
- memcpy (&ImageBuffer[unit][offset], buffer, movebytes);
- IMCB[unit].bufsiz = ((offset+movebytes-1) /IMCB[unit].blksiz) + 1;
- bytesleft = numbytes - movebytes;
- inptr = movebytes;
-
-
- /* Write out more buffer fulls and transfer until done */
- while (bytesleft > 0)
- {
- WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].maxbuf, status);
- if (strlen(status) > 0) return;
- IMCB[unit].block = IMCB[unit].block + IMCB[unit].maxbuf;
- if (bufsizebytes > bytesleft) movebytes = bytesleft;
- else movebytes = bufsizebytes;
- memset (&ImageBuffer[unit][movebytes], 0, bufsizebytes-movebytes);
- memcpy (ImageBuffer[unit], &buffer[inptr], movebytes);
- IMCB[unit].bufsiz = ( (movebytes-1) /IMCB[unit].blksiz ) + 1;
- bytesleft = bytesleft - movebytes;
- inptr = inptr + movebytes;
- }
-
- }
- }
-
-
-
- int CloseImage (int unit, char * status)
-
- /*** CloseImage closes the image file. If the image is opened for
- writing then the image buffer is first flushed.
-
- Parameter Type In/out Description
-
- unit int in Unit number of image (same as in open)
- status char ptr out Return string with error message
- (0 length string if no error)
- ***/
-
- {
- if (IMCB[unit].access == 'W')
- {
- WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
- IMCB[unit].bufsiz, status);
- if (strlen(status) > 0) return;
- }
- free (ImageBuffer[unit]);
- CloseFile (unit, status);
- }
-
-
-
-
- int CheckStatus (char * status)
-
- /*** CheckStatus checks the status string passed in. If there is no
- error the routine returns, otherwise the error message is printed
- to the terminal and the program is aborted.
-
- ***/
-
- {
- if (strlen(status) > 0)
- {
- printf ("%s\n", status);
- abort();
- }
- }
-
-
-
-
-
-
-
- int ConvertLine (unsigned char * inbuffer, unsigned char * outbuffer,
- int inbits, int outbits, int ns, char * status)
-
- /*** ConvertLine converts a line of pixels into a different format.
-
- Parameter Type In/out Description
-
- inbuffer char ptr in The input buffer of pixels
- outbuffer char ptr out The output buffer of pixels
- inbits int in The pixel format of the input buffer
- outbits int in The pixel format of the output buffer
- ns int in The number of samples to convert
- status char ptr out Return string with error message
-
-
- Conversions supported : outbits
- 1 4 8 16 32
- inbits 1 . - . . - . means supported
- 4 - . . . - - means not supported
- 8 . . . . .
- 16 . . . . .
- 32 - - . . .
- ***/
-
- {
-
- register i, j;
- int bit;
-
- union {
- unsigned char *b;
- int *i;
- long *l;
- } inbuf, outbuf;
- inbuf.b = inbuffer;
- outbuf.b = outbuffer;
-
-
-
- strcpy (status, "");
- i = 0; j = 0;
-
- if (inbits == outbits)
- memcpy (outbuffer, inbuffer, ( (long)ns*inbits - 1 )/8 + 1 );
-
- else if ( (inbits==8) && (outbits==16) )
- for (i = 0; i < ns; i++)
- outbuf.i[i] = inbuf.b[i];
-
- else if ( (inbits==16) && (outbits==8) )
- for (i = 0; i < ns; i++)
- outbuf.b[i] = inbuf.i[i];
-
- else if ( (inbits==16) && (outbits==32) )
- for (i = 0; i < ns; i++)
- outbuf.l[i] = inbuf.i[i];
-
- else if ( (inbits==32) && (outbits==16) )
- for (i = 0; i < ns; i++)
- outbuf.i[i] = inbuf.l[i];
-
- else if ( (inbits==8) && (outbits==32) )
- for (i = 0; i < ns; i++)
- outbuf.l[i] = inbuf.b[i];
-
- else if ( (inbits==32) && (outbits==8) )
- for (i = 0; i < ns; i++)
- outbuf.b[i] = inbuf.l[i];
-
- else if ( (inbits==4) && (outbits==8) )
- for (i = 0; i <= (ns-1)/2; i++)
- { outbuf.b[j++] = inbuf.b[i] >> 4;
- outbuf.b[j++] = inbuf.b[i] & 15;
- }
-
- else if ( (inbits==8) && (outbits==4) )
- for (j = 0; j <= (ns-1)/2; j++)
- outbuf.b[j] = (inbuf.b[i++] << 4) | (inbuf.b[i++] & 15);
-
- else if ( (inbits==1) && (outbits==8) )
- for (i = 0; i <= (ns-1)/8; i++)
- for (bit = 7; bit >= 0; bit--)
- outbuf.b[j++] = (inbuf.b[i] >> bit) & 1;
-
- else if ( (inbits==8) && (outbits==1) )
- for (j = 0; j <= (ns-1)/8; j++)
- { outbuf.b[j] = 0;
- for (bit = 7; bit >= 0; bit--)
- outbuf.b[j] |= ((inbuf.b[i++] & 1) << bit);
- }
-
-
- else if ( (inbits==4) && (outbits==16) )
- for (i = 0; i <= (ns-1)/2; i++)
- { outbuf.i[j++] = inbuf.b[i] >> 4;
- outbuf.i[j++] = inbuf.b[i] & 15;
- }
-
- else if ( (inbits==16) && (outbits==4) )
- for (j = 0; j <= (ns-1)/2; j++)
- outbuf.b[j] = (inbuf.i[i++] << 4) | (inbuf.i[i++] & 15);
-
- else if ( (inbits==1) && (outbits==16) )
- for (i = 0; i <= (ns-1)/8; i++)
- for (bit = 7; bit >= 0; bit--)
- outbuf.i[j++] = (inbuf.b[i] >> bit) & 1;
-
- else if ( (inbits==16) && (outbits==1) )
- for (j = 0; j <= (ns-1)/8; j++)
- { outbuf.b[j] = 0;
- for (bit = 7; bit >= 0; bit--)
- outbuf.b[j] |= ((inbuf.i[i++] & 1) << bit);
- }
-
- else
- strcpy (status, "That pixel conversion is not supported");
- }
-