dcmjpls/libcharls/scan.h

00001 //
00002 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
00003 //
00004 
00005 #ifndef CHARLS_SCAN
00006 #define CHARLS_SCAN
00007 
00008 #include "dcmtk/ofstd/ofmap.h"   /* For OFPair */
00009 #include "dcmtk/ofstd/oftypes.h" /* For OFTypename */
00010 
00011 #include "lokuptbl.h"
00012 
00013 // This file contains the code for handling a "scan". Usually an image is encoded as a single scan.
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 // Apply
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 // Two alternatives for GetPredictedValue() (second is slightly faster due to reduced branching)
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     // sign trick reduces the number of if statements (branches)
00087     LONG sgn = BitWiseSign(Rb - Ra);
00088 
00089     // is Ra between Rc and Rb?
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     // default case, valid if Rc element of [Ra,Rb]
00100     return Ra + Rb - Rc;
00101 }
00102 
00103 #endif
00104 
00105 inlinehint LONG UnMapErrVal(LONG mappedError)
00106 {
00107     //LONG sign = ~((mappedError & 1) - 1);
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       // Encode/decode a single sample. Performancewise the #1 important functions
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     // codec parameters
00298     TRAITS traits;
00299     JlsRect _rect;
00300     int _width;
00301     LONG T1;
00302     LONG T2;
00303     LONG T3;
00304 
00305     // compression context
00306     JlsContext _contexts[365];
00307     CContextRunMode _contextRunmode[2];
00308     LONG _RUNindex;
00309     PIXEL* _previousLine; // previous line ptr
00310     PIXEL* _currentLine; // current line ptr
00311 
00312 
00313     // quantization lookup table
00314     signed char* _pquant;
00315     OFVector<signed char> _rgquant;
00316 
00317     // debugging
00318     bool _bCompare;
00319 };
00320 
00321 
00322 // Functions to build tables used to decode short golomb codes.
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         // Q is not used when k != 0
00338         LONG merrval = GetMappedErrVal(nerr);//, k, -1);
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         // Q is not used when k != 0
00350         LONG merrval = GetMappedErrVal(nerr);//, k, -1);
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 // Encoding/decoding of golomb codes
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 // Sets up a lookup table to "Quantize" sample difference.
00412 
00413 template<class TRAITS, class STRATEGY>
00414 void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
00415 {
00416     // for lossless mode with default parameters, we have precomputed te luts for bitcounts 8,10,12 and 16
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 // RI = Run interruption: functions that handle the sample terminating a run.
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 // RunMode: Functions that handle run-length encoding
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);   // leading 0 + actual remaining length
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         // incomplete run
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     // run interruption
00641     PIXEL Rb = _previousLine[endIndex];
00642     _currentLine[endIndex] =    DecodeRIPixel(Ra, Rb);
00643     DecrementRunIndex();
00644     return endIndex - startIndex + 1;
00645 }
00646 
00647 
00648 // DoLine: Encodes/Decodes a scanline of samples
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 // DoLine: Encodes/Decodes a scanline of triplets in ILV_SAMPLE mode
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 // DoScan: Encodes or decodes a scan.
00717 // In ILV_SAMPLE mode, multiple components are handled in DoLine
00718 // In ILV_LINE mode, a call do DoLine is made for every component
00719 // In ILV_NONE mode, DoScan is called for each component
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             // initialize edge pixels used for prediction
00752             _previousLine[_width]   = _previousLine[_width - 1];
00753             _currentLine[-1]        = _previousLine[0];
00754             DoLine((PIXEL*) NULL); // dummy arg for overload resolution
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 // Factory function for ProcessLine objects to copy/transform unencoded pixels to/from our scanline buffers.
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 // Setup codec for encoding and calls DoScan
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 // Setup codec for decoding and calls DoScan
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 // Initialize the codec data structures. Depends on JPEG-LS parameters like T1-T3.
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


Generated on 6 Jan 2011 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.5.1