OFFIS DCMTK  Version 3.6.0
dimoipxt.h
1 /*
2  *
3  * Copyright (C) 1996-2011, 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: DicomMonochromeInputPixelTemplate (Header)
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2011-11-17 16:13:16 $
22  * CVS/RCS Revision: $Revision: 1.41 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 
30 #ifndef DIMOIPXT_H
31 #define DIMOIPXT_H
32 
33 #include "dcmtk/config/osconfig.h"
34 
35 #include "dcmtk/ofstd/ofbmanip.h"
36 #include "dcmtk/ofstd/ofcast.h"
37 
38 #include "dcmtk/dcmimgle/dimopxt.h"
39 #include "dcmtk/dcmimgle/diinpx.h"
40 
41 
42 /*---------------------*
43  * class declaration *
44  *---------------------*/
45 
48 template<class T1, class T2, class T3>
50  : public DiMonoPixelTemplate<T3>
51 {
52 
53  public:
54 
61  DiMonoModality *modality)
62  : DiMonoPixelTemplate<T3>(pixel, modality)
63  {
64  /* erase empty part of the buffer (= blacken the background) */
65  if ((this->Data != NULL) && (this->InputCount < this->Count))
66  OFBitmanipTemplate<T3>::zeroMem(this->Data + this->InputCount, this->Count - this->InputCount);
67  if ((pixel != NULL) && (this->Count > 0))
68  {
69  // check whether to apply any modality transform
70  if ((this->Modality != NULL) && this->Modality->hasLookupTable() && (bitsof(T1) <= MAX_TABLE_ENTRY_SIZE))
71  {
72  modlut(pixel);
73  // ignore modality LUT min/max values since the image does not necessarily have to use all LUT entries
74  this->determineMinMax();
75  }
76  else if ((this->Modality != NULL) && this->Modality->hasRescaling())
77  {
78  rescale(pixel, this->Modality->getRescaleSlope(), this->Modality->getRescaleIntercept());
79  this->determineMinMax(OFstatic_cast(T3, this->Modality->getMinValue()), OFstatic_cast(T3, this->Modality->getMaxValue()));
80  } else {
81  rescale(pixel); // "copy" or reference pixel data
82  this->determineMinMax(OFstatic_cast(T3, this->Modality->getMinValue()), OFstatic_cast(T3, this->Modality->getMaxValue()));
83  }
84  }
85  }
86 
90  {
91  }
92 
93 
94  private:
95 
103  inline int initOptimizationLUT(T3 *&lut,
104  const unsigned long ocnt)
105  {
106  int result = 0;
107  if ((sizeof(T1) <= 2) && (this->InputCount > 3 * ocnt)) // optimization criteria
108  { // use LUT for optimization
109  lut = new T3[ocnt];
110  if (lut != NULL)
111  {
112  DCMIMGLE_DEBUG("using optimized routine with additional LUT");
113  result = 1;
114  }
115  }
116  return result;
117  }
118 
123  void modlut(DiInputPixel *input)
124  {
125  const T1 *pixel = OFstatic_cast(const T1 *, input->getData());
126  if ((pixel != NULL) && (this->Modality != NULL))
127  {
128  const DiLookupTable *mlut = this->Modality->getTableData();
129  if (mlut != NULL)
130  {
131  const int useInputBuffer = (sizeof(T1) == sizeof(T3)) && (this->Count <= input->getCount());
132  if (useInputBuffer) // do not copy pixel data, reference them!
133  {
134  DCMIMGLE_DEBUG("re-using input buffer, do not copy pixel data");
135  this->Data = OFstatic_cast(T3 *, input->getDataPtr());
136  input->removeDataReference(); // avoid double deletion
137  } else
138  this->Data = new T3[this->Count];
139  if (this->Data != NULL)
140  {
141  DCMIMGLE_DEBUG("applying modality tranformation with LUT (" << mlut->getCount() << " entries)");
142  register T2 value = 0;
143  const T2 firstentry = mlut->getFirstEntry(value); // choose signed/unsigned method
144  const T2 lastentry = mlut->getLastEntry(value);
145  const T3 firstvalue = OFstatic_cast(T3, mlut->getFirstValue());
146  const T3 lastvalue = OFstatic_cast(T3, mlut->getLastValue());
147  register const T1 *p = pixel + input->getPixelStart();
148  register T3 *q = this->Data;
149  register unsigned long i;
150  T3 *lut = NULL;
151  const unsigned long ocnt = OFstatic_cast(unsigned long, input->getAbsMaxRange()); // number of LUT entries
152  if (initOptimizationLUT(lut, ocnt))
153  { // use LUT for optimization
154  const T2 absmin = OFstatic_cast(T2, input->getAbsMinimum());
155  q = lut;
156  for (i = 0; i < ocnt; ++i) // calculating LUT entries
157  {
158  value = OFstatic_cast(T2, i) + absmin;
159  if (value <= firstentry)
160  *(q++) = firstvalue;
161  else if (value >= lastentry)
162  *(q++) = lastvalue;
163  else
164  *(q++) = OFstatic_cast(T3, mlut->getValue(value));
165  }
166  const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry
167  q = this->Data;
168  for (i = this->InputCount; i != 0; --i) // apply LUT
169  *(q++) = *(lut0 + (*(p++)));
170  }
171  if (lut == NULL) // use "normal" transformation
172  {
173  for (i = this->InputCount; i != 0; --i)
174  {
175  value = OFstatic_cast(T2, *(p++));
176  if (value <= firstentry)
177  *(q++) = firstvalue;
178  else if (value >= lastentry)
179  *(q++) = lastvalue;
180  else
181  *(q++) = OFstatic_cast(T3, mlut->getValue(value));
182  }
183  }
184  delete[] lut;
185  }
186  }
187  }
188  }
189 
196  void rescale(DiInputPixel *input,
197  const double slope = 1.0,
198  const double intercept = 0.0)
199  {
200  const T1 *pixel = OFstatic_cast(const T1 *, input->getData());
201  if (pixel != NULL)
202  {
203  const int useInputBuffer = (sizeof(T1) == sizeof(T3)) && (this->Count <= input->getCount()) && (input->getPixelStart() == 0);
204  if (useInputBuffer)
205  { // do not copy pixel data, reference them!
206  DCMIMGLE_DEBUG("re-using input buffer, do not copy pixel data");
207  this->Data = OFstatic_cast(T3 *, input->getDataPtr());
208  input->removeDataReference(); // avoid double deletion
209  } else
210  this->Data = new T3[this->Count];
211  if (this->Data != NULL)
212  {
213  register T3 *q = this->Data;
214  register unsigned long i;
215  if ((slope == 1.0) && (intercept == 0.0))
216  {
217  if (!useInputBuffer)
218  {
219  register const T1 *p = pixel + input->getPixelStart();
220  for (i = this->InputCount; i != 0; --i) // copy pixel data: can't use copyMem because T1 isn't always equal to T3
221  *(q++) = OFstatic_cast(T3, *(p++));
222  }
223  } else {
224  DCMIMGLE_DEBUG("applying modality transformation with rescale slope = " << slope << ", intercept = " << intercept);
225  T3 *lut = NULL;
226  register const T1 *p = pixel + input->getPixelStart();
227  const unsigned long ocnt = OFstatic_cast(unsigned long, input->getAbsMaxRange()); // number of LUT entries
228  if (initOptimizationLUT(lut, ocnt))
229  { // use LUT for optimization
230  const double absmin = input->getAbsMinimum();
231  q = lut;
232  if (slope == 1.0)
233  {
234  for (i = 0; i < ocnt; ++i) // calculating LUT entries
235  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, i) + absmin + intercept);
236  } else {
237  if (intercept == 0.0)
238  {
239  for (i = 0; i < ocnt; ++i)
240  *(q++) = OFstatic_cast(T3, (OFstatic_cast(double, i) + absmin) * slope);
241  } else {
242  for (i = 0; i < ocnt; ++i)
243  *(q++) = OFstatic_cast(T3, (OFstatic_cast(double, i) + absmin) * slope + intercept);
244  }
245  }
246  const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry
247  q = this->Data;
248  for (i = this->InputCount; i != 0; --i) // apply LUT
249  *(q++) = *(lut0 + (*(p++)));
250  }
251  if (lut == NULL) // use "normal" transformation
252  {
253  if (slope == 1.0)
254  {
255  for (i = this->InputCount; i != 0; --i)
256  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, *(p++)) + intercept);
257  } else {
258  if (intercept == 0.0)
259  {
260  for (i = this->InputCount; i != 0; --i)
261  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, *(p++)) * slope);
262  } else {
263  for (i = this->InputCount; i != 0; --i)
264  *(q++) = OFstatic_cast(T3, OFstatic_cast(double, *(p++)) * slope + intercept);
265  }
266  }
267  }
268  delete[] lut;
269  }
270  }
271  }
272  }
273 };
274 
275 
276 #endif
277 
278 
279 /*
280  *
281  * CVS/RCS Log:
282  * $Log: dimoipxt.h,v $
283  * Revision 1.41 2011-11-17 16:13:16 joergr
284  * Minor fixes to keep XCode 4.2 on Mac OS X Lion (clang compiler) quiet.
285  *
286  * Revision 1.40 2010-10-14 13:16:26 joergr
287  * Updated copyright header. Added reference to COPYRIGHT file.
288  *
289  * Revision 1.39 2010-03-01 09:08:47 uli
290  * Removed some unnecessary include directives in the headers.
291  *
292  * Revision 1.38 2009-11-25 16:07:12 joergr
293  * Removed inclusion of header file "ofconsol.h". Revised logging messages.
294  *
295  * Revision 1.37 2009-10-28 14:38:16 joergr
296  * Fixed minor issues in log output.
297  *
298  * Revision 1.36 2009-10-28 09:53:40 uli
299  * Switched to logging mechanism provided by the "new" oflog module.
300  *
301  * Revision 1.35 2008-04-09 11:02:08 joergr
302  * Fixed wrong use of variable in "for" loop which might cause a crash.
303  *
304  * Revision 1.34 2006/08/15 16:30:11 meichel
305  * Updated the code in module dcmimgle to correctly compile when
306  * all standard C++ classes remain in namespace std.
307  *
308  * Revision 1.33 2005/12/08 16:47:51 meichel
309  * Changed include path schema for all DCMTK header files
310  *
311  * Revision 1.32 2004/04/21 10:00:36 meichel
312  * Minor modifications for compilation with gcc 3.4.0
313  *
314  * Revision 1.31 2004/02/06 11:07:50 joergr
315  * Distinguish more clearly between const and non-const access to pixel data.
316  *
317  * Revision 1.30 2004/01/05 14:52:20 joergr
318  * Removed acknowledgements with e-mail addresses from CVS log.
319  *
320  * Revision 1.29 2003/12/23 15:53:22 joergr
321  * Replaced post-increment/decrement operators by pre-increment/decrement
322  * operators where appropriate (e.g. 'i++' by '++i').
323  *
324  * Revision 1.28 2003/12/08 19:13:54 joergr
325  * Adapted type casts to new-style typecast operators defined in ofcast.h.
326  * Removed leading underscore characters from preprocessor symbols (reserved
327  * symbols). Updated CVS header.
328  *
329  * Revision 1.27 2003/06/12 15:08:34 joergr
330  * Fixed inconsistent API documentation reported by Doxygen.
331  *
332  * Revision 1.26 2003/06/02 17:06:21 joergr
333  * Fixed bug in optimization criterion which caused dcmimgle to ignore the
334  * "start frame" parameter in the DicomImage constructors under certain
335  * circumstances.
336  *
337  * Revision 1.25 2002/10/21 10:13:51 joergr
338  * Corrected wrong calculation of min/max pixel value in cases where the
339  * stored pixel data exceeds the expected size.
340  *
341  * Revision 1.24 2002/06/26 16:05:43 joergr
342  * Enhanced handling of corrupted pixel data and/or length.
343  *
344  * Revision 1.23 2001/11/13 18:10:43 joergr
345  * Fixed bug occurring when processing monochrome images with an odd number of
346  * pixels.
347  * Fixed bug with incorrect calculation of min/max pixel values in images with
348  * modality LUTs where not all LUT entries are used (previous optimization rule
349  * was apparently too optimistic).
350  *
351  * Revision 1.22 2001/09/28 13:07:12 joergr
352  * Added further robustness checks.
353  *
354  * Revision 1.21 2001/06/01 15:49:45 meichel
355  * Updated copyright header
356  *
357  * Revision 1.20 2000/06/02 12:40:50 joergr
358  * Removed debug message.
359  *
360  * Revision 1.19 2000/05/03 09:46:28 joergr
361  * Removed most informational and some warning messages from release built
362  * (#ifndef DEBUG).
363  *
364  * Revision 1.18 2000/04/28 12:32:31 joergr
365  * DebugLevel - global for the module - now derived from OFGlobal (MF-safe).
366  *
367  * Revision 1.17 2000/04/27 13:08:39 joergr
368  * Dcmimgle library code now consistently uses ofConsole for error output.
369  *
370  * Revision 1.16 2000/03/08 16:24:19 meichel
371  * Updated copyright header.
372  *
373  * Revision 1.15 2000/03/03 14:09:12 meichel
374  * Implemented library support for redirecting error messages into memory
375  * instead of printing them to stdout/stderr for GUI applications.
376  *
377  * Revision 1.14 1999/09/17 12:26:00 joergr
378  * Added/changed/completed DOC++ style comments in the header files.
379  * iEnhanced efficiency of some "for" loops.
380  *
381  * Revision 1.13 1999/07/23 14:04:35 joergr
382  * Optimized memory usage for converting input pixel data (reference instead
383  * of copying where possible).
384  *
385  * Revision 1.12 1999/05/03 15:43:20 joergr
386  * Replaced method applyOptimizationLUT by its contents (method body) to avoid
387  * warnings (and possible errors) on Sun CC 2.0.1 :-/
388  *
389  * Revision 1.11 1999/05/03 11:09:29 joergr
390  * Minor code purifications to keep Sun CC 2.0.1 quiet.
391  *
392  * Revision 1.10 1999/04/29 16:46:45 meichel
393  * Minor code purifications to keep DEC cxx 6 quiet.
394  *
395  * Revision 1.9 1999/04/28 14:50:35 joergr
396  * Introduced new scheme for the debug level variable: now each level can be
397  * set separately (there is no "include" relationship).
398  *
399  * Revision 1.8 1999/03/24 17:20:10 joergr
400  * Added/Modified comments and formatting.
401  *
402  * Revision 1.7 1999/03/02 12:02:27 joergr
403  * Corrected bug: when determining minimum and maximum pixel value (external)
404  * modality LUTs were ignored.
405  *
406  * Revision 1.6 1999/02/11 16:37:10 joergr
407  * Removed inline declarations from several methods.
408  *
409  * Revision 1.5 1999/02/03 17:29:19 joergr
410  * Added optimization LUT to transform pixel data.
411  *
412  * Revision 1.4 1999/01/20 15:06:24 joergr
413  * Replaced invocation of getCount() by member variable Count where possible.
414  * Added optimization to modality and VOI transformation (using additional
415  * LUTs).
416  *
417  * Revision 1.3 1998/12/22 14:29:39 joergr
418  * Replaced method copyMem by for-loop copying each item.
419  * Renamed some variables
420  *
421  * Revision 1.2 1998/12/14 17:21:09 joergr
422  * Added support for signed values as second entry in look-up tables
423  * (= first value mapped).
424  *
425  * Revision 1.1 1998/11/27 15:24:08 joergr
426  * Added copyright message.
427  * Added new cases to optimize rescaling.
428  * Added support for new bit manipulation class.
429  * Corrected bug in modality LUT transformation method.
430  *
431  * Revision 1.5 1998/07/01 08:39:23 joergr
432  * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional
433  * options), e.g. add copy constructors.
434  *
435  * Revision 1.4 1998/05/11 14:53:21 joergr
436  * Added CVS/RCS header to each file.
437  *
438  *
439  */


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