📄 dcrledec.h
字号:
/* * * Copyright (C) 1994-2005, OFFIS * * This software and supporting documentation were developed by * * Kuratorium OFFIS e.V. * Healthcare Information and Communication Systems * Escherweg 2 * D-26121 Oldenburg, Germany * * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND * PERFORMANCE OF THE SOFTWARE IS WITH THE USER. * * Module: dcmdata * * Author: Marco Eichelberg * * Purpose: RLE decompressor * * Last Update: $Author: meichel $ * Update Date: $Date: 2005/12/08 16:28:36 $ * Source File: $Source: /share/dicom/cvs-depot/dcmtk/dcmdata/include/dcmtk/dcmdata/dcrledec.h,v $ * CVS/RCS Revision: $Revision: 1.4 $ * Status: $State: Exp $ * * CVS/RCS Log at end of file * */#ifndef DCRLEDEC_H#define DCRLEDEC_H#include "dcmtk/config/osconfig.h"#include "dcmtk/dcmdata/dcerror.h"/** this class implements an RLE decompressor conforming to the DICOM standard. * The class is loosely based on an implementation by Phil Norman <forrey@eh.org> */class DcmRLEDecoder{public: /** constructor * @param outputBufferSize size of the output buffer (in bytes) * to which the RLE codec will write decompressed output. */ DcmRLEDecoder(size_t outputBufferSize) : fail_(0) , outputBufferSize_(outputBufferSize) , outputBuffer_(NULL) , offset_(0) , suspendInfo_(128) { if (outputBufferSize_ == 0) fail_ = 1; else { outputBuffer_ = new unsigned char[outputBufferSize_]; if (outputBuffer_ == NULL) fail_ = 1; } } /// destructor ~DcmRLEDecoder() { delete[] outputBuffer_; } /** resets the decoder object to newly constructed state. * The size and location of the output buffer is not changed. */ inline void clear() { offset_ = 0; suspendInfo_ = 128; if (outputBuffer_) fail_ = 0; } inline OFCondition decompress(void *compressedData, size_t compressedSize) { // we allow a call for zero bytes if (compressedSize == 0) return EC_Normal; OFCondition result = EC_IllegalCall; // check parameters passed by caller if (compressedData == NULL) fail_ = 1; if (! fail_) // if fail_ is true, just ignore input { result = EC_Normal; unsigned char ch; unsigned char nbytes; unsigned char *cp = OFstatic_cast(unsigned char *, compressedData); // check if we suspended last time, clean up if (suspendInfo_ > 128) { // DICOM packbit scheme uses 257 - nbytes to represent replicate runs nbytes = OFstatic_cast(unsigned char, 257 - suspendInfo_); // suspended replicate run. compressedSize cannot be zero now. suspendInfo_ = 128; ch = *cp++; --compressedSize; replicate(ch, nbytes); } else if (suspendInfo_ < 128) { // suspended literal run nbytes = OFstatic_cast(unsigned char, (suspendInfo_ & 0x7f) + 1); suspendInfo_ = 128; if (compressedSize < nbytes) { // we're going to suspend again (oops?), prepare everything suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1); nbytes = OFstatic_cast(unsigned char, compressedSize); result = EC_StreamNotifyClient; } literal(cp, nbytes); compressedSize -= nbytes; cp += nbytes; } // continue with ordinary RLE decompression while (compressedSize && (! fail_)) { ch = *cp++; --compressedSize; if (ch & 0x80) { // replicate run if (compressedSize) { // DICOM packbit scheme uses 257 - nbytes to represent replicate runs nbytes = OFstatic_cast(unsigned char, 257 - ch); ch = *cp++; --compressedSize; replicate(ch, nbytes); } else { // suspension: replicate run but second byte is in next block suspendInfo_ = ch; result = EC_StreamNotifyClient; } } else { // literal run nbytes = OFstatic_cast(unsigned char, (ch & 0x7f) + 1); if (compressedSize < nbytes) { // we're going to suspend, prepare everything suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1); nbytes = OFstatic_cast(unsigned char, compressedSize); result = EC_StreamNotifyClient; } literal(cp, nbytes); compressedSize -= nbytes; cp += nbytes; } } // failure status at this point means output buffer overflow if (fail_) result = EC_CorruptedData; } return result; } /** returns the number of bytes written to the output buffer * @return size of decompressed stream, in bytes */ inline size_t size() const { return offset_; } /** returns pointer to the output buffer */ inline void *getOutputBuffer() const { return outputBuffer_; } /** returns true if the RLE compressor has failed (out of memory or output buffer too small). */ inline OFBool fail() const { if (fail_) return OFTrue; else return OFFalse; }private: /// private undefined copy constructor DcmRLEDecoder(const DcmRLEDecoder&); /// private undefined copy assignment operator DcmRLEDecoder& operator=(const DcmRLEDecoder&); /** this method expands a replicate run * @param ch value to replicate * @param nbytes number of repetitions */ inline void replicate(unsigned char ch, unsigned char nbytes) { if (offset_ + nbytes > outputBufferSize_) { // output buffer overflow fail_ = 1; nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_); } while (nbytes--) outputBuffer_[offset_++] = ch; } /** this method expands a literal run * @param cp pointer to buffer * @param nbytes number of bytes in buffer */ inline void literal(unsigned char *cp, unsigned char nbytes) { if (offset_ + nbytes > outputBufferSize_) { // output buffer overflow fail_ = 1; nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_); } while (nbytes--) outputBuffer_[offset_++] = *cp++; } /* member variables */ /** this flag indicates a failure of the RLE codec. Once a failure is * flagged, the codec will consume all input and not produce any more * output. */ int fail_; /** size of output buffer, in bytes */ size_t outputBufferSize_; /** this member points to a block of size outputBufferSize_ * (unless fail_ is true). This is the block of data to * which the decompressed stream is written */ unsigned char *outputBuffer_; /** contains the number of bytes already written to outputBuffer_. * Value is always less or equal to outputBufferSize_. */ size_t offset_; /** contains suspension information. * If not suspended, contains 128. * If suspended during a replicate run, contains control byte of repeat run (> 128). * If suspended during a literal run, contains number of remaining bytes in literal run minus 1 (< 128). */ unsigned char suspendInfo_;};#endif/* * CVS/RCS Log * $Log: dcrledec.h,v $ * Revision 1.4 2005/12/08 16:28:36 meichel * Changed include path schema for all DCMTK header files * * Revision 1.3 2003/08/14 09:00:56 meichel * Adapted type casts to new-style typecast operators defined in ofcast.h * * Revision 1.2 2003/03/21 13:06:46 meichel * Minor code purifications for warnings reported by MSVC in Level 4 * * Revision 1.1 2002/06/06 14:52:36 meichel * Initial release of the new RLE codec classes * and the dcmcrle/dcmdrle tools in module dcmdata * * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -