OFFIS DCMTK  Version 3.6.0
dcrledec.h
1 /*
2  *
3  * Copyright (C) 1994-2010, OFFIS e.V.
4  * All rights reserved. See COPYRIGHT file for details.
5  *
6  * This software and supporting documentation were developed by
7  *
8  * OFFIS e.V.
9  * R&D Division Health
10  * Escherweg 2
11  * D-26121 Oldenburg, Germany
12  *
13  *
14  * Module: dcmdata
15  *
16  * Author: Marco Eichelberg
17  *
18  * Purpose: RLE decompressor
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2010-10-14 13:15:42 $
22  * CVS/RCS Revision: $Revision: 1.6 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 #ifndef DCRLEDEC_H
30 #define DCRLEDEC_H
31 
32 #include "dcmtk/config/osconfig.h"
33 #include "dcmtk/dcmdata/dcerror.h"
34 
39 {
40 public:
41 
46  DcmRLEDecoder(size_t outputBufferSize)
47  : fail_(0)
48  , outputBufferSize_(outputBufferSize)
49  , outputBuffer_(NULL)
50  , offset_(0)
51  , suspendInfo_(128)
52  {
53  if (outputBufferSize_ == 0) fail_ = 1;
54  else
55  {
56  outputBuffer_ = new unsigned char[outputBufferSize_];
57  if (outputBuffer_ == NULL) fail_ = 1;
58  }
59  }
60 
63  {
64  delete[] outputBuffer_;
65  }
66 
70  inline void clear()
71  {
72  offset_ = 0;
73  suspendInfo_ = 128;
74  if (outputBuffer_) fail_ = 0;
75  }
76 
77 
78  inline OFCondition decompress(void *compressedData, size_t compressedSize)
79  {
80  // we allow a call for zero bytes
81  if (compressedSize == 0) return EC_Normal;
82 
83  OFCondition result = EC_IllegalCall;
84 
85  // check parameters passed by caller
86  if (compressedData == NULL) fail_ = 1;
87 
88  if (! fail_) // if fail_ is true, just ignore input
89  {
90  result = EC_Normal;
91  unsigned char ch;
92  unsigned char nbytes;
93  unsigned char *cp = OFstatic_cast(unsigned char *, compressedData);
94 
95  // check if we suspended last time, clean up
96  if (suspendInfo_ > 128)
97  {
98  // DICOM packbit scheme uses 257 - nbytes to represent replicate runs
99  nbytes = OFstatic_cast(unsigned char, 257 - suspendInfo_);
100 
101  // suspended replicate run. compressedSize cannot be zero now.
102  suspendInfo_ = 128;
103 
104  ch = *cp++;
105  --compressedSize;
106  replicate(ch, nbytes);
107  }
108  else if (suspendInfo_ < 128)
109  {
110  // suspended literal run
111  nbytes = OFstatic_cast(unsigned char, (suspendInfo_ & 0x7f) + 1);
112  suspendInfo_ = 128;
113  if (compressedSize < nbytes)
114  {
115  // we're going to suspend again (oops?), prepare everything
116  suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1);
117  nbytes = OFstatic_cast(unsigned char, compressedSize);
118  result = EC_StreamNotifyClient;
119  }
120 
121  literal(cp, nbytes);
122  compressedSize -= nbytes;
123  cp += nbytes;
124  }
125 
126  // continue with ordinary RLE decompression
127  while (compressedSize && (! fail_))
128  {
129  ch = *cp++;
130  --compressedSize;
131 
132  if (ch & 0x80)
133  {
134  // replicate run
135  if (compressedSize)
136  {
137  // DICOM packbit scheme uses 257 - nbytes to represent replicate runs
138  nbytes = OFstatic_cast(unsigned char, 257 - ch);
139  ch = *cp++;
140  --compressedSize;
141  replicate(ch, nbytes);
142  }
143  else
144  {
145  // suspension: replicate run but second byte is in next block
146  suspendInfo_ = ch;
147  result = EC_StreamNotifyClient;
148  }
149  }
150  else
151  {
152  // literal run
153  nbytes = OFstatic_cast(unsigned char, (ch & 0x7f) + 1);
154  if (compressedSize < nbytes)
155  {
156  // we're going to suspend, prepare everything
157  suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1);
158  nbytes = OFstatic_cast(unsigned char, compressedSize);
159  result = EC_StreamNotifyClient;
160  }
161 
162  literal(cp, nbytes);
163  compressedSize -= nbytes;
164  cp += nbytes;
165  }
166  }
167 
168  // failure status at this point means output buffer overflow
169  if (fail_) result = EC_CorruptedData;
170  }
171 
172  return result;
173  }
174 
175 
179  inline size_t size() const
180  {
181  return offset_;
182  }
183 
186  inline void *getOutputBuffer() const
187  {
188  return outputBuffer_;
189  }
190 
193  inline OFBool fail() const
194  {
195  if (fail_) return OFTrue; else return OFFalse;
196  }
197 
198 private:
199 
202 
205 
206 
211  inline void replicate(unsigned char ch, unsigned char nbytes)
212  {
213  if (offset_ + nbytes > outputBufferSize_)
214  {
215  // output buffer overflow
216  fail_ = 1;
217  nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_);
218  }
219 
220  while (nbytes--) outputBuffer_[offset_++] = ch;
221  }
222 
223 
228  inline void literal(unsigned char *cp, unsigned char nbytes)
229  {
230  if (offset_ + nbytes > outputBufferSize_)
231  {
232  // output buffer overflow
233  fail_ = 1;
234  nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_);
235  }
236 
237  while (nbytes--) outputBuffer_[offset_++] = *cp++;
238  }
239 
240  /* member variables */
241 
246  int fail_;
247 
251 
256  unsigned char *outputBuffer_;
257 
261  size_t offset_;
262 
268  unsigned char suspendInfo_;
269 };
270 
271 #endif
272 
273 /*
274  * CVS/RCS Log
275  * $Log: dcrledec.h,v $
276  * Revision 1.6 2010-10-14 13:15:42 joergr
277  * Updated copyright header. Added reference to COPYRIGHT file.
278  *
279  * Revision 1.5 2009-11-04 09:58:07 uli
280  * Switched to logging mechanism provided by the "new" oflog module
281  *
282  * Revision 1.4 2005-12-08 16:28:36 meichel
283  * Changed include path schema for all DCMTK header files
284  *
285  * Revision 1.3 2003/08/14 09:00:56 meichel
286  * Adapted type casts to new-style typecast operators defined in ofcast.h
287  *
288  * Revision 1.2 2003/03/21 13:06:46 meichel
289  * Minor code purifications for warnings reported by MSVC in Level 4
290  *
291  * Revision 1.1 2002/06/06 14:52:36 meichel
292  * Initial release of the new RLE codec classes
293  * and the dcmcrle/dcmdrle tools in module dcmdata
294  *
295  *
296  */


Generated on Thu Dec 20 2012 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.8.2