00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef UT_COMPRESS_C
00022 #define UT_COMPRESS_C
00023
00024 #include <zlib.h>
00025
00026 #include "UT_Compress.h"
00027
00028 template <class Type>
00029 UT_Compress<Type>::UT_Compress()
00030 : myChunkSize(0),
00031 myRLEBuf(0),
00032 myCompressBuf(0)
00033 {
00034 ;
00035 }
00036
00037 template <class Type>
00038 UT_Compress<Type>::~UT_Compress()
00039 {
00040 delete [] myRLEBuf;
00041 delete [] myCompressBuf;
00042 }
00043
00044 template <class Type> void
00045 UT_Compress<Type>::setChunkSize(int size)
00046 {
00047 if(myChunkSize != size)
00048 {
00049 myChunkSize = size;
00050
00051 delete [] myRLEBuf;
00052 delete [] myCompressBuf;
00053
00054
00055 myCompressBuf = new unsigned char[sizeof(Type) * size * 11/10 + 12];
00056 myRLEBuf = new unsigned char[size * 2 * sizeof(Type)];
00057 }
00058 }
00059
00060
00061
00062 template <class Type> int
00063 UT_Compress<Type>::isConstant(const Type *data, int size) const
00064 {
00065 Type val = *data;
00066 const Type *itr = data;
00067
00068 if(size == -1)
00069 size = myChunkSize;
00070
00071 while(size > 0 && *itr++ == val) size--;
00072
00073 return (size == 0);
00074 }
00075
00076
00077 template<>
00078 inline int
00079 UT_Compress<unsigned char>::prefilter(unsigned char *data, int size)
00080 {
00081 unsigned char val = *data;
00082 unsigned char prev,tmp;
00083 unsigned char *itr = data;
00084 int constant = 1;
00085
00086 if(size == -1)
00087 size = myChunkSize;
00088
00089 prev = val;
00090 itr ++;
00091 size --;
00092
00093 while(size)
00094 {
00095 tmp = *itr;
00096 *itr -= prev;
00097
00098 if(tmp != prev)
00099 constant = 0;
00100
00101 prev = tmp;
00102 itr++;
00103 size--;
00104 }
00105
00106 return constant;
00107 }
00108
00109 template<>
00110 inline void
00111 UT_Compress<unsigned char>::postfilter(unsigned char *data, int size)
00112 {
00113 unsigned char prev;
00114
00115 if(size == -1)
00116 size = myChunkSize;
00117
00118 prev = *data;
00119 data ++;
00120 size --;
00121
00122 while(size)
00123 {
00124 *data += prev;
00125 prev = *data;
00126 data++;
00127 size--;
00128 }
00129 }
00130
00131 template<>
00132 inline int
00133 UT_Compress<unsigned short>::prefilter(unsigned short *data, int size)
00134 {
00135 unsigned short val = *data;
00136 unsigned short prev,tmp;
00137 unsigned short *itr = data;
00138 int constant = 1;
00139
00140 if(size == -1)
00141 size = myChunkSize;
00142
00143 prev = val;
00144 itr ++;
00145 size --;
00146
00147 while(size)
00148 {
00149 tmp = *itr;
00150 *itr -= prev;
00151
00152 if(tmp != prev)
00153 constant = 0;
00154
00155 prev = tmp;
00156 itr++;
00157 size--;
00158 }
00159
00160 return constant;
00161 }
00162
00163 template<>
00164 inline void
00165 UT_Compress<unsigned short>::postfilter(unsigned short *data, int size)
00166 {
00167 unsigned short prev;
00168
00169 if(size == -1)
00170 size = myChunkSize;
00171
00172 prev = *data;
00173 data ++;
00174 size --;
00175
00176 while(size)
00177 {
00178 *data += prev;
00179 prev = *data;
00180 data++;
00181 size--;
00182 }
00183 }
00184
00185 template<class Type> int
00186 UT_Compress<Type>::prefilter(Type *data, int size)
00187 {
00188 return isConstant(data,size);
00189 }
00190
00191 template<class Type> void
00192 UT_Compress<Type>::postfilter(Type *, int )
00193 {
00194 ;
00195 }
00196
00197
00198
00199 template <class Type> void *
00200 UT_Compress<Type>::encodeRLE(const Type *data, int &result_length,
00201 int size, int stride)
00202 {
00203 const Type *ci;
00204 unsigned char *co;
00205 int i,repeat;
00206
00207 ci = (Type *)data;
00208 co = myRLEBuf;
00209
00210 if(size == -1)
00211 size = myChunkSize;
00212
00213 while (size > 0)
00214 {
00215 if (size < 3)
00216 repeat = -size;
00217 else
00218 repeat = repeatCount(ci, (size<128) ? size : 128, stride);
00219 if (repeat < 0)
00220 {
00221 *co++ = char(repeat);
00222 size += repeat;
00223 if(stride == 1)
00224 {
00225 memcpy(co, ci, sizeof(Type)*(-repeat));
00226 ci += (-repeat);
00227 co += sizeof(Type)*(-repeat);
00228 }
00229 else
00230 {
00231 for (i=0; i< -repeat; i++)
00232 {
00233 memcpy(co,ci, sizeof(Type));;
00234 co += sizeof(Type);
00235 ci += stride;
00236 }
00237 }
00238 }
00239 else
00240 {
00241 *co++ = char(repeat-1);
00242 memcpy(co,ci,sizeof(Type));
00243 co += sizeof(Type);
00244
00245 ci += repeat * stride;
00246 size -= repeat;
00247 }
00248 }
00249
00250 result_length = co - myRLEBuf;
00251
00252 return myRLEBuf;
00253 }
00254
00255 template <class Type> int
00256 UT_Compress<Type>::repeatCount(const Type *data, int max_run, int stride)
00257 {
00258 const Type *ci, *ci1, *ci2;
00259 const Type *start;
00260 int repeat;
00261
00262 start = ci = data;
00263 ci += stride;
00264 for (repeat = 1; repeat < max_run; repeat++)
00265 {
00266 if (*ci != *start)
00267 break;
00268 ci += stride;
00269 }
00270 if (repeat != 1)
00271 return repeat;
00272
00273
00274 ci2 = data;
00275 ci1 = ci2+stride;
00276 ci = ci1+stride;
00277
00278 for (repeat = 2; repeat < max_run; repeat++)
00279 {
00280 if (*ci2 == *ci && *ci1 == *ci)
00281 { repeat -= 2;
00282 break;
00283 }
00284 ci2 = ci1;
00285 ci1 = ci;
00286 ci += stride;
00287 }
00288
00289 return -repeat;
00290 }
00291
00292 template<class Type> int
00293 UT_Compress<Type>::decodeRLE(const void *cdata,int length,Type *uncdata,
00294 int stride)
00295 {
00296 const unsigned char *ci, *end;
00297 Type *co;
00298 int count;
00299 int size;
00300 int i;
00301
00302 co = uncdata;
00303 ci = (unsigned char *)cdata;
00304 end = ci + length;
00305 size = 0;
00306
00307 while (ci < end)
00308 {
00309 if (*ci & 0x80)
00310 {
00311 count = 256 - int(*ci);
00312 size += count*sizeof(Type)+1;
00313 ci++;
00314
00315 if(stride == 1)
00316 {
00317 memcpy(co, ci, sizeof(Type)*count);
00318 ci+=sizeof(Type)*count;
00319 co+=count;
00320 }
00321 else
00322 {
00323 for (i=0; i<count; i++)
00324 {
00325 memcpy(co,ci,sizeof(Type));
00326 ci += sizeof(Type);
00327 co += stride;
00328 }
00329 }
00330 }
00331 else
00332 {
00333 count = 1 + int(*ci);
00334 size += 1 + sizeof(Type);
00335 ci++;
00336
00337 while(count--)
00338 {
00339 memcpy(co,ci, sizeof(Type));
00340 co += stride;
00341 }
00342
00343 ci+=sizeof(Type);
00344 }
00345 }
00346 return (end == ci) ? 0 : size;
00347 }
00348
00349
00350
00351 inline int
00352 compressLevel(Bytef *dest, uLongf *destLen, const Bytef *source,
00353 uLong sourceLen, int level)
00354 {
00355 z_stream stream;
00356 int err;
00357
00358 stream.next_in = (Bytef*)source;
00359 stream.avail_in = (uInt)sourceLen;
00360 #ifdef MAXSEG_64K
00361
00362 if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
00363 #endif
00364 stream.next_out = dest;
00365 stream.avail_out = (uInt)*destLen;
00366 if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
00367
00368 stream.zalloc = (alloc_func)0;
00369 stream.zfree = (free_func)0;
00370 stream.opaque = (voidpf)0;
00371
00372 err = deflateInit(&stream, level);
00373 if (err != Z_OK) return err;
00374
00375 err = deflate(&stream, Z_FINISH);
00376 if (err != Z_STREAM_END) {
00377 deflateEnd(&stream);
00378 return err == Z_OK ? Z_BUF_ERROR : err;
00379 }
00380 *destLen = stream.total_out;
00381
00382 err = deflateEnd(&stream);
00383 return err;
00384 }
00385
00386 template<class Type> void *
00387 UT_Compress<Type>::compress(const void *data, int &result_length, int size,
00388 int level)
00389 {
00390 uLongf length;
00391
00392 if(size == -1)
00393 size = myChunkSize;
00394
00395 length = sizeof(Type) * myChunkSize * 11 / 10 + 12;
00396
00397 if(Z_OK == ::compressLevel((Bytef *)myCompressBuf, &length,
00398 (const Bytef *)data,
00399 (uLong) size*sizeof(Type), level))
00400 {
00401 result_length = (int) length;
00402 return myCompressBuf;
00403 }
00404
00405 return 0;
00406 }
00407
00408 template<class Type> int
00409 UT_Compress<Type>::expand(const void *data, int size, void *dest)
00410 {
00411 uLongf length;
00412
00413 length = myChunkSize * sizeof(Type);
00414 size *= sizeof(Type);
00415
00416 if(Z_OK == ::uncompress((Bytef *)dest, &length,
00417 (Bytef *)data, (uLong) size))
00418 return (int)length;
00419
00420 return 0;
00421 }
00422
00423 #endif