OFFIS DCMTK  Version 3.6.0
dicoopxt.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: DicomColorOutputPixelTemplate (Header)
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2010-10-14 13:16:29 $
22  * CVS/RCS Revision: $Revision: 1.28 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 
30 #ifndef DICOOPXT_H
31 #define DICOOPXT_H
32 
33 #include "dcmtk/config/osconfig.h"
34 
35 #include "dcmtk/dcmimage/dicoopx.h"
36 #include "dcmtk/dcmimage/dicopx.h"
37 #include "dcmtk/dcmimgle/dipxrept.h"
38 
39 #include "dcmtk/ofstd/ofbmanip.h"
40 
41 
42 /*---------------------*
43  * class declaration *
44  *---------------------*/
45 
48 template<class T1, class T2>
50  : public DiColorOutputPixel,
52 {
53 
54  public:
55 
68  const DiColorPixel *pixel,
69  const unsigned long count,
70  const unsigned long frame,
71  const int bits1, /* input depth */
72  const int bits2, /* output depth */
73  const int planar,
74  const int inverse)
75  : DiColorOutputPixel(pixel, count, frame),
76  Data(NULL),
77  DeleteData(buffer == NULL),
78  isPlanar(planar)
79  {
80  if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
81  {
82  Data = OFstatic_cast(T2 *, buffer);
83  convert(OFstatic_cast(const T1 **, OFconst_cast(void *, pixel->getData())), frame * FrameSize, bits1, bits2, planar, inverse);
84  }
85  }
86 
97  const DiPixel *pixel,
98  const unsigned long count,
99  const unsigned long frame,
100  const unsigned long /*frames*/,
101  const int planar)
102  : DiColorOutputPixel(pixel, count, frame),
103  Data(NULL),
104  DeleteData(buffer == NULL),
105  isPlanar(planar)
106  {
107  if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
108  Data = OFstatic_cast(T2 *, buffer);
109  }
110 
114  {
115  if (DeleteData)
116  delete[] Data;
117  }
118 
123  inline EP_Representation getRepresentation() const
124  {
126  }
127 
132  inline size_t getItemSize() const
133  {
134  return sizeof(T2) * 3;
135  }
136 
141  inline const void *getData() const
142  {
143  return OFstatic_cast(const void *, Data);
144  }
145 
150  virtual void *getDataPtr()
151  {
152  return OFstatic_cast(void *, Data);
153  }
154 
161  inline const void *getPlane(const int plane) const
162  {
163  void *result = NULL;
164  if (Data != NULL)
165  {
166  if (plane <= 0)
167  result = OFstatic_cast(void *, Data);
168  else
169  {
170  if (isPlanar)
171  result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2) * FrameSize);
172  else
173  result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2));
174  }
175  }
176  return result;
177  }
178 
185  int writePPM(STD_NAMESPACE ostream& stream) const
186  {
187  if (Data != NULL)
188  {
189  register T2 *p = Data;
190  register unsigned long i;
191  register int j;
192  for (i = FrameSize; i != 0; --i)
193  for (j = 3; j != 0; --j)
194  stream << OFstatic_cast(unsigned long, *(p++)) << " "; // typecast to resolve problems with 'char'
195  return 1;
196  }
197  return 0;
198  }
199 
206  int writePPM(FILE *stream) const
207  {
208  if (Data != NULL)
209  {
210  register T2 *p = Data;
211  register unsigned long i;
212  register int j;
213  for (i = FrameSize; i != 0; --i)
214  for (j = 3; j != 0; --j)
215  fprintf(stream, "%lu ", OFstatic_cast(unsigned long, *(p++)));
216  return 1;
217  }
218  return 0;
219  }
220 
221 
222  protected:
223 
225  T2 *Data;
226 
227 
228  private:
229 
239  void convert(const T1 *pixel[3],
240  const unsigned long start,
241  const int bits1,
242  const int bits2,
243  const int planar,
244  const int inverse)
245  {
246  if ((pixel[0] != NULL) && (pixel[1] != NULL) && (pixel[2] != NULL))
247  {
248  if (Data == NULL)
249  Data = new T2[FrameSize * 3];
250  if (Data != NULL)
251  {
252  DCMIMAGE_DEBUG("converting color pixel data to output format");
253  register T2 *q = Data;
254  register unsigned long i;
255  const T2 max2 = OFstatic_cast(T2, DicomImageClass::maxval(bits2));
256  if (planar)
257  {
258  register const T1 *p;
259  if (bits1 == bits2)
260  {
261  for (int j = 0; j < 3; ++j)
262  {
263  p = pixel[j] + start;
264  /* invert output data */
265  if (inverse)
266  {
267  for (i = Count; i != 0; --i) // copy inverted data
268  *(q++) = max2 - OFstatic_cast(T2, *(p++));
269  } else {
270  for (i = Count; i != 0; --i) // copy
271  *(q++) = OFstatic_cast(T2, *(p++));
272  }
273  if (Count < FrameSize)
274  {
275  OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero
276  q += (FrameSize - Count);
277  }
278  }
279  }
280  else if (bits1 < bits2) // optimization possible using LUT
281  {
282  const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) /
283  OFstatic_cast(double, DicomImageClass::maxval(bits1));
284  const T2 gradient2 = OFstatic_cast(T2, gradient1);
285  for (int j = 0; j < 3; ++j)
286  {
287  p = pixel[j] + start;
288  if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
289  {
290  /* invert output data */
291  if (inverse)
292  {
293  for (i = Count; i != 0; --i) // expand depth & invert
294  *(q++) = max2 - OFstatic_cast(T2, *(p++)) * gradient2;
295  } else {
296  for (i = Count; i != 0; --i) // expand depth
297  *(q++) = OFstatic_cast(T2, *(p++)) * gradient2;
298  }
299  } else {
300  /* invert output data */
301  if (inverse)
302  {
303  for (i = Count; i != 0; --i) // expand depth & invert
304  *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1);
305  } else {
306  for (i = Count; i != 0; --i) // expand depth
307  *(q++) = OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1);
308  }
309  }
310  if (Count < FrameSize)
311  {
312  OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero
313  q += (FrameSize - Count);
314  }
315  } // ... to be enhanced !
316  }
317  else /* bits1 > bits2 */
318  {
319  const int shift = bits1 - bits2;
320  for (int j = 0; j < 3; ++j)
321  {
322  p = pixel[j] + start;
323  /* invert output data */
324  if (inverse)
325  {
326  for (i = Count; i != 0; --i) // reduce depth & invert
327  *(q++) = max2 - OFstatic_cast(T2, *(p++) >> shift);
328  } else {
329  for (i = Count; i != 0; --i) // reduce depth
330  *(q++) = OFstatic_cast(T2, *(p++) >> shift);
331  }
332  if (Count < FrameSize)
333  {
334  OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero
335  q += (FrameSize - Count);
336  }
337  }
338  }
339  }
340  else /* not planar */
341  {
342  register int j;
343  if (bits1 == bits2)
344  {
345  /* invert output data */
346  if (inverse)
347  {
348  for (i = start; i < start + Count; ++i)
349  for (j = 0; j < 3; ++j) // copy inverted data
350  *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]);
351  } else {
352  for (i = start; i < start + Count; ++i)
353  for (j = 0; j < 3; ++j) // copy
354  *(q++) = OFstatic_cast(T2, pixel[j][i]);
355  }
356  }
357  else if (bits1 < bits2) // optimization possible using LUT
358  {
359  const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) /
360  OFstatic_cast(double, DicomImageClass::maxval(bits1));
361  const T2 gradient2 = OFstatic_cast(T2, gradient1);
362  if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
363  {
364  /* invert output data */
365  if (inverse)
366  {
367  for (i = start; i < start + Count; ++i) // expand depth & invert
368  for (j = 0; j < 3; ++j)
369  *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]) * gradient2;
370  } else {
371  for (i = start; i < start + Count; ++i)
372  for (j = 0; j < 3; ++j) // expand depth
373  *(q++) = OFstatic_cast(T2, pixel[j][i]) * gradient2;
374  }
375  } else {
376  /* invert output data */
377  if (inverse)
378  {
379  for (i = start; i < start + Count; ++i)
380  for (j = 0; j < 3; ++j) // expand depth & invert
381  *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1);
382  } else {
383  for (i = start; i < start + Count; ++i)
384  for (j = 0; j < 3; ++j) // expand depth
385  *(q++) = OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1);
386  }
387  }
388  }
389  else /* bits1 > bits2 */
390  {
391  const int shift = bits1 - bits2;
392  /* invert output data */
393  if (inverse)
394  {
395  for (i = start; i < start + Count; ++i)
396  for (j = 0; j < 3; ++j) // reduce depth & invert
397  *(q++) = max2 - OFstatic_cast(T2, pixel[j][i] >> shift);
398  } else {
399  for (i = start; i < start + Count; ++i)
400  for (j = 0; j < 3; ++j) // reduce depth
401  *(q++) = OFstatic_cast(T2, pixel[j][i] >> shift);
402  }
403  }
404  if (Count < FrameSize)
405  OFBitmanipTemplate<T2>::zeroMem(q, 3 * (FrameSize - Count)); // set remaining pixels of frame to zero
406  }
407  }
408  } else
409  Data = NULL;
410  }
411 
415  int isPlanar;
416 
417  // --- declarations to avoid compiler warnings
418 
421 };
422 
423 
424 #endif
425 
426 
427 /*
428  *
429  * CVS/RCS Log:
430  * $Log: dicoopxt.h,v $
431  * Revision 1.28 2010-10-14 13:16:29 joergr
432  * Updated copyright header. Added reference to COPYRIGHT file.
433  *
434  * Revision 1.27 2010-10-05 15:34:41 joergr
435  * Output information on conversion process to the logger (debug mode).
436  * Fixed various Doxygen API documentation issues.
437  *
438  * Revision 1.26 2010-03-01 09:08:46 uli
439  * Removed some unnecessary include directives in the headers.
440  *
441  * Revision 1.25 2006-08-15 16:35:01 meichel
442  * Updated the code in module dcmimage to correctly compile when
443  * all standard C++ classes remain in namespace std.
444  *
445  * Revision 1.24 2005/12/08 16:01:33 meichel
446  * Changed include path schema for all DCMTK header files
447  *
448  * Revision 1.23 2004/02/06 11:18:18 joergr
449  * Distinguish more clearly between const and non-const access to pixel data.
450  *
451  * Revision 1.22 2003/12/23 16:06:21 joergr
452  * Replaced additional post-increment/decrement operators by pre-increment/
453  * decrement operators.
454  *
455  * Revision 1.21 2003/12/23 11:36:24 joergr
456  * Adapted type casts to new-style typecast operators defined in ofcast.h.
457  * Removed leading underscore characters from preprocessor symbols (reserved
458  * symbols). Updated copyright header.
459  * Replaced post-increment/decrement operators by pre-increment/decrement
460  * operators where appropriate (e.g. 'i++' by '++i').
461  *
462  * Revision 1.20 2002/06/26 17:20:31 joergr
463  * Added type cast to keep MSVC6 quiet.
464  *
465  * Revision 1.19 2002/06/26 16:17:16 joergr
466  * Added support for polarity flag to color images.
467  *
468  * Revision 1.18 2001/11/09 16:42:04 joergr
469  * Removed 'inline' specifier from certain methods.
470  *
471  * Revision 1.17 2001/06/01 15:49:29 meichel
472  * Updated copyright header
473  *
474  * Revision 1.16 2000/03/30 14:15:44 joergr
475  * Corrected wrong bit expansion of output pixel data (left shift is not
476  * correct).
477  *
478  * Revision 1.15 2000/03/08 16:21:50 meichel
479  * Updated copyright header.
480  *
481  * Revision 1.14 1999/09/17 14:03:43 joergr
482  * Enhanced efficiency of some "for" loops.
483  *
484  * Revision 1.13 1999/08/17 10:28:47 joergr
485  * Commented unused parameter name to avoid compiler warnings.
486  * Removed unused parameter.
487  *
488  * Revision 1.12 1999/07/23 13:20:45 joergr
489  * Enhanced handling of corrupted pixel data (wrong length).
490  *
491  * Revision 1.11 1999/04/30 16:12:03 meichel
492  * Minor code purifications to keep IBM xlC quiet
493  *
494  * Revision 1.10 1999/04/29 09:31:13 joergr
495  * Moved color related image files back to non-public part.
496  *
497  * Revision 1.1 1999/04/28 14:57:31 joergr
498  * Moved files from dcmimage module to dcmimgle to support new pastel color
499  * output format.
500  *
501  * Revision 1.8 1999/01/20 14:43:12 joergr
502  * Replaced invocation of getCount() by member variable Count where possible.
503  * Added new output method to fill external memory buffer with rendered pixel
504  * data.
505  *
506  * Revision 1.7 1998/12/22 13:23:57 joergr
507  * Added comments that the routines for expanding pixel's depth have to be
508  * enhanced in the future (replicate bit pattern instead of shifting). Same
509  * question for reducing depth.
510  *
511  * Revision 1.6 1998/11/27 13:46:00 joergr
512  * Added copyright message. Replaced delete by delete[] for array types.
513  *
514  * Revision 1.5 1998/07/01 08:39:19 joergr
515  * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional
516  * options), e.g. add copy constructors.
517  *
518  * Revision 1.4 1998/05/11 14:53:12 joergr
519  * Added CVS/RCS header to each file.
520  *
521  *
522  */


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