00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef DCRLEDEC_H
00035 #define DCRLEDEC_H
00036
00037 #include "dcmtk/config/osconfig.h"
00038 #include "dcmtk/dcmdata/dcerror.h"
00039
00043 class DcmRLEDecoder
00044 {
00045 public:
00046
00051 DcmRLEDecoder(size_t outputBufferSize)
00052 : fail_(0)
00053 , outputBufferSize_(outputBufferSize)
00054 , outputBuffer_(NULL)
00055 , offset_(0)
00056 , suspendInfo_(128)
00057 {
00058 if (outputBufferSize_ == 0) fail_ = 1;
00059 else
00060 {
00061 outputBuffer_ = new unsigned char[outputBufferSize_];
00062 if (outputBuffer_ == NULL) fail_ = 1;
00063 }
00064 }
00065
00067 ~DcmRLEDecoder()
00068 {
00069 delete[] outputBuffer_;
00070 }
00071
00075 inline void clear()
00076 {
00077 offset_ = 0;
00078 suspendInfo_ = 128;
00079 if (outputBuffer_) fail_ = 0;
00080 }
00081
00082
00083 inline OFCondition decompress(void *compressedData, size_t compressedSize)
00084 {
00085
00086 if (compressedSize == 0) return EC_Normal;
00087
00088 OFCondition result = EC_IllegalCall;
00089
00090
00091 if (compressedData == NULL) fail_ = 1;
00092
00093 if (! fail_)
00094 {
00095 result = EC_Normal;
00096 unsigned char ch;
00097 unsigned char nbytes;
00098 unsigned char *cp = OFstatic_cast(unsigned char *, compressedData);
00099
00100
00101 if (suspendInfo_ > 128)
00102 {
00103
00104 nbytes = OFstatic_cast(unsigned char, 257 - suspendInfo_);
00105
00106
00107 suspendInfo_ = 128;
00108
00109 ch = *cp++;
00110 --compressedSize;
00111 replicate(ch, nbytes);
00112 }
00113 else if (suspendInfo_ < 128)
00114 {
00115
00116 nbytes = OFstatic_cast(unsigned char, (suspendInfo_ & 0x7f) + 1);
00117 suspendInfo_ = 128;
00118 if (compressedSize < nbytes)
00119 {
00120
00121 suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1);
00122 nbytes = OFstatic_cast(unsigned char, compressedSize);
00123 result = EC_StreamNotifyClient;
00124 }
00125
00126 literal(cp, nbytes);
00127 compressedSize -= nbytes;
00128 cp += nbytes;
00129 }
00130
00131
00132 while (compressedSize && (! fail_))
00133 {
00134 ch = *cp++;
00135 --compressedSize;
00136
00137 if (ch & 0x80)
00138 {
00139
00140 if (compressedSize)
00141 {
00142
00143 nbytes = OFstatic_cast(unsigned char, 257 - ch);
00144 ch = *cp++;
00145 --compressedSize;
00146 replicate(ch, nbytes);
00147 }
00148 else
00149 {
00150
00151 suspendInfo_ = ch;
00152 result = EC_StreamNotifyClient;
00153 }
00154 }
00155 else
00156 {
00157
00158 nbytes = OFstatic_cast(unsigned char, (ch & 0x7f) + 1);
00159 if (compressedSize < nbytes)
00160 {
00161
00162 suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1);
00163 nbytes = OFstatic_cast(unsigned char, compressedSize);
00164 result = EC_StreamNotifyClient;
00165 }
00166
00167 literal(cp, nbytes);
00168 compressedSize -= nbytes;
00169 cp += nbytes;
00170 }
00171 }
00172
00173
00174 if (fail_) result = EC_CorruptedData;
00175 }
00176
00177 return result;
00178 }
00179
00180
00184 inline size_t size() const
00185 {
00186 return offset_;
00187 }
00188
00191 inline void *getOutputBuffer() const
00192 {
00193 return outputBuffer_;
00194 }
00195
00198 inline OFBool fail() const
00199 {
00200 if (fail_) return OFTrue; else return OFFalse;
00201 }
00202
00203 private:
00204
00206 DcmRLEDecoder(const DcmRLEDecoder&);
00207
00209 DcmRLEDecoder& operator=(const DcmRLEDecoder&);
00210
00211
00216 inline void replicate(unsigned char ch, unsigned char nbytes)
00217 {
00218 if (offset_ + nbytes > outputBufferSize_)
00219 {
00220
00221 fail_ = 1;
00222 nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_);
00223 }
00224
00225 while (nbytes--) outputBuffer_[offset_++] = ch;
00226 }
00227
00228
00233 inline void literal(unsigned char *cp, unsigned char nbytes)
00234 {
00235 if (offset_ + nbytes > outputBufferSize_)
00236 {
00237
00238 fail_ = 1;
00239 nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_);
00240 }
00241
00242 while (nbytes--) outputBuffer_[offset_++] = *cp++;
00243 }
00244
00245
00246
00251 int fail_;
00252
00255 size_t outputBufferSize_;
00256
00261 unsigned char *outputBuffer_;
00262
00266 size_t offset_;
00267
00273 unsigned char suspendInfo_;
00274 };
00275
00276 #endif
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295