00001 // 00002 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. 00003 // 00004 00005 #ifndef CHARLS_ENCODERSTRATEGY 00006 #define CHARLS_ENCODERSTRATEGY 00007 00008 #include "dcmtk/ofstd/ofaptr.h" 00009 #include "procline.h" 00010 #include "decodstr.h" 00011 00012 // Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy 00013 00014 class EncoderStrategy 00015 { 00016 00017 public: 00018 explicit EncoderStrategy(const JlsParameters& info) : 00019 _qdecoder(0), 00020 _info(info), 00021 _processLine(0), 00022 valcurrent(0), 00023 bitpos(0), 00024 _isFFWritten(false), 00025 _bytesWritten(0) 00026 00027 { 00028 } 00029 00030 virtual ~EncoderStrategy() 00031 { 00032 } 00033 00034 LONG PeekByte(); 00035 00036 void OnLineBegin(LONG cpixel, void* ptypeBuffer, LONG pixelStride) 00037 { 00038 _processLine->NewLineRequested(ptypeBuffer, cpixel, pixelStride); 00039 } 00040 00041 void OnLineEnd(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/) { } 00042 00043 virtual void SetPresets(const JlsCustomParameters& presets) = 0; 00044 00045 virtual size_t EncodeScan(const void* pvoid, void* pvoidOut, size_t byteCount, void* pvoidCompare) = 0; 00046 00047 protected: 00048 00049 void Init(BYTE* compressedBytes, size_t byteCount) 00050 { 00051 bitpos = 32; 00052 valcurrent = 0; 00053 _position = compressedBytes; 00054 _compressedLength = byteCount; 00055 } 00056 00057 00058 void AppendToBitStream(LONG value, LONG length) 00059 { 00060 ASSERT(length < 32 && length >= 0); 00061 00062 ASSERT((_qdecoder.get() == NULL) || (length == 0 && value == 0) ||( _qdecoder->ReadLongValue(length) == value)); 00063 00064 #ifndef NDEBUG 00065 if (length < 32) 00066 { 00067 int mask = (1 << (length)) - 1; 00068 ASSERT((value | mask) == mask); 00069 } 00070 #endif 00071 00072 bitpos -= length; 00073 if (bitpos >= 0) 00074 { 00075 valcurrent = valcurrent | (value << bitpos); 00076 return; 00077 } 00078 valcurrent |= value >> -bitpos; 00079 00080 Flush(); 00081 00082 ASSERT(bitpos >=0); 00083 valcurrent |= value << bitpos; 00084 00085 } 00086 00087 void EndScan() 00088 { 00089 Flush(); 00090 00091 // if a 0xff was written, Flush() will force one unset bit anyway 00092 if (_isFFWritten) 00093 AppendToBitStream(0, (bitpos - 1) % 8); 00094 else 00095 AppendToBitStream(0, bitpos % 8); 00096 00097 Flush(); 00098 ASSERT(bitpos == 0x20); 00099 } 00100 00101 void Flush() 00102 { 00103 for (LONG i = 0; i < 4; ++i) 00104 { 00105 if (bitpos >= 32) 00106 break; 00107 00108 if (_isFFWritten) 00109 { 00110 // insert highmost bit 00111 *_position = BYTE(valcurrent >> 25); 00112 valcurrent = valcurrent << 7; 00113 bitpos += 7; 00114 _isFFWritten = false; 00115 } 00116 else 00117 { 00118 *_position = BYTE(valcurrent >> 24); 00119 valcurrent = valcurrent << 8; 00120 bitpos += 8; 00121 _isFFWritten = *_position == 0xFF; 00122 } 00123 00124 _position++; 00125 _compressedLength--; 00126 _bytesWritten++; 00127 00128 } 00129 00130 } 00131 00132 size_t GetLength() 00133 { 00134 return _bytesWritten - (bitpos -32)/8; 00135 } 00136 00137 00138 inlinehint void AppendOnesToBitStream(LONG length) 00139 { 00140 AppendToBitStream((1 << length) - 1, length); 00141 } 00142 00143 00144 OFauto_ptr<DecoderStrategy> _qdecoder; 00145 00146 protected: 00147 JlsParameters _info; 00148 OFauto_ptr<ProcessLine> _processLine; 00149 private: 00150 00151 unsigned int valcurrent; 00152 LONG bitpos; 00153 size_t _compressedLength; 00154 00155 // encoding 00156 BYTE* _position; 00157 bool _isFFWritten; 00158 size_t _bytesWritten; 00159 00160 }; 00161 00162 #endif