00001 /* 00002 * 00003 * Copyright (C) 1996-2005, OFFIS 00004 * 00005 * This software and supporting documentation were developed by 00006 * 00007 * Kuratorium OFFIS e.V. 00008 * Healthcare Information and Communication Systems 00009 * Escherweg 2 00010 * D-26121 Oldenburg, Germany 00011 * 00012 * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY 00013 * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR 00014 * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR 00015 * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND 00016 * PERFORMANCE OF THE SOFTWARE IS WITH THE USER. 00017 * 00018 * Module: dcmimage 00019 * 00020 * Author: Joerg Riesmeier 00021 * 00022 * Purpose: DicomColorPixelTemplate (Header) 00023 * 00024 * Last Update: $Author: meichel $ 00025 * Update Date: $Date: 2005/12/08 16:01:35 $ 00026 * CVS/RCS Revision: $Revision: 1.25 $ 00027 * Status: $State: Exp $ 00028 * 00029 * CVS/RCS Log at end of file 00030 * 00031 */ 00032 00033 00034 #ifndef DICOPXT_H 00035 #define DICOPXT_H 00036 00037 #include "dcmtk/config/osconfig.h" 00038 #include "dcmtk/dcmdata/dctypes.h" 00039 #include "dcmtk/ofstd/ofbmanip.h" 00040 00041 #include "dcmtk/dcmimage/dicopx.h" 00042 #include "dcmtk/dcmimgle/dipxrept.h" 00043 00044 00045 /********************************************************************/ 00046 00047 00048 inline Uint8 removeSign(const Uint8 value, const Uint8) 00049 { 00050 return value; 00051 } 00052 00053 00054 inline Uint16 removeSign(const Uint16 value, const Uint16) 00055 { 00056 return value; 00057 } 00058 00059 00060 inline Uint32 removeSign(const Uint32 value, const Uint32) 00061 { 00062 return value; 00063 } 00064 00065 00066 inline Uint8 removeSign(const Sint8 value, const Sint8 offset) 00067 { 00068 return OFstatic_cast(Uint8, OFstatic_cast(Sint16, value) + OFstatic_cast(Sint16, offset) + 1); 00069 } 00070 00071 00072 inline Uint16 removeSign(const Sint16 value, const Sint16 offset) 00073 { 00074 return OFstatic_cast(Uint16, OFstatic_cast(Sint32, value) + OFstatic_cast(Sint32, offset) + 1); 00075 } 00076 00077 /* 00078 inline Uint32 removeSign(const Sint32 value, const Sint32 offset) 00079 { 00080 return (value < 0) ? OFstatic_cast(Uint32, value + offset + 1) : OFstatic_cast(Uint32, value) + OFstatic_cast(Uint32, offset) + 1; 00081 } 00082 00083 00084 inline Uint8 removeSign(const Sint8 value, const Uint8 mask) 00085 { 00086 return OFstatic_cast(Uint8, value) ^ mask; 00087 } 00088 00089 00090 inline Uint16 removeSign(const Sint16 value, const Uint16 mask) 00091 { 00092 return OFstatic_cast(Uint16, value) ^ mask; 00093 } 00094 */ 00095 00096 inline Uint32 removeSign(const Sint32 value, const Uint32 mask) 00097 { 00098 return OFstatic_cast(Uint32, value) ^ mask; 00099 } 00100 00101 00102 /*---------------------* 00103 * class declaration * 00104 *---------------------*/ 00105 00108 template<class T> 00109 class DiColorPixelTemplate 00110 : public DiColorPixel, 00111 public DiPixelRepresentationTemplate<T> 00112 { 00113 00114 public: 00115 00124 DiColorPixelTemplate(const DiDocument *docu, 00125 const DiInputPixel *pixel, 00126 const Uint16 samples, 00127 EI_Status &status, 00128 const Uint16 sample_rate = 0) 00129 : DiColorPixel(docu, pixel, samples, status, sample_rate) 00130 { 00131 Data[0] = NULL; 00132 Data[1] = NULL; 00133 Data[2] = NULL; 00134 } 00135 00138 virtual ~DiColorPixelTemplate() 00139 { 00140 delete[] Data[0]; 00141 delete[] Data[1]; 00142 delete[] Data[2]; 00143 } 00144 00149 inline EP_Representation getRepresentation() const 00150 { 00151 return DiPixelRepresentationTemplate<T>::getRepresentation(); 00152 } 00153 00159 inline const void *getData() const 00160 { 00161 return OFstatic_cast(const void *, Data); 00162 } 00163 00169 inline void *getDataPtr() 00170 { 00171 return OFstatic_cast(void *, Data); 00172 } 00173 00179 inline void *getDataArrayPtr() 00180 { 00181 return OFstatic_cast(void *, Data); 00182 } 00183 00193 OFBool getPixelData(void *data, 00194 const size_t count) const 00195 { 00196 OFBool result = OFFalse; 00197 /* check parameters and internal data */ 00198 if ((data != NULL) && (count >= Count * 3) && 00199 (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL)) 00200 { 00201 /* copy all three planes to the given memory block */ 00202 OFBitmanipTemplate<T>::copyMem(Data[0], OFstatic_cast(T *, data), Count); 00203 OFBitmanipTemplate<T>::copyMem(Data[1], OFstatic_cast(T *, data) + Count, Count); 00204 OFBitmanipTemplate<T>::copyMem(Data[2], OFstatic_cast(T *, data) + 2 * Count, Count); 00205 result = OFTrue; 00206 } 00207 return result; 00208 } 00209 00225 unsigned long createDIB(void *&data, 00226 const unsigned long size, 00227 const Uint16 width, 00228 const Uint16 height, 00229 const unsigned long frame, 00230 const int fromBits, 00231 const int toBits, 00232 const int mode, 00233 const int upsideDown, 00234 const int padding) const 00235 { 00236 unsigned long bytes = 0; 00237 if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) 00238 { 00239 const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); 00240 const unsigned long start = count * frame + ((upsideDown) ? 00241 OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0); 00242 const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0; 00243 register const T *r = Data[0] + start; 00244 register const T *g = Data[1] + start; 00245 register const T *b = Data[2] + start; 00246 register Uint16 x; 00247 register Uint16 y; 00248 if (mode == 24) // 24 bits per pixel 00249 { 00250 const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3; 00251 // each line has to start at 32-bit-address, if 'padding' is true 00252 const int gap = (padding) ? OFstatic_cast(int, (4 - wid3 & 0x3) & 0x3) : 0; 00253 unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height); 00254 if ((data == NULL) || (size >= fsize)) 00255 { 00256 if (data == NULL) 00257 data = new Uint8[fsize]; 00258 if (data != NULL) 00259 { 00260 register Uint8 *q = OFstatic_cast(Uint8 *, data); 00261 if (fromBits == toBits) 00262 { 00263 /* copy pixel data as is */ 00264 for (y = height; y != 0; y--) 00265 { 00266 for (x = width; x != 0; x--) 00267 { 00268 /* reverse sample order: B-G-R */ 00269 *(q++) = OFstatic_cast(Uint8, *(b++)); 00270 *(q++) = OFstatic_cast(Uint8, *(g++)); 00271 *(q++) = OFstatic_cast(Uint8, *(r++)); 00272 } 00273 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00274 q += gap; // new line: jump to next 32-bit address 00275 } 00276 } 00277 else if (fromBits < toBits) 00278 { 00279 /* increase color depth: multiply with factor */ 00280 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00281 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00282 const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1); 00283 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00284 { 00285 for (y = height; y != 0; y--) 00286 { 00287 for (x = width; x != 0; x--) 00288 { 00289 /* reverse sample order: B-G-R */ 00290 *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2); 00291 *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2); 00292 *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2); 00293 } 00294 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00295 q += gap; // new line: jump to next 32-bit address 00296 } 00297 } else { 00298 for (y = height; y != 0; y--) 00299 { 00300 for (x = width; x != 0; x--) 00301 { 00302 /* reverse sample order: B-G-R */ 00303 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1); 00304 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1); 00305 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1); 00306 } 00307 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00308 q += gap; // new line: jump to next 32-bit address 00309 } 00310 } 00311 } 00312 else /* fromBits > toBits */ 00313 { 00314 /* reduce color depth: right shift */ 00315 const int shift = fromBits - toBits; 00316 for (y = height; y != 0; y--) 00317 { 00318 for (x = width; x != 0; x--) 00319 { 00320 /* reverse sample order: B-G-R */ 00321 *(q++) = OFstatic_cast(Uint8, *(b++) >> shift); 00322 *(q++) = OFstatic_cast(Uint8, *(g++) >> shift); 00323 *(q++) = OFstatic_cast(Uint8, *(r++) >> shift); 00324 } 00325 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00326 q += gap; // new line: jump to next 32-bit address 00327 } 00328 } 00329 bytes = fsize; 00330 } 00331 } 00332 } 00333 else if (mode == 32) // 32 bits per pixel 00334 { 00335 const unsigned long fsize = count * 4; 00336 if ((data == NULL) || (size >= fsize)) 00337 { 00338 if (data == NULL) 00339 data = new Uint32[count]; 00340 if (data != NULL) 00341 { 00342 register Uint32 *q = OFstatic_cast(Uint32 *, data); 00343 if (fromBits == toBits) 00344 { 00345 /* copy pixel data as is */ 00346 for (y = height; y != 0; y--) 00347 { 00348 for (x = width; x != 0; x--) 00349 { 00350 /* reverse sample order: B-G-R-0 */ 00351 *(q++) = (OFstatic_cast(Uint32, *(b++)) << 24) | 00352 (OFstatic_cast(Uint32, *(g++)) << 16) | 00353 (OFstatic_cast(Uint32, *(r++)) << 8); 00354 } 00355 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00356 } 00357 } 00358 else if (fromBits < toBits) 00359 { 00360 /* increase color depth: multiply with factor */ 00361 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00362 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00363 const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); 00364 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00365 { 00366 for (y = height; y != 0; y--) 00367 { 00368 for (x = width; x != 0; x--) 00369 { 00370 /* reverse sample order: B-G-R-0 */ 00371 *(q++) = (OFstatic_cast(Uint32, *(b++) * gradient2) << 24) | 00372 (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) | 00373 (OFstatic_cast(Uint32, *(r++) * gradient2) << 8); 00374 } 00375 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00376 } 00377 } else { 00378 for (y = height; y != 0; y--) 00379 { 00380 for (x = width; x != 0; x--) 00381 { 00382 /* reverse sample order: B-G-R-0 */ 00383 *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 24) | 00384 (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) | 00385 (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 8); 00386 } 00387 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00388 } 00389 } 00390 } 00391 else /* fromBits > toBits */ 00392 { 00393 /* reduce color depth: right shift */ 00394 const int shift = fromBits - toBits; 00395 for (y = height; y != 0; y--) 00396 { 00397 for (x = width; x != 0; x--) 00398 { 00399 /* reverse sample order: B-G-R-0 */ 00400 *(q++) = (OFstatic_cast(Uint32, *(b++) >> shift) << 24) | 00401 (OFstatic_cast(Uint32, *(g++) >> shift) << 16) | 00402 (OFstatic_cast(Uint32, *(r++) >> shift) << 8); 00403 } 00404 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00405 } 00406 } 00407 bytes = fsize; 00408 } 00409 } 00410 } 00411 } 00412 return bytes; 00413 } 00414 00426 unsigned long createAWTBitmap(void *&data, 00427 const Uint16 width, 00428 const Uint16 height, 00429 const unsigned long frame, 00430 const int fromBits, 00431 const int toBits) const 00432 { 00433 data = NULL; 00434 unsigned long bytes = 0; 00435 if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) 00436 { 00437 const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); 00438 data = new Uint32[count]; 00439 if (data != NULL) 00440 { 00441 const unsigned long start = count * frame; 00442 register const T *r = Data[0] + start; 00443 register const T *g = Data[1] + start; 00444 register const T *b = Data[2] + start; 00445 register Uint32 *q = OFstatic_cast(Uint32 *, data); 00446 register unsigned long i; 00447 if (fromBits == toBits) 00448 { 00449 /* copy pixel data as is */ 00450 for (i = count; i != 0; --i) 00451 { 00452 /* sample order: R-G-B */ 00453 *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) | 00454 (OFstatic_cast(Uint32, *(g++)) << 16) | 00455 (OFstatic_cast(Uint32, *(b++)) << 8); 00456 } 00457 } 00458 else if (fromBits < toBits) 00459 { 00460 /* increase color depth: multiply with factor */ 00461 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00462 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00463 const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); 00464 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00465 { 00466 for (i = count; i != 0; --i) 00467 { 00468 /* sample order: R-G-B */ 00469 *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) | 00470 (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) | 00471 (OFstatic_cast(Uint32, *(b++) * gradient2) << 8); 00472 } 00473 } else { 00474 for (i = count; i != 0; --i) 00475 { 00476 /* sample order: R-G-B */ 00477 *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) | 00478 (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) | 00479 (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8); 00480 } 00481 } 00482 } 00483 else /* fromBits > toBits */ 00484 { 00485 /* reduce color depth: right shift */ 00486 const int shift = fromBits - toBits; 00487 for (i = count; i != 0; --i) 00488 { 00489 /* sample order: R-G-B */ 00490 *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) | 00491 (OFstatic_cast(Uint32, *(g++) >> shift) << 16) | 00492 (OFstatic_cast(Uint32, *(b++) >> shift) << 8); 00493 } 00494 } 00495 bytes = count * 4; 00496 } 00497 } 00498 return bytes; 00499 } 00500 00501 00502 protected: 00503 00509 DiColorPixelTemplate(const DiColorPixel *pixel, 00510 const unsigned long count) 00511 : DiColorPixel(pixel, count) 00512 { 00513 Data[0] = NULL; 00514 Data[1] = NULL; 00515 Data[2] = NULL; 00516 } 00517 00524 inline int Init(const void *pixel) 00525 { 00526 int result = 0; 00527 if (pixel != NULL) 00528 { 00529 result = 1; 00530 /* allocate data buffer for the 3 planes */ 00531 for (int j = 0; j < 3; j++) 00532 { 00533 Data[j] = new T[Count]; 00534 if (Data[j] != NULL) 00535 { 00536 /* erase empty part of the buffer (=blacken the background) */ 00537 if (InputCount < Count) 00538 OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount); 00539 } else 00540 result = 0; // at least one buffer could not be allocated! 00541 } 00542 } 00543 return result; 00544 } 00545 00546 00548 T *Data[3]; 00549 00550 00551 private: 00552 00553 // --- declarations to avoid compiler warnings 00554 00555 DiColorPixelTemplate(const DiColorPixelTemplate<T> &); 00556 DiColorPixelTemplate<T> &operator=(const DiColorPixelTemplate<T> &); 00557 }; 00558 00559 00560 #endif 00561 00562 00563 /* 00564 * 00565 * CVS/RCS Log: 00566 * $Log: dicopxt.h,v $ 00567 * Revision 1.25 2005/12/08 16:01:35 meichel 00568 * Changed include path schema for all DCMTK header files 00569 * 00570 * Revision 1.24 2004/10/19 12:57:47 joergr 00571 * Enhanced API documentation. 00572 * 00573 * Revision 1.23 2004/02/06 11:18:18 joergr 00574 * Distinguish more clearly between const and non-const access to pixel data. 00575 * 00576 * Revision 1.22 2004/01/21 12:59:43 meichel 00577 * Added OFconst_cast, needed for Visual C++ 6 00578 * 00579 * Revision 1.21 2003/12/23 11:43:03 joergr 00580 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00581 * Removed leading underscore characters from preprocessor symbols (reserved 00582 * symbols). Updated copyright header. Added missing API documentation. 00583 * Replaced post-increment/decrement operators by pre-increment/decrement 00584 * operators where appropriate (e.g. 'i++' by '++i'). 00585 * 00586 * Revision 1.20 2002/12/10 17:39:50 meichel 00587 * Added explicit type cast to avoid compilation error on gcc 3.2 00588 * 00589 * Revision 1.19 2002/12/09 13:37:24 joergr 00590 * Added private undefined copy constructor and/or assignment operator. 00591 * Fixed bug that caused method createAWTBitmap() to return always empty pixel 00592 * data. 00593 * 00594 * Revision 1.18 2002/09/12 14:10:37 joergr 00595 * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata 00596 * routine and is therefore more efficient. 00597 * 00598 * Revision 1.17 2002/08/29 12:57:49 joergr 00599 * Added method that creates pixel data in DICOM format. 00600 * 00601 * Revision 1.16 2002/06/26 16:17:41 joergr 00602 * Enhanced handling of corrupted pixel data and/or length. 00603 * 00604 * Revision 1.15 2002/01/29 17:07:08 joergr 00605 * Added optional flag to the "Windows DIB" methods allowing to switch off the 00606 * scanline padding. 00607 * 00608 * Revision 1.14 2001/12/11 14:23:44 joergr 00609 * Added type cast to keep old Sun compilers quiet. 00610 * 00611 * Revision 1.13 2001/11/09 16:44:35 joergr 00612 * Enhanced and renamed createTrueColorDIB() method. 00613 * 00614 * Revision 1.12 2001/06/01 15:49:29 meichel 00615 * Updated copyright header 00616 * 00617 * Revision 1.11 2000/03/08 16:21:51 meichel 00618 * Updated copyright header. 00619 * 00620 * Revision 1.10 1999/09/17 14:03:44 joergr 00621 * Enhanced efficiency of some "for" loops. 00622 * 00623 * Revision 1.9 1999/07/23 13:22:29 joergr 00624 * emoved inline method 'removeSign'which is no longer needed. 00625 * 00626 * Revision 1.8 1999/04/28 12:51:58 joergr 00627 * Corrected some typos, comments and formatting. 00628 * 00629 * Revision 1.7 1999/01/20 14:44:49 joergr 00630 * Corrected some typos and formatting. 00631 * 00632 * Revision 1.6 1998/11/27 13:50:20 joergr 00633 * Added copyright message. Replaced delete by delete[] for array types. 00634 * Added method to give direct (non const) access to internal data buffer. 00635 * 00636 * Revision 1.5 1998/05/11 14:53:13 joergr 00637 * Added CVS/RCS header to each file. 00638 * 00639 * 00640 */