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