home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / imdisp / source / imageio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-02  |  23.4 KB  |  682 lines

  1. /*************************************************************/
  2. /*  Copyright (C) 1989, California Institute of Technology   */
  3. /*  U. S. Government Sponsorship under NASA Contract         */
  4. /*  NAS7-918 is acknowledged.                                */
  5. /*************************************************************/
  6.  
  7. /***  IMDISP module IMAGEIO.C
  8.      Image I/O routines for labeled images
  9.  
  10.      Includes routines for opening images, reading and writing
  11.      image lines, and converting pixel formats.
  12. ***/
  13.  
  14. /* * * * INCLUDE files * * * */
  15.  
  16. #include <ctype.h>
  17. #include <malloc.h>
  18. #include <process.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include "imdef.h"
  23. #include "imdisp.h"
  24. #include "disputil.h"
  25. #include "fileio.h"
  26. #include "labutil.h"
  27. #include "refresh.h"
  28.  
  29. /* * * * External functions * * * */
  30.  
  31. /* * * * Function declarations * * * */
  32.  
  33. int ReadLabel (int ,char *,int ,char *);
  34. int WriteLabel (int ,char *,unsigned int ,char *);
  35. int OpenImage (char *,int ,char *,int *,int *,int *,char *);
  36. int ReadLine (int, char *, int, int, int, char *);
  37. int CloseImage (int ,char *);
  38. int CheckStatus (char *);
  39. int ConvertLine (unsigned char *,unsigned char *,int ,int ,int ,char *);
  40.  
  41. /* * * * Global Variables * * * */
  42.  
  43.               /* The image control block structure */
  44. struct ImageBlockType
  45.     {
  46.           long   block;        /* block # of start of buffer at */
  47.           int    blksiz;       /* block size in bytes */
  48.           int    maxbuf;       /* max size of buffer in blocks */
  49.           int    bufsiz;       /* # of blocks of buffer in use */
  50.  unsigned int    lblsiz;       /* label size in bytes */
  51.           int    pixsiz;       /* size of pixels in bits */
  52.           int    reclen;       /* record length in bytes */
  53.           int    nl, ns;       /* number of lines and samples */
  54.           int    linhed;       /* line header length in bytes */
  55.           char   access;       /* R for read, W for write */
  56.     }   IMCB[MaxNumImages];
  57.  
  58.  
  59. unsigned char *ImageBuffer[MaxNumImages];    /* pointers to image buffers */
  60. char           LabelBuf[LabelBufferLen];
  61. char           LabelFileName[64];
  62.  
  63. int ReadLabel (int unit, char * LabelBuf, int LabelLength, char * status)
  64.  
  65. /* ReadLabel reads a buffer full of the beginning of the file and
  66.     copies part of it to the label buffer in uppercase.
  67. */
  68.  
  69. {
  70.     int   i, * len, length, next = 0;
  71.  
  72.     IMCB[unit].block = 0L;
  73.     ReadBlocks (unit, ImageBuffer[unit],  IMCB[unit].block,
  74.                   IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
  75.     memcpy (LabelBuf, ImageBuffer[unit], LabelLength);
  76.     if (strncmp(LabelBuf+2,"CCSD",4) == 0 ||
  77.         strncmp(LabelBuf+2,"NJPL",4) == 0)
  78.       do
  79.        {
  80.         len = (int *)LabelBuf[next];
  81.         length = *len;
  82.         length += length%2;
  83.         LabelBuf[next] = 13; LabelBuf[next+1] = 10;
  84.         if (strncmp(LabelBuf+next+2,"END",3) == 0 && length < 5)
  85.           break;
  86.         next += length+2;
  87.        }  while (next < LabelLength);
  88.  
  89.     for (i = 0;  i < LabelLength;  i++)
  90.         {
  91.          LabelBuf[i] = toupper(LabelBuf[i]);
  92.          if (LabelBuf[i] == 0) LabelBuf[i] = 32;
  93.         }
  94. }
  95.  
  96.  
  97.  
  98.  
  99. int WriteLabel (int unit, char * LabelBuf, unsigned int labelsize,
  100.                 char * status)
  101.  
  102. /*  WriteLabel writes the passed label out to the image buffer.
  103.     If the label record is larger than the image buffer then
  104.     the buffer is written to disk.
  105. */
  106.  
  107. {
  108.     int   movebytes, bytesleft, inptr;
  109.  
  110.     strcpy (status, "");
  111.     memset (ImageBuffer[unit], 0, LabelBufferLen);
  112.  
  113.     IMCB[unit].block = 0L;
  114.     if (labelsize < LabelBufferLen)
  115.         movebytes = labelsize;
  116.     else
  117.         movebytes = LabelBufferLen;
  118.     memcpy (ImageBuffer[unit], LabelBuf, movebytes);
  119.     IMCB[unit].bufsiz = ((movebytes-1) / IMCB[unit].blksiz) + 1;
  120.     bytesleft = labelsize - movebytes;
  121.     inptr = movebytes;
  122.  
  123.     while (bytesleft > 0)
  124.     {
  125.         WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
  126.                        IMCB[unit].maxbuf, status);
  127.         if (strlen(status) > 0)  return;
  128.         IMCB[unit].block = IMCB[unit].block + IMCB[unit].maxbuf;
  129.         if (bytesleft < LabelBufferLen)
  130.             movebytes = bytesleft;
  131.         else
  132.             movebytes = LabelBufferLen;
  133.         memset (&ImageBuffer[unit][movebytes], 0, ImBufMax-movebytes);
  134.         memcpy (ImageBuffer[unit], &LabelBuf[inptr], movebytes);
  135.         IMCB[unit].bufsiz = ( (movebytes-1) / IMCB[unit].blksiz ) + 1;
  136.         bytesleft = bytesleft - movebytes;
  137.         inptr = inptr + movebytes;
  138.     }
  139. }
  140.  
  141. int OpenImage (char * filename, int unit, char * IOmode, int * p_nline,
  142.                int * p_nsamp, int * p_bitsperpix, char * status)
  143.  
  144. /***  OpenImage opens an image file either for reading or writing. The
  145.       size of the image and pixel format are returned if the file is
  146.       opened for reading.  If the file is opened for writing then the
  147.       passed number of lines and samples and pixel format are used for
  148.       the new image.  The unit number is used to refer to the file in
  149.       subsequent operations.  If the file is opened for input then the
  150.       label processing routines will parse Vicar2 and PDS labels and
  151.       will prompt for user info if the image is unlabeled. PDS detached
  152.       labels and palettes are handled transparently in this routine. If
  153.       the file is for writing then a PDS label will be output. An error
  154.       is returned if there is insufficient room to dynamically allocate
  155.       the image buffer, or if there is a file error. For images with
  156.       pixel sizes less than a byte, each line is assumed to start with a
  157.       new byte.
  158.  
  159.    Parameter    Type    In/out  Description
  160.  
  161.     filename  char ptr   in     Name of image file to open
  162.     unit        int      in     Unit number of image (0,1,2...)
  163.     IOmode    char ptr   in     Access mode of file
  164.                                   ("r..." for reading, "w..." for writing)
  165.     p_nline   int ptr  in/out   The number of lines in the image
  166.     p_nsamp   int ptr  in/out   The number of samples in the image
  167.  p_bitsperpix int ptr  in/out   The number of bits in a pixel (pixel format)
  168.                                   (16 for integer, 8 for byte,
  169.                                     4 for nibble,  1 for binary)
  170.     status    char ptr  out     Return string with error message
  171.                                   (0 length string if no error)
  172.  
  173. ***/
  174.  
  175. {
  176.     char    LabelBuf[LabelBufferLen];
  177.     int     reclen, lineheadbytes, p;
  178.     unsigned int labelsize;
  179.     unsigned int size;
  180.     char   accessmode[2], format,  DetachedFileName[64], tmpstr[64];
  181.     char   DetachedPaletteName[64];
  182.  
  183.  
  184.     if ( (unit < 0) || (unit > MaxNumImages-1) )
  185.     {
  186.         strcpy (status, "Illegal unit number");
  187.         return;
  188.     }
  189.     accessmode[1] = 0;
  190.     accessmode[0] = toupper(IOmode[0]);
  191.     if (accessmode[0] != 'W')
  192.         accessmode[0] = 'R';
  193.  
  194.     OpenFile (filename, unit, accessmode, &IMCB[unit].blksiz, status);
  195.     if (strlen(status) > 0) return;
  196.  
  197.     /* Allocate image buffer on heap */
  198.     /* Only allocate 2048 bytes for output buffer */
  199.     size = (accessmode[0]=='W') ? LabelBufferLen : ImBufMax;
  200.  
  201.     while ( (ImageBuffer[unit] = malloc (size)) == NULL )
  202.       FreeRefresh("imgbuffer");
  203.  
  204.     IMCB[unit].maxbuf = size / IMCB[unit].blksiz; /* MDM 2/3/88*/
  205.  
  206.     if (accessmode[0] == 'R')
  207.     {
  208.         ReadLabel (unit, LabelBuf, LabelBufferLen, status);
  209.         if (strlen(status) > 0)  goto CloseUp;
  210.  
  211. /*  patch for microsoft driver */
  212. /*  this checks for dates found in certain positions in the extended
  213.     attr record. These could be found elsewhere, but probably not */
  214.         if (LabelBuf[10] == '1' && LabelBuf[11] == '9' &&
  215.             LabelBuf[26] == '1' && LabelBuf[27] == '9')
  216.           {
  217.             Microsoft = 1; /*read the label again*/
  218.             ReadLabel (unit, LabelBuf, LabelBufferLen, status);
  219.             if (strlen(status) > 0)  goto CloseUp;
  220.           }
  221.         else Microsoft = 0;
  222.  
  223. /*  end of patch */
  224.  
  225.         InterpretLabel (LabelBuf, LabelBufferLen,
  226.                         &labelsize, p_nline, p_nsamp, p_bitsperpix,
  227.                         &reclen, &lineheadbytes,  DetachedFileName,
  228.                         DetachedPaletteName, unit);
  229.         if (reclen == 0) return(0);
  230.         LabelFileName[0]=NULL;
  231.         if (strlen(DetachedFileName) > 0)
  232.         {
  233.             strcpy(LabelFileName,filename);
  234.             CloseFile (unit, status);
  235.             if ( (strchr(DetachedFileName, '\\') == NULL) &&
  236.                  (strchr(DetachedFileName, ':')  == NULL) &&
  237.                  (strnicmp(filename,"CD:",3)     != 0)  )
  238.             {
  239.                 p = strlen(filename) - 1;
  240.                 while ((p > -1) && (filename[p] != '\\')
  241.                                 && (filename[p] != ':')) p--;
  242.                 strcpy (tmpstr, filename);
  243.                 tmpstr[p+1] = 0;
  244.                 strcat (tmpstr, DetachedFileName);
  245.                 strcpy (DetachedFileName, tmpstr);
  246.             }
  247.  
  248.             OpenFile (DetachedFileName, unit, accessmode,
  249.                                       &IMCB[unit].blksiz, status);
  250.             if (strlen(status) > 0)  goto FreeUp;
  251.             IMCB[unit].maxbuf = ImBufMax / IMCB[unit].blksiz;
  252.             IMCB[unit].block = 0L;
  253.             ReadBlocks (unit, ImageBuffer[unit],  IMCB[unit].block,
  254.                   IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
  255.             if (strlen(status) > 0)  goto CloseUp;
  256.  
  257. /*  patch for microsoft driver */
  258.         if (ImageBuffer[unit][10] == '1' && ImageBuffer[unit][11] == '9' &&
  259.             ImageBuffer[unit][26] == '1' && ImageBuffer[unit][27] == '9')
  260.           {
  261.             Microsoft = 1; /*read the label again*/
  262.             ReadBlocks (unit, ImageBuffer[unit],  IMCB[unit].block,
  263.                   IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
  264.             if (strlen(status) > 0)  goto CloseUp;
  265.           }
  266.         else Microsoft = 0;
  267.  
  268.         }
  269.  
  270.         if ( (strlen(DetachedPaletteName) > 0) || (Palette > 0L) )
  271.                                            /* Ron Baalke - Added detached   */
  272.         {                                  /* palette processing - 07/27/90 */
  273.             LoadPalette(DetachedPaletteName);
  274.         }
  275.  
  276.     }
  277.  
  278.     else
  279.     {
  280.         reclen = ( (long)*p_nsamp* (long)*p_bitsperpix - 1 )/8 + 1;
  281.         MakeLabel (LabelBuf, &labelsize, *p_nline, *p_nsamp,
  282.                                          *p_bitsperpix, reclen);
  283.         WriteLabel (unit, LabelBuf, labelsize, status);
  284.         if (strlen(status) > 0)  goto CloseUp;
  285.         lineheadbytes = 0;
  286.     }
  287.  
  288.     IMCB[unit].lblsiz = labelsize;
  289.     IMCB[unit].reclen = reclen;
  290.     IMCB[unit].nl = *p_nline;
  291.     IMCB[unit].ns = *p_nsamp;
  292.     IMCB[unit].pixsiz = *p_bitsperpix;
  293.     IMCB[unit].linhed = lineheadbytes;
  294.     IMCB[unit].access = accessmode[0];
  295.     return;
  296.  
  297.     CloseUp:
  298.       CloseFile (unit, LabelBuf);
  299.     FreeUp:
  300.       free(ImageBuffer[unit]);
  301. }
  302.  
  303.  
  304. int ReadLine (int unit, char * buffer, int line, int ss, int ns, char * status)
  305.  
  306. /***  ReadLine reads a line of pixels from the image into the user's
  307.       buffer.  The reading is completely random access, the lines may be
  308.       read in any order; it is more efficient, however, to read lines
  309.       sequentially.  Partial image lines may be read.  The output data
  310.       is in the same format as the file (the convert routine may be used
  311.       to convert pixel formats).
  312.  
  313.    Parameter Type   In/out  Description
  314.  
  315.     unit     int      in     Unit number of image (same as in open)
  316.     buffer  char ptr  out    Buffer to receive pixels
  317.     line     int      in     The number of the image line to read (1 is first)
  318.     ss       int      in     The starting sample in the line
  319.     ns       int      in     The number of samples to read into buffer
  320.     status  char ptr  out    Return string with error message
  321.                                   (0 length string if no error)
  322.  
  323. ***/
  324.  
  325. {
  326.  
  327.     long      filebyte, blknum;
  328.     int       offset, bufsizebytes, numbytes;
  329.     int       movebytes, bytesleft, outptr;
  330.     unsigned char    hold, hold1;
  331.     int       i,j;
  332.     if (line > IMCB[unit].nl)
  333.         strcpy (status, "Line off image");
  334.     else
  335.     {
  336.         strcpy (status, "");
  337.    /* Calculate the block in the image to start at,
  338.                     and read it in if necessary */
  339.        filebyte = IMCB[unit].lblsiz
  340.                    + (long)(line-1) * (long)IMCB[unit].reclen
  341.                    + ( (long)(ss-1) * (long)IMCB[unit].pixsiz) / 8
  342.                    + (long)IMCB[unit].linhed;
  343.         if (GiantLabel > 0)
  344.         filebyte = GiantLabel
  345.                    + (long)(line-1) * (long)IMCB[unit].reclen
  346.                    + ( (long)(ss-1) * (long)IMCB[unit].pixsiz) / 8
  347.                    + (long)IMCB[unit].linhed;
  348.         
  349.         blknum = filebyte/IMCB[unit].blksiz;
  350. /*
  351.         DisplayOff();
  352.         printf("Gl %ld, fb %ld, bn %ld",GiantLabel,filebyte,blknum);
  353.         exit();
  354. */
  355.        if ( (blknum < IMCB[unit].block) ||
  356.              (blknum > IMCB[unit].block + IMCB[unit].bufsiz-1)  )
  357.         {
  358.             IMCB[unit].block = blknum;
  359.             ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
  360.                  IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
  361.             if (strlen(status) > 0)  return;
  362.         }
  363.  
  364.  
  365.         offset =  filebyte - IMCB[unit].blksiz*IMCB[unit].block;
  366.         numbytes = ( (long)ns*IMCB[unit].pixsiz - 1 ) /8 + 1;
  367.  
  368.    /* Transfer the part of the line thats in the image buffer */
  369.         bufsizebytes = IMCB[unit].blksiz*IMCB[unit].bufsiz;
  370.         movebytes = bufsizebytes - offset;
  371.         if (movebytes > numbytes)  movebytes = numbytes;
  372.         if (IMCB[unit].pixsiz == 16 && ByteSwap == TRUE)
  373.           swab(&ImageBuffer[unit][offset], buffer, movebytes);
  374.         else
  375.           memcpy (buffer, &ImageBuffer[unit][offset], movebytes);
  376.         bytesleft = numbytes - movebytes;
  377.         outptr = movebytes;
  378.  
  379.    /* Read in more buffer fulls and transfer until done */
  380.         while (bytesleft > 0)
  381.         {
  382.             IMCB[unit].block = IMCB[unit].block + IMCB[unit].bufsiz;
  383.             ReadBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
  384.                           IMCB[unit].maxbuf, &IMCB[unit].bufsiz, status);
  385.             if (strlen(status) > 0) return;
  386.             bufsizebytes = IMCB[unit].blksiz*IMCB[unit].bufsiz;
  387.             if (bufsizebytes > bytesleft)  movebytes = bytesleft;
  388.                 else movebytes = bufsizebytes;
  389.             if (IMCB[unit].pixsiz == 16 && ByteSwap == TRUE)
  390.               swab(ImageBuffer[unit], &buffer[outptr], movebytes);
  391.             else
  392.               memcpy(&buffer[outptr], ImageBuffer[unit], movebytes);
  393.             bytesleft = bytesleft - movebytes;
  394.             outptr = outptr + movebytes;
  395.         }
  396.      /* swap bytes if FITS or other non swapped format */
  397. /*
  398.      if (IMCB[unit].pixsiz == 16  && ByteSwap == TRUE)
  399.        {
  400.          for (i=0;i<2*ns;i += 2)
  401.            {
  402.              hold = buffer[i+1];
  403.              buffer[i+1] = buffer[i];
  404.              buffer[i] = hold;
  405.            }
  406.        }
  407. */
  408.  
  409.      /* swap bytes for the 32 bits values. added by AEE, 4-4-89 */
  410.  
  411.      if ((IMCB[unit].pixsiz == 32) && ByteSwap == TRUE)
  412.        {
  413.         for (i=0; i <4*ns; i +=4)
  414.           {
  415.             hold= buffer[i+3];
  416.             hold1= buffer[i+2];
  417.             buffer[i+2]= buffer[i+1];
  418.             buffer[i+3]= buffer[i];
  419.             buffer[i]= hold;
  420.             buffer[i+1]= hold1;
  421.           }
  422.        }
  423.  
  424.  
  425.     }
  426. }
  427.  
  428.  
  429.  
  430.  
  431.  
  432. int WriteLine (int unit, unsigned char * buffer, int line, int ss, int ns,
  433.                char * status)
  434.  
  435. /***  WriteLine writes a line of pixels from the user buffer to the
  436.       image. Although the writing is buffered, completely random access
  437.       will not work; the image lines should be written sequentially.
  438.       Partial image lines may be written.  The input data must be in the
  439.       same format as the file (no conversion is performed).
  440.  
  441.    Parameter Type   In/out  Description
  442.  
  443.     unit     int      in     Unit number of image (same as in open)
  444.     buffer  char ptr  in     Buffer of image pixels
  445.     line     int      in     The number of the image line to write
  446.     ss       int      in     The starting sample in the line
  447.     ns       int      in     The number of samples to write from buffer
  448.     status  char ptr  out    Return string with error message
  449.                                   (0 length string if no error)
  450.  
  451. ***/
  452.  
  453. {
  454.     long      filebyte, blknum;
  455.     int       offset, bufsizebytes, numbytes;
  456.     int       movebytes, bytesleft, inptr;
  457.  
  458.  
  459.     if (line > IMCB[unit].nl)
  460.         strcpy (status, "Line off image");
  461.     else
  462.     {
  463.         strcpy (status, "");
  464.      /* Calculate the block in the image to start at */
  465.         filebyte = IMCB[unit].lblsiz
  466.                    + (line-1) * (long)IMCB[unit].reclen
  467.                    + ( (ss-1) * (long)IMCB[unit].pixsiz) / 8
  468.                    + IMCB[unit].linhed;
  469.         blknum = filebyte/IMCB[unit].blksiz;
  470.         if ( (blknum < IMCB[unit].block) ||
  471.              (blknum > IMCB[unit].block + IMCB[unit].bufsiz-1)  )
  472.         {
  473.             WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
  474.                           IMCB[unit].maxbuf,  status);
  475.             if (strlen(status) > 0)  return;
  476.             IMCB[unit].block = blknum;
  477.             memset (ImageBuffer[unit], 0, LabelBufferLen);
  478.         }
  479.  
  480.  
  481.         offset =  filebyte - IMCB[unit].blksiz*IMCB[unit].block;
  482.         numbytes = ( (long)ns*IMCB[unit].pixsiz - 1 ) /8 + 1;
  483.  
  484.  
  485.    /* Transfer the part of the line that fits in the image buffer */
  486.         bufsizebytes = LabelBufferLen;
  487.         movebytes = bufsizebytes - offset;
  488.           if (movebytes > numbytes)  movebytes = numbytes;
  489.         memcpy (&ImageBuffer[unit][offset], buffer, movebytes);
  490.         IMCB[unit].bufsiz = ((offset+movebytes-1) /IMCB[unit].blksiz) + 1;
  491.         bytesleft = numbytes - movebytes;
  492.         inptr = movebytes;
  493.  
  494.  
  495.    /* Write out more buffer fulls and transfer until done */
  496.         while (bytesleft > 0)
  497.         {
  498.             WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
  499.                            IMCB[unit].maxbuf, status);
  500.             if (strlen(status) > 0)  return;
  501.             IMCB[unit].block = IMCB[unit].block + IMCB[unit].maxbuf;
  502.             if (bufsizebytes > bytesleft)  movebytes = bytesleft;
  503.               else movebytes = bufsizebytes;
  504.             memset (&ImageBuffer[unit][movebytes], 0, bufsizebytes-movebytes);
  505.             memcpy (ImageBuffer[unit], &buffer[inptr], movebytes);
  506.             IMCB[unit].bufsiz = ( (movebytes-1) /IMCB[unit].blksiz ) + 1;
  507.             bytesleft = bytesleft - movebytes;
  508.             inptr = inptr + movebytes;
  509.         }
  510.  
  511.     }
  512. }
  513.  
  514.  
  515.  
  516. int CloseImage (int unit, char * status)
  517.  
  518. /***  CloseImage closes the image file.  If the image is opened for
  519.     writing then the image buffer is first flushed.
  520.  
  521.    Parameter Type   In/out  Description
  522.  
  523.     unit     int      in     Unit number of image (same as in open)
  524.     status  char ptr  out    Return string with error message
  525.                                   (0 length string if no error)
  526. ***/
  527.  
  528. {
  529.     if (IMCB[unit].access == 'W')
  530.     {
  531.         WriteBlocks (unit, ImageBuffer[unit], IMCB[unit].block,
  532.                              IMCB[unit].bufsiz, status);
  533.         if (strlen(status) > 0) return;
  534.     }
  535.     free (ImageBuffer[unit]);
  536.     CloseFile (unit, status);
  537. }
  538.  
  539.  
  540.  
  541.  
  542. int CheckStatus (char * status)
  543.  
  544. /***  CheckStatus checks the status string passed in.  If there is no
  545.       error the routine returns, otherwise the error message is printed
  546.       to the terminal and the program is aborted.
  547.  
  548. ***/
  549.  
  550. {
  551.     if (strlen(status) > 0)
  552.     {
  553.         printf ("%s\n", status);
  554.         abort();
  555.     }
  556. }
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564. int ConvertLine (unsigned char * inbuffer, unsigned char * outbuffer,
  565.                  int inbits, int outbits, int ns, char * status)
  566.  
  567. /***  ConvertLine converts a line of pixels into a different format.
  568.  
  569.    Parameter     Type   In/out  Description
  570.  
  571.     inbuffer   char ptr  in    The input buffer of pixels
  572.     outbuffer  char ptr  out   The output buffer of pixels
  573.     inbits      int      in    The pixel format of the input buffer
  574.     outbits     int      in    The pixel format of the output buffer
  575.     ns          int      in    The number of samples to convert
  576.     status     char ptr  out   Return string with error message
  577.  
  578.  
  579.    Conversions supported :        outbits
  580.                                 1  4  8  16 32
  581.                    inbits    1  .  -  .  .  -    . means supported
  582.                              4  -  .  .  .  -    - means not supported
  583.                              8  .  .  .  .  .
  584.                             16  .  .  .  .  .
  585.                             32  -  -  .  .  .
  586. ***/
  587.  
  588. {
  589.  
  590.     register  i, j;
  591.     int       bit;
  592.  
  593.     union {
  594.           unsigned char   *b;
  595.           int             *i;
  596.           long            *l;
  597.           } inbuf, outbuf;
  598.     inbuf.b = inbuffer;
  599.     outbuf.b = outbuffer;
  600.  
  601.  
  602.  
  603.     strcpy (status, "");
  604.     i = 0;   j = 0;
  605.  
  606.     if (inbits == outbits)
  607.         memcpy (outbuffer, inbuffer, ( (long)ns*inbits - 1 )/8 + 1 );
  608.  
  609.     else if ( (inbits==8) && (outbits==16) )
  610.         for (i = 0; i < ns; i++)
  611.             outbuf.i[i] = inbuf.b[i];
  612.  
  613.     else if ( (inbits==16) && (outbits==8) )
  614.         for (i = 0; i < ns; i++)
  615.             outbuf.b[i] = inbuf.i[i];
  616.  
  617.     else if ( (inbits==16) && (outbits==32) )
  618.         for (i = 0; i < ns; i++)
  619.             outbuf.l[i] = inbuf.i[i];
  620.  
  621.     else if ( (inbits==32) && (outbits==16) )
  622.         for (i = 0; i < ns; i++)
  623.             outbuf.i[i] = inbuf.l[i];
  624.  
  625.     else if ( (inbits==8) && (outbits==32) )
  626.         for (i = 0; i < ns; i++)
  627.             outbuf.l[i] = inbuf.b[i];
  628.  
  629.     else if ( (inbits==32) && (outbits==8) )
  630.         for (i = 0; i < ns; i++)
  631.             outbuf.b[i] = inbuf.l[i];
  632.  
  633.     else if ( (inbits==4) && (outbits==8) )
  634.         for (i = 0; i <= (ns-1)/2; i++)
  635.         {   outbuf.b[j++] = inbuf.b[i] >> 4;
  636.             outbuf.b[j++] = inbuf.b[i] & 15;
  637.         }
  638.  
  639.     else if ( (inbits==8) && (outbits==4) )
  640.         for (j = 0; j <= (ns-1)/2; j++)
  641.             outbuf.b[j] = (inbuf.b[i++] << 4) | (inbuf.b[i++] & 15);
  642.  
  643.     else if ( (inbits==1) && (outbits==8) )
  644.         for (i = 0; i <= (ns-1)/8; i++)
  645.             for (bit = 7; bit >= 0; bit--)
  646.                 outbuf.b[j++] = (inbuf.b[i] >> bit) & 1;
  647.  
  648.     else if ( (inbits==8) && (outbits==1) )
  649.         for (j = 0; j <= (ns-1)/8; j++)
  650.         {   outbuf.b[j] = 0;
  651.             for (bit = 7; bit >= 0; bit--)
  652.                 outbuf.b[j] |= ((inbuf.b[i++] & 1) << bit);
  653.         }
  654.  
  655.  
  656.     else if ( (inbits==4) && (outbits==16) )
  657.         for (i = 0; i <= (ns-1)/2; i++)
  658.         {   outbuf.i[j++] = inbuf.b[i] >> 4;
  659.             outbuf.i[j++] = inbuf.b[i] & 15;
  660.         }
  661.  
  662.     else if ( (inbits==16) && (outbits==4) )
  663.         for (j = 0; j <= (ns-1)/2; j++)
  664.             outbuf.b[j] = (inbuf.i[i++] << 4) | (inbuf.i[i++] & 15);
  665.  
  666.     else if ( (inbits==1) && (outbits==16) )
  667.         for (i = 0; i <= (ns-1)/8; i++)
  668.             for (bit = 7; bit >= 0; bit--)
  669.                 outbuf.i[j++] = (inbuf.b[i] >> bit) & 1;
  670.  
  671.     else if ( (inbits==16) && (outbits==1) )
  672.         for (j = 0; j <= (ns-1)/8; j++)
  673.         {   outbuf.b[j] = 0;
  674.             for (bit = 7; bit >= 0; bit--)
  675.                 outbuf.b[j] |= ((inbuf.i[i++] & 1) << bit);
  676.         }
  677.  
  678.     else
  679.         strcpy (status, "That pixel conversion is not supported");
  680. }
  681.  
  682.