00001 // 00002 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. 00003 // 00004 #ifndef CHARLS_PROCESSLINE 00005 #define CHARLS_PROCESSLINE 00006 00007 #include "clrtrans.h" 00008 00009 // 00010 // This file defines the ProcessLine base class, its derivitives and helper functions. 00011 // During coding/decoding, CharLS process one line at a time. The different Processline implementations 00012 // convert the uncompressed format to and from the internal format for encoding. 00013 // Conversions include color transforms, line interleaved vs sample interleaved, masking out unused bits, 00014 // accounting for line padding etc. 00015 // This mechanism could be used to encode/decode images as they are received. 00016 // 00017 00018 class ProcessLine 00019 { 00020 public: 00021 virtual ~ProcessLine() {} 00022 virtual void NewLineDecoded(const void* pSrc, int pixelCount, int bytesperline) = 0; 00023 virtual void NewLineRequested(void* pSrc, int pixelCount, int bytesperline) = 0; 00024 }; 00025 00026 00027 class PostProcesSingleComponent : public ProcessLine 00028 { 00029 public: 00030 PostProcesSingleComponent(void* pbyteOutput, const JlsParameters& info, int bytesPerPixel) : 00031 _pbyteOutput((BYTE*)pbyteOutput), 00032 _bytesPerPixel(bytesPerPixel), 00033 _bytesPerLine(info.bytesperline) 00034 { 00035 } 00036 00037 void NewLineRequested(void* pDst, int pixelCount, int /*byteStride*/) 00038 { 00039 OFBitmanipTemplate<BYTE>::copyMem(_pbyteOutput, (BYTE*) pDst, pixelCount * _bytesPerPixel); 00040 _pbyteOutput += _bytesPerLine; 00041 } 00042 00043 void NewLineDecoded(const void* pSrc, int pixelCount, int /*byteStride*/) 00044 { 00045 OFBitmanipTemplate<BYTE>::copyMem((BYTE*) pSrc, _pbyteOutput, pixelCount * _bytesPerPixel); 00046 _pbyteOutput += _bytesPerLine; 00047 } 00048 00049 private: 00050 BYTE* _pbyteOutput; 00051 int _bytesPerPixel; 00052 int _bytesPerLine; 00053 }; 00054 00055 00056 template<class TRANSFORM, class SAMPLE> 00057 void TransformLineToQuad(const SAMPLE* ptypeInput, LONG pixelStrideIn, Quad<SAMPLE>* pbyteBuffer, LONG pixelStride, TRANSFORM& transform) 00058 { 00059 int cpixel = MIN(pixelStride, pixelStrideIn); 00060 Quad<SAMPLE>* ptypeBuffer = (Quad<SAMPLE>*)pbyteBuffer; 00061 00062 for (int x = 0; x < cpixel; ++x) 00063 { 00064 Quad<SAMPLE> pixel(transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]),ptypeInput[x + 3*pixelStrideIn]) ; 00065 00066 ptypeBuffer[x] = pixel; 00067 } 00068 } 00069 00070 00071 template<class TRANSFORM, class SAMPLE> 00072 void TransformQuadToLine(const Quad<SAMPLE>* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform) 00073 { 00074 int cpixel = MIN(pixelStride, pixelStrideIn); 00075 const Quad<SAMPLE>* ptypeBufferIn = (Quad<SAMPLE>*)pbyteInput; 00076 00077 for (int x = 0; x < cpixel; ++x) 00078 { 00079 Quad<SAMPLE> color = ptypeBufferIn[x]; 00080 Quad<SAMPLE> colorTranformed(transform(color.v1, color.v2, color.v3), color.v4); 00081 00082 ptypeBuffer[x] = colorTranformed.v1; 00083 ptypeBuffer[x + pixelStride] = colorTranformed.v2; 00084 ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3; 00085 ptypeBuffer[x + 3 *pixelStride] = colorTranformed.v4; 00086 } 00087 } 00088 00089 00090 template<class SAMPLE> 00091 void TransformRgbToBgr(SAMPLE* pDest, int samplesPerPixel, int pixelCount) 00092 { 00093 for (int i = 0; i < pixelCount; ++i) 00094 { 00095 SAMPLE tmp = pDest[0]; 00096 pDest[0] = pDest[2]; 00097 pDest[2] = tmp; 00098 pDest += samplesPerPixel; 00099 } 00100 } 00101 00102 00103 template<class TRANSFORM, class SAMPLE> 00104 void TransformLine(Triplet<SAMPLE>* pDest, const Triplet<SAMPLE>* pSrc, int pixelCount, TRANSFORM& transform) 00105 { 00106 for (int i = 0; i < pixelCount; ++i) 00107 { 00108 pDest[i] = transform(pSrc[i].v1, pSrc[i].v2, pSrc[i].v3); 00109 } 00110 } 00111 00112 00113 template<class TRANSFORM, class SAMPLE> 00114 void TransformLineToTriplet(const SAMPLE* ptypeInput, LONG pixelStrideIn, Triplet<SAMPLE>* pbyteBuffer, LONG pixelStride, TRANSFORM& transform) 00115 { 00116 int cpixel = MIN(pixelStride, pixelStrideIn); 00117 Triplet<SAMPLE>* ptypeBuffer = (Triplet<SAMPLE>*)pbyteBuffer; 00118 00119 for (int x = 0; x < cpixel; ++x) 00120 { 00121 ptypeBuffer[x] = transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]); 00122 } 00123 } 00124 00125 00126 template<class TRANSFORM, class SAMPLE> 00127 void TransformTripletToLine(const Triplet<SAMPLE>* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform) 00128 { 00129 int cpixel = MIN(pixelStride, pixelStrideIn); 00130 const Triplet<SAMPLE>* ptypeBufferIn = (Triplet<SAMPLE>*)pbyteInput; 00131 00132 for (int x = 0; x < cpixel; ++x) 00133 { 00134 Triplet<SAMPLE> color = ptypeBufferIn[x]; 00135 Triplet<SAMPLE> colorTranformed = transform(color.v1, color.v2, color.v3); 00136 00137 ptypeBuffer[x] = colorTranformed.v1; 00138 ptypeBuffer[x + pixelStride] = colorTranformed.v2; 00139 ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3; 00140 } 00141 } 00142 00143 00144 template<class TRANSFORM> 00145 class ProcessTransformed : public ProcessLine 00146 { 00147 typedef typename TRANSFORM::SAMPLE SAMPLE; 00148 00149 ProcessTransformed(const ProcessTransformed&) {} 00150 public: 00151 ProcessTransformed(void* pbyteOutput, const JlsParameters& info, TRANSFORM transform) : 00152 _pbyteOutput((BYTE*)pbyteOutput), 00153 _info(info), 00154 _templine(info.width * info.components), 00155 _transform(transform), 00156 _inverseTransform(transform) 00157 { 00158 // ASSERT(_info.components == sizeof(TRIPLET)/sizeof(TRIPLET::SAMPLE)); 00159 } 00160 00161 00162 void NewLineRequested(void* pDst, int pixelCount, int stride) 00163 { 00164 SAMPLE* pLine = (SAMPLE*)_pbyteOutput; 00165 if (_info.outputBgr) 00166 { 00167 pLine = &_templine[0]; 00168 memcpy(pLine, _pbyteOutput, sizeof(Triplet<SAMPLE>)*pixelCount); 00169 TransformRgbToBgr(pLine, _info.components, pixelCount); 00170 } 00171 00172 if (_info.components == 3) 00173 { 00174 if (_info.ilv == ILV_SAMPLE) 00175 { 00176 TransformLine((Triplet<SAMPLE>*)pDst, (const Triplet<SAMPLE>*)pLine, pixelCount, _transform); 00177 } 00178 else 00179 { 00180 TransformTripletToLine((const Triplet<SAMPLE>*)pLine, pixelCount, (SAMPLE*)pDst, stride, _transform); 00181 } 00182 } 00183 else if (_info.components == 4 && _info.ilv == ILV_LINE) 00184 { 00185 TransformQuadToLine((const Quad<SAMPLE>*)pLine, pixelCount, (SAMPLE*)pDst, stride, _transform); 00186 } 00187 _pbyteOutput += _info.bytesperline; 00188 } 00189 00190 00191 void NewLineDecoded(const void* pSrc, int pixelCount, int byteStride) 00192 { 00193 if (_info.components == 3) 00194 { 00195 if (_info.ilv == ILV_SAMPLE) 00196 { 00197 TransformLine((Triplet<SAMPLE>*)_pbyteOutput, (const Triplet<SAMPLE>*)pSrc, pixelCount, _inverseTransform); 00198 } 00199 else 00200 { 00201 TransformLineToTriplet((const SAMPLE*)pSrc, byteStride, (Triplet<SAMPLE>*)_pbyteOutput, pixelCount, _inverseTransform); 00202 } 00203 } 00204 else if (_info.components == 4 && _info.ilv == ILV_LINE) 00205 { 00206 TransformLineToQuad((const SAMPLE*)pSrc, byteStride, (Quad<SAMPLE>*)_pbyteOutput, pixelCount, _inverseTransform); 00207 } 00208 00209 if (_info.outputBgr) 00210 { 00211 TransformRgbToBgr(_pbyteOutput, _info.components, pixelCount); 00212 } 00213 _pbyteOutput += _info.bytesperline; 00214 } 00215 00216 00217 private: 00218 BYTE* _pbyteOutput; 00219 const JlsParameters& _info; 00220 OFVector<SAMPLE> _templine; 00221 TRANSFORM _transform; 00222 typename TRANSFORM::INVERSE _inverseTransform; 00223 }; 00224 00225 00226 00227 #endif