/***************************************************************************** * * NCSA HDF version 3.10 * July 1, 1990 * * NCSA HDF Version 3.10 source code and documentation are in the public * domain. Specifically, we give to the public domain all rights for future * licensing of the source code, all resale rights, and all publishing rights. * * We ask, but do not require, that the following message be included in all * derived works: * * Portions developed at the National Center for Supercomputing Applications at * the University of Illinois at Urbana-Champaign. * * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE * *****************************************************************************/ #ifdef RCSID static char RcsId??(??) = "@(#)$Revision: 3.2 $"; #endif /* $Header: /pita/work/HDF/dev/RCS/src/dfcomp.c,v 3.2 90/07/02 10:12:14 clow beta $ $Log: dfcomp.c,v $ * Revision 3.2 90/07/02 10:12:14 clow * some cosmetic modifications * */ /*----------------------------------------------------------------------------- * File: dfcomp.c * Purpose: File compression * Invokes: df.c dfimcomp.c df.h * Contents: * DFputcomp: compress image and write it to HDF file * DFgetcomp: read compressed image from HDF file and decompress it * DFCrle: compress string using run length encoding * DFCunrle: decompress string using run length encoding * Remarks: DFgetcomp and DFputcomp constitute a general compression interface *---------------------------------------------------------------------------*/ #include "df.h" #ifndef VMS extern void DFCimcomp(), DFCunimcomp(); #else /*VMS*/ extern void _DFCimcomp(), _DFCunimcomp(); #endif /*----------------------------------------------------------------------------- * Name: DFputcomp * Purpose: Compress and write images to HDF file * Inputs: dfile: pointer to HDF file * tag, ref: tag, ref of compressed image for writing out * image: image to be compressed * xdim, ydim: dimensions of image * palette: palette associated with image * newpal: modified palette, produced if compression scheme is IMCOMP * scheme: compression scheme to be used * Returns: 0 on success, -1 on failure with DFerror set * Users: HDF programmers, DF8putrig, other routines * Invokes: DFCrle, DFCimcomp, DFaccess, DFwrite, DFIcheck * Remarks: IMCOMP modifies the palette associated with the image * Hence the palette and newpal arguments * This is a general compression interface - to be used anytime image * compression is needed in HDF * Note that rseq does its own compression, because that is part of * the interactive color raster protocol * The space needed for compression and decompression can be allocated * statically or dynamically, depending on the DF_DYNAMIC flag, and * for entire image or part of it (reused) depending on availability * Accordingly, writing out is whole image, or row by row * Note that compression is always row by row for RLE. *---------------------------------------------------------------------------*/ int DFputcomp(dfile, tag, ref, image, xdim, ydim, palette, newpal, scheme) DF *dfile; uint16 tag, ref; char *image; int32 xdim, ydim; char *palette, *newpal; int16 scheme; { char *buffer; /* buffer to hold compressed image */ char *in; /* pointer to input for compression */ char *out; /* pointer to space for compressed output */ int32 cisize; /* maximum size of compressed image */ int32 crowsize; /* maximum size of compressed row */ int32 buftype; /* buftype = 1: buffer enough for whole image*/ /* buftype = 2: buffer holds 1 row */ int32 n; /* number of compressed bytes produced */ int32 total; /* total compressed bytes produced so far */ int i, ret=0; if (DFIcheck(dfile)<0) return(-1); if (!tag) { DFerror = DFE_BADTAG; return(-1); } if (!ref) { DFerror = DFE_BADREF; return(-1); } if ((xdim<=0) || (ydim<=0)) { DFerror = DFE_BADDIM; return(-1); } if (!image) { DFerror = DFE_BADPTR; return(-1); } if (DFaccess(dfile, tag, ref, "w")<0) return(-1); /* setup to write CI */ switch (scheme) { case DFTAG_RLE: cisize = ydim*(xdim*121/120+1); /* 120 chars can compress to 121! */ crowsize = xdim*121/120 + 128; /* allocate buffer for compression */ #ifdef DF_DYNAMIC /* large mallocs OK */ buffer = (char *) DFIgetspace((unsigned)cisize); if (!buffer) { buffer = (char *) DFIgetspace((unsigned)crowsize); if (!buffer) { DFerror = DFE_NOSPACE; return(-1); } buftype = 2; /* compress and write out row by row */ } else buftype = 1; /* can hold whole image, then write */ #else /*DF_DYNAMIC use static buffers */ buffer = DFtbuf; if (DF_TBUFSZ>=cisize) buftype = 1; else if (DF_TBUFSZ>crowsize) buftype = 2; else { DFerror = DFE_NOSPACE; return(-1); } #endif /*DF_DYNAMIC*/ in = image; out = buffer; n = total = 0; /* no bytes compressed so far */ /* compress row by row */ for (i=0; idd??(cdd??).length; if (DFaccess(dfile, tag, ref, "r")<0) return(-1); switch (scheme) { case DFTAG_RLE: crowsize = xdim*121/120 + 128; /* max size of a row */ #ifdef DF_DYNAMIC buffer = (char *) DFIgetspace((unsigned)cisize); if (!buffer) { buffer = (char *) DFIgetspace((unsigned)crowsize); if (!buffer) { DFerror = DFE_NOSPACE; return(-1); } buflen = crowsize; } else buflen = cisize; #else /*DF_DYNAMIC*/ if (DF_TBUFSZ=cisize) { if (DFread(dfile, buffer, cisize) 0) { /* encode stuff until gone */ q = p + 1; i = len-1; while (i && i+120 > len && *p == *q) { q++; i--; } if (q > p + 2) { /* three in a row */ if (p > begp) { *cfoll = p - begp; cfoll = clead; } *cfoll++ = 128 | (q-p); /* len of seq */ *cfoll++ = *p; /* char of seq */ len -= q-p; /* subtract len of seq */ p = q; clead = cfoll+1; begp = p; } else { *clead++ = *p++; /* copy one char */ len--; if (p > begp + 120) { *cfoll = p - begp; cfoll = clead++; begp = p; } } } /* * fill in last bytecount */ if (p > begp) *cfoll = (p - begp); else clead--; /* don't need count position */ return((int)(clead - bufto)); /* how many stored as encoded */ } /*----------------------------------------------------------------------------- * Name: DFCunrle * Purpose: decompress run length encoding * Inputs: buf: buffer containing compressed data * bufto: space for returning decompressed data * outlen: number of *decompressed* bytes desired. * resetsave: don't use any stored state info - used for fresh image * Returns: number of compressed bytes used up on success, -1 on failure * Users: HDF programmers, DFgetcomp, other routines * Invokes: none * Remarks: has been modified so it will decompress even non-rowwise compression * Hence the static storage stuff *---------------------------------------------------------------------------*/ int DFCunrle(buf,bufto,outlen, resetsave) int32 outlen; char *buf,*bufto; int resetsave; { register int cnt; register char *p,*q; char *endp; static char save??(255??), *savestart=NULL, *saveend=NULL; /* save has a list of decompressed bytes not returned in previous call. savestart and saveend specify the position at which this list starts and ends in the array save */ p = buf; endp = bufto + outlen; q = bufto; if (resetsave) savestart = saveend = save; /* forget saved state */ while ((saveend>savestart) && (q=saveend) savestart = saveend = save; /* all copied */ while (q < endp) { cnt = *p++; /* count field */ if (!(cnt & 128)) { /* is set of uniques */ while (cnt--) { if (q