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 #ifndef DCRLEENC_H
00030 #define DCRLEENC_H
00031
00032 #include "dcmtk/config/osconfig.h"
00033 #include "dcmtk/ofstd/oflist.h"
00034
00035 #define INCLUDE_CSTRING
00036 #include "dcmtk/ofstd/ofstdinc.h"
00037
00038 #define DcmRLEEncoder_BLOCKSIZE 16384
00039
00040
00045 class DcmEncoderOutputStream
00046 {
00047 public:
00052 virtual void write(const unsigned char *buf, size_t bufsize) =0;
00053
00056 virtual ~DcmEncoderOutputStream() {}
00057
00058 };
00059
00060
00064 class DcmRLEEncoder
00065 {
00066 public:
00067
00071 DcmRLEEncoder(int doPad)
00072 : fail_(0)
00073 , pad_(doPad)
00074 , currentBlock_(new unsigned char[DcmRLEEncoder_BLOCKSIZE])
00075 , offset_(0)
00076 , blockList_()
00077 , RLE_buff_(new unsigned char[132])
00078 , RLE_prev_(-1)
00079 , RLE_pcount_(0)
00080 , RLE_bindex_(1)
00081 {
00082 if ((! RLE_buff_)||(! currentBlock_)) fail_ = 1;
00083 else RLE_buff_[0] = 0;
00084 }
00085
00087 ~DcmRLEEncoder()
00088 {
00089 delete[] currentBlock_;
00090 delete[] RLE_buff_;
00091 OFListIterator(unsigned char *) first = blockList_.begin();
00092 OFListIterator(unsigned char *) last = blockList_.end();
00093 while (first != last)
00094 {
00095 delete[] *first;
00096 first = blockList_.erase(first);
00097 }
00098 }
00099
00104 inline void add(unsigned char ch)
00105 {
00106 if (! fail_)
00107 {
00108
00109
00110
00111 if (OFstatic_cast(int, ch) == RLE_prev_) RLE_pcount_++;
00112 else
00113 {
00114
00115
00116 switch (RLE_pcount_)
00117 {
00118 case 0:
00119
00120 break;
00121 case 2:
00122
00123 RLE_buff_[RLE_bindex_++] = OFstatic_cast(unsigned char, RLE_prev_);
00124
00125 case 1:
00126
00127 RLE_buff_[RLE_bindex_++] = OFstatic_cast(unsigned char, RLE_prev_);
00128 break;
00129 default:
00130
00131 if (RLE_bindex_ > 1)
00132 {
00133
00134
00135 RLE_buff_[0] = OFstatic_cast(unsigned char, RLE_bindex_-2);
00136 move(RLE_bindex_);
00137 }
00138
00139 RLE_buff_[1] = OFstatic_cast(unsigned char, RLE_prev_);
00140
00141 for (; RLE_pcount_>0; RLE_pcount_-=128)
00142 {
00143
00144
00145
00146
00147 if (RLE_pcount_ > 128) RLE_buff_[0] = 0x81;
00148 else RLE_buff_[0] = OFstatic_cast(unsigned char, 257 - RLE_pcount_);
00149 move(2);
00150 }
00151
00152 RLE_buff_[0] = 0;
00153 RLE_bindex_ = 1;
00154 break;
00155 }
00156
00157
00158 if (RLE_bindex_ > 129)
00159 {
00160 RLE_buff_[0] = 127;
00161 move(129);
00162 RLE_bindex_ -= 128;
00163 if (RLE_bindex_ > 1)
00164 RLE_buff_[1] = RLE_buff_[129];
00165 if (RLE_bindex_ > 2)
00166 RLE_buff_[2] = RLE_buff_[130];
00167 }
00168
00169
00170 RLE_prev_ = ch;
00171 RLE_pcount_ = 1;
00172 }
00173 }
00174 }
00175
00181 inline void add(const unsigned char *buf, size_t bufcount)
00182 {
00183 if (buf)
00184 {
00185 while (bufcount--) add(*buf++);
00186 }
00187 }
00188
00195 inline void flush()
00196 {
00197 if (! fail_)
00198 {
00199
00200 if (RLE_pcount_ < 2)
00201 {
00202 for (; RLE_pcount_>0; --RLE_pcount_) RLE_buff_[RLE_bindex_++] = OFstatic_cast(unsigned char, RLE_prev_);
00203 }
00204
00205
00206 if (RLE_bindex_ > 129)
00207 {
00208 RLE_buff_[0] = 127;
00209 move(129);
00210 RLE_bindex_ -= 128;
00211 if (RLE_bindex_ > 1)
00212 RLE_buff_[1] = RLE_buff_[129];
00213 if (RLE_bindex_ > 2)
00214 RLE_buff_[2] = RLE_buff_[130];
00215 }
00216
00217
00218 if (RLE_bindex_ > 1)
00219 {
00220 RLE_buff_[0] = OFstatic_cast(unsigned char, RLE_bindex_-2);
00221 move(RLE_bindex_);
00222 }
00223
00224
00225 if (RLE_pcount_ >= 2)
00226 {
00227 RLE_buff_[1] = OFstatic_cast(unsigned char, RLE_prev_);
00228
00229 for (; RLE_pcount_>0; RLE_pcount_-=128)
00230 {
00231
00232
00233
00234
00235 if (RLE_pcount_ > 128) RLE_buff_[0] = 0x81;
00236 else RLE_buff_[0] = OFstatic_cast(unsigned char, 257 - RLE_pcount_);
00237 move(2);
00238 }
00239 }
00240
00241
00242 RLE_buff_[0] = 0;
00243 RLE_prev_ = -1;
00244 RLE_pcount_ = 0;
00245 RLE_bindex_ = 1;
00246 }
00247 }
00248
00256 inline size_t size() const
00257 {
00258 size_t result = blockList_.size() * DcmRLEEncoder_BLOCKSIZE + offset_;
00259 if (pad_ && (result & 1)) result++;
00260 return result;
00261 }
00262
00266 inline OFBool fail() const
00267 {
00268 if (fail_) return OFTrue; else return OFFalse;
00269 }
00270
00275 inline void write(void *target) const
00276 {
00277 if ((!fail_) && target)
00278 {
00279 unsigned char *current = NULL;
00280 unsigned char *target8 = OFstatic_cast(unsigned char *, target);
00281 OFListConstIterator(unsigned char *) first = blockList_.begin();
00282 OFListConstIterator(unsigned char *) last = blockList_.end();
00283 while (first != last)
00284 {
00285 current = *first;
00286 memcpy(target8, current, DcmRLEEncoder_BLOCKSIZE);
00287 target8 += DcmRLEEncoder_BLOCKSIZE;
00288 ++first;
00289 }
00290 if (offset_ > 0)
00291 {
00292 memcpy(target8, currentBlock_, offset_);
00293 }
00294
00295
00296 if (pad_ && ((blockList_.size() * DcmRLEEncoder_BLOCKSIZE + offset_) & 1))
00297 {
00298 target8 += offset_;
00299 *target8 = 0;
00300 }
00301 }
00302 }
00303
00308 inline void write(DcmEncoderOutputStream& os) const
00309 {
00310 if (!fail_)
00311 {
00312 OFListConstIterator(unsigned char *) first = blockList_.begin();
00313 OFListConstIterator(unsigned char *) last = blockList_.end();
00314 while (first != last)
00315 {
00316 os.write(*first, DcmRLEEncoder_BLOCKSIZE);
00317 ++first;
00318 }
00319 if (offset_ > 0)
00320 {
00321 os.write(currentBlock_, offset_);
00322 }
00323
00324
00325 if (pad_ && ((blockList_.size() * DcmRLEEncoder_BLOCKSIZE + offset_) & 1))
00326 {
00327 unsigned char c = 0;
00328 os.write(&c, 1);
00329 }
00330 }
00331 }
00332
00333 private:
00334
00336 DcmRLEEncoder(const DcmRLEEncoder&);
00337
00339 DcmRLEEncoder& operator=(const DcmRLEEncoder&);
00340
00346 inline void move(size_t numberOfBytes)
00347 {
00348 size_t i=0;
00349 while (i < numberOfBytes)
00350 {
00351 if (offset_ == DcmRLEEncoder_BLOCKSIZE)
00352 {
00353 blockList_.push_back(currentBlock_);
00354 currentBlock_ = new unsigned char[DcmRLEEncoder_BLOCKSIZE];
00355 offset_ = 0;
00356 if (! currentBlock_)
00357 {
00358 fail_ = 1;
00359 break;
00360 }
00361 }
00362 currentBlock_[offset_++] = RLE_buff_[i++];
00363 }
00364 }
00365
00366
00367
00373 int fail_;
00374
00379 int pad_;
00380
00385 unsigned char *currentBlock_;
00386
00391 size_t offset_;
00392
00397 OFList<unsigned char *> blockList_;
00398
00402 unsigned char *RLE_buff_;
00403
00408 int RLE_prev_;
00409
00413 int RLE_pcount_;
00414
00417 unsigned int RLE_bindex_;
00418
00419 };
00420
00421 #endif
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470