OFFIS DCMTK  Version 3.6.0
dimoopxt.h
1 /*
2  *
3  * Copyright (C) 1996-2010, OFFIS e.V.
4  * All rights reserved. See COPYRIGHT file for details.
5  *
6  * This software and supporting documentation were developed by
7  *
8  * OFFIS e.V.
9  * R&D Division Health
10  * Escherweg 2
11  * D-26121 Oldenburg, Germany
12  *
13  *
14  * Module: dcmimgle
15  *
16  * Author: Joerg Riesmeier
17  *
18  * Purpose: DicomMonoOutputPixelTemplate (Header)
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2010-10-28 10:58:38 $
22  * CVS/RCS Revision: $Revision: 1.54 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 
30 #ifndef DIMOOPXT_H
31 #define DIMOOPXT_H
32 
33 #include "dcmtk/config/osconfig.h"
34 
35 #include "dcmtk/ofstd/ofcast.h"
36 #include "dcmtk/ofstd/ofbmanip.h"
37 
38 #include "dcmtk/dcmimgle/dimoopx.h"
39 #include "dcmtk/dcmimgle/dimopx.h"
40 #include "dcmtk/dcmimgle/diluptab.h"
41 #include "dcmtk/dcmimgle/diovlay.h"
42 #include "dcmtk/dcmimgle/dipxrept.h"
43 #include "dcmtk/dcmimgle/didispfn.h"
44 #include "dcmtk/dcmimgle/didislut.h"
45 
46 #ifdef PASTEL_COLOR_OUTPUT
47 #include "dimcopxt.h"
48 #endif
49 
50 #define INCLUDE_CMATH
51 #include "dcmtk/ofstd/ofstdinc.h"
52 
53 
54 /*---------------------*
55  * class declaration *
56  *---------------------*/
57 
60 template<class T1, class T2, class T3>
62  : public DiMonoOutputPixel,
64 {
65 
66  public:
67 
88  const DiMonoPixel *pixel,
89  DiOverlay *overlays[2],
90  const DiLookupTable *vlut,
91  const DiLookupTable *plut,
92  DiDisplayFunction *disp,
93  const EF_VoiLutFunction vfunc,
94  const double center,
95  const double width,
96  const Uint32 low,
97  const Uint32 high,
98  const Uint16 columns,
99  const Uint16 rows,
100  const unsigned long frame,
101 #ifdef PASTEL_COLOR_OUTPUT
102  const unsigned long frames,
103 #else
104  const unsigned long /*frames*/,
105 #endif
106  const int pastel = 0)
107  : DiMonoOutputPixel(pixel, OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows), frame,
108  OFstatic_cast(unsigned long, fabs(OFstatic_cast(double, high - low)))),
109  Data(NULL),
110  DeleteData(buffer == NULL),
111  ColorData(NULL)
112  {
113  if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
114  {
115  if (pastel)
116 #ifdef PASTEL_COLOR_OUTPUT
117  color(buffer, pixel, frame, frames);
118 #else
119  DCMIMGLE_ERROR("pastel color output not supported");
120 #endif
121  else
122  {
123  DCMIMGLE_TRACE("monochrome output image - columns: " << columns << ", rows: " << rows << ", frame: " << frame);
124  DCMIMGLE_TRACE("monochrome output values - low: " << OFstatic_cast(unsigned long, low) << ", high: "
125  << OFstatic_cast(unsigned long, high) << ((low > high) ? " (inverted)" : ""));
126  Data = OFstatic_cast(T3 *, buffer);
127  if ((vlut != NULL) && (vlut->isValid())) // valid VOI LUT ?
128  voilut(pixel, frame * FrameSize, vlut, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
129  else
130  {
131  if (width < 1) // no valid window according to supplement 33
132  nowindow(pixel, frame * FrameSize, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
133  else if (vfunc == EFV_Sigmoid)
134  sigmoid(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
135  else // linear
136  window(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
137  }
138  overlay(overlays, disp, columns, rows, frame); // add (visible) overlay planes to output bitmap
139  }
140  }
141  }
142 
146  {
147  if (DeleteData)
148  delete[] Data;
149  delete ColorData;
150  }
151 
156  inline EP_Representation getRepresentation() const
157  {
159  }
160 
165  inline size_t getItemSize() const
166  {
167  return (ColorData != NULL) ? ColorData->getItemSize() : sizeof(T3);
168  }
169 
174  inline const void *getData() const
175  {
176  return (ColorData != NULL) ? ColorData->getData() : OFstatic_cast(const void *, Data);
177  }
178 
183  virtual void *getDataPtr()
184  {
185  return (ColorData != NULL) ? ColorData->getDataPtr() : OFstatic_cast(void *, Data);
186  }
187 
190  inline void removeDataReference()
191  {
192  Data = NULL;
193  DeleteData = 0;
194  }
195 
202  inline int writePPM(STD_NAMESPACE ostream& stream) const
203  {
204  if (Data != NULL)
205  {
206  register unsigned long i;
207  for (i = 0; i < FrameSize; ++i)
208  stream << OFstatic_cast(unsigned long, Data[i]) << " "; // typecast to resolve problems with 'char'
209  return 1;
210  }
211  if (ColorData != NULL)
212  return ColorData->writePPM(stream);
213  return 0;
214  }
215 
222  inline int writePPM(FILE *stream) const
223  {
224  if (Data != NULL)
225  {
226  register unsigned long i;
227  for (i = 0; i < FrameSize; ++i)
228  fprintf(stream, "%lu ", OFstatic_cast(unsigned long, Data[i]));
229  return 1;
230  }
231  if (ColorData != NULL)
232  return ColorData->writePPM(stream);
233  return 0;
234  }
235 
236 
237  protected:
238 
241  inline void determineUsedValues()
242  {
243  if ((UsedValues == NULL) && (MaxValue > 0) && (MaxValue < MAX_TABLE_ENTRY_COUNT))
244  {
245  UsedValues = new Uint8[MaxValue + 1];
246  if (UsedValues != NULL)
247  {
248  OFBitmanipTemplate<Uint8>::zeroMem(UsedValues, MaxValue + 1); // initialize array
249  register const T3 *p = Data;
250  register Uint8 *q = UsedValues;
251  register unsigned long i;
252  for (i = Count; i != 0; --i)
253  *(q + *(p++)) = 1; // mark used entries
254  }
255  }
256  }
257 
258 
259  private:
260 
267  inline void createDisplayLUT(const DiDisplayLUT *&dlut,
268  DiDisplayFunction *disp,
269  const int bits)
270  {
271  if ((disp != NULL) && (disp->isValid()))
272  { // create Display LUT
273  dlut = disp->getLookupTable(bits);
274  if ((dlut != NULL) && (dlut->isValid())) // LUT is valid
275  {
276  DCMIMGLE_DEBUG("using display transformation");
277  } else {
278  DCMIMGLE_WARN("can't create display LUT ... ignoring display transformation");
279  dlut = NULL;
280  }
281  }
282  }
283 
289  inline int initOptimizationLUT(T3 *&lut,
290  const unsigned long ocnt)
291  {
292  int result = 0;
293  if ((sizeof(T1) <= 2) && (Count > 3 * ocnt)) // optimization criteria
294  { // use LUT for optimization
295  lut = new T3[ocnt];
296  if (lut != NULL)
297  {
298  DCMIMGLE_DEBUG("using optimized routine with additional LUT (" << ocnt << " entries)");
299  result = 1;
300  }
301  }
302  return result;
303  }
304 
305 #ifdef PASTEL_COLOR_OUTPUT
306  void color(void *buffer, // create true color pastel image
307  const DiMonoPixel *inter,
308  const unsigned long frame,
309  const unsigned long frames)
310  {
311  ColorData = new DiMonoColorOutputPixelTemplate<T1, T3>(buffer, inter, frame, frames);
312  if (ColorData != NULL)
313  DCMIMGLE_DEBUG(">>> COLOR <<<");
314  }
315 #endif
316 
327  void voilut(const DiMonoPixel *inter,
328  const Uint32 start,
329  const DiLookupTable *vlut,
330  const DiLookupTable *plut,
331  DiDisplayFunction *disp,
332  const T3 low,
333  const T3 high)
334  {
335  const T1 *pixel = OFstatic_cast(const T1 *, inter->getData());
336  if ((pixel != NULL) && (vlut != NULL))
337  {
338  if (Data == NULL)
339  Data = new T3[FrameSize];
340  if (Data != NULL)
341  {
342  DCMIMGLE_DEBUG("applying VOI transformation with LUT (" << vlut->getCount() << " entries)");
343  const DiDisplayLUT *dlut = NULL;
344  const double minvalue = vlut->getMinValue();
345  const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1;
346  register unsigned long i;
347  if (minvalue == vlut->getMaxValue()) // LUT has only one entry or all entries are equal
348  {
349  T3 value;
350  if ((plut != NULL) && (plut->isValid())) // has presentation LUT
351  {
352  DCMIMGLE_DEBUG("applying presentation LUT transformation");
353  createDisplayLUT(dlut, disp, plut->getBits());
354  const Uint32 value2 = OFstatic_cast(Uint32, (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * plut->getCount());
355  if (dlut != NULL) // perform display transformation
356  {
357  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #1 - UNTESTED");
358  if (low > high) // invers
359  value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getAbsMaxRange() - plut->getValue(value2) - 1)));
360  else // normal
361  value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getValue(value2))));
362  } else { // don't use display: invalid or absent
363  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #2");
364  value = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * outrange / OFstatic_cast(double, plut->getAbsMaxRange()));
365  }
366  } else { // has no presentation LUT
367  createDisplayLUT(dlut, disp, vlut->getBits());
368  if (dlut != NULL) // perform display transformation
369  {
370  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #3 - UNTESTED");
371  if (low > high) // invers
372  value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, vlut->getAbsMaxRange() - minvalue - 1)));
373  else // normal
374  value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, minvalue)));
375  } else { // don't use display: invalid or absent
376  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #4");
377  value = OFstatic_cast(T3, OFstatic_cast(double, low) + (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * outrange);
378  }
379  }
380  OFBitmanipTemplate<T3>::setMem(Data, value, Count); // set output pixels to LUT value
381  } else {
382  register T2 value = 0;
383  const T2 absmin = OFstatic_cast(T2, inter->getAbsMinimum());
384  const T2 firstentry = vlut->getFirstEntry(value); // choose signed/unsigned method
385  const T2 lastentry = vlut->getLastEntry(value);
386  const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries
387  register const T1 *p = pixel + start;
388  register T3 *q = Data;
389  T3 *lut = NULL;
390  if ((plut != NULL) && (plut->isValid())) // has presentation LUT
391  {
392  DCMIMGLE_DEBUG("applying presentation LUT transformation");
393  createDisplayLUT(dlut, disp, plut->getBits());
394  register Uint32 value2; // presentation LUT is always unsigned
395  const Uint32 pcnt = plut->getCount();
396  const double gradient1 = OFstatic_cast(double, pcnt) / OFstatic_cast(double, vlut->getAbsMaxRange());
397  const Uint32 firstvalue = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getFirstValue()) * gradient1);
398  const Uint32 lastvalue = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getLastValue()) * gradient1);
399  if (initOptimizationLUT(lut, ocnt))
400  { // use LUT for optimization
401  q = lut;
402  if (dlut != NULL) // perform display transformation
403  {
404  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #5");
405  if (low > high) // inverse
406  {
407  const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1);
408  for (i = 0; i < ocnt; ++i)
409  {
410  value = OFstatic_cast(T2, i) + absmin;
411  if (value <= firstentry)
412  value2 = firstvalue;
413  else if (value >= lastentry)
414  value2 = lastvalue;
415  else
416  value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1);
417  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value2))));
418  }
419  } else { // normal
420  for (i = 0; i < ocnt; ++i)
421  {
422  value = OFstatic_cast(T2, i) + absmin;
423  if (value <= firstentry)
424  value2 = firstvalue;
425  else if (value >= lastentry)
426  value2 = lastvalue;
427  else
428  value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1);
429  *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value2)));
430  }
431  }
432  } else { // don't use display: invalid or absent
433  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #6");
434  const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange());
435  for (i = 0; i < ocnt; ++i)
436  {
437  value = OFstatic_cast(T2, i) + absmin;
438  if (value <= firstentry)
439  value2 = firstvalue;
440  else if (value >= lastentry)
441  value2 = lastvalue;
442  else
443  value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1);
444  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2);
445  }
446  }
447  const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry
448  q = Data;
449  for (i = Count; i != 0; --i) // apply LUT
450  *(q++) = *(lut0 + (*(p++)));
451  }
452  if (lut == NULL) // use "normal" transformation
453  {
454  if (dlut != NULL) // perform display transformation
455  {
456  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #7");
457  if (low > high) // inverse
458  {
459  const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1);
460  for (i = Count; i != 0; --i)
461  {
462  value = OFstatic_cast(T2, *(p++)); // pixel value
463  if (value <= firstentry)
464  value2 = firstvalue;
465  else if (value >= lastentry)
466  value2 = lastvalue;
467  else
468  value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1);
469  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value2))));
470  }
471  } else { // normal
472  for (i = Count; i != 0; --i)
473  {
474  value = OFstatic_cast(T2, *(p++)); // pixel value
475  if (value <= firstentry)
476  value2 = firstvalue;
477  else if (value >= lastentry)
478  value2 = lastvalue;
479  else
480  value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1);
481  *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value2)));
482  }
483  }
484  } else { // don't use display: invalid or absent
485  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #8");
486  const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange());
487  for (i = Count; i != 0; --i)
488  {
489  value = OFstatic_cast(T2, *(p++)); // pixel value
490  if (value <= firstentry)
491  value2 = firstvalue;
492  else if (value >= lastentry)
493  value2 = lastvalue;
494  else
495  value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1);
496  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2);
497  }
498  }
499  }
500  } else { // has no presentation LUT
501  createDisplayLUT(dlut, disp, vlut->getBits());
502  const double gradient = outrange / OFstatic_cast(double, vlut->getAbsMaxRange());
503  const T3 firstvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getFirstValue()) * gradient);
504  const T3 lastvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getLastValue()) * gradient);
505  if (initOptimizationLUT(lut, ocnt))
506  { // use LUT for optimization
507  q = lut;
508  if (dlut != NULL) // perform display transformation
509  {
510  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #9");
511  if (low > high) // inverse
512  {
513  const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1);
514  for (i = 0; i < ocnt; ++i)
515  {
516  value = OFstatic_cast(T2, i) + absmin;
517  if (value < firstentry)
518  value = firstentry;
519  else if (value > lastentry)
520  value = lastentry;
521  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - vlut->getValue(value))));
522  }
523  } else { // normal
524  for (i = 0; i < ocnt; ++i)
525  {
526  value = OFstatic_cast(T2, i) + absmin;
527  if (value < firstentry)
528  value = firstentry;
529  else if (value > lastentry)
530  value = lastentry;
531  *(q++) = OFstatic_cast(T3, dlut->getValue(vlut->getValue(value)));
532  }
533  }
534  } else { // don't use display: invalid or absent
535  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #10");
536  for (i = 0; i < ocnt; ++i) // calculating LUT entries
537  {
538  value = OFstatic_cast(T2, i) + absmin;
539  if (value <= firstentry)
540  *(q++) = firstvalue;
541  else if (value >= lastentry)
542  *(q++) = lastvalue;
543  else
544  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient);
545  }
546  }
547  const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry
548  q = Data;
549  for (i = Count; i != 0; --i) // apply LUT
550  *(q++) = *(lut0 + (*(p++)));
551  }
552  if (lut == NULL) // use "normal" transformation
553  {
554  if (dlut != NULL) // perform display transformation
555  {
556  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #11");
557  if (low > high) // inverse
558  {
559  const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1);
560  for (i = Count; i != 0; --i)
561  {
562  value = OFstatic_cast(T2, *(p++));
563  if (value < firstentry)
564  value = firstentry;
565  else if (value > lastentry)
566  value = lastentry;
567  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - vlut->getValue(value))));
568  }
569  } else { // normal
570  for (i = Count; i != 0; --i)
571  {
572  value = OFstatic_cast(T2, *(p++));
573  if (value < firstentry)
574  value = firstentry;
575  else if (value > lastentry)
576  value = lastentry;
577  *(q++) = OFstatic_cast(T3, dlut->getValue(vlut->getValue(value)));
578  }
579  }
580  } else { // don't use display: invalid or absent
581  DCMIMGLE_TRACE("monochrome rendering: VOI LUT #12");
582  for (i = 0; i < Count; ++i)
583  {
584  value = OFstatic_cast(T2, *(p++));
585  if (value <= firstentry)
586  *(q++) = firstvalue;
587  else if (value >= lastentry)
588  *(q++) = lastvalue;
589  else
590  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient);
591  }
592  }
593  }
594  }
595  delete[] lut;
596  }
597  if (Count < FrameSize)
598  OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero
599  }
600  } else
601  Data = NULL;
602  }
603 
613  void nowindow(const DiMonoPixel *inter,
614  const Uint32 start,
615  const DiLookupTable *plut,
616  DiDisplayFunction *disp,
617  const T3 low,
618  const T3 high)
619  {
620  const DiDisplayLUT *dlut = NULL;
621  const T1 *pixel = OFstatic_cast(const T1 *, inter->getData());
622  if (pixel != NULL)
623  {
624  if (Data == NULL) // create new output buffer
625  Data = new T3[FrameSize];
626  if (Data != NULL)
627  {
628  DCMIMGLE_DEBUG("applying no VOI transformation (linear scaling)");
629  const double absmin = inter->getAbsMinimum();
630  const double absmax = inter->getAbsMaximum();
631  const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1;
632  const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries
633  register const T1 *p = pixel + start;
634  register T3 *q = Data;
635  register unsigned long i;
636  T3 *lut = NULL;
637  if ((plut != NULL) && (plut->isValid())) // has presentation LUT
638  {
639  DCMIMGLE_DEBUG("applying presentation LUT transformation");
640  createDisplayLUT(dlut, disp, plut->getBits());
641  register Uint32 value; // presentation LUT is always unsigned
642  const double gradient1 = OFstatic_cast(double, plut->getCount()) / inter->getAbsMaxRange();
643  const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange());
644  if (initOptimizationLUT(lut, ocnt))
645  { // use LUT for optimization
646  q = lut;
647  if (dlut != NULL) // perform display transformation
648  {
649  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #1");
650  if (low > high) // inverse
651  {
652  const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1);
653  for (i = 0; i < ocnt; ++i)
654  {
655  value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1);
656  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value))));
657  }
658  } else { // normal
659  for (i = 0; i < ocnt; ++i)
660  {
661  value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1);
662  *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value)));
663  }
664  }
665  } else { // don't use display: invalid or absent
666  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #2");
667  for (i = 0; i < ocnt; ++i)
668  {
669  value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1);
670  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2);
671  }
672  }
673  const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry
674  q = Data;
675  for (i = Count; i != 0; --i) // apply LUT
676  *(q++) = *(lut0 + (*(p++)));
677  }
678  if (lut == NULL) // use "normal" transformation
679  {
680  if (dlut != NULL) // perform display transformation
681  {
682  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #3");
683  if (low > high) // inverse
684  {
685  const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1);
686  for (i = Count; i != 0; --i)
687  {
688  value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1);
689  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value))));
690  }
691  } else { // normal
692  for (i = Count; i != 0; --i)
693  {
694  value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1);
695  *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value)));
696  }
697  }
698  } else { // don't use display: invalid or absent
699  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #4");
700  for (i = Count; i != 0; --i)
701  {
702  value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1);
703  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2);
704  }
705  }
706  }
707  } else { // has no presentation LUT
708  createDisplayLUT(dlut, disp, inter->getBits());
709  register const double gradient = outrange / (inter->getAbsMaxRange());
710  if (initOptimizationLUT(lut, ocnt))
711  { // use LUT for optimization
712  q = lut;
713  if (dlut != NULL) // perform display transformation
714  {
715  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #5");
716  if (low > high) // inverse
717  {
718  for (i = ocnt; i != 0; --i) // calculating LUT entries
719  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, i - 1)));
720  } else { // normal
721  for (i = 0; i < ocnt; ++i) // calculating LUT entries
722  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, i)));
723  }
724  } else { // don't use display: invalid or absent
725  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #6");
726  for (i = 0; i < ocnt; ++i) // calculating LUT entries
727  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, i) * gradient);
728  }
729  const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry
730  q = Data;
731  for (i = Count; i != 0; --i) // apply LUT
732  *(q++) = *(lut0 + (*(p++)));
733  }
734  if (lut == NULL) // use "normal" transformation
735  {
736  if (dlut != NULL) // perform display transformation
737  {
738  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #7");
739  if (low > high) // inverse
740  {
741  for (i = Count; i != 0; --i)
742  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, absmax - (OFstatic_cast(double, *(p++)) - absmin))));
743  } else { // normal
744  for (i = Count; i != 0; --i)
745  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, OFstatic_cast(double, *(p++)) - absmin)));
746  }
747  } else { // don't use display: invalid or absent
748  DCMIMGLE_TRACE("monochrome rendering: VOI NONE #8");
749  for (i = Count; i != 0; --i)
750  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + (OFstatic_cast(double, *(p++)) - absmin) * gradient);
751  }
752  }
753  }
754  delete[] lut;
755  if (Count < FrameSize)
756  OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero
757  }
758  } else
759  Data = NULL;
760  }
761 
773  void sigmoid(const DiMonoPixel *inter,
774  const Uint32 start,
775  const DiLookupTable *plut,
776  DiDisplayFunction *disp,
777  const double center,
778  const double width,
779  const T3 low,
780  const T3 high)
781  {
782  const T1 *pixel = OFstatic_cast(const T1 *, inter->getData());
783  if (pixel != NULL)
784  {
785  if (Data == NULL)
786  Data = new T3[FrameSize]; // create new output buffer
787  if (Data != NULL)
788  {
789  DCMIMGLE_DEBUG("applying sigmoid VOI transformation with window center = " << center << ", width = " << width);
790  const DiDisplayLUT *dlut = NULL;
791  const double absmin = inter->getAbsMinimum();
792  const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range
793  const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries
794  register const T1 *p = pixel + start;
795  register T3 *q = Data;
796  register unsigned long i;
797  register double value;
798  T3 *lut = NULL;
799  if ((plut != NULL) && (plut->isValid())) // has presentation LUT
800  {
801  DCMIMGLE_DEBUG("applying presentation LUT transformation");
802  createDisplayLUT(dlut, disp, plut->getBits());
803  register Uint32 value2; // presentation LUT is always unsigned
804  const double plutcnt_1 = OFstatic_cast(double, plut->getCount() - 1);
805  const double plutmax_1 = OFstatic_cast(double, plut->getAbsMaxRange() - 1);
806  if (initOptimizationLUT(lut, ocnt))
807  { // use LUT for optimization
808  q = lut;
809  if (dlut != NULL) // perform display transformation
810  {
811  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #1");
812  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
813  const double offset = (low > high) ? maxvalue : 0;
814  const double gradient = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1);
815  for (i = 0; i < ocnt; ++i)
816  {
817  value = OFstatic_cast(double, i) + absmin;
818  value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width)));
819  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient)));
820  }
821  } else { // don't use display: invalid or absent
822  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #2");
823  const double gradient = outrange / plutmax_1;
824  for (i = 0; i < ocnt; ++i)
825  {
826  value = OFstatic_cast(double, i) + absmin;
827  value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width)));
828  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient);
829  }
830  }
831  const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry
832  q = Data;
833  for (i = Count; i != 0; --i) // apply LUT
834  *(q++) = *(lut0 + (*(p++)));
835  }
836  if (lut == NULL) // use "normal" transformation
837  {
838  if (dlut != NULL) // perform display transformation
839  {
840  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #3");
841  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
842  const double offset = (low > high) ? maxvalue : 0;
843  const double gradient = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1);
844  for (i = Count; i != 0; --i)
845  {
846  value = OFstatic_cast(double, *(p++));
847  value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width)));
848  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient)));
849  }
850  } else { // don't use display: invalid or absent
851  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #4");
852  const double gradient = outrange / plutmax_1;
853  for (i = Count; i != 0; --i)
854  {
855  value = OFstatic_cast(double, *(p++));
856  value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width)));
857  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient);
858  }
859  }
860  }
861  } else { // has no presentation LUT
862  createDisplayLUT(dlut, disp, bitsof(T1));
863  if (initOptimizationLUT(lut, ocnt))
864  { // use LUT for optimization
865  q = lut;
866  if (dlut != NULL) // perform display transformation
867  {
868  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #5");
869  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
870  const double outrange2 = (low > high) ? -maxvalue : maxvalue;
871  const double offset = (low > high) ? maxvalue : 0;
872  for (i = 0; i < ocnt; ++i) // calculating LUT entries
873  {
874  value = OFstatic_cast(double, i) + absmin;
875  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + outrange2 / (1 + exp(-4 * (value - center) / width)))));
876  }
877  } else { // don't use display: invalid or absent
878  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #6");
879  for (i = 0; i < ocnt; ++i) // calculating LUT entries
880  {
881  value = OFstatic_cast(double, i) + absmin;
882  *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width)));
883  }
884  }
885  const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry
886  q = Data;
887  for (i = Count; i != 0; --i) // apply LUT
888  *(q++) = *(lut0 + (*(p++)));
889  }
890  if (lut == NULL) // use "normal" transformation
891  {
892  if (dlut != NULL) // perform display transformation
893  {
894  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #7");
895  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
896  const double outrange2 = (low > high) ? -maxvalue : maxvalue;
897  const double offset = (low > high) ? maxvalue : 0;
898  for (i = Count; i != 0; --i)
899  {
900  value = OFstatic_cast(double, *(p++));
901  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + outrange2 / (1 + exp(-4 * (value - center) / width)))));
902  }
903  } else { // don't use display: invalid or absent
904  DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #8");
905  for (i = Count; i != 0; --i)
906  {
907  value = OFstatic_cast(double, *(p++));
908  *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width)));
909  }
910  }
911  }
912  }
913  delete[] lut;
914  if (Count < FrameSize)
915  OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero
916  }
917  } else
918  Data = NULL;
919  }
920 
932  void window(const DiMonoPixel *inter,
933  const Uint32 start,
934  const DiLookupTable *plut,
935  DiDisplayFunction *disp,
936  const double center,
937  const double width,
938  const T3 low,
939  const T3 high)
940  {
941  const T1 *pixel = OFstatic_cast(const T1 *, inter->getData());
942  if (pixel != NULL)
943  {
944  if (Data == NULL)
945  Data = new T3[FrameSize]; // create new output buffer
946  if (Data != NULL)
947  {
948  DCMIMGLE_DEBUG("applying linear VOI transformation with window center = " << center << ", width = " << width);
949  const DiDisplayLUT *dlut = NULL;
950  const double absmin = inter->getAbsMinimum();
951  const double width_1 = width - 1;
952  const double leftBorder = center - 0.5 - width_1 / 2; // window borders, according to supplement 33
953  const double rightBorder = center - 0.5 + width_1 / 2;
954  const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range
955  const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries
956  register const T1 *p = pixel + start;
957  register T3 *q = Data;
958  register unsigned long i;
959  register double value;
960  T3 *lut = NULL;
961  if ((plut != NULL) && (plut->isValid())) // has presentation LUT
962  {
963  DCMIMGLE_DEBUG("applying presentation LUT transformation");
964  createDisplayLUT(dlut, disp, plut->getBits());
965  register Uint32 value2; // presentation LUT is always unsigned
966  const Uint32 pcnt = plut->getCount();
967  const double plutmax_1 = OFstatic_cast(double, plut->getAbsMaxRange()) - 1;
968  const double gradient1 = (width_1 == 0) ? 0 : OFstatic_cast(double, pcnt - 1) / width_1;
969  if (initOptimizationLUT(lut, ocnt))
970  { // use LUT for optimization
971  q = lut;
972  if (dlut != NULL) // perform display transformation
973  {
974  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #1");
975  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
976  const double offset = (low > high) ? maxvalue : 0;
977  const double gradient2 = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1);
978  for (i = 0; i < ocnt; ++i)
979  {
980  value = OFstatic_cast(double, i) + absmin; // pixel value
981  if (value <= leftBorder)
982  value2 = 0; // first LUT index
983  else if (value > rightBorder)
984  value2 = pcnt - 1; // last LUT index
985  else
986  value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1);
987  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient2)));
988  }
989  } else { // don't use display: invalid or absent
990  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #2");
991  const double gradient2 = outrange / plutmax_1;
992  for (i = 0; i < ocnt; ++i)
993  {
994  value = OFstatic_cast(double, i) + absmin; // pixel value
995  if (value <= leftBorder)
996  value2 = 0; // first LUT index
997  else if (value > rightBorder)
998  value2 = pcnt - 1; // last LUT index
999  else
1000  value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1);
1001  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2);
1002  }
1003  }
1004  const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry
1005  q = Data;
1006  for (i = Count; i != 0; --i) // apply LUT
1007  *(q++) = *(lut0 + (*(p++)));
1008  }
1009  if (lut == NULL) // use "normal" transformation
1010  {
1011  if (dlut != NULL) // perform display transformation
1012  {
1013  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #3");
1014  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
1015  const double offset = (low > high) ? maxvalue : 0;
1016  const double gradient2 = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1);
1017  for (i = Count; i != 0; --i)
1018  {
1019  value = OFstatic_cast(double, *(p++)); // pixel value
1020  if (value <= leftBorder)
1021  value2 = 0; // first LUT index
1022  else if (value > rightBorder)
1023  value2 = pcnt - 1; // last LUT index
1024  else
1025  value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1);
1026  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient2)));
1027  }
1028  } else { // don't use display: invalid or absent
1029  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #4");
1030  const double gradient2 = outrange / plutmax_1;
1031  for (i = Count; i != 0; --i)
1032  {
1033  value = OFstatic_cast(double, *(p++)); // pixel value
1034  if (value <= leftBorder)
1035  value2 = 0; // first LUT index
1036  else if (value > rightBorder)
1037  value2 = pcnt - 1; // last LUT index
1038  else
1039  value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1);
1040  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2);
1041  }
1042  }
1043  }
1044  } else { // has no presentation LUT
1045  createDisplayLUT(dlut, disp, bitsof(T1));
1046  if (initOptimizationLUT(lut, ocnt))
1047  { // use LUT for optimization
1048  q = lut;
1049  if (dlut != NULL) // perform display transformation
1050  {
1051  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #5");
1052  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
1053  const double offset = (low > high) ? maxvalue : 0;
1054  const double gradient = (width_1 == 0) ? 0 : ((low > high) ? (-maxvalue / width_1) : (maxvalue / width_1));
1055  for (i = 0; i < ocnt; ++i) // calculating LUT entries
1056  {
1057  value = OFstatic_cast(double, i) + absmin - leftBorder;
1058  if (value < 0) // left border
1059  value = 0;
1060  else if (value > width_1) // right border
1061  value = width_1;
1062  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + value * gradient))); // calculate value
1063  }
1064  } else { // don't use display: invalid or absent
1065  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #6");
1066  const double offset = (width_1 == 0) ? 0 : (high - ((center - 0.5) / width_1 + 0.5) * outrange);
1067  const double gradient = (width_1 == 0) ? 0 : outrange / width_1;
1068  for (i = 0; i < ocnt; ++i) // calculating LUT entries
1069  {
1070  value = OFstatic_cast(double, i) + absmin;
1071  if (value <= leftBorder)
1072  *(q++) = low; // black/white
1073  else if (value > rightBorder)
1074  *(q++) = high; // white/black
1075  else
1076  *(q++) = OFstatic_cast(T3, offset + value * gradient); // gray value
1077  }
1078  }
1079  const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry
1080  q = Data;
1081  for (i = Count; i != 0; --i) // apply LUT
1082  *(q++) = *(lut0 + (*(p++)));
1083  }
1084  if (lut == NULL) // use "normal" transformation
1085  {
1086  if (dlut != NULL) // perform display transformation
1087  {
1088  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #7");
1089  const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1);
1090  const double offset = (low > high) ? maxvalue : 0;
1091  const double gradient = (width_1 == 0) ? 0 : ((low > high) ? (-maxvalue / width_1) : (maxvalue / width_1));
1092  for (i = Count; i != 0; --i) // calculating LUT entries
1093  {
1094  value = OFstatic_cast(double, *(p++)) - leftBorder;
1095  if (value < 0) // left border
1096  value = 0;
1097  else if (value > width_1) // right border
1098  value = width_1;
1099  *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + value * gradient))); // calculate value
1100  }
1101  } else { // don't use display: invalid or absent
1102  DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #8");
1103  const double offset = (width_1 == 0) ? 0 : (high - ((center - 0.5) / width_1 + 0.5) * outrange);
1104  const double gradient = (width_1 == 0) ? 0 : outrange / width_1;
1105  for (i = Count; i != 0; --i)
1106  {
1107  value = OFstatic_cast(double, *(p++));
1108  if (value <= leftBorder)
1109  *(q++) = low; // black/white
1110  else if (value > rightBorder)
1111  *(q++) = high; // white/black
1112  else
1113  *(q++) = OFstatic_cast(T3, offset + value * gradient); // gray value
1114  }
1115  }
1116  }
1117  }
1118  delete[] lut;
1119  if (Count < FrameSize)
1120  OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero
1121  }
1122  } else
1123  Data = NULL;
1124  }
1125 
1126 
1135  void overlay(DiOverlay *overlays[2],
1136  DiDisplayFunction *disp,
1137  const Uint16 columns,
1138  const Uint16 rows,
1139  const unsigned long frame)
1140  {
1141  if ((Data != NULL) && (overlays != NULL))
1142  {
1143  for (unsigned int j = 0; j < 2; ++j)
1144  {
1145  if (overlays[j] != NULL)
1146  {
1147  if (overlays[j]->getCount() > 0)
1148  DCMIMGLE_DEBUG("applying " << ((j == 0) ? "built-in" : "additional") << " overlay planes");
1149  const signed long left_pos = overlays[j]->getLeft();
1150  const signed long top_pos = overlays[j]->getTop();
1151  register DiOverlayPlane *plane;
1152  for (unsigned int i = 0; i < overlays[j]->getCount(); ++i)
1153  {
1154  plane = overlays[j]->getPlane(i);
1155  if ((plane != NULL) && plane->isVisible() && plane->reset(frame))
1156  {
1157  register T3 *q;
1158  register Uint16 x;
1159  register Uint16 y;
1160  const Uint16 xmin = (plane->getLeft(left_pos) > 0) ? plane->getLeft(left_pos) : 0;
1161  const Uint16 ymin = (plane->getTop(top_pos) > 0) ? plane->getTop(top_pos) : 0;
1162  const Uint16 xmax = (plane->getRight(left_pos) < columns) ? plane->getRight(left_pos) : columns;
1163  const Uint16 ymax = (plane->getBottom(top_pos) < rows) ? plane->getBottom(top_pos) : rows;
1164  const T3 maxvalue = OFstatic_cast(T3, DicomImageClass::maxval(bitsof(T3)));
1165  switch (plane->getMode())
1166  {
1167  case EMO_Replace:
1168  {
1169  DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'replace' mode");
1170  const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue);
1171  for (y = ymin; y < ymax; ++y)
1172  {
1173  plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y));
1174  q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin);
1175  for (x = xmin; x < xmax; ++x, ++q)
1176  {
1177  if (plane->getNextBit())
1178  *q = fore;
1179  }
1180  }
1181  break;
1182  }
1183  case EMO_ThresholdReplace:
1184  {
1185  DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'threshold replace' mode");
1186  const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue);
1187  const T3 thresh = OFstatic_cast(T3, plane->getThreshold() * maxvalue);
1188  for (y = ymin; y < ymax; ++y)
1189  {
1190  plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y));
1191  q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin);
1192  for (x = xmin; x < xmax; ++x, ++q)
1193  {
1194  if (plane->getNextBit())
1195  *q = (*q <= thresh) ? fore : 1;
1196  }
1197  }
1198  break;
1199  }
1200  case EMO_Complement:
1201  {
1202  DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'complement' mode");
1203  const T3 thresh = OFstatic_cast(T3, DicomImageClass::maxval(bitsof(T3) / 2));
1204  for (y = ymin; y < ymax; ++y)
1205  {
1206  plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y));
1207  q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin);
1208  for (x = xmin; x < xmax; ++x, ++q)
1209  {
1210  if (plane->getNextBit())
1211  *q = (*q <= thresh) ? maxvalue : 0;
1212  }
1213  }
1214  break;
1215  }
1216  case EMO_InvertBitmap:
1217  {
1218  DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'invert bitmap' mode");
1219  const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue);
1220  for (y = ymin; y < ymax; ++y)
1221  {
1222  plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y));
1223  q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin);
1224  for (x = xmin; x < xmax; ++x, ++q)
1225  {
1226  if (!plane->getNextBit())
1227  *q = fore;
1228  }
1229  }
1230  break;
1231  }
1232  case EMO_RegionOfInterest:
1233  {
1234  DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'region of interest' mode");
1235  const int dim = bitsof(T3) / 2;
1236  for (y = ymin; y < ymax; ++y)
1237  {
1238  plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y));
1239  q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin);
1240  for (x = xmin; x < xmax; ++x, ++q)
1241  {
1242  if (!plane->getNextBit())
1243  *q = *q >> dim;
1244  }
1245  }
1246  break;
1247  }
1248  case EMO_BitmapShutter:
1249  {
1250  DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'bitmap shutter' mode");
1251  register T3 fore = OFstatic_cast(T3, OFstatic_cast(double, maxvalue) * OFstatic_cast(double, plane->getPValue()) / OFstatic_cast(double, DicomImageClass::maxval(WIDTH_OF_PVALUES)));
1252  if ((disp != NULL) && (disp->isValid()))
1253  {
1254  const DiDisplayLUT *dlut = disp->getLookupTable(WIDTH_OF_PVALUES);
1255  if ((dlut != NULL) && (dlut->isValid()))
1256  fore = OFstatic_cast(T3, dlut->getValue(plane->getPValue()));
1257  }
1258  for (y = ymin; y < ymax; ++y)
1259  {
1260  plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y));
1261  q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin);
1262  for (x = xmin; x < xmax; ++x, ++q)
1263  {
1264  if (plane->getNextBit())
1265  *q = fore;
1266  }
1267  }
1268  break;
1269  }
1270  default: /* e.g. EMO_Default */
1271  DCMIMGLE_WARN("unhandled overlay mode (" << OFstatic_cast(int, plane->getMode()) << ")");
1272  }
1273  }
1274  }
1275  }
1276  }
1277  }
1278  }
1279 
1280 
1282  T3 *Data;
1285 
1286 #ifdef PASTEL_COLOR_OUTPUT
1287  DiMonoColorOutputPixelTemplate<T1, T3> *ColorData;
1288 #else
1289  // dummy variable
1290  DiMonoOutputPixel *ColorData;
1291 #endif
1292 
1293  // --- declarations to avoid compiler warnings
1294 
1297 };
1298 
1299 
1300 #endif
1301 
1302 
1303 /*
1304  *
1305  * CVS/RCS Log:
1306  * $Log: dimoopxt.h,v $
1307  * Revision 1.54 2010-10-28 10:58:38 joergr
1308  * Implemented missing rendering code for sigmoid VOI LUT function.
1309  * Added more trace log messages which might be helpful for detailed debugging.
1310  *
1311  * Revision 1.53 2010-10-14 13:16:26 joergr
1312  * Updated copyright header. Added reference to COPYRIGHT file.
1313  *
1314  * Revision 1.52 2010-10-05 15:25:10 joergr
1315  * Added preliminary support for VOI LUT function. Please note, however, that
1316  * the sigmoid transformation is not yet implemented.
1317  * In debug mode, output more details on overlay plane to the logger.
1318  *
1319  * Revision 1.51 2010-03-01 09:08:47 uli
1320  * Removed some unnecessary include directives in the headers.
1321  *
1322  * Revision 1.50 2009-11-25 16:08:26 joergr
1323  * Removed inclusion of header file "ofconsol.h".
1324  * Revised logging messages. Added more logging messages.
1325  *
1326  * Revision 1.49 2009-10-28 14:38:16 joergr
1327  * Fixed minor issues in log output.
1328  *
1329  * Revision 1.48 2009-10-28 09:53:40 uli
1330  * Switched to logging mechanism provided by the "new" oflog module.
1331  *
1332  * Revision 1.47 2006-08-15 16:30:11 meichel
1333  * Updated the code in module dcmimgle to correctly compile when
1334  * all standard C++ classes remain in namespace std.
1335  *
1336  * Revision 1.46 2005/12/08 16:47:54 meichel
1337  * Changed include path schema for all DCMTK header files
1338  *
1339  * Revision 1.45 2005/03/09 17:30:42 joergr
1340  * Added support for new overlay mode "invert bitmap".
1341  *
1342  * Revision 1.44 2004/02/06 11:07:50 joergr
1343  * Distinguish more clearly between const and non-const access to pixel data.
1344  *
1345  * Revision 1.43 2003/12/23 15:53:22 joergr
1346  * Replaced post-increment/decrement operators by pre-increment/decrement
1347  * operators where appropriate (e.g. 'i++' by '++i').
1348  *
1349  * Revision 1.42 2003/12/23 10:51:52 joergr
1350  * Updated documentation to get rid of doxygen warnings.
1351  *
1352  * Revision 1.41 2003/12/09 16:49:11 joergr
1353  * Adapted type casts to new-style typecast operators defined in ofcast.h.
1354  * Removed leading underscore characters from preprocessor symbols (reserved
1355  * symbols). Updated copyright header.
1356  *
1357  * Revision 1.40 2003/06/12 15:08:34 joergr
1358  * Fixed inconsistent API documentation reported by Doxygen.
1359  *
1360  * Revision 1.39 2002/12/09 13:32:53 joergr
1361  * Renamed parameter/local variable to avoid name clashes with global
1362  * declaration left and/or right (used for as iostream manipulators).
1363  *
1364  * Revision 1.38 2002/11/27 14:08:06 meichel
1365  * Adapted module dcmimgle to use of new header file ofstdinc.h
1366  *
1367  * Revision 1.37 2002/06/19 08:12:01 meichel
1368  * Added typecasts to avoid ambiguity with built-in functions on gcc 3.2
1369  *
1370  * Revision 1.36 2001/06/01 15:49:46 meichel
1371  * Updated copyright header
1372  *
1373  * Revision 1.35 2000/05/03 09:46:28 joergr
1374  * Removed most informational and some warning messages from release built
1375  * (#ifndef DEBUG).
1376  *
1377  * Revision 1.34 2000/04/28 12:32:31 joergr
1378  * DebugLevel - global for the module - now derived from OFGlobal (MF-safe).
1379  *
1380  * Revision 1.33 2000/04/27 13:08:40 joergr
1381  * Dcmimgle library code now consistently uses ofConsole for error output.
1382  *
1383  * Revision 1.32 2000/03/08 16:24:20 meichel
1384  * Updated copyright header.
1385  *
1386  * Revision 1.31 2000/03/07 16:15:12 joergr
1387  * Added explicit type casts to make Sun CC 2.0.1 happy.
1388  *
1389  * Revision 1.30 2000/03/06 18:19:36 joergr
1390  * Moved get-method to base class, renamed method and made method virtual to
1391  * avoid hiding of methods (reported by Sun CC 4.2).
1392  *
1393  * Revision 1.29 2000/03/03 14:09:13 meichel
1394  * Implemented library support for redirecting error messages into memory
1395  * instead of printing them to stdout/stderr for GUI applications.
1396  *
1397  * Revision 1.28 2000/02/01 10:52:37 meichel
1398  * Avoiding to include <stdlib.h> as extern "C" on Borland C++ Builder 4,
1399  * workaround for bug in compiler header files.
1400  *
1401  * Revision 1.27 1999/10/11 20:14:14 joergr
1402  * Fixed bug in window() routine for cases where presentation LUT is active.
1403  *
1404  * Revision 1.26 1999/10/06 13:42:03 joergr
1405  * Added method to remove reference to (internally handled) pixel data.
1406  *
1407  * Revision 1.25 1999/09/17 12:40:45 joergr
1408  * Added/changed/completed DOC++ style comments in the header files.
1409  * Enhanced efficiency of some "for" loops.
1410  *
1411  * Revision 1.24 1999/09/10 08:45:19 joergr
1412  * Added support for CIELAB display function.
1413  *
1414  * Revision 1.23 1999/08/25 16:41:53 joergr
1415  * Added new feature: Allow clipping region to be outside the image
1416  * (overlapping).
1417  *
1418  * Revision 1.22 1999/08/17 10:26:08 joergr
1419  * Commented unused parameter names to avoid compiler warnings.
1420  *
1421  * Revision 1.21 1999/07/23 14:08:44 joergr
1422  * Changed implementation/interpretation of windows center/width (according to
1423  * new letter ballot of supplement 33).
1424  * Enhanced handling of corrupted pixel data (wrong length).
1425  *
1426  * Revision 1.20 1999/05/03 15:43:21 joergr
1427  * Replaced method applyOptimizationLUT by its contents (method body) to avoid
1428  * warnings (and possible errors) on Sun CC 2.0.1 :-/
1429  *
1430  * Revision 1.18 1999/04/30 16:10:50 meichel
1431  * Minor code purifications to keep IBM xlC quiet
1432  *
1433  * Revision 1.17 1999/04/29 16:46:46 meichel
1434  * Minor code purifications to keep DEC cxx 6 quiet.
1435  *
1436  * Revision 1.16 1999/04/29 09:38:34 joergr
1437  * Changed position of "#ifdef" to avoid compiler warnings.
1438  *
1439  * Revision 1.15 1999/04/29 09:20:01 joergr
1440  * Removed color related image files from public toolkit part.
1441  *
1442  * Revision 1.14 1999/04/28 18:56:07 joergr
1443  * Removed support for pastel color output from public DCMTK part.
1444  *
1445  * Revision 1.13 1999/04/28 14:51:44 joergr
1446  * Added experimental support to create grayscale images with more than 256
1447  * shades of gray to be displayed on a consumer monitor (use pastel colors).
1448  * Introduced new scheme for the debug level variable: now each level can be
1449  * set separately (there is no "include" relationship).
1450  *
1451  * Revision 1.12 1999/03/24 17:20:14 joergr
1452  * Added/Modified comments and formatting.
1453  *
1454  * Revision 1.11 1999/03/02 12:03:52 joergr
1455  * Corrected bug in output routine of monochrome pixel data (wrong scaling when
1456  * Barten transformation and windowing are active).
1457  *
1458  * Revision 1.10 1999/02/28 16:41:01 joergr
1459  * Corrected bug: the output bits for bitmaps shutters were inverted (this was
1460  * done due to an error in the used test images).
1461  *
1462  * Revision 1.9 1999/02/11 16:40:19 joergr
1463  * Added routine to check whether particular grayscale values are unused in
1464  * the output data.
1465  * Removed two small memory leaks reported by dmalloc library.
1466  *
1467  * Revision 1.8 1999/02/05 16:44:52 joergr
1468  * Corrected calculation of DDL value for bitmaps shutters (overlays).
1469  *
1470  * Revision 1.7 1999/02/05 15:13:36 joergr
1471  * Added conversion P-Value to DDL when display function is absent.
1472  *
1473  * Revision 1.6 1999/02/03 17:32:43 joergr
1474  * Added optimization LUT to transform pixel data.
1475  * Added support for calibration according to Barten transformation (incl.
1476  * a DISPLAY file describing the monitor characteristic).
1477  *
1478  * Revision 1.5 1999/01/20 15:11:05 joergr
1479  * Replaced invocation of getCount() by member variable Count where possible.
1480  * Added new output method to fill external memory buffer with rendered pixel
1481  * data.
1482  * Added new overlay plane mode for bitmap shutters.
1483  * Added optimization to modality and VOI transformation (using additional
1484  * LUTs).
1485  *
1486  * Revision 1.4 1998/12/23 12:40:01 joergr
1487  * Removed unused parameter (BitsPerSample).
1488  *
1489  * Revision 1.3 1998/12/22 14:32:49 joergr
1490  * Improved implementation of presentation LUT application (and other gray
1491  * scale transformations). Tested with ECR test images from David Clunie.
1492  *
1493  * Revision 1.2 1998/12/14 17:25:55 joergr
1494  * Added support for correct scaling of input/output values for grayscale
1495  * transformations.
1496  *
1497  * Revision 1.1 1998/11/27 15:29:53 joergr
1498  * Added copyright message.
1499  * Introduced global debug level for dcmimage module to control error output.
1500  * Corrected bug in VOI LUT transformation method.
1501  * Changed behaviour: now window width of 0 is valid and negative width
1502  * is invalid.
1503  *
1504  * Revision 1.6 1998/07/01 08:39:24 joergr
1505  * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional
1506  * options), e.g. add copy constructors.
1507  *
1508  * Revision 1.5 1998/05/11 14:53:22 joergr
1509  * Added CVS/RCS header to each file.
1510  *
1511  *
1512  */


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