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: dcmimgle 00015 * 00016 * Author: Joerg Riesmeier 00017 * 00018 * Purpose: DicomColorOutputPixelTemplate (Header) 00019 * 00020 * Last Update: $Author: joergr $ 00021 * Update Date: $Date: 2010-10-14 13:16:29 $ 00022 * CVS/RCS Revision: $Revision: 1.28 $ 00023 * Status: $State: Exp $ 00024 * 00025 * CVS/RCS Log at end of file 00026 * 00027 */ 00028 00029 00030 #ifndef DICOOPXT_H 00031 #define DICOOPXT_H 00032 00033 #include "dcmtk/config/osconfig.h" 00034 00035 #include "dcmtk/dcmimage/dicoopx.h" 00036 #include "dcmtk/dcmimage/dicopx.h" 00037 #include "dcmtk/dcmimgle/dipxrept.h" 00038 00039 #include "dcmtk/ofstd/ofbmanip.h" 00040 00041 00042 /*---------------------* 00043 * class declaration * 00044 *---------------------*/ 00045 00048 template<class T1, class T2> 00049 class DiColorOutputPixelTemplate 00050 : public DiColorOutputPixel, 00051 public DiPixelRepresentationTemplate<T2> 00052 { 00053 00054 public: 00055 00067 DiColorOutputPixelTemplate(void *buffer, 00068 const DiColorPixel *pixel, 00069 const unsigned long count, 00070 const unsigned long frame, 00071 const int bits1, /* input depth */ 00072 const int bits2, /* output depth */ 00073 const int planar, 00074 const int inverse) 00075 : DiColorOutputPixel(pixel, count, frame), 00076 Data(NULL), 00077 DeleteData(buffer == NULL), 00078 isPlanar(planar) 00079 { 00080 if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count)) 00081 { 00082 Data = OFstatic_cast(T2 *, buffer); 00083 convert(OFstatic_cast(const T1 **, OFconst_cast(void *, pixel->getData())), frame * FrameSize, bits1, bits2, planar, inverse); 00084 } 00085 } 00086 00096 DiColorOutputPixelTemplate(void *buffer, 00097 const DiPixel *pixel, 00098 const unsigned long count, 00099 const unsigned long frame, 00100 const unsigned long /*frames*/, 00101 const int planar) 00102 : DiColorOutputPixel(pixel, count, frame), 00103 Data(NULL), 00104 DeleteData(buffer == NULL), 00105 isPlanar(planar) 00106 { 00107 if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count)) 00108 Data = OFstatic_cast(T2 *, buffer); 00109 } 00110 00113 virtual ~DiColorOutputPixelTemplate() 00114 { 00115 if (DeleteData) 00116 delete[] Data; 00117 } 00118 00123 inline EP_Representation getRepresentation() const 00124 { 00125 return DiPixelRepresentationTemplate<T2>::getRepresentation(); 00126 } 00127 00132 inline size_t getItemSize() const 00133 { 00134 return sizeof(T2) * 3; 00135 } 00136 00141 inline const void *getData() const 00142 { 00143 return OFstatic_cast(const void *, Data); 00144 } 00145 00150 virtual void *getDataPtr() 00151 { 00152 return OFstatic_cast(void *, Data); 00153 } 00154 00161 inline const void *getPlane(const int plane) const 00162 { 00163 void *result = NULL; 00164 if (Data != NULL) 00165 { 00166 if (plane <= 0) 00167 result = OFstatic_cast(void *, Data); 00168 else 00169 { 00170 if (isPlanar) 00171 result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2) * FrameSize); 00172 else 00173 result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2)); 00174 } 00175 } 00176 return result; 00177 } 00178 00185 int writePPM(STD_NAMESPACE ostream& stream) const 00186 { 00187 if (Data != NULL) 00188 { 00189 register T2 *p = Data; 00190 register unsigned long i; 00191 register int j; 00192 for (i = FrameSize; i != 0; --i) 00193 for (j = 3; j != 0; --j) 00194 stream << OFstatic_cast(unsigned long, *(p++)) << " "; // typecast to resolve problems with 'char' 00195 return 1; 00196 } 00197 return 0; 00198 } 00199 00206 int writePPM(FILE *stream) const 00207 { 00208 if (Data != NULL) 00209 { 00210 register T2 *p = Data; 00211 register unsigned long i; 00212 register int j; 00213 for (i = FrameSize; i != 0; --i) 00214 for (j = 3; j != 0; --j) 00215 fprintf(stream, "%lu ", OFstatic_cast(unsigned long, *(p++))); 00216 return 1; 00217 } 00218 return 0; 00219 } 00220 00221 00222 protected: 00223 00225 T2 *Data; 00226 00227 00228 private: 00229 00239 void convert(const T1 *pixel[3], 00240 const unsigned long start, 00241 const int bits1, 00242 const int bits2, 00243 const int planar, 00244 const int inverse) 00245 { 00246 if ((pixel[0] != NULL) && (pixel[1] != NULL) && (pixel[2] != NULL)) 00247 { 00248 if (Data == NULL) 00249 Data = new T2[FrameSize * 3]; 00250 if (Data != NULL) 00251 { 00252 DCMIMAGE_DEBUG("converting color pixel data to output format"); 00253 register T2 *q = Data; 00254 register unsigned long i; 00255 const T2 max2 = OFstatic_cast(T2, DicomImageClass::maxval(bits2)); 00256 if (planar) 00257 { 00258 register const T1 *p; 00259 if (bits1 == bits2) 00260 { 00261 for (int j = 0; j < 3; ++j) 00262 { 00263 p = pixel[j] + start; 00264 /* invert output data */ 00265 if (inverse) 00266 { 00267 for (i = Count; i != 0; --i) // copy inverted data 00268 *(q++) = max2 - OFstatic_cast(T2, *(p++)); 00269 } else { 00270 for (i = Count; i != 0; --i) // copy 00271 *(q++) = OFstatic_cast(T2, *(p++)); 00272 } 00273 if (Count < FrameSize) 00274 { 00275 OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero 00276 q += (FrameSize - Count); 00277 } 00278 } 00279 } 00280 else if (bits1 < bits2) // optimization possible using LUT 00281 { 00282 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) / 00283 OFstatic_cast(double, DicomImageClass::maxval(bits1)); 00284 const T2 gradient2 = OFstatic_cast(T2, gradient1); 00285 for (int j = 0; j < 3; ++j) 00286 { 00287 p = pixel[j] + start; 00288 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00289 { 00290 /* invert output data */ 00291 if (inverse) 00292 { 00293 for (i = Count; i != 0; --i) // expand depth & invert 00294 *(q++) = max2 - OFstatic_cast(T2, *(p++)) * gradient2; 00295 } else { 00296 for (i = Count; i != 0; --i) // expand depth 00297 *(q++) = OFstatic_cast(T2, *(p++)) * gradient2; 00298 } 00299 } else { 00300 /* invert output data */ 00301 if (inverse) 00302 { 00303 for (i = Count; i != 0; --i) // expand depth & invert 00304 *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1); 00305 } else { 00306 for (i = Count; i != 0; --i) // expand depth 00307 *(q++) = OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1); 00308 } 00309 } 00310 if (Count < FrameSize) 00311 { 00312 OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero 00313 q += (FrameSize - Count); 00314 } 00315 } // ... to be enhanced ! 00316 } 00317 else /* bits1 > bits2 */ 00318 { 00319 const int shift = bits1 - bits2; 00320 for (int j = 0; j < 3; ++j) 00321 { 00322 p = pixel[j] + start; 00323 /* invert output data */ 00324 if (inverse) 00325 { 00326 for (i = Count; i != 0; --i) // reduce depth & invert 00327 *(q++) = max2 - OFstatic_cast(T2, *(p++) >> shift); 00328 } else { 00329 for (i = Count; i != 0; --i) // reduce depth 00330 *(q++) = OFstatic_cast(T2, *(p++) >> shift); 00331 } 00332 if (Count < FrameSize) 00333 { 00334 OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero 00335 q += (FrameSize - Count); 00336 } 00337 } 00338 } 00339 } 00340 else /* not planar */ 00341 { 00342 register int j; 00343 if (bits1 == bits2) 00344 { 00345 /* invert output data */ 00346 if (inverse) 00347 { 00348 for (i = start; i < start + Count; ++i) 00349 for (j = 0; j < 3; ++j) // copy inverted data 00350 *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]); 00351 } else { 00352 for (i = start; i < start + Count; ++i) 00353 for (j = 0; j < 3; ++j) // copy 00354 *(q++) = OFstatic_cast(T2, pixel[j][i]); 00355 } 00356 } 00357 else if (bits1 < bits2) // optimization possible using LUT 00358 { 00359 const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) / 00360 OFstatic_cast(double, DicomImageClass::maxval(bits1)); 00361 const T2 gradient2 = OFstatic_cast(T2, gradient1); 00362 if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? 00363 { 00364 /* invert output data */ 00365 if (inverse) 00366 { 00367 for (i = start; i < start + Count; ++i) // expand depth & invert 00368 for (j = 0; j < 3; ++j) 00369 *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]) * gradient2; 00370 } else { 00371 for (i = start; i < start + Count; ++i) 00372 for (j = 0; j < 3; ++j) // expand depth 00373 *(q++) = OFstatic_cast(T2, pixel[j][i]) * gradient2; 00374 } 00375 } else { 00376 /* invert output data */ 00377 if (inverse) 00378 { 00379 for (i = start; i < start + Count; ++i) 00380 for (j = 0; j < 3; ++j) // expand depth & invert 00381 *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1); 00382 } else { 00383 for (i = start; i < start + Count; ++i) 00384 for (j = 0; j < 3; ++j) // expand depth 00385 *(q++) = OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1); 00386 } 00387 } 00388 } 00389 else /* bits1 > bits2 */ 00390 { 00391 const int shift = bits1 - bits2; 00392 /* invert output data */ 00393 if (inverse) 00394 { 00395 for (i = start; i < start + Count; ++i) 00396 for (j = 0; j < 3; ++j) // reduce depth & invert 00397 *(q++) = max2 - OFstatic_cast(T2, pixel[j][i] >> shift); 00398 } else { 00399 for (i = start; i < start + Count; ++i) 00400 for (j = 0; j < 3; ++j) // reduce depth 00401 *(q++) = OFstatic_cast(T2, pixel[j][i] >> shift); 00402 } 00403 } 00404 if (Count < FrameSize) 00405 OFBitmanipTemplate<T2>::zeroMem(q, 3 * (FrameSize - Count)); // set remaining pixels of frame to zero 00406 } 00407 } 00408 } else 00409 Data = NULL; 00410 } 00411 00413 int DeleteData; 00415 int isPlanar; 00416 00417 // --- declarations to avoid compiler warnings 00418 00419 DiColorOutputPixelTemplate(const DiColorOutputPixelTemplate<T1,T2> &); 00420 DiColorOutputPixelTemplate<T1,T2> &operator=(const DiColorOutputPixelTemplate<T1,T2> &); 00421 }; 00422 00423 00424 #endif 00425 00426 00427 /* 00428 * 00429 * CVS/RCS Log: 00430 * $Log: dicoopxt.h,v $ 00431 * Revision 1.28 2010-10-14 13:16:29 joergr 00432 * Updated copyright header. Added reference to COPYRIGHT file. 00433 * 00434 * Revision 1.27 2010-10-05 15:34:41 joergr 00435 * Output information on conversion process to the logger (debug mode). 00436 * Fixed various Doxygen API documentation issues. 00437 * 00438 * Revision 1.26 2010-03-01 09:08:46 uli 00439 * Removed some unnecessary include directives in the headers. 00440 * 00441 * Revision 1.25 2006-08-15 16:35:01 meichel 00442 * Updated the code in module dcmimage to correctly compile when 00443 * all standard C++ classes remain in namespace std. 00444 * 00445 * Revision 1.24 2005/12/08 16:01:33 meichel 00446 * Changed include path schema for all DCMTK header files 00447 * 00448 * Revision 1.23 2004/02/06 11:18:18 joergr 00449 * Distinguish more clearly between const and non-const access to pixel data. 00450 * 00451 * Revision 1.22 2003/12/23 16:06:21 joergr 00452 * Replaced additional post-increment/decrement operators by pre-increment/ 00453 * decrement operators. 00454 * 00455 * Revision 1.21 2003/12/23 11:36:24 joergr 00456 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00457 * Removed leading underscore characters from preprocessor symbols (reserved 00458 * symbols). Updated copyright header. 00459 * Replaced post-increment/decrement operators by pre-increment/decrement 00460 * operators where appropriate (e.g. 'i++' by '++i'). 00461 * 00462 * Revision 1.20 2002/06/26 17:20:31 joergr 00463 * Added type cast to keep MSVC6 quiet. 00464 * 00465 * Revision 1.19 2002/06/26 16:17:16 joergr 00466 * Added support for polarity flag to color images. 00467 * 00468 * Revision 1.18 2001/11/09 16:42:04 joergr 00469 * Removed 'inline' specifier from certain methods. 00470 * 00471 * Revision 1.17 2001/06/01 15:49:29 meichel 00472 * Updated copyright header 00473 * 00474 * Revision 1.16 2000/03/30 14:15:44 joergr 00475 * Corrected wrong bit expansion of output pixel data (left shift is not 00476 * correct). 00477 * 00478 * Revision 1.15 2000/03/08 16:21:50 meichel 00479 * Updated copyright header. 00480 * 00481 * Revision 1.14 1999/09/17 14:03:43 joergr 00482 * Enhanced efficiency of some "for" loops. 00483 * 00484 * Revision 1.13 1999/08/17 10:28:47 joergr 00485 * Commented unused parameter name to avoid compiler warnings. 00486 * Removed unused parameter. 00487 * 00488 * Revision 1.12 1999/07/23 13:20:45 joergr 00489 * Enhanced handling of corrupted pixel data (wrong length). 00490 * 00491 * Revision 1.11 1999/04/30 16:12:03 meichel 00492 * Minor code purifications to keep IBM xlC quiet 00493 * 00494 * Revision 1.10 1999/04/29 09:31:13 joergr 00495 * Moved color related image files back to non-public part. 00496 * 00497 * Revision 1.1 1999/04/28 14:57:31 joergr 00498 * Moved files from dcmimage module to dcmimgle to support new pastel color 00499 * output format. 00500 * 00501 * Revision 1.8 1999/01/20 14:43:12 joergr 00502 * Replaced invocation of getCount() by member variable Count where possible. 00503 * Added new output method to fill external memory buffer with rendered pixel 00504 * data. 00505 * 00506 * Revision 1.7 1998/12/22 13:23:57 joergr 00507 * Added comments that the routines for expanding pixel's depth have to be 00508 * enhanced in the future (replicate bit pattern instead of shifting). Same 00509 * question for reducing depth. 00510 * 00511 * Revision 1.6 1998/11/27 13:46:00 joergr 00512 * Added copyright message. Replaced delete by delete[] for array types. 00513 * 00514 * Revision 1.5 1998/07/01 08:39:19 joergr 00515 * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional 00516 * options), e.g. add copy constructors. 00517 * 00518 * Revision 1.4 1998/05/11 14:53:12 joergr 00519 * Added CVS/RCS header to each file. 00520 * 00521 * 00522 */