00001 /* 00002 * 00003 * Copyright (C) 1996-2010, OFFIS e.V. 00004 * All rights reserved. See COPYRIGHT file for details. 00005 * 00006 * This software and supporting documentation were developed by 00007 * 00008 * OFFIS e.V. 00009 * R&D Division Health 00010 * Escherweg 2 00011 * D-26121 Oldenburg, Germany 00012 * 00013 * 00014 * Module: dcmimage 00015 * 00016 * Author: Joerg Riesmeier 00017 * 00018 * Purpose: DicomColorPixelTemplate (Header) 00019 * 00020 * Last Update: $Author: joergr $ 00021 * Update Date: $Date: 2010-10-14 13:16:29 $ 00022 * CVS/RCS Revision: $Revision: 1.30 $ 00023 * Status: $State: Exp $ 00024 * 00025 * CVS/RCS Log at end of file 00026 * 00027 */ 00028 00029 00030 #ifndef DICOPXT_H 00031 #define DICOPXT_H 00032 00033 #include "dcmtk/config/osconfig.h" 00034 #include "dcmtk/ofstd/ofbmanip.h" 00035 00036 #include "dcmtk/dcmimage/dicopx.h" 00037 #include "dcmtk/dcmimgle/dipxrept.h" 00038 00039 00040 /********************************************************************/ 00041 00042 00043 inline Uint8 removeSign(const Uint8 value, const Uint8) 00044 { 00045 return value; 00046 } 00047 00048 00049 inline Uint16 removeSign(const Uint16 value, const Uint16) 00050 { 00051 return value; 00052 } 00053 00054 00055 inline Uint32 removeSign(const Uint32 value, const Uint32) 00056 { 00057 return value; 00058 } 00059 00060 00061 inline Uint8 removeSign(const Sint8 value, const Sint8 offset) 00062 { 00063 return OFstatic_cast(Uint8, OFstatic_cast(Sint16, value) + OFstatic_cast(Sint16, offset) + 1); 00064 } 00065 00066 00067 inline Uint16 removeSign(const Sint16 value, const Sint16 offset) 00068 { 00069 return OFstatic_cast(Uint16, OFstatic_cast(Sint32, value) + OFstatic_cast(Sint32, offset) + 1); 00070 } 00071 00072 /* 00073 inline Uint32 removeSign(const Sint32 value, const Sint32 offset) 00074 { 00075 return (value < 0) ? OFstatic_cast(Uint32, value + offset + 1) : OFstatic_cast(Uint32, value) + OFstatic_cast(Uint32, offset) + 1; 00076 } 00077 00078 00079 inline Uint8 removeSign(const Sint8 value, const Uint8 mask) 00080 { 00081 return OFstatic_cast(Uint8, value) ^ mask; 00082 } 00083 00084 00085 inline Uint16 removeSign(const Sint16 value, const Uint16 mask) 00086 { 00087 return OFstatic_cast(Uint16, value) ^ mask; 00088 } 00089 */ 00090 00091 inline Uint32 removeSign(const Sint32 value, const Uint32 mask) 00092 { 00093 return OFstatic_cast(Uint32, value) ^ mask; 00094 } 00095 00096 00097 /*---------------------* 00098 * class declaration * 00099 *---------------------*/ 00100 00103 template<class T> 00104 class DiColorPixelTemplate 00105 : public DiColorPixel, 00106 public DiPixelRepresentationTemplate<T> 00107 { 00108 00109 public: 00110 00119 DiColorPixelTemplate(const DiDocument *docu, 00120 const DiInputPixel *pixel, 00121 const Uint16 samples, 00122 EI_Status &status, 00123 const Uint16 sample_rate = 0) 00124 : DiColorPixel(docu, pixel, samples, status, sample_rate) 00125 { 00126 Data[0] = NULL; 00127 Data[1] = NULL; 00128 Data[2] = NULL; 00129 } 00130 00133 virtual ~DiColorPixelTemplate() 00134 { 00135 delete[] Data[0]; 00136 delete[] Data[1]; 00137 delete[] Data[2]; 00138 } 00139 00144 inline EP_Representation getRepresentation() const 00145 { 00146 return DiPixelRepresentationTemplate<T>::getRepresentation(); 00147 } 00148 00154 inline const void *getData() const 00155 { 00156 return OFstatic_cast(const void *, Data); 00157 } 00158 00164 inline void *getDataPtr() 00165 { 00166 return OFstatic_cast(void *, Data); 00167 } 00168 00174 inline void *getDataArrayPtr() 00175 { 00176 return OFstatic_cast(void *, Data); 00177 } 00178 00189 OFBool getPixelData(void *data, 00190 const unsigned long count, 00191 const unsigned long fcount, 00192 const unsigned long frames, 00193 const int planar) const 00194 { 00195 OFBool result = OFFalse; 00196 /* check parameters and internal data */ 00197 if ((data != NULL) && (count >= Count * 3) && (frames > 0) && (frames * fcount <= Count) && 00198 (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL)) 00199 { 00200 register T *q = OFstatic_cast(T *, data); 00201 register int j; 00202 register unsigned long k; 00203 register unsigned long offset = 0; 00204 if (planar) 00205 { 00206 /* for all frames ... */ 00207 for (k = 0; k < frames; ++k) 00208 { 00209 /* copy all three planes to the given memory block */ 00210 for (j = 0; j < 3; ++j) 00211 { 00212 OFBitmanipTemplate<T>::copyMem(Data[j] + offset, q, fcount); 00213 q += fcount; 00214 } 00215 offset += fcount; 00216 } 00217 } else { 00218 register unsigned long i; 00219 /* for all frames ... */ 00220 for (k = 0; k < frames; ++k) 00221 { 00222 /* copy pixel data values from internal representation */ 00223 for (i = 0; i < fcount; ++i) 00224 { 00225 for (j = 0; j < 3; ++j) 00226 *(q++) = Data[j][i + offset]; 00227 } 00228 offset += fcount; 00229 } 00230 } 00231 result = OFTrue; 00232 } 00233 return result; 00234 } 00235 00251 unsigned long createDIB(void *&data, 00252 const unsigned long size, 00253 const Uint16 width, 00254 const Uint16 height, 00255 const unsigned long frame, 00256 const int fromBits, 00257 const int toBits, 00258 const int mode, 00259 const int upsideDown, 00260 const int padding) const 00261 { 00262 unsigned long bytes = 0; 00263 if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) 00264 { 00265 const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); 00266 const unsigned long start = count * frame + ((upsideDown) ? 00267 OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0); 00268 const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0; 00269 register const T *r = Data[0] + start; 00270 register const T *g = Data[1] + start; 00271 register const T *b = Data[2] + start; 00272 register Uint16 x; 00273 register Uint16 y; 00274 if (mode == 24) // 24 bits per pixel 00275 { 00276 const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3; 00277 // each line has to start at 32-bit-address, if 'padding' is true 00278 const int gap = (padding) ? OFstatic_cast(int, (4 - (wid3 & 0x3)) & 0x3) : 0; 00279 unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height); 00280 if ((data == NULL) || (size >= fsize)) 00281 { 00282 if (data == NULL) 00283 data = new Uint8[fsize]; 00284 if (data != NULL) 00285 { 00286 register Uint8 *q = OFstatic_cast(Uint8 *, data); 00287 if (fromBits == toBits) 00288 { 00289 /* copy pixel data as is */ 00290 for (y = height; y != 0; y--) 00291 { 00292 for (x = width; x != 0; x--) 00293 { 00294 /* reverse sample order: B-G-R */ 00295 *(q++) = OFstatic_cast(Uint8, *(b++)); 00296 *(q++) = OFstatic_cast(Uint8, *(g++)); 00297 *(q++) = OFstatic_cast(Uint8, *(r++)); 00298 } 00299 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00300 q += gap; // new line: jump to next 32-bit address 00301 } 00302 } 00303 else if (fromBits < toBits) 00304 { 00305 /* increase color depth: multiply with factor */ 00306 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00307 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00308 const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1); 00309 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00310 { 00311 for (y = height; y != 0; y--) 00312 { 00313 for (x = width; x != 0; x--) 00314 { 00315 /* reverse sample order: B-G-R */ 00316 *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2); 00317 *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2); 00318 *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2); 00319 } 00320 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00321 q += gap; // new line: jump to next 32-bit address 00322 } 00323 } else { 00324 for (y = height; y != 0; y--) 00325 { 00326 for (x = width; x != 0; x--) 00327 { 00328 /* reverse sample order: B-G-R */ 00329 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1); 00330 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1); 00331 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1); 00332 } 00333 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00334 q += gap; // new line: jump to next 32-bit address 00335 } 00336 } 00337 } 00338 else /* fromBits > toBits */ 00339 { 00340 /* reduce color depth: right shift */ 00341 const int shift = fromBits - toBits; 00342 for (y = height; y != 0; y--) 00343 { 00344 for (x = width; x != 0; x--) 00345 { 00346 /* reverse sample order: B-G-R */ 00347 *(q++) = OFstatic_cast(Uint8, *(b++) >> shift); 00348 *(q++) = OFstatic_cast(Uint8, *(g++) >> shift); 00349 *(q++) = OFstatic_cast(Uint8, *(r++) >> shift); 00350 } 00351 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00352 q += gap; // new line: jump to next 32-bit address 00353 } 00354 } 00355 bytes = fsize; 00356 } 00357 } 00358 } 00359 else if (mode == 32) // 32 bits per pixel 00360 { 00361 const unsigned long fsize = count * 4; 00362 if ((data == NULL) || (size >= fsize)) 00363 { 00364 if (data == NULL) 00365 data = new Uint32[count]; 00366 if (data != NULL) 00367 { 00368 register Uint32 *q = OFstatic_cast(Uint32 *, data); 00369 if (fromBits == toBits) 00370 { 00371 /* copy pixel data as is */ 00372 for (y = height; y != 0; y--) 00373 { 00374 for (x = width; x != 0; x--) 00375 { 00376 /* normal sample order: 0-R-G-B */ 00377 *(q++) = (OFstatic_cast(Uint32, *(r++)) << 16) | 00378 (OFstatic_cast(Uint32, *(g++)) << 8) | 00379 OFstatic_cast(Uint32, *(b++)); 00380 } 00381 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00382 } 00383 } 00384 else if (fromBits < toBits) 00385 { 00386 /* increase color depth: multiply with factor */ 00387 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00388 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00389 const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); 00390 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00391 { 00392 for (y = height; y != 0; y--) 00393 { 00394 for (x = width; x != 0; x--) 00395 { 00396 /* normal sample order: 0-R-G-B */ 00397 *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 16) | 00398 (OFstatic_cast(Uint32, *(g++) * gradient2) << 8) | 00399 OFstatic_cast(Uint32, *(b++) * gradient2); 00400 } 00401 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00402 } 00403 } else { 00404 for (y = height; y != 0; y--) 00405 { 00406 for (x = width; x != 0; x--) 00407 { 00408 /* normal sample order: 0-R-G-B */ 00409 *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 16) | 00410 (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 8) | 00411 OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1); 00412 } 00413 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00414 } 00415 } 00416 } 00417 else /* fromBits > toBits */ 00418 { 00419 /* reduce color depth: right shift */ 00420 const int shift = fromBits - toBits; 00421 for (y = height; y != 0; y--) 00422 { 00423 for (x = width; x != 0; x--) 00424 { 00425 /* normal sample order: 0-R-G-B */ 00426 *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 16) | 00427 (OFstatic_cast(Uint32, *(g++) >> shift) << 8) | 00428 OFstatic_cast(Uint32, *(b++) >> shift); 00429 } 00430 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00431 } 00432 } 00433 bytes = fsize; 00434 } 00435 } 00436 } 00437 } 00438 return bytes; 00439 } 00440 00452 unsigned long createAWTBitmap(void *&data, 00453 const Uint16 width, 00454 const Uint16 height, 00455 const unsigned long frame, 00456 const int fromBits, 00457 const int toBits) const 00458 { 00459 data = NULL; 00460 unsigned long bytes = 0; 00461 if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) 00462 { 00463 const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); 00464 data = new Uint32[count]; 00465 if (data != NULL) 00466 { 00467 const unsigned long start = count * frame; 00468 register const T *r = Data[0] + start; 00469 register const T *g = Data[1] + start; 00470 register const T *b = Data[2] + start; 00471 register Uint32 *q = OFstatic_cast(Uint32 *, data); 00472 register unsigned long i; 00473 if (fromBits == toBits) 00474 { 00475 /* copy pixel data as is */ 00476 for (i = count; i != 0; --i) 00477 { 00478 /* sample order: R-G-B */ 00479 *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) | 00480 (OFstatic_cast(Uint32, *(g++)) << 16) | 00481 (OFstatic_cast(Uint32, *(b++)) << 8); 00482 } 00483 } 00484 else if (fromBits < toBits) 00485 { 00486 /* increase color depth: multiply with factor */ 00487 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00488 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00489 const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); 00490 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00491 { 00492 for (i = count; i != 0; --i) 00493 { 00494 /* sample order: R-G-B */ 00495 *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) | 00496 (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) | 00497 (OFstatic_cast(Uint32, *(b++) * gradient2) << 8); 00498 } 00499 } else { 00500 for (i = count; i != 0; --i) 00501 { 00502 /* sample order: R-G-B */ 00503 *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) | 00504 (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) | 00505 (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8); 00506 } 00507 } 00508 } 00509 else /* fromBits > toBits */ 00510 { 00511 /* reduce color depth: right shift */ 00512 const int shift = fromBits - toBits; 00513 for (i = count; i != 0; --i) 00514 { 00515 /* sample order: R-G-B */ 00516 *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) | 00517 (OFstatic_cast(Uint32, *(g++) >> shift) << 16) | 00518 (OFstatic_cast(Uint32, *(b++) >> shift) << 8); 00519 } 00520 } 00521 bytes = count * 4; 00522 } 00523 } 00524 return bytes; 00525 } 00526 00527 00528 protected: 00529 00535 DiColorPixelTemplate(const DiColorPixel *pixel, 00536 const unsigned long count) 00537 : DiColorPixel(pixel, count) 00538 { 00539 Data[0] = NULL; 00540 Data[1] = NULL; 00541 Data[2] = NULL; 00542 } 00543 00550 inline int Init(const void *pixel) 00551 { 00552 int result = 0; 00553 if (pixel != NULL) 00554 { 00555 result = 1; 00556 /* allocate data buffer for the 3 planes */ 00557 for (int j = 0; j < 3; j++) 00558 { 00559 Data[j] = new T[Count]; 00560 if (Data[j] != NULL) 00561 { 00562 /* erase empty part of the buffer (=blacken the background) */ 00563 if (InputCount < Count) 00564 OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount); 00565 } else 00566 result = 0; // at least one buffer could not be allocated! 00567 } 00568 } 00569 return result; 00570 } 00571 00572 00574 T *Data[3]; 00575 00576 00577 private: 00578 00579 // --- declarations to avoid compiler warnings 00580 00581 DiColorPixelTemplate(const DiColorPixelTemplate<T> &); 00582 DiColorPixelTemplate<T> &operator=(const DiColorPixelTemplate<T> &); 00583 }; 00584 00585 00586 #endif 00587 00588 00589 /* 00590 * 00591 * CVS/RCS Log: 00592 * $Log: dicopxt.h,v $ 00593 * Revision 1.30 2010-10-14 13:16:29 joergr 00594 * Updated copyright header. Added reference to COPYRIGHT file. 00595 * 00596 * Revision 1.29 2010-03-01 09:08:46 uli 00597 * Removed some unnecessary include directives in the headers. 00598 * 00599 * Revision 1.28 2009-08-26 07:51:31 joergr 00600 * Added parentheses around + or - in operand of & in order to avoid warnings 00601 * reported by gcc 4.3.2. 00602 * 00603 * Revision 1.27 2008-05-13 10:03:34 joergr 00604 * Fixed issue with multi-frame color images: writeImageToDataset() used wrong 00605 * format for color-by-plane output. 00606 * 00607 * Revision 1.26 2006/07/10 10:59:26 joergr 00608 * Fixed incorrect order of sample values in 32-bit DIB images. 00609 * 00610 * Revision 1.25 2005/12/08 16:01:35 meichel 00611 * Changed include path schema for all DCMTK header files 00612 * 00613 * Revision 1.24 2004/10/19 12:57:47 joergr 00614 * Enhanced API documentation. 00615 * 00616 * Revision 1.23 2004/02/06 11:18:18 joergr 00617 * Distinguish more clearly between const and non-const access to pixel data. 00618 * 00619 * Revision 1.22 2004/01/21 12:59:43 meichel 00620 * Added OFconst_cast, needed for Visual C++ 6 00621 * 00622 * Revision 1.21 2003/12/23 11:43:03 joergr 00623 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00624 * Removed leading underscore characters from preprocessor symbols (reserved 00625 * symbols). Updated copyright header. Added missing API documentation. 00626 * Replaced post-increment/decrement operators by pre-increment/decrement 00627 * operators where appropriate (e.g. 'i++' by '++i'). 00628 * 00629 * Revision 1.20 2002/12/10 17:39:50 meichel 00630 * Added explicit type cast to avoid compilation error on gcc 3.2 00631 * 00632 * Revision 1.19 2002/12/09 13:37:24 joergr 00633 * Added private undefined copy constructor and/or assignment operator. 00634 * Fixed bug that caused method createAWTBitmap() to return always empty pixel 00635 * data. 00636 * 00637 * Revision 1.18 2002/09/12 14:10:37 joergr 00638 * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata 00639 * routine and is therefore more efficient. 00640 * 00641 * Revision 1.17 2002/08/29 12:57:49 joergr 00642 * Added method that creates pixel data in DICOM format. 00643 * 00644 * Revision 1.16 2002/06/26 16:17:41 joergr 00645 * Enhanced handling of corrupted pixel data and/or length. 00646 * 00647 * Revision 1.15 2002/01/29 17:07:08 joergr 00648 * Added optional flag to the "Windows DIB" methods allowing to switch off the 00649 * scanline padding. 00650 * 00651 * Revision 1.14 2001/12/11 14:23:44 joergr 00652 * Added type cast to keep old Sun compilers quiet. 00653 * 00654 * Revision 1.13 2001/11/09 16:44:35 joergr 00655 * Enhanced and renamed createTrueColorDIB() method. 00656 * 00657 * Revision 1.12 2001/06/01 15:49:29 meichel 00658 * Updated copyright header 00659 * 00660 * Revision 1.11 2000/03/08 16:21:51 meichel 00661 * Updated copyright header. 00662 * 00663 * Revision 1.10 1999/09/17 14:03:44 joergr 00664 * Enhanced efficiency of some "for" loops. 00665 * 00666 * Revision 1.9 1999/07/23 13:22:29 joergr 00667 * emoved inline method 'removeSign'which is no longer needed. 00668 * 00669 * Revision 1.8 1999/04/28 12:51:58 joergr 00670 * Corrected some typos, comments and formatting. 00671 * 00672 * Revision 1.7 1999/01/20 14:44:49 joergr 00673 * Corrected some typos and formatting. 00674 * 00675 * Revision 1.6 1998/11/27 13:50:20 joergr 00676 * Added copyright message. Replaced delete by delete[] for array types. 00677 * Added method to give direct (non const) access to internal data buffer. 00678 * 00679 * Revision 1.5 1998/05/11 14:53:13 joergr 00680 * Added CVS/RCS header to each file. 00681 * 00682 * 00683 */