OFFIS DCMTK  Version 3.6.0
dicopxt.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: dcmimage
15  *
16  * Author: Joerg Riesmeier
17  *
18  * Purpose: DicomColorPixelTemplate (Header)
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2010-10-14 13:16:29 $
22  * CVS/RCS Revision: $Revision: 1.30 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 
30 #ifndef DICOPXT_H
31 #define DICOPXT_H
32 
33 #include "dcmtk/config/osconfig.h"
34 #include "dcmtk/ofstd/ofbmanip.h"
35 
36 #include "dcmtk/dcmimage/dicopx.h"
37 #include "dcmtk/dcmimgle/dipxrept.h"
38 
39 
40 /********************************************************************/
41 
42 
43 inline Uint8 removeSign(const Uint8 value, const Uint8)
44 {
45  return value;
46 }
47 
48 
49 inline Uint16 removeSign(const Uint16 value, const Uint16)
50 {
51  return value;
52 }
53 
54 
55 inline Uint32 removeSign(const Uint32 value, const Uint32)
56 {
57  return value;
58 }
59 
60 
61 inline Uint8 removeSign(const Sint8 value, const Sint8 offset)
62 {
63  return OFstatic_cast(Uint8, OFstatic_cast(Sint16, value) + OFstatic_cast(Sint16, offset) + 1);
64 }
65 
66 
67 inline Uint16 removeSign(const Sint16 value, const Sint16 offset)
68 {
69  return OFstatic_cast(Uint16, OFstatic_cast(Sint32, value) + OFstatic_cast(Sint32, offset) + 1);
70 }
71 
72 /*
73 inline Uint32 removeSign(const Sint32 value, const Sint32 offset)
74 {
75  return (value < 0) ? OFstatic_cast(Uint32, value + offset + 1) : OFstatic_cast(Uint32, value) + OFstatic_cast(Uint32, offset) + 1;
76 }
77 
78 
79 inline Uint8 removeSign(const Sint8 value, const Uint8 mask)
80 {
81  return OFstatic_cast(Uint8, value) ^ mask;
82 }
83 
84 
85 inline Uint16 removeSign(const Sint16 value, const Uint16 mask)
86 {
87  return OFstatic_cast(Uint16, value) ^ mask;
88 }
89 */
90 
91 inline Uint32 removeSign(const Sint32 value, const Uint32 mask)
92 {
93  return OFstatic_cast(Uint32, value) ^ mask;
94 }
95 
96 
97 /*---------------------*
98  * class declaration *
99  *---------------------*/
100 
103 template<class T>
105  : public DiColorPixel,
107 {
108 
109  public:
110 
120  const DiInputPixel *pixel,
121  const Uint16 samples,
122  EI_Status &status,
123  const Uint16 sample_rate = 0)
124  : DiColorPixel(docu, pixel, samples, status, sample_rate)
125  {
126  Data[0] = NULL;
127  Data[1] = NULL;
128  Data[2] = NULL;
129  }
130 
134  {
135  delete[] Data[0];
136  delete[] Data[1];
137  delete[] Data[2];
138  }
139 
144  inline EP_Representation getRepresentation() const
145  {
147  }
148 
154  inline const void *getData() const
155  {
156  return OFstatic_cast(const void *, Data);
157  }
158 
164  inline void *getDataPtr()
165  {
166  return OFstatic_cast(void *, Data);
167  }
168 
174  inline void *getDataArrayPtr()
175  {
176  return OFstatic_cast(void *, Data);
177  }
178 
189  OFBool getPixelData(void *data,
190  const unsigned long count,
191  const unsigned long fcount,
192  const unsigned long frames,
193  const int planar) const
194  {
195  OFBool result = OFFalse;
196  /* check parameters and internal data */
197  if ((data != NULL) && (count >= Count * 3) && (frames > 0) && (frames * fcount <= Count) &&
198  (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL))
199  {
200  register T *q = OFstatic_cast(T *, data);
201  register int j;
202  register unsigned long k;
203  register unsigned long offset = 0;
204  if (planar)
205  {
206  /* for all frames ... */
207  for (k = 0; k < frames; ++k)
208  {
209  /* copy all three planes to the given memory block */
210  for (j = 0; j < 3; ++j)
211  {
212  OFBitmanipTemplate<T>::copyMem(Data[j] + offset, q, fcount);
213  q += fcount;
214  }
215  offset += fcount;
216  }
217  } else {
218  register unsigned long i;
219  /* for all frames ... */
220  for (k = 0; k < frames; ++k)
221  {
222  /* copy pixel data values from internal representation */
223  for (i = 0; i < fcount; ++i)
224  {
225  for (j = 0; j < 3; ++j)
226  *(q++) = Data[j][i + offset];
227  }
228  offset += fcount;
229  }
230  }
231  result = OFTrue;
232  }
233  return result;
234  }
235 
251  unsigned long createDIB(void *&data,
252  const unsigned long size,
253  const Uint16 width,
254  const Uint16 height,
255  const unsigned long frame,
256  const int fromBits,
257  const int toBits,
258  const int mode,
259  const int upsideDown,
260  const int padding) const
261  {
262  unsigned long bytes = 0;
263  if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
264  {
265  const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
266  const unsigned long start = count * frame + ((upsideDown) ?
267  OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0);
268  const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0;
269  register const T *r = Data[0] + start;
270  register const T *g = Data[1] + start;
271  register const T *b = Data[2] + start;
272  register Uint16 x;
273  register Uint16 y;
274  if (mode == 24) // 24 bits per pixel
275  {
276  const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3;
277  // each line has to start at 32-bit-address, if 'padding' is true
278  const int gap = (padding) ? OFstatic_cast(int, (4 - (wid3 & 0x3)) & 0x3) : 0;
279  unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height);
280  if ((data == NULL) || (size >= fsize))
281  {
282  if (data == NULL)
283  data = new Uint8[fsize];
284  if (data != NULL)
285  {
286  register Uint8 *q = OFstatic_cast(Uint8 *, data);
287  if (fromBits == toBits)
288  {
289  /* copy pixel data as is */
290  for (y = height; y != 0; y--)
291  {
292  for (x = width; x != 0; x--)
293  {
294  /* reverse sample order: B-G-R */
295  *(q++) = OFstatic_cast(Uint8, *(b++));
296  *(q++) = OFstatic_cast(Uint8, *(g++));
297  *(q++) = OFstatic_cast(Uint8, *(r++));
298  }
299  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
300  q += gap; // new line: jump to next 32-bit address
301  }
302  }
303  else if (fromBits < toBits)
304  {
305  /* increase color depth: multiply with factor */
306  const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
307  OFstatic_cast(double, DicomImageClass::maxval(fromBits));
308  const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1);
309  if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
310  {
311  for (y = height; y != 0; y--)
312  {
313  for (x = width; x != 0; x--)
314  {
315  /* reverse sample order: B-G-R */
316  *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2);
317  *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2);
318  *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2);
319  }
320  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
321  q += gap; // new line: jump to next 32-bit address
322  }
323  } else {
324  for (y = height; y != 0; y--)
325  {
326  for (x = width; x != 0; x--)
327  {
328  /* reverse sample order: B-G-R */
329  *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1);
330  *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1);
331  *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1);
332  }
333  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
334  q += gap; // new line: jump to next 32-bit address
335  }
336  }
337  }
338  else /* fromBits > toBits */
339  {
340  /* reduce color depth: right shift */
341  const int shift = fromBits - toBits;
342  for (y = height; y != 0; y--)
343  {
344  for (x = width; x != 0; x--)
345  {
346  /* reverse sample order: B-G-R */
347  *(q++) = OFstatic_cast(Uint8, *(b++) >> shift);
348  *(q++) = OFstatic_cast(Uint8, *(g++) >> shift);
349  *(q++) = OFstatic_cast(Uint8, *(r++) >> shift);
350  }
351  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
352  q += gap; // new line: jump to next 32-bit address
353  }
354  }
355  bytes = fsize;
356  }
357  }
358  }
359  else if (mode == 32) // 32 bits per pixel
360  {
361  const unsigned long fsize = count * 4;
362  if ((data == NULL) || (size >= fsize))
363  {
364  if (data == NULL)
365  data = new Uint32[count];
366  if (data != NULL)
367  {
368  register Uint32 *q = OFstatic_cast(Uint32 *, data);
369  if (fromBits == toBits)
370  {
371  /* copy pixel data as is */
372  for (y = height; y != 0; y--)
373  {
374  for (x = width; x != 0; x--)
375  {
376  /* normal sample order: 0-R-G-B */
377  *(q++) = (OFstatic_cast(Uint32, *(r++)) << 16) |
378  (OFstatic_cast(Uint32, *(g++)) << 8) |
379  OFstatic_cast(Uint32, *(b++));
380  }
381  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
382  }
383  }
384  else if (fromBits < toBits)
385  {
386  /* increase color depth: multiply with factor */
387  const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
388  OFstatic_cast(double, DicomImageClass::maxval(fromBits));
389  const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
390  if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
391  {
392  for (y = height; y != 0; y--)
393  {
394  for (x = width; x != 0; x--)
395  {
396  /* normal sample order: 0-R-G-B */
397  *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 16) |
398  (OFstatic_cast(Uint32, *(g++) * gradient2) << 8) |
399  OFstatic_cast(Uint32, *(b++) * gradient2);
400  }
401  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
402  }
403  } else {
404  for (y = height; y != 0; y--)
405  {
406  for (x = width; x != 0; x--)
407  {
408  /* normal sample order: 0-R-G-B */
409  *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 16) |
410  (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 8) |
411  OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1);
412  }
413  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
414  }
415  }
416  }
417  else /* fromBits > toBits */
418  {
419  /* reduce color depth: right shift */
420  const int shift = fromBits - toBits;
421  for (y = height; y != 0; y--)
422  {
423  for (x = width; x != 0; x--)
424  {
425  /* normal sample order: 0-R-G-B */
426  *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 16) |
427  (OFstatic_cast(Uint32, *(g++) >> shift) << 8) |
428  OFstatic_cast(Uint32, *(b++) >> shift);
429  }
430  r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
431  }
432  }
433  bytes = fsize;
434  }
435  }
436  }
437  }
438  return bytes;
439  }
440 
452  unsigned long createAWTBitmap(void *&data,
453  const Uint16 width,
454  const Uint16 height,
455  const unsigned long frame,
456  const int fromBits,
457  const int toBits) const
458  {
459  data = NULL;
460  unsigned long bytes = 0;
461  if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
462  {
463  const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
464  data = new Uint32[count];
465  if (data != NULL)
466  {
467  const unsigned long start = count * frame;
468  register const T *r = Data[0] + start;
469  register const T *g = Data[1] + start;
470  register const T *b = Data[2] + start;
471  register Uint32 *q = OFstatic_cast(Uint32 *, data);
472  register unsigned long i;
473  if (fromBits == toBits)
474  {
475  /* copy pixel data as is */
476  for (i = count; i != 0; --i)
477  {
478  /* sample order: R-G-B */
479  *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) |
480  (OFstatic_cast(Uint32, *(g++)) << 16) |
481  (OFstatic_cast(Uint32, *(b++)) << 8);
482  }
483  }
484  else if (fromBits < toBits)
485  {
486  /* increase color depth: multiply with factor */
487  const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
488  OFstatic_cast(double, DicomImageClass::maxval(fromBits));
489  const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
490  if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
491  {
492  for (i = count; i != 0; --i)
493  {
494  /* sample order: R-G-B */
495  *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) |
496  (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) |
497  (OFstatic_cast(Uint32, *(b++) * gradient2) << 8);
498  }
499  } else {
500  for (i = count; i != 0; --i)
501  {
502  /* sample order: R-G-B */
503  *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) |
504  (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) |
505  (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8);
506  }
507  }
508  }
509  else /* fromBits > toBits */
510  {
511  /* reduce color depth: right shift */
512  const int shift = fromBits - toBits;
513  for (i = count; i != 0; --i)
514  {
515  /* sample order: R-G-B */
516  *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) |
517  (OFstatic_cast(Uint32, *(g++) >> shift) << 16) |
518  (OFstatic_cast(Uint32, *(b++) >> shift) << 8);
519  }
520  }
521  bytes = count * 4;
522  }
523  }
524  return bytes;
525  }
526 
527 
528  protected:
529 
536  const unsigned long count)
537  : DiColorPixel(pixel, count)
538  {
539  Data[0] = NULL;
540  Data[1] = NULL;
541  Data[2] = NULL;
542  }
543 
550  inline int Init(const void *pixel)
551  {
552  int result = 0;
553  if (pixel != NULL)
554  {
555  result = 1;
556  /* allocate data buffer for the 3 planes */
557  for (int j = 0; j < 3; j++)
558  {
559  Data[j] = new T[Count];
560  if (Data[j] != NULL)
561  {
562  /* erase empty part of the buffer (=blacken the background) */
563  if (InputCount < Count)
565  } else
566  result = 0; // at least one buffer could not be allocated!
567  }
568  }
569  return result;
570  }
571 
572 
574  T *Data[3];
575 
576 
577  private:
578 
579  // --- declarations to avoid compiler warnings
580 
583 };
584 
585 
586 #endif
587 
588 
589 /*
590  *
591  * CVS/RCS Log:
592  * $Log: dicopxt.h,v $
593  * Revision 1.30 2010-10-14 13:16:29 joergr
594  * Updated copyright header. Added reference to COPYRIGHT file.
595  *
596  * Revision 1.29 2010-03-01 09:08:46 uli
597  * Removed some unnecessary include directives in the headers.
598  *
599  * Revision 1.28 2009-08-26 07:51:31 joergr
600  * Added parentheses around + or - in operand of & in order to avoid warnings
601  * reported by gcc 4.3.2.
602  *
603  * Revision 1.27 2008-05-13 10:03:34 joergr
604  * Fixed issue with multi-frame color images: writeImageToDataset() used wrong
605  * format for color-by-plane output.
606  *
607  * Revision 1.26 2006/07/10 10:59:26 joergr
608  * Fixed incorrect order of sample values in 32-bit DIB images.
609  *
610  * Revision 1.25 2005/12/08 16:01:35 meichel
611  * Changed include path schema for all DCMTK header files
612  *
613  * Revision 1.24 2004/10/19 12:57:47 joergr
614  * Enhanced API documentation.
615  *
616  * Revision 1.23 2004/02/06 11:18:18 joergr
617  * Distinguish more clearly between const and non-const access to pixel data.
618  *
619  * Revision 1.22 2004/01/21 12:59:43 meichel
620  * Added OFconst_cast, needed for Visual C++ 6
621  *
622  * Revision 1.21 2003/12/23 11:43:03 joergr
623  * Adapted type casts to new-style typecast operators defined in ofcast.h.
624  * Removed leading underscore characters from preprocessor symbols (reserved
625  * symbols). Updated copyright header. Added missing API documentation.
626  * Replaced post-increment/decrement operators by pre-increment/decrement
627  * operators where appropriate (e.g. 'i++' by '++i').
628  *
629  * Revision 1.20 2002/12/10 17:39:50 meichel
630  * Added explicit type cast to avoid compilation error on gcc 3.2
631  *
632  * Revision 1.19 2002/12/09 13:37:24 joergr
633  * Added private undefined copy constructor and/or assignment operator.
634  * Fixed bug that caused method createAWTBitmap() to return always empty pixel
635  * data.
636  *
637  * Revision 1.18 2002/09/12 14:10:37 joergr
638  * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata
639  * routine and is therefore more efficient.
640  *
641  * Revision 1.17 2002/08/29 12:57:49 joergr
642  * Added method that creates pixel data in DICOM format.
643  *
644  * Revision 1.16 2002/06/26 16:17:41 joergr
645  * Enhanced handling of corrupted pixel data and/or length.
646  *
647  * Revision 1.15 2002/01/29 17:07:08 joergr
648  * Added optional flag to the "Windows DIB" methods allowing to switch off the
649  * scanline padding.
650  *
651  * Revision 1.14 2001/12/11 14:23:44 joergr
652  * Added type cast to keep old Sun compilers quiet.
653  *
654  * Revision 1.13 2001/11/09 16:44:35 joergr
655  * Enhanced and renamed createTrueColorDIB() method.
656  *
657  * Revision 1.12 2001/06/01 15:49:29 meichel
658  * Updated copyright header
659  *
660  * Revision 1.11 2000/03/08 16:21:51 meichel
661  * Updated copyright header.
662  *
663  * Revision 1.10 1999/09/17 14:03:44 joergr
664  * Enhanced efficiency of some "for" loops.
665  *
666  * Revision 1.9 1999/07/23 13:22:29 joergr
667  * emoved inline method 'removeSign'which is no longer needed.
668  *
669  * Revision 1.8 1999/04/28 12:51:58 joergr
670  * Corrected some typos, comments and formatting.
671  *
672  * Revision 1.7 1999/01/20 14:44:49 joergr
673  * Corrected some typos and formatting.
674  *
675  * Revision 1.6 1998/11/27 13:50:20 joergr
676  * Added copyright message. Replaced delete by delete[] for array types.
677  * Added method to give direct (non const) access to internal data buffer.
678  *
679  * Revision 1.5 1998/05/11 14:53:13 joergr
680  * Added CVS/RCS header to each file.
681  *
682  *
683  */


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