00001
00002
00003
00004
00005 #ifndef CHARLS_SCAN
00006 #define CHARLS_SCAN
00007
00008 #include "dcmtk/ofstd/ofmap.h"
00009 #include "dcmtk/ofstd/oftypes.h"
00010
00011 #include "lokuptbl.h"
00012
00013
00014
00015
00016 #ifdef _MSC_VER
00017 #pragma warning (disable: 4127)
00018 #endif
00019
00020
00021 extern CTable decodingTables[16];
00022 extern OFVector<signed char> rgquant8Ll;
00023 extern OFVector<signed char> rgquant10Ll;
00024 extern OFVector<signed char> rgquant12Ll;
00025 extern OFVector<signed char> rgquant16Ll;
00026
00027
00028
00029 inlinehint LONG ApplySign(LONG i, LONG sign)
00030 { return (sign ^ i) - sign; }
00031
00032
00033 LONG CLAMP(LONG i, LONG j, LONG MAXVAL)
00034 {
00035 if (i > MAXVAL || i < j)
00036 return j;
00037
00038 return i;
00039 }
00040
00041 Presets ComputeDefault(LONG MAXVAL, LONG NEAR)
00042 {
00043 Presets preset;
00044
00045 LONG FACTOR = (MIN(MAXVAL, 4095) + 128)/256;
00046
00047 preset.T1 = CLAMP(FACTOR * (BASIC_T1 - 2) + 2 + 3*NEAR, NEAR + 1, MAXVAL);
00048 preset.T2 = CLAMP(FACTOR * (BASIC_T2 - 3) + 3 + 5*NEAR, preset.T1, MAXVAL);
00049 preset.T3 = CLAMP(FACTOR * (BASIC_T3 - 4) + 4 + 7*NEAR, preset.T2, MAXVAL);
00050 preset.MAXVAL = MAXVAL;
00051 preset.RESET = BASIC_RESET;
00052 return preset;
00053 }
00054
00055
00056
00057
00058 #if 0
00059
00060 inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
00061 {
00062 if (Ra < Rb)
00063 {
00064 if (Rc < Ra)
00065 return Rb;
00066
00067 if (Rc > Rb)
00068 return Ra;
00069 }
00070 else
00071 {
00072 if (Rc < Rb)
00073 return Ra;
00074
00075 if (Rc > Ra)
00076 return Rb;
00077 }
00078
00079 return Ra + Rb - Rc;
00080 }
00081
00082 #else
00083
00084 inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
00085 {
00086
00087 LONG sgn = BitWiseSign(Rb - Ra);
00088
00089
00090 if ((sgn ^ (Rc - Ra)) < 0)
00091 {
00092 return Rb;
00093 }
00094 else if ((sgn ^ (Rb - Rc)) < 0)
00095 {
00096 return Ra;
00097 }
00098
00099
00100 return Ra + Rb - Rc;
00101 }
00102
00103 #endif
00104
00105 inlinehint LONG UnMapErrVal(LONG mappedError)
00106 {
00107
00108 LONG sign = LONG(mappedError << (LONG_BITCOUNT-1)) >> (LONG_BITCOUNT-1);
00109 return sign ^ (mappedError >> 1);
00110 }
00111
00112
00113
00114 inlinehint LONG GetMappedErrVal(LONG Errval)
00115 {
00116 LONG mappedError = (Errval >> (LONG_BITCOUNT-2)) ^ (2 * Errval);
00117 return mappedError;
00118 }
00119
00120
00121
00122 inlinehint LONG ComputeContextID(LONG Q1, LONG Q2, LONG Q3)
00123 { return (Q1*9 + Q2)*9 + Q3; }
00124
00125
00126
00127
00128
00129 template <class TRAITS, class STRATEGY>
00130 class JlsCodec : public STRATEGY
00131 {
00132 public:
00133 typedef typename TRAITS::PIXEL PIXEL;
00134 typedef typename TRAITS::SAMPLE SAMPLE;
00135
00136 public:
00137
00138 JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : STRATEGY(info),
00139 traits(inTraits),
00140 _rect(),
00141 _width(0),
00142 T1(0),
00143 T2(0),
00144 T3(0),
00145 _RUNindex(0),
00146 _pquant(0),
00147 _bCompare(0)
00148
00149 {
00150 if (Info().ilv == ILV_NONE)
00151 {
00152 Info().components = 1;
00153 }
00154 }
00155
00156
00157 void SetPresets(const JlsCustomParameters& presets)
00158 {
00159
00160 Presets presetDefault = ComputeDefault(traits.MAXVAL, traits.NEAR);
00161
00162 InitParams(presets.T1 != 0 ? presets.T1 : presetDefault.T1,
00163 presets.T2 != 0 ? presets.T2 : presetDefault.T2,
00164 presets.T3 != 0 ? presets.T3 : presetDefault.T3,
00165 presets.RESET != 0 ? presets.RESET : presetDefault.RESET);
00166 }
00167
00168
00169 bool IsInterleaved()
00170 {
00171 if (Info().ilv == ILV_NONE)
00172 return false;
00173
00174 if (Info().components == 1)
00175 return false;
00176
00177 return true;
00178 }
00179
00180 JlsParameters& Info() { return STRATEGY::_info; }
00181
00182 signed char QuantizeGratientOrg(LONG Di);
00183 inlinehint LONG QuantizeGratient(LONG Di)
00184 {
00185 ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di));
00186 return *(_pquant + Di);
00187 }
00188
00189 void InitQuantizationLUT();
00190
00191 LONG DecodeValue(LONG k, LONG limit, LONG qbpp);
00192 inlinehint void EncodeMappedValue(LONG k, LONG mappedError, LONG limit);
00193
00194 void IncrementRunIndex()
00195 { _RUNindex = MIN(31,_RUNindex + 1); }
00196 void DecrementRunIndex()
00197 { _RUNindex = MAX(0,_RUNindex - 1); }
00198
00199 LONG DecodeRIError(CContextRunMode& ctx);
00200 Triplet<SAMPLE> DecodeRIPixel(Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb);
00201 SAMPLE DecodeRIPixel(LONG Ra, LONG Rb)
00202 {
00203 if (ABS(Ra - Rb) <= traits.NEAR)
00204 {
00205 LONG ErrVal = DecodeRIError(_contextRunmode[1]);
00206 return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
00207 }
00208 else
00209 {
00210 LONG ErrVal = DecodeRIError(_contextRunmode[0]);
00211 return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
00212 }
00213 }
00214
00215
00216 LONG DecodeRunPixels(PIXEL Ra, PIXEL* ptype, LONG cpixelMac);
00217 LONG DoRunMode(LONG index, DecoderStrategy*);
00218
00219 void EncodeRIError(CContextRunMode& ctx, LONG Errval);
00220 SAMPLE EncodeRIPixel(LONG x, LONG Ra, LONG Rb)
00221 {
00222 if (ABS(Ra - Rb) <= traits.NEAR)
00223 {
00224 LONG ErrVal = traits.ComputeErrVal(x - Ra);
00225 EncodeRIError(_contextRunmode[1], ErrVal);
00226 return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
00227 }
00228 else
00229 {
00230 LONG ErrVal = traits.ComputeErrVal((x - Rb) * Sign(Rb - Ra));
00231 EncodeRIError(_contextRunmode[0], ErrVal);
00232 return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
00233 }
00234 }
00235
00236
00237 Triplet<SAMPLE> EncodeRIPixel(Triplet<SAMPLE> x, Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb);
00238 void EncodeRunPixels(LONG runLength, bool bEndofline);
00239 LONG DoRunMode(LONG index, EncoderStrategy*);
00240
00241
00242 SAMPLE DoRegular(LONG Qs, LONG, LONG pred, DecoderStrategy*)
00243 {
00244 LONG sign = BitWiseSign(Qs);
00245 JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
00246 LONG k = ctx.GetGolomb();
00247 LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
00248
00249 LONG ErrVal;
00250 const Code& code = decodingTables[k].Get(STRATEGY::PeekByte());
00251 if (code.GetLength() != 0)
00252 {
00253 STRATEGY::Skip(code.GetLength());
00254 ErrVal = code.GetValue();
00255 ASSERT(ABS(ErrVal) < 65535);
00256 }
00257 else
00258 {
00259 ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
00260 if (ABS(ErrVal) > 65535)
00261 throw JlsException(InvalidCompressedData);
00262 }
00263 ErrVal = ErrVal ^ ((traits.NEAR == 0) ? ctx.GetErrorCorrection(k) : 0);
00264 ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
00265 ErrVal = ApplySign(ErrVal, sign);
00266 return traits.ComputeReconstructedSample(Px, ErrVal);
00267 }
00268
00269 SAMPLE DoRegular(LONG Qs, LONG x, LONG pred, EncoderStrategy*)
00270 {
00271 LONG sign = BitWiseSign(Qs);
00272 JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
00273 LONG k = ctx.GetGolomb();
00274 LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
00275
00276 LONG ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign));
00277
00278 EncodeMappedValue(k, GetMappedErrVal(ctx.GetErrorCorrection(k | traits.NEAR) ^ ErrVal), traits.LIMIT);
00279 ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
00280 ASSERT(traits.IsNear(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)), x));
00281 return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)));
00282 }
00283
00284 void DoLine(SAMPLE* pdummy);
00285 void DoLine(Triplet<SAMPLE>* pdummy);
00286 void DoScan(BYTE* compressedBytes, size_t compressedLength);
00287
00288 public:
00289 ProcessLine* CreateProcess(void* pvoidOut);
00290 void InitDefault();
00291 void InitParams(LONG t1, LONG t2, LONG t3, LONG nReset);
00292
00293 size_t EncodeScan(const void* rawData, void* pvoidOut, size_t compressedLength, void* pvoidCompare);
00294 size_t DecodeScan(void* rawData, const JlsRect& size, const void* compressedData, size_t compressedLength, bool bCompare);
00295
00296 protected:
00297
00298 TRAITS traits;
00299 JlsRect _rect;
00300 int _width;
00301 LONG T1;
00302 LONG T2;
00303 LONG T3;
00304
00305
00306 JlsContext _contexts[365];
00307 CContextRunMode _contextRunmode[2];
00308 LONG _RUNindex;
00309 PIXEL* _previousLine;
00310 PIXEL* _currentLine;
00311
00312
00313
00314 signed char* _pquant;
00315 OFVector<signed char> _rgquant;
00316
00317
00318 bool _bCompare;
00319 };
00320
00321
00322
00323
00324 inlinehint OFPair<LONG, LONG> CreateEncodedValue(LONG k, LONG mappedError)
00325 {
00326 LONG highbits = mappedError >> k;
00327 return OFMake_pair<LONG, LONG>(highbits + k + 1, (LONG(1) << k) | (mappedError & ((LONG(1) << k) - 1)));
00328 }
00329
00330
00331 CTable InitTable(LONG k)
00332 {
00333 CTable table;
00334 short nerr;
00335 for (nerr = 0; ; nerr++)
00336 {
00337
00338 LONG merrval = GetMappedErrVal(nerr);
00339 OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
00340 if (paircode.first > CTable::cbit)
00341 break;
00342
00343 Code code = Code( nerr, short(paircode.first) );
00344 table.AddEntry(BYTE(paircode.second), code);
00345 }
00346
00347 for (nerr = -1; ; nerr--)
00348 {
00349
00350 LONG merrval = GetMappedErrVal(nerr);
00351 OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
00352 if (paircode.first > CTable::cbit)
00353 break;
00354
00355 Code code = Code(nerr, short(paircode.first));
00356 table.AddEntry(BYTE(paircode.second), code);
00357 }
00358
00359 return table;
00360 }
00361
00362
00363
00364
00365 template<class TRAITS, class STRATEGY>
00366 LONG JlsCodec<TRAITS,STRATEGY>::DecodeValue(LONG k, LONG limit, LONG qbpp)
00367 {
00368 LONG highbits = STRATEGY::ReadHighbits();
00369
00370 if (highbits >= limit - (qbpp + 1))
00371 return STRATEGY::ReadValue(qbpp) + 1;
00372
00373 if (k == 0)
00374 return highbits;
00375
00376 return (highbits << k) + STRATEGY::ReadValue(k);
00377 }
00378
00379
00380
00381 template<class TRAITS, class STRATEGY>
00382 inlinehint void JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mappedError, LONG limit)
00383 {
00384 LONG highbits = mappedError >> k;
00385
00386 if (highbits < limit - traits.qbpp - 1)
00387 {
00388 if (highbits + 1 > 31)
00389 {
00390 STRATEGY::AppendToBitStream(0, highbits / 2);
00391 highbits = highbits - highbits / 2;
00392 }
00393 STRATEGY::AppendToBitStream(1, highbits + 1);
00394 STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k);
00395 return;
00396 }
00397
00398 if (limit - traits.qbpp > 31)
00399 {
00400 STRATEGY::AppendToBitStream(0, 31);
00401 STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
00402 }
00403 else
00404 {
00405 STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
00406 }
00407 STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 1), traits.qbpp);
00408 }
00409
00410
00411
00412
00413 template<class TRAITS, class STRATEGY>
00414 void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
00415 {
00416
00417 if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1)
00418 {
00419 Presets presets = ComputeDefault(traits.MAXVAL, traits.NEAR);
00420 if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3)
00421 {
00422 if (traits.bpp == 8)
00423 {
00424 _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
00425 return;
00426 }
00427 if (traits.bpp == 10)
00428 {
00429 _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
00430 return;
00431 }
00432 if (traits.bpp == 12)
00433 {
00434 _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
00435 return;
00436 }
00437 if (traits.bpp == 16)
00438 {
00439 _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
00440 return;
00441 }
00442 }
00443 }
00444
00445 LONG RANGE = 1 << traits.bpp;
00446
00447 _rgquant.resize(RANGE * 2);
00448
00449 _pquant = &_rgquant[RANGE];
00450 for (LONG i = -RANGE; i < RANGE; ++i)
00451 {
00452 _pquant[i] = QuantizeGratientOrg(i);
00453 }
00454 }
00455
00456
00457 template<class TRAITS, class STRATEGY>
00458 signed char JlsCodec<TRAITS,STRATEGY>::QuantizeGratientOrg(LONG Di)
00459 {
00460 if (Di <= -T3) return -4;
00461 if (Di <= -T2) return -3;
00462 if (Di <= -T1) return -2;
00463 if (Di < -traits.NEAR) return -1;
00464 if (Di <= traits.NEAR) return 0;
00465 if (Di < T1) return 1;
00466 if (Di < T2) return 2;
00467 if (Di < T3) return 3;
00468
00469 return 4;
00470 }
00471
00472
00473
00474
00475
00476 template<class TRAITS, class STRATEGY>
00477 LONG JlsCodec<TRAITS,STRATEGY>::DecodeRIError(CContextRunMode& ctx)
00478 {
00479 LONG k = ctx.GetGolomb();
00480 LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp);
00481 LONG Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k);
00482 ctx.UpdateVariables(Errval, EMErrval);
00483 return Errval;
00484 }
00485
00486
00487
00488 template<class TRAITS, class STRATEGY>
00489 void JlsCodec<TRAITS,STRATEGY>::EncodeRIError(CContextRunMode& ctx, LONG Errval)
00490 {
00491 LONG k = ctx.GetGolomb();
00492 bool map = ctx.ComputeMap(Errval, k);
00493 LONG EMErrval = 2 * ABS(Errval) - ctx._nRItype - map;
00494
00495 ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
00496 EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1);
00497 ctx.UpdateVariables(Errval, EMErrval);
00498 }
00499
00500
00501 template<class TRAITS, class STRATEGY>
00502 Triplet<OFTypename TRAITS::SAMPLE> JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb)
00503 {
00504 LONG Errval1 = DecodeRIError(_contextRunmode[0]);
00505 LONG Errval2 = DecodeRIError(_contextRunmode[0]);
00506 LONG Errval3 = DecodeRIError(_contextRunmode[0]);
00507
00508 return Triplet<SAMPLE>(traits.ComputeReconstructedSample(Rb.v1, Errval1 * Sign(Rb.v1 - Ra.v1)),
00509 traits.ComputeReconstructedSample(Rb.v2, Errval2 * Sign(Rb.v2 - Ra.v2)),
00510 traits.ComputeReconstructedSample(Rb.v3, Errval3 * Sign(Rb.v3 - Ra.v3)));
00511 }
00512
00513
00514
00515 template<class TRAITS, class STRATEGY>
00516 Triplet<OFTypename TRAITS::SAMPLE> JlsCodec<TRAITS,STRATEGY>::EncodeRIPixel(Triplet<SAMPLE> x, Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb)
00517 {
00518 LONG errval1 = traits.ComputeErrVal(Sign(Rb.v1 - Ra.v1) * (x.v1 - Rb.v1));
00519 EncodeRIError(_contextRunmode[0], errval1);
00520
00521 LONG errval2 = traits.ComputeErrVal(Sign(Rb.v2 - Ra.v2) * (x.v2 - Rb.v2));
00522 EncodeRIError(_contextRunmode[0], errval2);
00523
00524 LONG errval3 = traits.ComputeErrVal(Sign(Rb.v3 - Ra.v3) * (x.v3 - Rb.v3));
00525 EncodeRIError(_contextRunmode[0], errval3);
00526
00527
00528 return Triplet<SAMPLE>(traits.ComputeReconstructedSample(Rb.v1, errval1 * Sign(Rb.v1 - Ra.v1)),
00529 traits.ComputeReconstructedSample(Rb.v2, errval2 * Sign(Rb.v2 - Ra.v2)),
00530 traits.ComputeReconstructedSample(Rb.v3, errval3 * Sign(Rb.v3 - Ra.v3)));
00531 }
00532
00533
00534
00535
00536
00537 template<class TRAITS, class STRATEGY>
00538 void JlsCodec<TRAITS,STRATEGY>::EncodeRunPixels(LONG runLength, bool endOfLine)
00539 {
00540 while (runLength >= LONG(1 << J[_RUNindex]))
00541 {
00542 STRATEGY::AppendOnesToBitStream(1);
00543 runLength = runLength - LONG(1 << J[_RUNindex]);
00544 IncrementRunIndex();
00545 }
00546
00547 if (endOfLine)
00548 {
00549 if (runLength != 0)
00550 {
00551 STRATEGY::AppendOnesToBitStream(1);
00552 }
00553 }
00554 else
00555 {
00556 STRATEGY::AppendToBitStream(runLength, J[_RUNindex] + 1);
00557 }
00558 }
00559
00560
00561 template<class TRAITS, class STRATEGY>
00562 LONG JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, PIXEL* startPos, LONG cpixelMac)
00563 {
00564 LONG index = 0;
00565 while (STRATEGY::ReadBit())
00566 {
00567 int count = MIN(1 << J[_RUNindex], int(cpixelMac - index));
00568 index += count;
00569 ASSERT(index <= cpixelMac);
00570
00571 if (count == (1 << J[_RUNindex]))
00572 {
00573 IncrementRunIndex();
00574 }
00575
00576 if (index == cpixelMac)
00577 break;
00578 }
00579
00580
00581 if (index != cpixelMac)
00582 {
00583
00584 index += (J[_RUNindex] > 0) ? STRATEGY::ReadValue(J[_RUNindex]) : 0;
00585 }
00586
00587 if (index > cpixelMac)
00588 throw JlsException(InvalidCompressedData);
00589
00590 for (LONG i = 0; i < index; ++i)
00591 {
00592 startPos[i] = Ra;
00593 }
00594
00595 return index;
00596 }
00597
00598 template<class TRAITS, class STRATEGY>
00599 LONG JlsCodec<TRAITS,STRATEGY>::DoRunMode(LONG index, EncoderStrategy*)
00600 {
00601 LONG ctypeRem = _width - index;
00602 PIXEL* ptypeCurX = _currentLine + index;
00603 PIXEL* ptypePrevX = _previousLine + index;
00604
00605 PIXEL Ra = ptypeCurX[-1];
00606
00607 LONG runLength = 0;
00608
00609 while (traits.IsNear(ptypeCurX[runLength],Ra))
00610 {
00611 ptypeCurX[runLength] = Ra;
00612 runLength++;
00613
00614 if (runLength == ctypeRem)
00615 break;
00616 }
00617
00618 EncodeRunPixels(runLength, runLength == ctypeRem);
00619
00620 if (runLength == ctypeRem)
00621 return runLength;
00622
00623 ptypeCurX[runLength] = EncodeRIPixel(ptypeCurX[runLength], Ra, ptypePrevX[runLength]);
00624 DecrementRunIndex();
00625 return runLength + 1;
00626 }
00627
00628
00629 template<class TRAITS, class STRATEGY>
00630 LONG JlsCodec<TRAITS,STRATEGY>::DoRunMode(LONG startIndex, DecoderStrategy*)
00631 {
00632 PIXEL Ra = _currentLine[startIndex-1];
00633
00634 LONG runLength = DecodeRunPixels(Ra, _currentLine + startIndex, _width - startIndex);
00635 LONG endIndex = startIndex + runLength;
00636
00637 if (endIndex == _width)
00638 return endIndex - startIndex;
00639
00640
00641 PIXEL Rb = _previousLine[endIndex];
00642 _currentLine[endIndex] = DecodeRIPixel(Ra, Rb);
00643 DecrementRunIndex();
00644 return endIndex - startIndex + 1;
00645 }
00646
00647
00648
00649
00650 template<class TRAITS, class STRATEGY>
00651 void JlsCodec<TRAITS,STRATEGY>::DoLine(SAMPLE*)
00652 {
00653 LONG index = 0;
00654 LONG Rb = _previousLine[index-1];
00655 LONG Rd = _previousLine[index];
00656
00657 while(index < _width)
00658 {
00659 LONG Ra = _currentLine[index -1];
00660 LONG Rc = Rb;
00661 Rb = Rd;
00662 Rd = _previousLine[index + 1];
00663
00664 LONG Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
00665
00666 if (Qs != 0)
00667 {
00668 _currentLine[index] = DoRegular(Qs, _currentLine[index], GetPredictedValue(Ra, Rb, Rc), (STRATEGY*)(NULL));
00669 index++;
00670 }
00671 else
00672 {
00673 index += DoRunMode(index, (STRATEGY*)(NULL));
00674 Rb = _previousLine[index-1];
00675 Rd = _previousLine[index];
00676 }
00677 }
00678 }
00679
00680
00681
00682
00683 template<class TRAITS, class STRATEGY>
00684 void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet<SAMPLE>*)
00685 {
00686 LONG index = 0;
00687 while(index < _width)
00688 {
00689 Triplet<SAMPLE> Ra = _currentLine[index -1];
00690 Triplet<SAMPLE> Rc = _previousLine[index-1];
00691 Triplet<SAMPLE> Rb = _previousLine[index];
00692 Triplet<SAMPLE> Rd = _previousLine[index + 1];
00693
00694 LONG Qs1 = ComputeContextID(QuantizeGratient(Rd.v1 - Rb.v1), QuantizeGratient(Rb.v1 - Rc.v1), QuantizeGratient(Rc.v1 - Ra.v1));
00695 LONG Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2));
00696 LONG Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3));
00697
00698
00699 if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
00700 {
00701 index += DoRunMode(index, (STRATEGY*)(NULL));
00702 }
00703 else
00704 {
00705 Triplet<SAMPLE> Rx;
00706 Rx.v1 = DoRegular(Qs1, _currentLine[index].v1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1), (STRATEGY*)(NULL));
00707 Rx.v2 = DoRegular(Qs2, _currentLine[index].v2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2), (STRATEGY*)(NULL));
00708 Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), (STRATEGY*)(NULL));
00709 _currentLine[index] = Rx;
00710 index++;
00711 }
00712 }
00713 }
00714
00715
00716
00717
00718
00719
00720
00721 template<class TRAITS, class STRATEGY>
00722 void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE* compressedBytes, size_t compressedLength)
00723 {
00724 _width = Info().width;
00725
00726 STRATEGY::Init(compressedBytes, compressedLength);
00727
00728 LONG pixelstride = _width + 4;
00729 int components = Info().ilv == ILV_LINE ? Info().components : 1;
00730
00731 OFVector<PIXEL> vectmp(2 * components * pixelstride);
00732 OFVector<LONG> rgRUNindex(components);
00733
00734 for (LONG line = 0; line < Info().height; ++line)
00735 {
00736 _previousLine = &vectmp[1];
00737 _currentLine = &vectmp[1 + components * pixelstride];
00738 if ((line & 1) == 1)
00739 {
00740 PIXEL *tmp = _previousLine;
00741 _previousLine = _currentLine;
00742 _currentLine = tmp;
00743 }
00744
00745 STRATEGY::OnLineBegin(_width, _currentLine, pixelstride);
00746
00747 for (int component = 0; component < components; ++component)
00748 {
00749 _RUNindex = rgRUNindex[component];
00750
00751
00752 _previousLine[_width] = _previousLine[_width - 1];
00753 _currentLine[-1] = _previousLine[0];
00754 DoLine((PIXEL*) NULL);
00755
00756 rgRUNindex[component] = _RUNindex;
00757 _previousLine += pixelstride;
00758 _currentLine += pixelstride;
00759 }
00760
00761 if (_rect.Y <= line && line < _rect.Y + _rect.Height)
00762 {
00763 STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X - (components * pixelstride), pixelstride);
00764 }
00765 }
00766
00767 STRATEGY::EndScan();
00768 }
00769
00770
00771
00772
00773 template<class TRAITS, class STRATEGY>
00774 ProcessLine* JlsCodec<TRAITS,STRATEGY>::CreateProcess(void* pvoidOut)
00775 {
00776 if (!IsInterleaved())
00777 return new PostProcesSingleComponent(pvoidOut, Info(), sizeof(typename TRAITS::PIXEL));
00778
00779 if (Info().colorTransform == 0)
00780 return new ProcessTransformed<TransformNone<OFTypename TRAITS::SAMPLE> >(pvoidOut, Info(), TransformNone<SAMPLE>());
00781
00782 if ((Info().bitspersample == sizeof(SAMPLE)*8))
00783 {
00784 switch(Info().colorTransform)
00785 {
00786 case COLORXFORM_HP1 : return new ProcessTransformed<TransformHp1<SAMPLE> >(pvoidOut, Info(), TransformHp1<SAMPLE>()); break;
00787 case COLORXFORM_HP2 : return new ProcessTransformed<TransformHp2<SAMPLE> >(pvoidOut, Info(), TransformHp2<SAMPLE>()); break;
00788 case COLORXFORM_HP3 : return new ProcessTransformed<TransformHp3<SAMPLE> >(pvoidOut, Info(), TransformHp3<SAMPLE>()); break;
00789 default: throw JlsException(UnsupportedColorTransform);
00790 }
00791 }
00792 else if (Info().bitspersample > 8)
00793 {
00794 int shift = 16 - Info().bitspersample;
00795 switch(Info().colorTransform)
00796 {
00797 case COLORXFORM_HP1 : return new ProcessTransformed<TransformShifted<TransformHp1<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp1<USHORT> >(shift)); break;
00798 case COLORXFORM_HP2 : return new ProcessTransformed<TransformShifted<TransformHp2<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp2<USHORT> >(shift)); break;
00799 case COLORXFORM_HP3 : return new ProcessTransformed<TransformShifted<TransformHp3<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp3<USHORT> >(shift)); break;
00800 default: throw JlsException(UnsupportedColorTransform);
00801 }
00802 }
00803 throw JlsException(UnsupportedBitDepthForTransform);
00804 }
00805
00806
00807
00808
00809
00810 template<class TRAITS, class STRATEGY>
00811 size_t JlsCodec<TRAITS,STRATEGY>::EncodeScan(const void* rawData, void* compressedData, size_t compressedLength, void* pvoidCompare)
00812 {
00813 STRATEGY::_processLine = OFauto_ptr<ProcessLine>(CreateProcess(const_cast<void*>(rawData)));
00814
00815 BYTE* compressedBytes = static_cast<BYTE*>(compressedData);
00816
00817 if (pvoidCompare != NULL)
00818 {
00819 STRATEGY::_qdecoder = OFauto_ptr<DecoderStrategy>(new JlsCodec<TRAITS,DecoderStrategy>(traits, Info()));
00820 STRATEGY::_qdecoder->Init((BYTE*)pvoidCompare, compressedLength);
00821 }
00822
00823 DoScan(compressedBytes, compressedLength);
00824
00825 return STRATEGY::GetLength();
00826
00827 }
00828
00829
00830
00831 template<class TRAITS, class STRATEGY>
00832 size_t JlsCodec<TRAITS,STRATEGY>::DecodeScan(void* rawData, const JlsRect& rect, const void* compressedData, size_t compressedLength, bool bCompare)
00833 {
00834 STRATEGY::_processLine = OFauto_ptr<ProcessLine>(CreateProcess(rawData));
00835
00836 BYTE* compressedBytes = const_cast<BYTE*>(static_cast<const BYTE*>(compressedData));
00837 _bCompare = bCompare;
00838
00839 BYTE rgbyte[20];
00840
00841 LONG readBytes = 0;
00842 ::memcpy(rgbyte, compressedBytes, 4);
00843 readBytes += 4;
00844
00845 size_t cbyteScanheader = rgbyte[3] - 2;
00846
00847 if (cbyteScanheader > sizeof(rgbyte))
00848 throw JlsException(InvalidCompressedData);
00849
00850 ::memcpy(rgbyte, compressedBytes, cbyteScanheader);
00851 readBytes += cbyteScanheader;
00852
00853 _rect = rect;
00854
00855 DoScan(compressedBytes + readBytes, compressedLength - readBytes);
00856
00857 return STRATEGY::GetCurBytePos() - compressedBytes;
00858 }
00859
00860
00861
00862 template<class TRAITS, class STRATEGY>
00863 void JlsCodec<TRAITS,STRATEGY>::InitParams(LONG t1, LONG t2, LONG t3, LONG nReset)
00864 {
00865 T1 = t1;
00866 T2 = t2;
00867 T3 = t3;
00868
00869 InitQuantizationLUT();
00870
00871 LONG A = MAX(2, (traits.RANGE + 32)/64);
00872 for (unsigned int Q = 0; Q < sizeof(_contexts) / sizeof(_contexts[0]); ++Q)
00873 {
00874 _contexts[Q] = JlsContext(A);
00875 }
00876
00877 _contextRunmode[0] = CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 0, nReset);
00878 _contextRunmode[1] = CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 1, nReset);
00879 _RUNindex = 0;
00880 }
00881
00882 #endif