HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Compress.C
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_Compress.C UT library (C++)
7  *
8  * COMMENTS:
9  * Class to do simple (RLE) and complex compression (zlib).
10  * Also has some other simple prefilter and constant checking methods.
11  *
12  */
13 #ifndef UT_COMPRESS_C
14 #define UT_COMPRESS_C
15 
16 #include <zlib.h>
17 
18 #include "UT_Compress.h"
19 
20 template <class Type>
22  : myChunkSize(0),
23  myRLEBuf(0),
24  myCompressBuf(0)
25 {
26  ;
27 }
28 
29 template <class Type>
31 {
32  delete [] myRLEBuf;
33  delete [] myCompressBuf;
34 }
35 
36 template <class Type> void
38 {
39  if(myChunkSize != size)
40  {
41  myChunkSize = size;
42 
43  delete [] myRLEBuf;
44  delete [] myCompressBuf;
45 
46  // size restriction of zlib
47  myCompressBuf = new unsigned char[sizeof(Type) * size * 11/10 + 12];
48  myRLEBuf = new unsigned char[size * 2 * sizeof(Type)];
49  }
50 }
51 
52 // Constant Checking & Prefiltering ----------------------------------------
53 
54 template <class Type> int
56 {
57  Type val = *data;
58  const Type *itr = data;
59 
60  if(size == -1)
61  size = myChunkSize;
62 
63  while(size > 0 && *itr++ == val) size--;
64 
65  return (size == 0);
66 }
67 
68 // prefilter only really works for 8 bits.
69 template<>
70 inline int
72 {
73  unsigned char val = *data;
74  unsigned char prev,tmp;
75  unsigned char *itr = data;
76  int constant = 1;
77 
78  if(size == -1)
79  size = myChunkSize;
80 
81  prev = val;
82  itr ++;
83  size --;
84 
85  while(size)
86  {
87  tmp = *itr;
88  *itr -= prev;
89 
90  if(tmp != prev)
91  constant = 0;
92 
93  prev = tmp;
94  itr++;
95  size--;
96  }
97 
98  return constant;
99 }
100 
101 template<>
102 inline void
104 {
105  unsigned char prev;
106 
107  if(size == -1)
108  size = myChunkSize;
109 
110  prev = *data;
111  data ++;
112  size --;
113 
114  while(size)
115  {
116  *data += prev;
117  prev = *data;
118  data++;
119  size--;
120  }
121 }
122 
123 template<>
124 inline int
126 {
127  unsigned short val = *data;
128  unsigned short prev,tmp;
129  unsigned short *itr = data;
130  int constant = 1;
131 
132  if(size == -1)
133  size = myChunkSize;
134 
135  prev = val;
136  itr ++;
137  size --;
138 
139  while(size)
140  {
141  tmp = *itr;
142  *itr -= prev;
143 
144  if(tmp != prev)
145  constant = 0;
146 
147  prev = tmp;
148  itr++;
149  size--;
150  }
151 
152  return constant;
153 }
154 
155 template<>
156 inline void
158 {
159  unsigned short prev;
160 
161  if(size == -1)
162  size = myChunkSize;
163 
164  prev = *data;
165  data ++;
166  size --;
167 
168  while(size)
169  {
170  *data += prev;
171  prev = *data;
172  data++;
173  size--;
174  }
175 }
176 
177 template<class Type> int
179 {
180  return isConstant(data,size);
181 }
182 
183 template<class Type> void
185 {
186  ;
187 }
188 
189 // RLE Encoding & Decoding --------------------------------------------------
190 
191 template <class Type> void *
192 UT_Compress<Type>::encodeRLE(const Type *data, int &result_length,
193  int size, int stride)
194 {
195  const Type *ci;
196  unsigned char *co;
197  int i,repeat;
198 
199  ci = (Type *)data;
200  co = myRLEBuf;
201 
202  if(size == -1)
203  size = myChunkSize;
204 
205  while (size > 0)
206  {
207  if (size < 3)
208  repeat = -size;
209  else
210  repeat = repeatCount(ci, (size<128) ? size : 128, stride);
211  if (repeat < 0)
212  {
213  *co++ = char(repeat);
214  size += repeat;
215  if(stride == 1)
216  {
217  memcpy(co, ci, sizeof(Type)*(-repeat));
218  ci += (-repeat);
219  co += sizeof(Type)*(-repeat);
220  }
221  else
222  {
223  for (i=0; i< -repeat; i++)
224  {
225  memcpy(co,ci, sizeof(Type));
226  co += sizeof(Type);
227  ci += stride;
228  }
229  }
230  }
231  else
232  {
233  *co++ = char(repeat-1);
234  memcpy(co,ci,sizeof(Type));
235  co += sizeof(Type);
236 
237  ci += repeat * stride;
238  size -= repeat;
239  }
240  }
241 
242  result_length = co - myRLEBuf;
243 
244  return myRLEBuf;
245 }
246 
247 template <class Type> int
248 UT_Compress<Type>::repeatCount(const Type *data, int max_run, int stride)
249 {
250  const Type *ci, *ci1, *ci2;
251  const Type *start;
252  int repeat;
253 
254  start = ci = data;
255  ci += stride;
256  for (repeat = 1; repeat < max_run; repeat++)
257  {
258  if (*ci != *start)
259  break;
260  ci += stride;
261  }
262  if (repeat != 1)
263  return repeat;
264 
265  // Raw run - only gets here when max_run > 2
266  ci2 = data; // ci-2
267  ci1 = ci2+stride; // ci-1
268  ci = ci1+stride; // ci
269 
270  for (repeat = 2; repeat < max_run; repeat++)
271  {
272  if (*ci2 == *ci && *ci1 == *ci)
273  { repeat -= 2;
274  break;
275  }
276  ci2 = ci1;
277  ci1 = ci;
278  ci += stride;
279  }
280 
281  return -repeat;
282 }
283 
284 template<class Type> int
285 UT_Compress<Type>::decodeRLE(const void *cdata,int length,Type *uncdata,
286  int stride)
287 {
288  const unsigned char *ci, *end;
289  Type *co;
290  int count;
291  int size;
292  int i;
293 
294  co = uncdata;
295  ci = (unsigned char *)cdata;
296  end = ci + length;
297  size = 0;
298 
299  while (ci < end)
300  {
301  if (*ci & 0x80) // Run of raw data
302  {
303  count = 256 - int(*ci);
304  size += count*sizeof(Type)+1; // We've read this many bytes
305  ci++;
306 
307  if(stride == 1)
308  {
309  memcpy(co, ci, sizeof(Type)*count);
310  ci+=sizeof(Type)*count;
311  co+=count;
312  }
313  else
314  {
315  for (i=0; i<count; i++)
316  {
317  memcpy(co,ci,sizeof(Type));
318  ci += sizeof(Type);
319  co += stride;
320  }
321  }
322  }
323  else
324  {
325  count = 1 + int(*ci);
326  size += 1 + sizeof(Type); // We read 2 chars from the buffer
327  ci++; // Find out what char we repeat
328 
329  while(count--)
330  {
331  memcpy(co,ci, sizeof(Type));
332  co += stride;
333  }
334 
335  ci+=sizeof(Type);
336  }
337  }
338  return (end == ci) ? 0 : size;
339 }
340 
341 // ZLib compression --------------------------------------------------------
342 
343 inline int
344 compressLevel(Bytef *dest, uLongf *destLen, const Bytef *source,
345  uLong sourceLen, int level)
346 {
347  z_stream stream;
348  int err;
349 
350  stream.next_in = (Bytef*)source;
351  stream.avail_in = (uInt)sourceLen;
352 #ifdef MAXSEG_64K
353  /* Check for source > 64K on 16-bit machine: */
354  if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
355 #endif
356  stream.next_out = dest;
357  stream.avail_out = (uInt)*destLen;
358  if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
359 
360  stream.zalloc = (alloc_func)0;
361  stream.zfree = (free_func)0;
362  stream.opaque = (voidpf)0;
363 
364  err = deflateInit(&stream, level);
365  if (err != Z_OK) return err;
366 
367  err = deflate(&stream, Z_FINISH);
368  if (err != Z_STREAM_END) {
369  deflateEnd(&stream);
370  return err == Z_OK ? Z_BUF_ERROR : err;
371  }
372  *destLen = stream.total_out;
373 
374  err = deflateEnd(&stream);
375  return err;
376 }
377 
378 template<class Type> void *
379 UT_Compress<Type>::compress(const void *data, int &result_length, int size,
380  int level)
381 {
382  uLongf length;
383 
384  if(size == -1)
385  size = myChunkSize;
386 
387  length = sizeof(Type) * myChunkSize * 11 / 10 + 12;
388 
389  if(Z_OK == ::compressLevel((Bytef *)myCompressBuf, &length,
390  (const Bytef *)data,
391  (uLong) size*sizeof(Type), level))
392  {
393  result_length = (int) length;
394  return myCompressBuf;
395  }
396 
397  return 0;
398 }
399 
400 template<class Type> int
401 UT_Compress<Type>::expand(const void *data, int size, void *dest)
402 {
403  uLongf length;
404 
405  length = myChunkSize * sizeof(Type);
406  size *= sizeof(Type);
407 
408  if(Z_OK == ::uncompress((Bytef *)dest, &length,
409  (Bytef *)data, (uLong) size))
410  return (int)length;
411 
412  return 0;
413 }
414 
415 #endif
GLuint GLuint stream
Definition: glcorearb.h:1832
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
Byte FAR * voidpf
Definition: zconf.h:387
GLboolean * data
Definition: glcorearb.h:131
GLuint start
Definition: glcorearb.h:475
void setChunkSize(int size)
Definition: UT_Compress.C:37
GLint level
Definition: glcorearb.h:108
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
unsigned long uLong
Definition: zconf.h:368
int compressLevel(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
Definition: UT_Compress.C:344
Byte FAR Bytef
Definition: zconf.h:374
int prefilter(Type *data, int size=-1)
Definition: UT_Compress.C:178
GLuint GLuint end
Definition: glcorearb.h:475
int expand(const void *data, int size, void *dest)
Definition: UT_Compress.C:401
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
void * encodeRLE(const Type *data, int &result_length, int size=-1, int stride=1)
Definition: UT_Compress.C:192
int isConstant(const Type *data, int size=-1) const
Definition: UT_Compress.C:55
int decodeRLE(const void *data, int size, Type *dest, int stride=1)
Definition: UT_Compress.C:285
void postfilter(Type *data, int size=-1)
Definition: UT_Compress.C:184
std::string OIIO_UTIL_API repeat(string_view str, int n)
Repeat a string formed by concatenating str n times.
GLsizeiptr size
Definition: glcorearb.h:664
uLong FAR uLongf
Definition: zconf.h:379
GLuint GLfloat * val
Definition: glcorearb.h:1608
void * compress(const void *data, int &result_length, int size=-1, int level=1)
Definition: UT_Compress.C:379
GLint GLsizei count
Definition: glcorearb.h:405
Definition: format.h:895
unsigned int uInt
Definition: zconf.h:367