8 #include "dcmtk/ofstd/ofmap.h"
9 #include "dcmtk/ofstd/oftypes.h"
17 #pragma warning (disable: 4127)
21 extern CTable decodingTables[16];
29 inlinehint LONG ApplySign(LONG i, LONG sign)
30 {
return (sign ^ i) - sign; }
33 LONG CLAMP(LONG i, LONG j, LONG MAXVAL)
35 if (i > MAXVAL || i < j)
41 Presets ComputeDefault(LONG MAXVAL, LONG NEAR)
45 LONG FACTOR = (MIN(MAXVAL, 4095) + 128)/256;
47 preset.T1 = CLAMP(FACTOR * (BASIC_T1 - 2) + 2 + 3*NEAR, NEAR + 1, MAXVAL);
48 preset.T2 = CLAMP(FACTOR * (BASIC_T2 - 3) + 3 + 5*NEAR, preset.T1, MAXVAL);
49 preset.T3 = CLAMP(FACTOR * (BASIC_T3 - 4) + 4 + 7*NEAR, preset.T2, MAXVAL);
50 preset.MAXVAL = MAXVAL;
51 preset.RESET = BASIC_RESET;
60 inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
84 inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
87 LONG sgn = BitWiseSign(Rb - Ra);
90 if ((sgn ^ (Rc - Ra)) < 0)
94 else if ((sgn ^ (Rb - Rc)) < 0)
105 inlinehint LONG UnMapErrVal(LONG mappedError)
108 LONG sign = LONG(mappedError << (LONG_BITCOUNT-1)) >> (LONG_BITCOUNT-1);
109 return sign ^ (mappedError >> 1);
114 inlinehint LONG GetMappedErrVal(LONG Errval)
116 LONG mappedError = (Errval >> (LONG_BITCOUNT-2)) ^ (2 * Errval);
122 inlinehint LONG ComputeContextID(LONG Q1, LONG Q2, LONG Q3)
123 {
return (Q1*9 + Q2)*9 + Q3; }
129 template <
class TRAITS,
class STRATEGY>
133 typedef typename TRAITS::PIXEL PIXEL;
134 typedef typename TRAITS::SAMPLE SAMPLE;
150 if (Info().ilv == ILV_NONE)
152 Info().components = 1;
160 Presets presetDefault = ComputeDefault(traits.MAXVAL, traits.NEAR);
162 InitParams(presets.T1 != 0 ? presets.T1 : presetDefault.T1,
163 presets.T2 != 0 ? presets.T2 : presetDefault.T2,
164 presets.T3 != 0 ? presets.T3 : presetDefault.T3,
165 presets.RESET != 0 ? presets.RESET : presetDefault.RESET);
171 if (Info().ilv == ILV_NONE)
174 if (Info().components == 1)
182 signed char QuantizeGratientOrg(LONG Di);
183 inlinehint LONG QuantizeGratient(LONG Di)
185 ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di));
186 return *(_pquant + Di);
189 void InitQuantizationLUT();
191 LONG DecodeValue(LONG k, LONG limit, LONG qbpp);
192 inlinehint
void EncodeMappedValue(LONG k, LONG mappedError, LONG limit);
194 void IncrementRunIndex()
195 { _RUNindex = MIN(31,_RUNindex + 1); }
196 void DecrementRunIndex()
197 { _RUNindex = MAX(0,_RUNindex - 1); }
201 SAMPLE DecodeRIPixel(LONG Ra, LONG Rb)
203 if (ABS(Ra - Rb) <= traits.NEAR)
205 LONG ErrVal = DecodeRIError(_contextRunmode[1]);
206 return static_cast<SAMPLE
>(traits.ComputeReconstructedSample(Ra, ErrVal));
210 LONG ErrVal = DecodeRIError(_contextRunmode[0]);
211 return static_cast<SAMPLE
>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
216 LONG DecodeRunPixels(PIXEL Ra, PIXEL* ptype, LONG cpixelMac);
220 SAMPLE EncodeRIPixel(LONG x, LONG Ra, LONG Rb)
222 if (ABS(Ra - Rb) <= traits.NEAR)
224 LONG ErrVal = traits.ComputeErrVal(x - Ra);
225 EncodeRIError(_contextRunmode[1], ErrVal);
226 return static_cast<SAMPLE
>(traits.ComputeReconstructedSample(Ra, ErrVal));
230 LONG ErrVal = traits.ComputeErrVal((x - Rb) * Sign(Rb - Ra));
231 EncodeRIError(_contextRunmode[0], ErrVal);
232 return static_cast<SAMPLE
>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
238 void EncodeRunPixels(LONG runLength,
bool bEndofline);
244 LONG sign = BitWiseSign(Qs);
245 JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
246 LONG k = ctx.GetGolomb();
247 LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
250 const Code& code = decodingTables[k].Get(STRATEGY::PeekByte());
251 if (code.GetLength() != 0)
253 STRATEGY::Skip(code.GetLength());
254 ErrVal = code.GetValue();
255 ASSERT(ABS(ErrVal) < 65535);
259 ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
260 if (ABS(ErrVal) > 65535)
263 ErrVal = ErrVal ^ ((traits.NEAR == 0) ? ctx.GetErrorCorrection(k) : 0);
264 ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
265 ErrVal = ApplySign(ErrVal, sign);
266 return traits.ComputeReconstructedSample(Px, ErrVal);
271 LONG sign = BitWiseSign(Qs);
272 JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
273 LONG k = ctx.GetGolomb();
274 LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
276 LONG ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign));
278 EncodeMappedValue(k, GetMappedErrVal(ctx.GetErrorCorrection(k | traits.NEAR) ^ ErrVal), traits.LIMIT);
279 ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
280 ASSERT(traits.IsNear(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)), x));
281 return static_cast<SAMPLE
>(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)));
284 void DoLine(SAMPLE* pdummy);
286 void DoScan(BYTE* compressedBytes,
size_t compressedLength);
291 void InitParams(LONG t1, LONG t2, LONG t3, LONG nReset);
293 size_t EncodeScan(
const void* rawData,
void* pvoidOut,
size_t compressedLength,
void* pvoidCompare);
294 size_t DecodeScan(
void* rawData,
const JlsRect& size,
const void* compressedData,
size_t compressedLength,
bool bCompare);
309 PIXEL* _previousLine;
314 signed char* _pquant;
326 LONG highbits = mappedError >> k;
327 return OFMake_pair<LONG, LONG>(highbits + k + 1, (LONG(1) << k) | (mappedError & ((LONG(1) << k) - 1)));
335 for (nerr = 0; ; nerr++)
338 LONG merrval = GetMappedErrVal(nerr);
340 if (paircode.
first > CTable::cbit)
344 table.AddEntry(BYTE(paircode.
second), code);
347 for (nerr = -1; ; nerr--)
350 LONG merrval = GetMappedErrVal(nerr);
352 if (paircode.
first > CTable::cbit)
356 table.AddEntry(BYTE(paircode.
second), code);
365 template<
class TRAITS,
class STRATEGY>
368 LONG highbits = STRATEGY::ReadHighbits();
370 if (highbits >= limit - (qbpp + 1))
371 return STRATEGY::ReadValue(qbpp) + 1;
376 return (highbits << k) + STRATEGY::ReadValue(k);
381 template<
class TRAITS,
class STRATEGY>
384 LONG highbits = mappedError >> k;
386 if (highbits < limit - traits.qbpp - 1)
388 if (highbits + 1 > 31)
390 STRATEGY::AppendToBitStream(0, highbits / 2);
391 highbits = highbits - highbits / 2;
393 STRATEGY::AppendToBitStream(1, highbits + 1);
394 STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k);
398 if (limit - traits.qbpp > 31)
400 STRATEGY::AppendToBitStream(0, 31);
401 STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
405 STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
407 STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 1), traits.qbpp);
413 template<
class TRAITS,
class STRATEGY>
417 if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1)
419 Presets presets = ComputeDefault(traits.MAXVAL, traits.NEAR);
420 if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3)
424 _pquant = &rgquant8Ll[rgquant8Ll.
size() / 2 ];
427 if (traits.bpp == 10)
429 _pquant = &rgquant10Ll[rgquant10Ll.
size() / 2 ];
432 if (traits.bpp == 12)
434 _pquant = &rgquant12Ll[rgquant12Ll.
size() / 2 ];
437 if (traits.bpp == 16)
439 _pquant = &rgquant16Ll[rgquant16Ll.
size() / 2 ];
445 LONG RANGE = 1 << traits.bpp;
447 _rgquant.
resize(RANGE * 2);
449 _pquant = &_rgquant[RANGE];
450 for (LONG i = -RANGE; i < RANGE; ++i)
452 _pquant[i] = QuantizeGratientOrg(i);
457 template<
class TRAITS,
class STRATEGY>
460 if (Di <= -T3)
return -4;
461 if (Di <= -T2)
return -3;
462 if (Di <= -T1)
return -2;
463 if (Di < -traits.NEAR)
return -1;
464 if (Di <= traits.NEAR)
return 0;
465 if (Di < T1)
return 1;
466 if (Di < T2)
return 2;
467 if (Di < T3)
return 3;
476 template<
class TRAITS,
class STRATEGY>
479 LONG k = ctx.GetGolomb();
480 LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp);
481 LONG Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k);
482 ctx.UpdateVariables(Errval, EMErrval);
488 template<
class TRAITS,
class STRATEGY>
491 LONG k = ctx.GetGolomb();
492 bool map = ctx.ComputeMap(Errval, k);
493 LONG EMErrval = 2 * ABS(Errval) - ctx._nRItype - map;
495 ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
496 EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1);
497 ctx.UpdateVariables(Errval, EMErrval);
501 template<
class TRAITS,
class STRATEGY>
504 LONG Errval1 = DecodeRIError(_contextRunmode[0]);
505 LONG Errval2 = DecodeRIError(_contextRunmode[0]);
506 LONG Errval3 = DecodeRIError(_contextRunmode[0]);
508 return Triplet<SAMPLE>(traits.ComputeReconstructedSample(Rb.v1, Errval1 * Sign(Rb.v1 - Ra.v1)),
509 traits.ComputeReconstructedSample(Rb.v2, Errval2 * Sign(Rb.v2 - Ra.v2)),
510 traits.ComputeReconstructedSample(Rb.v3, Errval3 * Sign(Rb.v3 - Ra.v3)));
515 template<
class TRAITS,
class STRATEGY>
518 LONG errval1 = traits.ComputeErrVal(Sign(Rb.v1 - Ra.v1) * (x.v1 - Rb.v1));
519 EncodeRIError(_contextRunmode[0], errval1);
521 LONG errval2 = traits.ComputeErrVal(Sign(Rb.v2 - Ra.v2) * (x.v2 - Rb.v2));
522 EncodeRIError(_contextRunmode[0], errval2);
524 LONG errval3 = traits.ComputeErrVal(Sign(Rb.v3 - Ra.v3) * (x.v3 - Rb.v3));
525 EncodeRIError(_contextRunmode[0], errval3);
528 return Triplet<SAMPLE>(traits.ComputeReconstructedSample(Rb.v1, errval1 * Sign(Rb.v1 - Ra.v1)),
529 traits.ComputeReconstructedSample(Rb.v2, errval2 * Sign(Rb.v2 - Ra.v2)),
530 traits.ComputeReconstructedSample(Rb.v3, errval3 * Sign(Rb.v3 - Ra.v3)));
537 template<
class TRAITS,
class STRATEGY>
540 while (runLength >= LONG(1 << J[_RUNindex]))
542 STRATEGY::AppendOnesToBitStream(1);
543 runLength = runLength - LONG(1 << J[_RUNindex]);
551 STRATEGY::AppendOnesToBitStream(1);
556 STRATEGY::AppendToBitStream(runLength, J[_RUNindex] + 1);
561 template<
class TRAITS,
class STRATEGY>
565 while (STRATEGY::ReadBit())
567 int count = MIN(1 << J[_RUNindex],
int(cpixelMac - index));
569 ASSERT(index <= cpixelMac);
571 if (count == (1 << J[_RUNindex]))
576 if (index == cpixelMac)
581 if (index != cpixelMac)
584 index += (J[_RUNindex] > 0) ? STRATEGY::ReadValue(J[_RUNindex]) : 0;
587 if (index > cpixelMac)
590 for (LONG i = 0; i < index; ++i)
598 template<
class TRAITS,
class STRATEGY>
601 LONG ctypeRem = _width - index;
602 PIXEL* ptypeCurX = _currentLine + index;
603 PIXEL* ptypePrevX = _previousLine + index;
605 PIXEL Ra = ptypeCurX[-1];
609 while (traits.IsNear(ptypeCurX[runLength],Ra))
611 ptypeCurX[runLength] = Ra;
614 if (runLength == ctypeRem)
618 EncodeRunPixels(runLength, runLength == ctypeRem);
620 if (runLength == ctypeRem)
623 ptypeCurX[runLength] = EncodeRIPixel(ptypeCurX[runLength], Ra, ptypePrevX[runLength]);
625 return runLength + 1;
629 template<
class TRAITS,
class STRATEGY>
632 PIXEL Ra = _currentLine[startIndex-1];
634 LONG runLength = DecodeRunPixels(Ra, _currentLine + startIndex, _width - startIndex);
635 LONG endIndex = startIndex + runLength;
637 if (endIndex == _width)
638 return endIndex - startIndex;
641 PIXEL Rb = _previousLine[endIndex];
642 _currentLine[endIndex] = DecodeRIPixel(Ra, Rb);
644 return endIndex - startIndex + 1;
650 template<
class TRAITS,
class STRATEGY>
654 LONG Rb = _previousLine[index-1];
655 LONG Rd = _previousLine[index];
657 while(index < _width)
659 LONG Ra = _currentLine[index -1];
662 Rd = _previousLine[index + 1];
664 LONG Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
668 _currentLine[index] = DoRegular(Qs, _currentLine[index], GetPredictedValue(Ra, Rb, Rc), (STRATEGY*)(NULL));
673 index += DoRunMode(index, (STRATEGY*)(NULL));
674 Rb = _previousLine[index-1];
675 Rd = _previousLine[index];
683 template<
class TRAITS,
class STRATEGY>
687 while(index < _width)
694 LONG Qs1 = ComputeContextID(QuantizeGratient(Rd.v1 - Rb.v1), QuantizeGratient(Rb.v1 - Rc.v1), QuantizeGratient(Rc.v1 - Ra.v1));
695 LONG Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2));
696 LONG Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3));
699 if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
701 index += DoRunMode(index, (STRATEGY*)(NULL));
706 Rx.v1 = DoRegular(Qs1, _currentLine[index].v1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1), (STRATEGY*)(NULL));
707 Rx.v2 = DoRegular(Qs2, _currentLine[index].v2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2), (STRATEGY*)(NULL));
708 Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), (STRATEGY*)(NULL));
709 _currentLine[index] = Rx;
721 template<
class TRAITS,
class STRATEGY>
724 _width = Info().width;
726 STRATEGY::Init(compressedBytes, compressedLength);
728 LONG pixelstride = _width + 4;
729 int components = Info().ilv == ILV_LINE ? Info().components : 1;
734 for (LONG line = 0; line < Info().height; ++line)
736 _previousLine = &vectmp[1];
737 _currentLine = &vectmp[1 + components * pixelstride];
740 PIXEL *tmp = _previousLine;
741 _previousLine = _currentLine;
745 STRATEGY::OnLineBegin(_width, _currentLine, pixelstride);
747 for (
int component = 0; component < components; ++component)
749 _RUNindex = rgRUNindex[component];
752 _previousLine[_width] = _previousLine[_width - 1];
753 _currentLine[-1] = _previousLine[0];
754 DoLine((PIXEL*) NULL);
756 rgRUNindex[component] = _RUNindex;
757 _previousLine += pixelstride;
758 _currentLine += pixelstride;
761 if (_rect.Y <= line && line < _rect.Y + _rect.Height)
763 STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X - (components * pixelstride), pixelstride);
773 template<
class TRAITS,
class STRATEGY>
776 if (!IsInterleaved())
779 if (Info().colorTransform == 0)
782 if ((Info().bitspersample ==
sizeof(SAMPLE)*8))
784 switch(Info().colorTransform)
792 else if (Info().bitspersample > 8)
794 int shift = 16 - Info().bitspersample;
795 switch(Info().colorTransform)
810 template<
class TRAITS,
class STRATEGY>
815 BYTE* compressedBytes =
static_cast<BYTE*
>(compressedData);
817 if (pvoidCompare != NULL)
820 STRATEGY::_qdecoder->Init((BYTE*)pvoidCompare, compressedLength);
823 DoScan(compressedBytes, compressedLength);
825 return STRATEGY::GetLength();
831 template<
class TRAITS,
class STRATEGY>
836 BYTE* compressedBytes =
const_cast<BYTE*
>(
static_cast<const BYTE*
>(compressedData));
837 _bCompare = bCompare;
842 ::memcpy(rgbyte, compressedBytes, 4);
845 size_t cbyteScanheader = rgbyte[3] - 2;
847 if (cbyteScanheader >
sizeof(rgbyte))
850 ::memcpy(rgbyte, compressedBytes, cbyteScanheader);
851 readBytes += cbyteScanheader;
855 DoScan(compressedBytes + readBytes, compressedLength - readBytes);
857 return STRATEGY::GetCurBytePos() - compressedBytes;
862 template<
class TRAITS,
class STRATEGY>
869 InitQuantizationLUT();
871 LONG A = MAX(2, (traits.RANGE + 32)/64);
872 for (
unsigned int Q = 0; Q <
sizeof(_contexts) /
sizeof(_contexts[0]); ++Q)
877 _contextRunmode[0] =
CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 0, nReset);
878 _contextRunmode[1] =
CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 1, nReset);