OFFIS DCMTK  Version 3.6.0
scan.h
1 //
2 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
3 //
4 
5 #ifndef CHARLS_SCAN
6 #define CHARLS_SCAN
7 
8 #include "dcmtk/ofstd/ofmap.h" /* For OFPair */
9 #include "dcmtk/ofstd/oftypes.h" /* For OFTypename */
10 
11 #include "lokuptbl.h"
12 
13 // This file contains the code for handling a "scan". Usually an image is encoded as a single scan.
14 
15 
16 #ifdef _MSC_VER
17 #pragma warning (disable: 4127)
18 #endif
19 
20 
21 extern CTable decodingTables[16];
22 extern OFVector<signed char> rgquant8Ll;
23 extern OFVector<signed char> rgquant10Ll;
24 extern OFVector<signed char> rgquant12Ll;
25 extern OFVector<signed char> rgquant16Ll;
26 //
27 // Apply
28 //
29 inlinehint LONG ApplySign(LONG i, LONG sign)
30 { return (sign ^ i) - sign; }
31 
32 
33 LONG CLAMP(LONG i, LONG j, LONG MAXVAL)
34 {
35  if (i > MAXVAL || i < j)
36  return j;
37 
38  return i;
39 }
40 
41 Presets ComputeDefault(LONG MAXVAL, LONG NEAR)
42 {
43  Presets preset;
44 
45  LONG FACTOR = (MIN(MAXVAL, 4095) + 128)/256;
46 
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;
52  return preset;
53 }
54 
55 
56 // Two alternatives for GetPredictedValue() (second is slightly faster due to reduced branching)
57 
58 #if 0
59 
60 inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
61 {
62  if (Ra < Rb)
63  {
64  if (Rc < Ra)
65  return Rb;
66 
67  if (Rc > Rb)
68  return Ra;
69  }
70  else
71  {
72  if (Rc < Rb)
73  return Ra;
74 
75  if (Rc > Ra)
76  return Rb;
77  }
78 
79  return Ra + Rb - Rc;
80 }
81 
82 #else
83 
84 inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
85 {
86  // sign trick reduces the number of if statements (branches)
87  LONG sgn = BitWiseSign(Rb - Ra);
88 
89  // is Ra between Rc and Rb?
90  if ((sgn ^ (Rc - Ra)) < 0)
91  {
92  return Rb;
93  }
94  else if ((sgn ^ (Rb - Rc)) < 0)
95  {
96  return Ra;
97  }
98 
99  // default case, valid if Rc element of [Ra,Rb]
100  return Ra + Rb - Rc;
101 }
102 
103 #endif
104 
105 inlinehint LONG UnMapErrVal(LONG mappedError)
106 {
107  //LONG sign = ~((mappedError & 1) - 1);
108  LONG sign = LONG(mappedError << (LONG_BITCOUNT-1)) >> (LONG_BITCOUNT-1);
109  return sign ^ (mappedError >> 1);
110 }
111 
112 
113 
114 inlinehint LONG GetMappedErrVal(LONG Errval)
115 {
116  LONG mappedError = (Errval >> (LONG_BITCOUNT-2)) ^ (2 * Errval);
117  return mappedError;
118 }
119 
120 
121 
122 inlinehint LONG ComputeContextID(LONG Q1, LONG Q2, LONG Q3)
123 { return (Q1*9 + Q2)*9 + Q3; }
124 
125 
126 //
127 //
128 //
129 template <class TRAITS, class STRATEGY>
130 class JlsCodec : public STRATEGY
131 {
132 public:
133  typedef typename TRAITS::PIXEL PIXEL;
134  typedef typename TRAITS::SAMPLE SAMPLE;
135 
136 public:
137 
138  JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : STRATEGY(info),
139  traits(inTraits),
140  _rect(),
141  _width(0),
142  T1(0),
143  T2(0),
144  T3(0),
145  _RUNindex(0),
146  _pquant(0),
147  _bCompare(0)
148 
149  {
150  if (Info().ilv == ILV_NONE)
151  {
152  Info().components = 1;
153  }
154  }
155 
156 
157  void SetPresets(const JlsCustomParameters& presets)
158  {
159 
160  Presets presetDefault = ComputeDefault(traits.MAXVAL, traits.NEAR);
161 
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);
166  }
167 
168 
169  bool IsInterleaved()
170  {
171  if (Info().ilv == ILV_NONE)
172  return false;
173 
174  if (Info().components == 1)
175  return false;
176 
177  return true;
178  }
179 
180  JlsParameters& Info() { return STRATEGY::_info; }
181 
182  signed char QuantizeGratientOrg(LONG Di);
183  inlinehint LONG QuantizeGratient(LONG Di)
184  {
185  ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di));
186  return *(_pquant + Di);
187  }
188 
189  void InitQuantizationLUT();
190 
191  LONG DecodeValue(LONG k, LONG limit, LONG qbpp);
192  inlinehint void EncodeMappedValue(LONG k, LONG mappedError, LONG limit);
193 
194  void IncrementRunIndex()
195  { _RUNindex = MIN(31,_RUNindex + 1); }
196  void DecrementRunIndex()
197  { _RUNindex = MAX(0,_RUNindex - 1); }
198 
199  LONG DecodeRIError(CContextRunMode& ctx);
200  Triplet<SAMPLE> DecodeRIPixel(Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb);
201  SAMPLE DecodeRIPixel(LONG Ra, LONG Rb)
202  {
203  if (ABS(Ra - Rb) <= traits.NEAR)
204  {
205  LONG ErrVal = DecodeRIError(_contextRunmode[1]);
206  return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
207  }
208  else
209  {
210  LONG ErrVal = DecodeRIError(_contextRunmode[0]);
211  return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
212  }
213  }
214 
215 
216  LONG DecodeRunPixels(PIXEL Ra, PIXEL* ptype, LONG cpixelMac);
217  LONG DoRunMode(LONG index, DecoderStrategy*);
218 
219  void EncodeRIError(CContextRunMode& ctx, LONG Errval);
220  SAMPLE EncodeRIPixel(LONG x, LONG Ra, LONG Rb)
221  {
222  if (ABS(Ra - Rb) <= traits.NEAR)
223  {
224  LONG ErrVal = traits.ComputeErrVal(x - Ra);
225  EncodeRIError(_contextRunmode[1], ErrVal);
226  return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
227  }
228  else
229  {
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)));
233  }
234  }
235 
236 
238  void EncodeRunPixels(LONG runLength, bool bEndofline);
239  LONG DoRunMode(LONG index, EncoderStrategy*);
240 
241  // Encode/decode a single sample. Performancewise the #1 important functions
242  SAMPLE DoRegular(LONG Qs, LONG, LONG pred, DecoderStrategy*)
243  {
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));
248 
249  LONG ErrVal;
250  const Code& code = decodingTables[k].Get(STRATEGY::PeekByte());
251  if (code.GetLength() != 0)
252  {
253  STRATEGY::Skip(code.GetLength());
254  ErrVal = code.GetValue();
255  ASSERT(ABS(ErrVal) < 65535);
256  }
257  else
258  {
259  ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
260  if (ABS(ErrVal) > 65535)
261  throw JlsException(InvalidCompressedData);
262  }
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);
267  }
268 
269  SAMPLE DoRegular(LONG Qs, LONG x, LONG pred, EncoderStrategy*)
270  {
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));
275 
276  LONG ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign));
277 
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)));
282  }
283 
284  void DoLine(SAMPLE* pdummy);
285  void DoLine(Triplet<SAMPLE>* pdummy);
286  void DoScan(BYTE* compressedBytes, size_t compressedLength);
287 
288 public:
289  ProcessLine* CreateProcess(void* pvoidOut);
290  void InitDefault();
291  void InitParams(LONG t1, LONG t2, LONG t3, LONG nReset);
292 
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);
295 
296 protected:
297  // codec parameters
298  TRAITS traits;
299  JlsRect _rect;
300  int _width;
301  LONG T1;
302  LONG T2;
303  LONG T3;
304 
305  // compression context
306  JlsContext _contexts[365];
307  CContextRunMode _contextRunmode[2];
308  LONG _RUNindex;
309  PIXEL* _previousLine; // previous line ptr
310  PIXEL* _currentLine; // current line ptr
311 
312 
313  // quantization lookup table
314  signed char* _pquant;
315  OFVector<signed char> _rgquant;
316 
317  // debugging
318  bool _bCompare;
319 };
320 
321 
322 // Functions to build tables used to decode short golomb codes.
323 
324 inlinehint OFPair<LONG, LONG> CreateEncodedValue(LONG k, LONG mappedError)
325 {
326  LONG highbits = mappedError >> k;
327  return OFMake_pair<LONG, LONG>(highbits + k + 1, (LONG(1) << k) | (mappedError & ((LONG(1) << k) - 1)));
328 }
329 
330 
331 CTable InitTable(LONG k)
332 {
333  CTable table;
334  short nerr;
335  for (nerr = 0; ; nerr++)
336  {
337  // Q is not used when k != 0
338  LONG merrval = GetMappedErrVal(nerr);//, k, -1);
339  OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
340  if (paircode.first > CTable::cbit)
341  break;
342 
343  Code code = Code( nerr, short(paircode.first) );
344  table.AddEntry(BYTE(paircode.second), code);
345  }
346 
347  for (nerr = -1; ; nerr--)
348  {
349  // Q is not used when k != 0
350  LONG merrval = GetMappedErrVal(nerr);//, k, -1);
351  OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
352  if (paircode.first > CTable::cbit)
353  break;
354 
355  Code code = Code(nerr, short(paircode.first));
356  table.AddEntry(BYTE(paircode.second), code);
357  }
358 
359  return table;
360 }
361 
362 
363 // Encoding/decoding of golomb codes
364 
365 template<class TRAITS, class STRATEGY>
366 LONG JlsCodec<TRAITS,STRATEGY>::DecodeValue(LONG k, LONG limit, LONG qbpp)
367 {
368  LONG highbits = STRATEGY::ReadHighbits();
369 
370  if (highbits >= limit - (qbpp + 1))
371  return STRATEGY::ReadValue(qbpp) + 1;
372 
373  if (k == 0)
374  return highbits;
375 
376  return (highbits << k) + STRATEGY::ReadValue(k);
377 }
378 
379 
380 
381 template<class TRAITS, class STRATEGY>
382 inlinehint void JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mappedError, LONG limit)
383 {
384  LONG highbits = mappedError >> k;
385 
386  if (highbits < limit - traits.qbpp - 1)
387  {
388  if (highbits + 1 > 31)
389  {
390  STRATEGY::AppendToBitStream(0, highbits / 2);
391  highbits = highbits - highbits / 2;
392  }
393  STRATEGY::AppendToBitStream(1, highbits + 1);
394  STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k);
395  return;
396  }
397 
398  if (limit - traits.qbpp > 31)
399  {
400  STRATEGY::AppendToBitStream(0, 31);
401  STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
402  }
403  else
404  {
405  STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
406  }
407  STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 1), traits.qbpp);
408 }
409 
410 
411 // Sets up a lookup table to "Quantize" sample difference.
412 
413 template<class TRAITS, class STRATEGY>
415 {
416  // for lossless mode with default parameters, we have precomputed te luts for bitcounts 8,10,12 and 16
417  if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1)
418  {
419  Presets presets = ComputeDefault(traits.MAXVAL, traits.NEAR);
420  if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3)
421  {
422  if (traits.bpp == 8)
423  {
424  _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
425  return;
426  }
427  if (traits.bpp == 10)
428  {
429  _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
430  return;
431  }
432  if (traits.bpp == 12)
433  {
434  _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
435  return;
436  }
437  if (traits.bpp == 16)
438  {
439  _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
440  return;
441  }
442  }
443  }
444 
445  LONG RANGE = 1 << traits.bpp;
446 
447  _rgquant.resize(RANGE * 2);
448 
449  _pquant = &_rgquant[RANGE];
450  for (LONG i = -RANGE; i < RANGE; ++i)
451  {
452  _pquant[i] = QuantizeGratientOrg(i);
453  }
454 }
455 
456 
457 template<class TRAITS, class STRATEGY>
459 {
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;
468 
469  return 4;
470 }
471 
472 
473 
474 // RI = Run interruption: functions that handle the sample terminating a run.
475 
476 template<class TRAITS, class STRATEGY>
478 {
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);
483  return Errval;
484 }
485 
486 
487 
488 template<class TRAITS, class STRATEGY>
490 {
491  LONG k = ctx.GetGolomb();
492  bool map = ctx.ComputeMap(Errval, k);
493  LONG EMErrval = 2 * ABS(Errval) - ctx._nRItype - map;
494 
495  ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
496  EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1);
497  ctx.UpdateVariables(Errval, EMErrval);
498 }
499 
500 
501 template<class TRAITS, class STRATEGY>
503 {
504  LONG Errval1 = DecodeRIError(_contextRunmode[0]);
505  LONG Errval2 = DecodeRIError(_contextRunmode[0]);
506  LONG Errval3 = DecodeRIError(_contextRunmode[0]);
507 
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)));
511 }
512 
513 
514 
515 template<class TRAITS, class STRATEGY>
517 {
518  LONG errval1 = traits.ComputeErrVal(Sign(Rb.v1 - Ra.v1) * (x.v1 - Rb.v1));
519  EncodeRIError(_contextRunmode[0], errval1);
520 
521  LONG errval2 = traits.ComputeErrVal(Sign(Rb.v2 - Ra.v2) * (x.v2 - Rb.v2));
522  EncodeRIError(_contextRunmode[0], errval2);
523 
524  LONG errval3 = traits.ComputeErrVal(Sign(Rb.v3 - Ra.v3) * (x.v3 - Rb.v3));
525  EncodeRIError(_contextRunmode[0], errval3);
526 
527 
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)));
531 }
532 
533 
534 
535 // RunMode: Functions that handle run-length encoding
536 
537 template<class TRAITS, class STRATEGY>
538 void JlsCodec<TRAITS,STRATEGY>::EncodeRunPixels(LONG runLength, bool endOfLine)
539 {
540  while (runLength >= LONG(1 << J[_RUNindex]))
541  {
542  STRATEGY::AppendOnesToBitStream(1);
543  runLength = runLength - LONG(1 << J[_RUNindex]);
544  IncrementRunIndex();
545  }
546 
547  if (endOfLine)
548  {
549  if (runLength != 0)
550  {
551  STRATEGY::AppendOnesToBitStream(1);
552  }
553  }
554  else
555  {
556  STRATEGY::AppendToBitStream(runLength, J[_RUNindex] + 1); // leading 0 + actual remaining length
557  }
558 }
559 
560 
561 template<class TRAITS, class STRATEGY>
562 LONG JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, PIXEL* startPos, LONG cpixelMac)
563 {
564  LONG index = 0;
565  while (STRATEGY::ReadBit())
566  {
567  int count = MIN(1 << J[_RUNindex], int(cpixelMac - index));
568  index += count;
569  ASSERT(index <= cpixelMac);
570 
571  if (count == (1 << J[_RUNindex]))
572  {
573  IncrementRunIndex();
574  }
575 
576  if (index == cpixelMac)
577  break;
578  }
579 
580 
581  if (index != cpixelMac)
582  {
583  // incomplete run
584  index += (J[_RUNindex] > 0) ? STRATEGY::ReadValue(J[_RUNindex]) : 0;
585  }
586 
587  if (index > cpixelMac)
588  throw JlsException(InvalidCompressedData);
589 
590  for (LONG i = 0; i < index; ++i)
591  {
592  startPos[i] = Ra;
593  }
594 
595  return index;
596 }
597 
598 template<class TRAITS, class STRATEGY>
600 {
601  LONG ctypeRem = _width - index;
602  PIXEL* ptypeCurX = _currentLine + index;
603  PIXEL* ptypePrevX = _previousLine + index;
604 
605  PIXEL Ra = ptypeCurX[-1];
606 
607  LONG runLength = 0;
608 
609  while (traits.IsNear(ptypeCurX[runLength],Ra))
610  {
611  ptypeCurX[runLength] = Ra;
612  runLength++;
613 
614  if (runLength == ctypeRem)
615  break;
616  }
617 
618  EncodeRunPixels(runLength, runLength == ctypeRem);
619 
620  if (runLength == ctypeRem)
621  return runLength;
622 
623  ptypeCurX[runLength] = EncodeRIPixel(ptypeCurX[runLength], Ra, ptypePrevX[runLength]);
624  DecrementRunIndex();
625  return runLength + 1;
626 }
627 
628 
629 template<class TRAITS, class STRATEGY>
631 {
632  PIXEL Ra = _currentLine[startIndex-1];
633 
634  LONG runLength = DecodeRunPixels(Ra, _currentLine + startIndex, _width - startIndex);
635  LONG endIndex = startIndex + runLength;
636 
637  if (endIndex == _width)
638  return endIndex - startIndex;
639 
640  // run interruption
641  PIXEL Rb = _previousLine[endIndex];
642  _currentLine[endIndex] = DecodeRIPixel(Ra, Rb);
643  DecrementRunIndex();
644  return endIndex - startIndex + 1;
645 }
646 
647 
648 // DoLine: Encodes/Decodes a scanline of samples
649 
650 template<class TRAITS, class STRATEGY>
652 {
653  LONG index = 0;
654  LONG Rb = _previousLine[index-1];
655  LONG Rd = _previousLine[index];
656 
657  while(index < _width)
658  {
659  LONG Ra = _currentLine[index -1];
660  LONG Rc = Rb;
661  Rb = Rd;
662  Rd = _previousLine[index + 1];
663 
664  LONG Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
665 
666  if (Qs != 0)
667  {
668  _currentLine[index] = DoRegular(Qs, _currentLine[index], GetPredictedValue(Ra, Rb, Rc), (STRATEGY*)(NULL));
669  index++;
670  }
671  else
672  {
673  index += DoRunMode(index, (STRATEGY*)(NULL));
674  Rb = _previousLine[index-1];
675  Rd = _previousLine[index];
676  }
677  }
678 }
679 
680 
681 // DoLine: Encodes/Decodes a scanline of triplets in ILV_SAMPLE mode
682 
683 template<class TRAITS, class STRATEGY>
685 {
686  LONG index = 0;
687  while(index < _width)
688  {
689  Triplet<SAMPLE> Ra = _currentLine[index -1];
690  Triplet<SAMPLE> Rc = _previousLine[index-1];
691  Triplet<SAMPLE> Rb = _previousLine[index];
692  Triplet<SAMPLE> Rd = _previousLine[index + 1];
693 
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));
697 
698 
699  if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
700  {
701  index += DoRunMode(index, (STRATEGY*)(NULL));
702  }
703  else
704  {
705  Triplet<SAMPLE> Rx;
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;
710  index++;
711  }
712  }
713 }
714 
715 
716 // DoScan: Encodes or decodes a scan.
717 // In ILV_SAMPLE mode, multiple components are handled in DoLine
718 // In ILV_LINE mode, a call do DoLine is made for every component
719 // In ILV_NONE mode, DoScan is called for each component
720 
721 template<class TRAITS, class STRATEGY>
722 void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE* compressedBytes, size_t compressedLength)
723 {
724  _width = Info().width;
725 
726  STRATEGY::Init(compressedBytes, compressedLength);
727 
728  LONG pixelstride = _width + 4;
729  int components = Info().ilv == ILV_LINE ? Info().components : 1;
730 
731  OFVector<PIXEL> vectmp(2 * components * pixelstride);
732  OFVector<LONG> rgRUNindex(components);
733 
734  for (LONG line = 0; line < Info().height; ++line)
735  {
736  _previousLine = &vectmp[1];
737  _currentLine = &vectmp[1 + components * pixelstride];
738  if ((line & 1) == 1)
739  {
740  PIXEL *tmp = _previousLine;
741  _previousLine = _currentLine;
742  _currentLine = tmp;
743  }
744 
745  STRATEGY::OnLineBegin(_width, _currentLine, pixelstride);
746 
747  for (int component = 0; component < components; ++component)
748  {
749  _RUNindex = rgRUNindex[component];
750 
751  // initialize edge pixels used for prediction
752  _previousLine[_width] = _previousLine[_width - 1];
753  _currentLine[-1] = _previousLine[0];
754  DoLine((PIXEL*) NULL); // dummy arg for overload resolution
755 
756  rgRUNindex[component] = _RUNindex;
757  _previousLine += pixelstride;
758  _currentLine += pixelstride;
759  }
760 
761  if (_rect.Y <= line && line < _rect.Y + _rect.Height)
762  {
763  STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X - (components * pixelstride), pixelstride);
764  }
765  }
766 
767  STRATEGY::EndScan();
768 }
769 
770 
771 // Factory function for ProcessLine objects to copy/transform unencoded pixels to/from our scanline buffers.
772 
773 template<class TRAITS, class STRATEGY>
775 {
776  if (!IsInterleaved())
777  return new PostProcesSingleComponent(pvoidOut, Info(), sizeof(typename TRAITS::PIXEL));
778 
779  if (Info().colorTransform == 0)
781 
782  if ((Info().bitspersample == sizeof(SAMPLE)*8))
783  {
784  switch(Info().colorTransform)
785  {
786  case COLORXFORM_HP1 : return new ProcessTransformed<TransformHp1<SAMPLE> >(pvoidOut, Info(), TransformHp1<SAMPLE>()); break;
787  case COLORXFORM_HP2 : return new ProcessTransformed<TransformHp2<SAMPLE> >(pvoidOut, Info(), TransformHp2<SAMPLE>()); break;
788  case COLORXFORM_HP3 : return new ProcessTransformed<TransformHp3<SAMPLE> >(pvoidOut, Info(), TransformHp3<SAMPLE>()); break;
789  default: throw JlsException(UnsupportedColorTransform);
790  }
791  }
792  else if (Info().bitspersample > 8)
793  {
794  int shift = 16 - Info().bitspersample;
795  switch(Info().colorTransform)
796  {
797  case COLORXFORM_HP1 : return new ProcessTransformed<TransformShifted<TransformHp1<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp1<USHORT> >(shift)); break;
798  case COLORXFORM_HP2 : return new ProcessTransformed<TransformShifted<TransformHp2<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp2<USHORT> >(shift)); break;
799  case COLORXFORM_HP3 : return new ProcessTransformed<TransformShifted<TransformHp3<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp3<USHORT> >(shift)); break;
800  default: throw JlsException(UnsupportedColorTransform);
801  }
802  }
803  throw JlsException(UnsupportedBitDepthForTransform);
804 }
805 
806 
807 
808 // Setup codec for encoding and calls DoScan
809 
810 template<class TRAITS, class STRATEGY>
811 size_t JlsCodec<TRAITS,STRATEGY>::EncodeScan(const void* rawData, void* compressedData, size_t compressedLength, void* pvoidCompare)
812 {
813  STRATEGY::_processLine = OFauto_ptr<ProcessLine>(CreateProcess(const_cast<void*>(rawData)));
814 
815  BYTE* compressedBytes = static_cast<BYTE*>(compressedData);
816 
817  if (pvoidCompare != NULL)
818  {
819  STRATEGY::_qdecoder = OFauto_ptr<DecoderStrategy>(new JlsCodec<TRAITS,DecoderStrategy>(traits, Info()));
820  STRATEGY::_qdecoder->Init((BYTE*)pvoidCompare, compressedLength);
821  }
822 
823  DoScan(compressedBytes, compressedLength);
824 
825  return STRATEGY::GetLength();
826 
827 }
828 
829 // Setup codec for decoding and calls DoScan
830 
831 template<class TRAITS, class STRATEGY>
832 size_t JlsCodec<TRAITS,STRATEGY>::DecodeScan(void* rawData, const JlsRect& rect, const void* compressedData, size_t compressedLength, bool bCompare)
833 {
834  STRATEGY::_processLine = OFauto_ptr<ProcessLine>(CreateProcess(rawData));
835 
836  BYTE* compressedBytes = const_cast<BYTE*>(static_cast<const BYTE*>(compressedData));
837  _bCompare = bCompare;
838 
839  BYTE rgbyte[20];
840 
841  LONG readBytes = 0;
842  ::memcpy(rgbyte, compressedBytes, 4);
843  readBytes += 4;
844 
845  size_t cbyteScanheader = rgbyte[3] - 2;
846 
847  if (cbyteScanheader > sizeof(rgbyte))
848  throw JlsException(InvalidCompressedData);
849 
850  ::memcpy(rgbyte, compressedBytes, cbyteScanheader);
851  readBytes += cbyteScanheader;
852 
853  _rect = rect;
854 
855  DoScan(compressedBytes + readBytes, compressedLength - readBytes);
856 
857  return STRATEGY::GetCurBytePos() - compressedBytes;
858 }
859 
860 // Initialize the codec data structures. Depends on JPEG-LS parameters like T1-T3.
861 
862 template<class TRAITS, class STRATEGY>
863 void JlsCodec<TRAITS,STRATEGY>::InitParams(LONG t1, LONG t2, LONG t3, LONG nReset)
864 {
865  T1 = t1;
866  T2 = t2;
867  T3 = t3;
868 
869  InitQuantizationLUT();
870 
871  LONG A = MAX(2, (traits.RANGE + 32)/64);
872  for (unsigned int Q = 0; Q < sizeof(_contexts) / sizeof(_contexts[0]); ++Q)
873  {
874  _contexts[Q] = JlsContext(A);
875  }
876 
877  _contextRunmode[0] = CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 0, nReset);
878  _contextRunmode[1] = CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 1, nReset);
879  _RUNindex = 0;
880 }
881 
882 #endif


Generated on Thu Dec 20 2012 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.8.2