00001 /* 00002 * 00003 * Copyright (C) 1996-2004, 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: joergr $ 00025 * Update Date: $Date: 2004/02/06 11:18:18 $ 00026 * CVS/RCS Revision: $Revision: 1.23 $ 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 "osconfig.h" 00038 #include "dctypes.h" 00039 #include "ofbmanip.h" 00040 00041 #include "dicopx.h" 00042 #include "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 00158 inline const void *getData() const 00159 { 00160 return OFstatic_cast(const void *, Data); 00161 } 00162 00167 inline void *getDataPtr() 00168 { 00169 return OFstatic_cast(void *, Data); 00170 } 00171 00176 inline void *getDataArrayPtr() 00177 { 00178 return OFstatic_cast(void *, Data); 00179 } 00180 00190 OFBool getPixelData(void *data, 00191 const size_t count) const 00192 { 00193 OFBool result = OFFalse; 00194 /* check parameters and internal data */ 00195 if ((data != NULL) && (count >= Count * 3) && 00196 (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL)) 00197 { 00198 /* copy all three planes to the given memory block */ 00199 OFBitmanipTemplate<T>::copyMem(Data[0], OFstatic_cast(T *, data), Count); 00200 OFBitmanipTemplate<T>::copyMem(Data[1], OFstatic_cast(T *, data) + Count, Count); 00201 OFBitmanipTemplate<T>::copyMem(Data[2], OFstatic_cast(T *, data) + 2 * Count, Count); 00202 result = OFTrue; 00203 } 00204 return result; 00205 } 00206 00222 unsigned long createDIB(void *&data, 00223 const unsigned long size, 00224 const Uint16 width, 00225 const Uint16 height, 00226 const unsigned long frame, 00227 const int fromBits, 00228 const int toBits, 00229 const int mode, 00230 const int upsideDown, 00231 const int padding) const 00232 { 00233 unsigned long bytes = 0; 00234 if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) 00235 { 00236 const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); 00237 const unsigned long start = count * frame + ((upsideDown) ? 00238 OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0); 00239 const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0; 00240 register const T *r = Data[0] + start; 00241 register const T *g = Data[1] + start; 00242 register const T *b = Data[2] + start; 00243 register Uint16 x; 00244 register Uint16 y; 00245 if (mode == 24) // 24 bits per pixel 00246 { 00247 const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3; 00248 // each line has to start at 32-bit-address, if 'padding' is true 00249 const int gap = (padding) ? OFstatic_cast(int, (4 - wid3 & 0x3) & 0x3) : 0; 00250 unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height); 00251 if ((data == NULL) || (size >= fsize)) 00252 { 00253 if (data == NULL) 00254 data = new Uint8[fsize]; 00255 if (data != NULL) 00256 { 00257 register Uint8 *q = OFstatic_cast(Uint8 *, data); 00258 if (fromBits == toBits) 00259 { 00260 /* copy pixel data as is */ 00261 for (y = height; y != 0; y--) 00262 { 00263 for (x = width; x != 0; x--) 00264 { 00265 /* reverse sample order: B-G-R */ 00266 *(q++) = OFstatic_cast(Uint8, *(b++)); 00267 *(q++) = OFstatic_cast(Uint8, *(g++)); 00268 *(q++) = OFstatic_cast(Uint8, *(r++)); 00269 } 00270 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00271 q += gap; // new line: jump to next 32-bit address 00272 } 00273 } 00274 else if (fromBits < toBits) 00275 { 00276 /* increase color depth: multiply with factor */ 00277 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00278 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00279 const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1); 00280 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00281 { 00282 for (y = height; y != 0; y--) 00283 { 00284 for (x = width; x != 0; x--) 00285 { 00286 /* reverse sample order: B-G-R */ 00287 *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2); 00288 *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2); 00289 *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2); 00290 } 00291 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00292 q += gap; // new line: jump to next 32-bit address 00293 } 00294 } else { 00295 for (y = height; y != 0; y--) 00296 { 00297 for (x = width; x != 0; x--) 00298 { 00299 /* reverse sample order: B-G-R */ 00300 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1); 00301 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1); 00302 *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1); 00303 } 00304 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00305 q += gap; // new line: jump to next 32-bit address 00306 } 00307 } 00308 } 00309 else /* fromBits > toBits */ 00310 { 00311 /* reduce color depth: right shift */ 00312 const int shift = fromBits - toBits; 00313 for (y = height; y != 0; y--) 00314 { 00315 for (x = width; x != 0; x--) 00316 { 00317 /* reverse sample order: B-G-R */ 00318 *(q++) = OFstatic_cast(Uint8, *(b++) >> shift); 00319 *(q++) = OFstatic_cast(Uint8, *(g++) >> shift); 00320 *(q++) = OFstatic_cast(Uint8, *(r++) >> shift); 00321 } 00322 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00323 q += gap; // new line: jump to next 32-bit address 00324 } 00325 } 00326 bytes = fsize; 00327 } 00328 } 00329 } 00330 else if (mode == 32) // 32 bits per pixel 00331 { 00332 const unsigned long fsize = count * 4; 00333 if ((data == NULL) || (size >= fsize)) 00334 { 00335 if (data == NULL) 00336 data = new Uint32[count]; 00337 if (data != NULL) 00338 { 00339 register Uint32 *q = OFstatic_cast(Uint32 *, data); 00340 if (fromBits == toBits) 00341 { 00342 /* copy pixel data as is */ 00343 for (y = height; y != 0; y--) 00344 { 00345 for (x = width; x != 0; x--) 00346 { 00347 /* reverse sample order: B-G-R-0 */ 00348 *(q++) = (OFstatic_cast(Uint32, *(b++)) << 24) | 00349 (OFstatic_cast(Uint32, *(g++)) << 16) | 00350 (OFstatic_cast(Uint32, *(r++)) << 8); 00351 } 00352 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00353 } 00354 } 00355 else if (fromBits < toBits) 00356 { 00357 /* increase color depth: multiply with factor */ 00358 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00359 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00360 const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); 00361 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00362 { 00363 for (y = height; y != 0; y--) 00364 { 00365 for (x = width; x != 0; x--) 00366 { 00367 /* reverse sample order: B-G-R-0 */ 00368 *(q++) = (OFstatic_cast(Uint32, *(b++) * gradient2) << 24) | 00369 (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) | 00370 (OFstatic_cast(Uint32, *(r++) * gradient2) << 8); 00371 } 00372 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00373 } 00374 } else { 00375 for (y = height; y != 0; y--) 00376 { 00377 for (x = width; x != 0; x--) 00378 { 00379 /* reverse sample order: B-G-R-0 */ 00380 *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 24) | 00381 (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) | 00382 (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 8); 00383 } 00384 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00385 } 00386 } 00387 } 00388 else /* fromBits > toBits */ 00389 { 00390 /* reduce color depth: right shift */ 00391 const int shift = fromBits - toBits; 00392 for (y = height; y != 0; y--) 00393 { 00394 for (x = width; x != 0; x--) 00395 { 00396 /* reverse sample order: B-G-R-0 */ 00397 *(q++) = (OFstatic_cast(Uint32, *(b++) >> shift) << 24) | 00398 (OFstatic_cast(Uint32, *(g++) >> shift) << 16) | 00399 (OFstatic_cast(Uint32, *(r++) >> shift) << 8); 00400 } 00401 r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' 00402 } 00403 } 00404 bytes = fsize; 00405 } 00406 } 00407 } 00408 } 00409 return bytes; 00410 } 00411 00423 unsigned long createAWTBitmap(void *&data, 00424 const Uint16 width, 00425 const Uint16 height, 00426 const unsigned long frame, 00427 const int fromBits, 00428 const int toBits) const 00429 { 00430 data = NULL; 00431 unsigned long bytes = 0; 00432 if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) 00433 { 00434 const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); 00435 data = new Uint32[count]; 00436 if (data != NULL) 00437 { 00438 const unsigned long start = count * frame; 00439 register const T *r = Data[0] + start; 00440 register const T *g = Data[1] + start; 00441 register const T *b = Data[2] + start; 00442 register Uint32 *q = OFstatic_cast(Uint32 *, data); 00443 register unsigned long i; 00444 if (fromBits == toBits) 00445 { 00446 /* copy pixel data as is */ 00447 for (i = count; i != 0; --i) 00448 { 00449 /* sample order: R-G-B */ 00450 *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) | 00451 (OFstatic_cast(Uint32, *(g++)) << 16) | 00452 (OFstatic_cast(Uint32, *(b++)) << 8); 00453 } 00454 } 00455 else if (fromBits < toBits) 00456 { 00457 /* increase color depth: multiply with factor */ 00458 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / 00459 OFstatic_cast(double, DicomImageClass::maxval(fromBits)); 00460 const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); 00461 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00462 { 00463 for (i = count; i != 0; --i) 00464 { 00465 /* sample order: R-G-B */ 00466 *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) | 00467 (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) | 00468 (OFstatic_cast(Uint32, *(b++) * gradient2) << 8); 00469 } 00470 } else { 00471 for (i = count; i != 0; --i) 00472 { 00473 /* sample order: R-G-B */ 00474 *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) | 00475 (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) | 00476 (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8); 00477 } 00478 } 00479 } 00480 else /* fromBits > toBits */ 00481 { 00482 /* reduce color depth: right shift */ 00483 const int shift = fromBits - toBits; 00484 for (i = count; i != 0; --i) 00485 { 00486 /* sample order: R-G-B */ 00487 *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) | 00488 (OFstatic_cast(Uint32, *(g++) >> shift) << 16) | 00489 (OFstatic_cast(Uint32, *(b++) >> shift) << 8); 00490 } 00491 } 00492 bytes = count * 4; 00493 } 00494 } 00495 return bytes; 00496 } 00497 00498 00499 protected: 00500 00506 DiColorPixelTemplate(const DiColorPixel *pixel, 00507 const unsigned long count) 00508 : DiColorPixel(pixel, count) 00509 { 00510 Data[0] = NULL; 00511 Data[1] = NULL; 00512 Data[2] = NULL; 00513 } 00514 00521 inline int Init(const void *pixel) 00522 { 00523 int result = 0; 00524 if (pixel != NULL) 00525 { 00526 result = 1; 00527 /* allocate data buffer for the 3 planes */ 00528 for (int j = 0; j < 3; j++) 00529 { 00530 Data[j] = new T[Count]; 00531 if (Data[j] != NULL) 00532 { 00533 /* erase empty part of the buffer (=blacken the background) */ 00534 if (InputCount < Count) 00535 OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount); 00536 } else 00537 result = 0; // at least one buffer could not be allocated! 00538 } 00539 } 00540 return result; 00541 } 00542 00543 00545 T *Data[3]; 00546 00547 00548 private: 00549 00550 // --- declarations to avoid compiler warnings 00551 00552 DiColorPixelTemplate(const DiColorPixelTemplate<T> &); 00553 DiColorPixelTemplate<T> &operator=(const DiColorPixelTemplate<T> &); 00554 }; 00555 00556 00557 #endif 00558 00559 00560 /* 00561 * 00562 * CVS/RCS Log: 00563 * $Log: dicopxt.h,v $ 00564 * Revision 1.23 2004/02/06 11:18:18 joergr 00565 * Distinguish more clearly between const and non-const access to pixel data. 00566 * 00567 * Revision 1.22 2004/01/21 12:59:43 meichel 00568 * Added OFconst_cast, needed for Visual C++ 6 00569 * 00570 * Revision 1.21 2003/12/23 11:43:03 joergr 00571 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00572 * Removed leading underscore characters from preprocessor symbols (reserved 00573 * symbols). Updated copyright header. Added missing API documentation. 00574 * Replaced post-increment/decrement operators by pre-increment/decrement 00575 * operators where appropriate (e.g. 'i++' by '++i'). 00576 * 00577 * Revision 1.20 2002/12/10 17:39:50 meichel 00578 * Added explicit type cast to avoid compilation error on gcc 3.2 00579 * 00580 * Revision 1.19 2002/12/09 13:37:24 joergr 00581 * Added private undefined copy constructor and/or assignment operator. 00582 * Fixed bug that caused method createAWTBitmap() to return always empty pixel 00583 * data. 00584 * 00585 * Revision 1.18 2002/09/12 14:10:37 joergr 00586 * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata 00587 * routine and is therefore more efficient. 00588 * 00589 * Revision 1.17 2002/08/29 12:57:49 joergr 00590 * Added method that creates pixel data in DICOM format. 00591 * 00592 * Revision 1.16 2002/06/26 16:17:41 joergr 00593 * Enhanced handling of corrupted pixel data and/or length. 00594 * 00595 * Revision 1.15 2002/01/29 17:07:08 joergr 00596 * Added optional flag to the "Windows DIB" methods allowing to switch off the 00597 * scanline padding. 00598 * 00599 * Revision 1.14 2001/12/11 14:23:44 joergr 00600 * Added type cast to keep old Sun compilers quiet. 00601 * 00602 * Revision 1.13 2001/11/09 16:44:35 joergr 00603 * Enhanced and renamed createTrueColorDIB() method. 00604 * 00605 * Revision 1.12 2001/06/01 15:49:29 meichel 00606 * Updated copyright header 00607 * 00608 * Revision 1.11 2000/03/08 16:21:51 meichel 00609 * Updated copyright header. 00610 * 00611 * Revision 1.10 1999/09/17 14:03:44 joergr 00612 * Enhanced efficiency of some "for" loops. 00613 * 00614 * Revision 1.9 1999/07/23 13:22:29 joergr 00615 * emoved inline method 'removeSign'which is no longer needed. 00616 * 00617 * Revision 1.8 1999/04/28 12:51:58 joergr 00618 * Corrected some typos, comments and formatting. 00619 * 00620 * Revision 1.7 1999/01/20 14:44:49 joergr 00621 * Corrected some typos and formatting. 00622 * 00623 * Revision 1.6 1998/11/27 13:50:20 joergr 00624 * Added copyright message. Replaced delete by delete[] for array types. 00625 * Added method to give direct (non const) access to internal data buffer. 00626 * 00627 * Revision 1.5 1998/05/11 14:53:13 joergr 00628 * Added CVS/RCS header to each file. 00629 * 00630 * 00631 */