home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / compstol / cmpsttl1.lha / CompositeTool / v1.1.dist / HDF / dfcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-08  |  14.9 KB  |  506 lines

  1. /*****************************************************************************
  2. *              NCSA HDF version 3.00
  3. *                December, 1989
  4. *
  5. * NCSA HDF Version 3.00 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************/
  16.  
  17. /*-----------------------------------------------------------------------------
  18.  * File:    dfcomp.c
  19.  * Purpose: File compression
  20.  * Invokes: df.c dfimcomp.c df.h
  21.  * Contents: 
  22.  *  DFputcomp: compress image and write it to HDF file
  23.  *  DFgetcomp: read compressed image from HDF file and decompress it
  24.  *  DFCrle: compress string using run length encoding
  25.  *  DFCunrle: decompress string using run length encoding
  26.  * Remarks: DFgetcomp and DFputcomp constitute a general compression interface
  27.  *---------------------------------------------------------------------------*/
  28.  
  29. #include "df.h"
  30.  
  31. #ifndef VMS
  32. extern void DFCimcomp(), DFCunimcomp();
  33. #else /*VMS*/
  34. extern void _DFCimcomp(), _DFCunimcomp();
  35. #endif
  36.  
  37. /*-----------------------------------------------------------------------------
  38.  * Name:    DFputcomp
  39.  * Purpose: Compress and write images to HDF file
  40.  * Inputs:  dfile: pointer to HDF file
  41.  *          tag, ref: tag, ref of compressed image for writing out
  42.  *          image: image to be compressed
  43.  *          xdim, ydim: dimensions of image
  44.  *          palette: palette associated with image
  45.  *          newpal: modified palette, produced if compression scheme is IMCOMP
  46.  *          scheme: compression scheme to be used
  47.  * Returns: 0 on success, -1 on failure with DFerror set
  48.  * Users:   HDF programmers, DF8putrig, other routines
  49.  * Invokes: DFCrle, DFCimcomp, DFaccess, DFwrite, DFIcheck
  50.  * Remarks: IMCOMP modifies the palette associated with the image
  51.  *          Hence the palette and newpal arguments
  52.  *          This is a general compression interface - to be used anytime image
  53.  *          compression is needed in HDF
  54.  *          Note that rseq does its own compression, because that is part of
  55.  *          the interactive color raster protocol
  56.  *          The space needed for compression and decompression can be allocated
  57.  *          statically or dynamically, depending on the DF_DYNAMIC flag, and
  58.  *          for entire image or part of it (reused) depending on availability
  59.  *          Accordingly, writing out is whole image, or row by row
  60.  *          Note that compression is always row by row for RLE.
  61.  *---------------------------------------------------------------------------*/
  62.  
  63.  
  64. int DFputcomp(dfile, tag, ref, image, xdim, ydim, palette, newpal, scheme)
  65. DF *dfile;
  66. uint16 tag, ref;
  67. char *image;
  68. int32 xdim, ydim;
  69. char *palette, *newpal;
  70. int16 scheme;
  71. {
  72.     char *buffer;        /* buffer to hold compressed image */
  73.     char *in;            /* pointer to input for compression */
  74.     char *out;            /* pointer to space for compressed output */
  75.     int32 cisize;        /* maximum size of compressed image */
  76.     int32 crowsize;        /* maximum size of compressed row */
  77.     int32 buftype;        /* buftype = 1: buffer enough for whole image*/
  78.                 /* buftype = 2: buffer holds 1 row */
  79.     int32 n;            /* number of compressed bytes produced */
  80.     int32 total;        /* total compressed bytes produced so far */
  81.     int i, ret=0;
  82.  
  83.     if (DFIcheck(dfile)<0) return(-1);
  84.     if (!tag) {
  85.         DFerror = DFE_BADTAG;
  86.         return(-1);
  87.     }
  88.     if (!ref) {
  89.         DFerror = DFE_BADREF;
  90.         return(-1);
  91.     }
  92.     if ((xdim<=0) || (ydim<=0)) {
  93.         DFerror = DFE_BADDIM;
  94.         return(-1);
  95.     }
  96.     if (!image) {
  97.         DFerror = DFE_BADPTR;
  98.         return(-1);
  99.     }
  100.  
  101.     if (DFaccess(dfile, tag, ref, "w")<0) return(-1); /* setup to write CI */
  102.  
  103.     switch (scheme) {
  104.       case DFTAG_RLE:
  105.     cisize = xdim*(ydim*121/120+1);    /* 120 chars can compress to 121! */
  106.     crowsize = xdim*121/120 + 128;
  107.  
  108.     /* allocate buffer for compression */
  109. #ifdef DF_DYNAMIC        /* large mallocs OK */
  110.     buffer = (char *) DFIgetspace((unsigned)cisize);
  111.     if (!buffer) {
  112.         buffer = (char *) DFIgetspace((unsigned)crowsize);
  113.         if (!buffer) {
  114.         DFerror = DFE_NOSPACE;
  115.         return(-1);
  116.         }
  117.         buftype = 2;    /* compress and write out row by row */
  118.     }
  119.     else buftype = 1;       /* can hold whole image, then write */
  120.  
  121. #else /*DF_DYNAMIC                    use static buffers */
  122.     buffer = DFtbuf;
  123.     if (DF_TBUFSZ>=cisize) buftype = 1;
  124.     else if (DF_TBUFSZ>crowsize) buftype = 2;
  125.     else {
  126.         DFerror = DFE_NOSPACE;
  127.         return(-1);
  128.     }
  129. #endif /*DF_DYNAMIC*/
  130.  
  131.     in = image;
  132.     out = buffer;
  133.     n = total = 0;        /* no bytes compressed so far */
  134.  
  135.     /* compress row by row */
  136.     for (i=0; i<ydim; i++) {
  137.         n = DFCrle(in, out, xdim); /* compress row */
  138.         in += xdim;        /* move input pointer */
  139.         total += n;        /* keep running total */
  140.         if (buftype==1)    /* can hold whole image */
  141.         out = &buffer[total]; /* move out buffer pointer */
  142.         else {        /* buffer too small, */
  143.                 /* write out what was produced */
  144.         if (DFwrite(dfile, buffer, n)<0) {
  145.             ret = -1;    /* flag value */
  146.             break;
  147.         }
  148.         out = buffer;    /* reset output pointer */
  149.         }
  150.     }
  151.  
  152.     if (buftype==1)        /* write out entire image */
  153.                 ret = DFwrite(dfile, buffer, total);
  154.     break;
  155.  
  156.       case DFTAG_IMC:
  157.         if (!palette || !newpal) { /* need palette and newpal */
  158.             DFerror = DFE_BADPTR;
  159.             return(-1);
  160.         }
  161.         cisize = xdim*ydim/4;    /* IMCOMP always cuts to 1/4 */
  162.  
  163. #ifdef DF_DYNAMIC
  164.         buffer = (char *) DFIgetspace((unsigned)cisize);
  165.         if (!buffer) {
  166.             DFerror = DFE_NOSPACE;
  167.             return(-1);
  168.         }
  169. #else /*DF_DYNAMIC*/
  170.         if (DF_TBUFSZ<cisize) {
  171.             DFerror = DFE_NOSPACE;
  172.             return(-1);
  173.         }
  174.         buffer = DFtbuf;
  175. #endif /*DF_DYNAMIC*/
  176.  
  177.         DFCimcomp(xdim, ydim, image, buffer, palette, newpal, 0);
  178.         ret = DFwrite(dfile, buffer, cisize);
  179.         break;
  180.  
  181.     default:            /* unknown compression scheme */
  182.         DFerror = DFE_BADSCHEME;
  183.         return(-1);
  184.         break;
  185.     }
  186. #ifdef DF_DYNAMIC
  187.     DFIfreespace((char*)buffer);
  188. #endif /*DF_DYNAMIC*/
  189.     return(ret);
  190. }
  191.  
  192. /*-----------------------------------------------------------------------------
  193.  * Name:    DFgetcomp
  194.  * Purpose: Read compressed image and decompress it
  195.  * Inputs:  dfile: HDF file pointer
  196.  *          tag, ref: id of image to be decompressed
  197.  *          image: space to return decompressed image in
  198.  *          xdim, ydim: dimensions of decompressed image
  199.  *          scheme: compression scheme used
  200.  * Returns: 0 on success, -1 on failure with DFerror set
  201.  * Users:   HDF programmers, DF8getrig, other routines
  202.  * Invokes: DFIcheck, DFIfind, DFaccess, DFread, DFCunrle, DFCunimcomp
  203.  * Remarks: Will use dynamic/static memory allocation for buffer
  204.  *          will read in image in parts if memory insufficient
  205.  *          Decompression of rle is not necessarily row by row
  206.  *          Other encodings can also be decoded with this
  207.  *---------------------------------------------------------------------------*/
  208.  
  209. int DFgetcomp(dfile, tag, ref, image, xdim, ydim, scheme)
  210. DF *dfile;
  211. uint16 tag, ref;
  212. char *image;
  213. int32 xdim, ydim;
  214. uint16 scheme;
  215. {
  216.     char *buffer, *in, *out;
  217.     int32 cisize, crowsize, buflen, bufleft; /* bufleft: bytes left in buffer*/
  218.     DFdle *dlep;
  219.     int cdd, i, n, totalread;
  220.  
  221.     if (DFIcheck(dfile)<0) return(-1);
  222.     if (!tag) {
  223.         DFerror = DFE_BADTAG;
  224.         return(-1);
  225.     }
  226.     if (!ref) {
  227.         DFerror = DFE_BADREF;
  228.         return(-1);
  229.     }
  230.     if (!image) {
  231.         DFerror = DFE_BADPTR;
  232.         return(-1);
  233.     }
  234.     if ((xdim<=0) || (ydim<=0)) {
  235.         DFerror = DFE_BADDIM;
  236.         return(-1);
  237.     }
  238.  
  239.     if (DFIfind(dfile, tag, ref, 1, 0, 0, &dlep, &cdd)<0) {
  240.         DFerror = DFE_NOMATCH;
  241.         return(-1);
  242.     }
  243.     cisize = dlep->dd[cdd].length;
  244.  
  245.     if (DFaccess(dfile, tag, ref, "r")<0) return(-1);
  246.     switch (scheme) {
  247.       case DFTAG_RLE:
  248.     crowsize = xdim*121/120 + 128; /* max size of a row */
  249.  
  250. #ifdef DF_DYNAMIC
  251.     buffer = (char *) DFIgetspace((unsigned)cisize);
  252.     if (!buffer) {
  253.         buffer = (char *) DFIgetspace((unsigned)crowsize);
  254.         if (!buffer) {
  255.         DFerror = DFE_NOSPACE;
  256.         return(-1);
  257.         }
  258.         buflen = crowsize;
  259.     }
  260.     else buflen = cisize;
  261. #else /*DF_DYNAMIC*/
  262.     if (DF_TBUFSZ<crowsize) {
  263.         DFerror = DFE_NOSPACE;
  264.         return(-1);
  265.     }
  266.     buffer = DFtbuf;    /* static compression buffer */
  267.     buflen = DF_TBUFSZ;
  268. #endif /*DF_DYNAMIC*/
  269.  
  270.     in = buffer;
  271.     out = image;
  272.     if ((n=DFread(dfile, in, buflen))<0) {
  273. #ifdef DF_DYNAMIC
  274.         DFIfreespace((char*)buffer);
  275. #endif /*DF_DYNAMIC*/
  276.         return(-1);
  277.     }
  278.     totalread = n;
  279.     bufleft = n;
  280.     for (i=0; i<ydim; i++) {
  281.         n = DFCunrle(in, out, xdim, !i); /* no of bytes used up */
  282.         /* last arg=TRUE if i=0 - resets decompress */
  283.         in += n;
  284.         out += xdim;
  285.         bufleft -= n;
  286.         /* check if more bytes may be needed for next read */
  287.         if ((bufleft<crowsize) && (totalread<cisize)) {
  288.         DFmovmem(in, buffer, (int)bufleft);
  289.         in = buffer;
  290.         if ((n=DFread(dfile,&in[bufleft],buflen-bufleft))<0) {
  291. #ifdef DF_DYNAMIC
  292.             DFIfreespace((char*)buffer);
  293. #endif /*DF_DYNAMIC   */
  294.             return(-1);
  295.         }
  296.         totalread += n;
  297.         bufleft += n;
  298.         }
  299.     }
  300.     break;
  301.  
  302.       case DFTAG_IMC:
  303.     crowsize = xdim;    /* size of compressed row */
  304.  
  305. #ifdef DF_DYNAMIC
  306.     buffer = (char *) DFIgetspace((unsigned)cisize);
  307.     if (!buffer) {
  308.         buffer = (char *) DFIgetspace((unsigned)crowsize);
  309.         if (!buffer) {
  310.         DFerror = DFE_NOSPACE;
  311.         return(-1);
  312.         }
  313.         buflen = crowsize;
  314.     }
  315.     else buflen = cisize;
  316. #else /*DF_DYNAMIC*/
  317.     buffer = DFtbuf;    /* static compression buffer */
  318.     if (DF_TBUFSZ<crowsize) {
  319.         DFerror = DFE_NOSPACE;
  320.         return(-1);
  321.     }
  322.     buflen = DF_TBUFSZ;
  323. #endif /*DF_DYNAMIC*/
  324.     if (buflen>=cisize) {
  325.         if (DFread(dfile, buffer, cisize)<cisize) {
  326. #ifdef DF_DYNAMIC
  327.         DFIfreespace((char*)buffer);
  328. #endif /*DF_DYNAMIC*/
  329.         return(-1);
  330.         }
  331.         DFCunimcomp(xdim, ydim, buffer, image);
  332.         break;        /* go to end of switch */
  333.     }
  334.  
  335.     in = buffer;        /* if can only read piecemeal */
  336.     out = image;
  337.     if ((n=DFread(dfile, in, buflen))<0) {
  338. #ifdef DF_DYNAMIC
  339.         DFIfreespace((char*)buffer);
  340. #endif /*DF_DYNAMIC*/
  341.         return(-1);
  342.     }
  343.     totalread = n;
  344.     bufleft = n;
  345.     for (i=0; i<ydim; i+=4) {
  346.         DFCunimcomp(xdim, (int32)4, in, out);
  347.         in += xdim;
  348.         out += 4*xdim;
  349.         bufleft -= xdim;
  350.         if ((bufleft<crowsize) && (totalread<cisize)) {
  351.         DFmovmem(in, buffer, (int)bufleft);
  352.         in = buffer;
  353.         if ((n=DFread(dfile,&in[bufleft],buflen-bufleft))<0) {
  354. #ifdef DF_DYNAMIC
  355.             DFIfreespace((char*)buffer);
  356. #endif /*DF_DYNAMIC*/
  357.             return(-1);
  358.         }
  359.         totalread += n;
  360.         bufleft += n;
  361.         }
  362.     }
  363.     break;
  364.  
  365.       default:            /* unknown scheme */
  366.     DFerror = DFE_BADSCHEME;
  367.     return(-1);
  368.     break;
  369.     }
  370. #ifdef DF_DYNAMIC
  371.     DFIfreespace((char*)buffer);
  372. #endif /*DF_DYNAMIC*/
  373.     return(0);
  374. }
  375.  
  376. /*-----------------------------------------------------------------------------
  377.  * Name:    DFCrle
  378.  * Purpose: compress a string of bytes
  379.  * Inputs:  buf: buffer containing data to be compressed
  380.  *          bufto: space for compressed data - assumed big enough
  381.  *          len: number of bytes to compress
  382.  * Returns: number of compressed bytes on success, -1 on failure
  383.  * Users:   HDF programmers, DFputcomp, other routines
  384.  * Invokes: none
  385.  * Remarks: Written for efficiency
  386.  *---------------------------------------------------------------------------*/
  387.  
  388. int DFCrle(buf,bufto,len)
  389. int32 len;
  390. char *buf,*bufto;
  391. {
  392.     register char *p,*q,*cfoll,*clead;
  393.     char *begp;
  394.     int32 i;
  395.  
  396.     p = buf;
  397.     cfoll = bufto;        /* place to copy to */
  398.     clead = cfoll + 1;
  399.     
  400.     begp = p;
  401.     while (len > 0) {           /* encode stuff until gone */
  402.  
  403.         q = p + 1;
  404.         i = len-1;
  405.         while (i && i+120 > len && *p == *q) {
  406.             q++;
  407.             i--;
  408.         }
  409.         
  410.         if (q > p + 2) {        /* three in a row */
  411.             if (p > begp) {
  412.                 *cfoll = p - begp;
  413.                 cfoll = clead;
  414.             }
  415.             *cfoll++ = 128 | (q-p); /* len of seq */
  416.             *cfoll++ = *p;      /* char of seq */
  417.             len -= q-p;         /* subtract len of seq */
  418.             p = q;
  419.             clead = cfoll+1;
  420.             begp = p;
  421.         }
  422.         else {
  423.             *clead++ = *p++;    /* copy one char */
  424.             len--;
  425.             if (p > begp + 120) {
  426.                 *cfoll = p - begp;
  427.                 cfoll = clead++;
  428.                 begp = p;
  429.             }
  430.         }
  431.         
  432.     }
  433. /*
  434.  *  fill in last bytecount
  435.  */
  436.     if (p > begp) 
  437.         *cfoll = (p - begp);
  438.     else
  439.         clead--;                    /* don't need count position */
  440.     
  441.     return((int)(clead - bufto));   /* how many stored as encoded */
  442. }
  443.  
  444. /*-----------------------------------------------------------------------------
  445.  * Name:    DFCunrle
  446.  * Purpose: decompress run length encoding
  447.  * Inputs:  buf: buffer containing compressed data
  448.  *          bufto: space for returning decompressed data
  449.  *          outlen: number of *decompressed* bytes desired.
  450.  *          resetsave: don't use any stored state info - used for fresh image
  451.  * Returns: number of compressed bytes used up on success, -1 on failure
  452.  * Users:   HDF programmers, DFgetcomp, other routines
  453.  * Invokes: none
  454.  * Remarks: has been modified so it will decompress even non-rowwise compression
  455.  *          Hence the static storage stuff
  456.  *---------------------------------------------------------------------------*/
  457.  
  458. int DFCunrle(buf,bufto,outlen, resetsave)
  459. int32 outlen;
  460. char *buf,*bufto;
  461. int resetsave;
  462. {
  463.     register int cnt;
  464.     register char *p,*q;
  465.     char *endp;
  466.     static char save[255], *savestart=NULL, *saveend=NULL;
  467.     /* save has a list of decompressed bytes not returned in
  468.        previous call.  savestart and saveend specify the position
  469.        at which this list starts and ends in the array save */
  470.     
  471.     p = buf;
  472.     endp = bufto + outlen;
  473.     q = bufto;
  474.     if (resetsave) savestart = saveend = save; /* forget saved state */
  475.     while ((saveend>savestart) && (q<endp)) /* copy saved stuff */
  476.         *q++ = *savestart++;
  477.     if (savestart>=saveend) savestart = saveend = save;    /* all copied */
  478.     while (q < endp) {
  479.         cnt = *p++;        /* count field */
  480.         if (!(cnt & 128)) {    /* is set of uniques */
  481.             while (cnt--) {
  482.                 if (q<endp)
  483.                     *q++ = *p++; /* copy unmodified */
  484.                 else
  485.                     *saveend++ = *p++;
  486.             }
  487.         }
  488.         else {
  489.             cnt &= 127;        /* strip high bit */
  490.             while (cnt--) {
  491.                 if (q<endp)
  492.                     *q++ = *p;  /* copy unmodified */
  493.                 else
  494.                     *saveend++ = *p;
  495.             }
  496.             p++;                /* skip that character */
  497.         }
  498.     }
  499.     return((int)(p-buf));
  500. }
  501.