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: DicomMonochromePixelTemplate (Header) 00023 * 00024 * Last Update: $Author: meichel $ 00025 * Update Date: $Date: 2005/12/08 16:47:56 $ 00026 * CVS/RCS Revision: $Revision: 1.27 $ 00027 * Status: $State: Exp $ 00028 * 00029 * CVS/RCS Log at end of file 00030 * 00031 */ 00032 00033 00034 #ifndef DIMOPXT_H 00035 #define DIMOPXT_H 00036 00037 #include "dcmtk/config/osconfig.h" 00038 #include "dcmtk/ofstd/ofconsol.h" 00039 #include "dcmtk/ofstd/ofbmanip.h" 00040 #include "dcmtk/ofstd/ofcast.h" 00041 00042 #include "dcmtk/dcmdata/dctypes.h" 00043 #include "dcmtk/dcmdata/dcdefine.h" 00044 00045 #include "dcmtk/dcmimgle/dimopx.h" 00046 #include "dcmtk/dcmimgle/dipxrept.h" 00047 #include "dcmtk/dcmimgle/dimomod.h" 00048 #include "dcmtk/dcmimgle/diinpx.h" 00049 #include "dcmtk/dcmimgle/dimoopx.h" 00050 00051 00052 /*---------------------* 00053 * class declaration * 00054 *---------------------*/ 00055 00058 template<class T> 00059 class DiMonoPixelTemplate 00060 : public DiMonoPixel, 00061 public DiPixelRepresentationTemplate<T> 00062 { 00063 00064 public: 00065 00070 DiMonoPixelTemplate(const unsigned long count) 00071 : DiMonoPixel(count), 00072 Data(NULL) 00073 { 00074 MinValue[0] = 0; 00075 MinValue[1] = 0; 00076 MaxValue[0] = 0; 00077 MaxValue[1] = 0; 00078 // allocate buffer of given size 00079 Data = new T[Count]; 00080 } 00081 00087 DiMonoPixelTemplate(const DiInputPixel *pixel, 00088 DiMonoModality *modality) 00089 : DiMonoPixel(pixel, modality), 00090 Data(NULL) 00091 { 00092 MinValue[0] = 0; 00093 MinValue[1] = 0; 00094 MaxValue[0] = 0; 00095 MaxValue[1] = 0; 00096 } 00097 00103 DiMonoPixelTemplate(DiMonoOutputPixel *pixel, 00104 DiMonoModality *modality) 00105 : DiMonoPixel(pixel, modality), 00106 Data(OFstatic_cast(T *, pixel->getDataPtr())) 00107 { 00108 MinValue[0] = 0; 00109 MinValue[1] = 0; 00110 MaxValue[0] = 0; 00111 MaxValue[1] = 0; 00112 } 00113 00116 virtual ~DiMonoPixelTemplate() 00117 { 00118 delete[] Data; 00119 } 00120 00125 inline EP_Representation getRepresentation() const 00126 { 00127 return DiPixelRepresentationTemplate<T>::getRepresentation(); 00128 } 00129 00134 inline const void *getData() const 00135 { 00136 return OFstatic_cast(const void *, Data); 00137 } 00138 00143 inline void *getDataPtr() 00144 { 00145 return OFstatic_cast(void *, Data); 00146 } 00147 00154 inline void *getDataArrayPtr() 00155 { 00156 return OFstatic_cast(void *, &Data); 00157 } 00158 00166 inline int getMinMaxValues(double &min, 00167 double &max) const 00168 { 00169 min = MinValue[0]; 00170 max = MaxValue[0]; 00171 return 1; 00172 } 00173 00182 inline int getMinMaxWindow(const int idx, 00183 double ¢er, 00184 double &width) 00185 { 00186 int result = 0; 00187 if ((idx >= 0) && (idx <= 1)) 00188 { 00189 if ((idx == 1) && (MinValue[1] == 0) && (MaxValue[1] == 0)) 00190 determineMinMax(0, 0, 0x2); // determine on demand 00191 /* suppl. 33: "A Window Center of 2^n-1 and a Window Width of 2^n 00192 selects the range of input values from 0 to 2^n-1." 00193 */ 00194 center = (OFstatic_cast(double, MinValue[idx]) + OFstatic_cast(double, MaxValue[idx]) + 1) / 2; // type cast to avoid overflows ! 00195 width = OFstatic_cast(double, MaxValue[idx]) - OFstatic_cast(double, MinValue[idx]) + 1; 00196 result = (width > 0); // check for valid value 00197 } 00198 return result; 00199 } 00200 00215 virtual int getRoiWindow(const unsigned long left_pos, 00216 const unsigned long top_pos, 00217 const unsigned long width, 00218 const unsigned long height, 00219 const unsigned long columns, 00220 const unsigned long rows, 00221 const unsigned long frame, 00222 double &voiCenter, 00223 double &voiWidth) 00224 { 00225 int result = 0; 00226 if ((Data != NULL) && (left_pos < columns) && (top_pos < rows)) 00227 { 00228 register T *p = Data + (columns * rows * frame) + (top_pos * columns) + left_pos; 00229 const unsigned long right_pos = (left_pos + width < columns) ? left_pos + width : columns; 00230 const unsigned long bottom = (top_pos + height < rows) ? top_pos + height : rows; 00231 const unsigned long skip_x = left_pos + (columns - right_pos); 00232 register unsigned long x; 00233 register unsigned long y; 00234 register T value = 0; 00235 register T min = *p; // get first pixel as initial value for min ... 00236 register T max = min; // ... and max 00237 for (y = top_pos; y < bottom; ++y) 00238 { 00239 for (x = left_pos; x < right_pos; ++x) 00240 { 00241 value = *(p++); 00242 if (value < min) 00243 min = value; 00244 else if (value > max) 00245 max = value; 00246 } 00247 p += skip_x; // skip rest of current line and beginning of next 00248 } 00249 /* suppl. 33: "A Window Center of 2^n-1 and a Window Width of 2^n 00250 selects the range of input values from 0 to 2^n-1." 00251 */ 00252 voiCenter = (OFstatic_cast(double, min) + OFstatic_cast(double, max) + 1) / 2; // type cast to avoid overflows ! 00253 voiWidth = OFstatic_cast(double, max) - OFstatic_cast(double, min) + 1; 00254 result = (width > 0); // check for valid value 00255 } 00256 return result; 00257 } 00258 00267 int getHistogramWindow(const double thresh, // could be optimized if necessary (see diinpxt.h)! 00268 double ¢er, 00269 double &width) 00270 { 00271 if ((Data != NULL) && (MinValue[0] < MaxValue[0])) 00272 { 00273 const Uint32 count = OFstatic_cast(Uint32, MaxValue[0] - MinValue[0] + 1); 00274 Uint32 *quant = new Uint32[count]; 00275 if (quant != NULL) 00276 { 00277 register unsigned long i; 00278 OFBitmanipTemplate<Uint32>::zeroMem(quant, count); // initialize array 00279 for (i = 0; i < Count; ++i) 00280 { 00281 if ((Data[i] >= MinValue[0]) && (Data[i] <= MaxValue[0])) // only for stability ! 00282 ++quant[OFstatic_cast(Uint32, Data[i] - MinValue[0])]; // count values 00283 #ifdef DEBUG 00284 else if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Warnings)) 00285 { 00286 ofConsole.lockCerr() << "WARNING: invalid value (" << Data[i] << ") in " 00287 << "int DiMonoPixelTemplate<T>::getHistogramWindow() ! " << endl; 00288 ofConsole.unlockCerr(); 00289 } 00290 #endif 00291 } 00292 const Uint32 threshvalue = OFstatic_cast(Uint32, thresh * OFstatic_cast(double, Count)); 00293 register Uint32 t = 0; 00294 i = 0; 00295 while ((i < count) && (t < threshvalue)) 00296 t += quant[i++]; 00297 const T minvalue = (i < count) ? OFstatic_cast(T, MinValue[0] + i) : 0; 00298 t = 0; 00299 i = count; 00300 while ((i > 0) && (t < threshvalue)) 00301 t += quant[--i]; 00302 const T maxvalue = (i > 0) ? OFstatic_cast(T, MinValue[0] + i) : 0; 00303 delete[] quant; 00304 if (minvalue < maxvalue) 00305 { 00306 /* suppl. 33: "A Window Center of 2^n-1 and a Window Width of 2^n 00307 selects the range of input values from 0 to 2^n-1." 00308 */ 00309 center = (OFstatic_cast(double, minvalue) + OFstatic_cast(double, maxvalue) + 1) / 2; 00310 width = OFstatic_cast(double, maxvalue) - OFstatic_cast(double, minvalue) + 1; 00311 return (width > 0); 00312 } 00313 } 00314 } 00315 return 0; 00316 } 00317 00318 00319 protected: 00320 00326 DiMonoPixelTemplate(const DiPixel *pixel, 00327 DiMonoModality *modality) 00328 : DiMonoPixel(pixel, modality), 00329 Data(NULL) 00330 { 00331 MinValue[0] = 0; 00332 MinValue[1] = 0; 00333 MaxValue[0] = 0; 00334 MaxValue[1] = 0; 00335 } 00336 00342 DiMonoPixelTemplate(const DiMonoPixel *pixel, 00343 const unsigned long count) 00344 : DiMonoPixel(pixel, count), 00345 Data(NULL) 00346 { 00347 MinValue[0] = 0; 00348 MinValue[1] = 0; 00349 MaxValue[0] = 0; 00350 MaxValue[1] = 0; 00351 } 00352 00360 void determineMinMax(T minvalue = 0, 00361 T maxvalue = 0, 00362 const int mode = 0x1) 00363 { 00364 if (Data != NULL) 00365 { 00366 if (mode & 0x1) 00367 { 00368 if ((minvalue == 0) && (maxvalue == 0)) 00369 { 00370 register T *p = Data; 00371 register T value = *p; 00372 register unsigned long i; 00373 minvalue = value; 00374 maxvalue = value; 00375 for (i = Count; i > 1; --i) // could be optimized if necessary (see diinpxt.h) ! 00376 { 00377 value = *(++p); 00378 if (value < minvalue) 00379 minvalue = value; 00380 else if (value > maxvalue) 00381 maxvalue = value; 00382 } 00383 } 00384 MinValue[0] = minvalue; // global minimum 00385 MaxValue[0] = maxvalue; // global maximum 00386 MinValue[1] = 0; // invalidate value 00387 MaxValue[1] = 0; 00388 } else { 00389 minvalue = MinValue[0]; 00390 maxvalue = MaxValue[0]; 00391 } 00392 if (mode & 0x2) 00393 { 00394 register T *p = Data; 00395 register T value; 00396 register int firstmin = 1; 00397 register int firstmax = 1; 00398 register unsigned long i; 00399 for (i = Count; i != 0; --i) // could be optimized if necessary (see diinpxt.h) ! 00400 { 00401 value = *(p++); 00402 if ((value > minvalue) && ((value < MinValue[1]) || firstmin)) 00403 { 00404 MinValue[1] = value; 00405 firstmin = 0; 00406 } 00407 if ((value < maxvalue) && ((value > MaxValue[1]) || firstmax)) 00408 { 00409 MaxValue[1] = value; 00410 firstmax = 0; 00411 } 00412 } 00413 } 00414 } 00415 } 00416 00418 T *Data; 00419 00420 00421 private: 00422 00424 T MinValue[2]; 00426 T MaxValue[2]; 00427 00428 // --- declarations to avoid compiler warnings 00429 00430 DiMonoPixelTemplate(const DiMonoPixelTemplate<T> &); 00431 DiMonoPixelTemplate<T> &operator=(const DiMonoPixelTemplate<T> &); 00432 }; 00433 00434 00435 #endif 00436 00437 00438 /* 00439 * 00440 * CVS/RCS Log: 00441 * $Log: dimopxt.h,v $ 00442 * Revision 1.27 2005/12/08 16:47:56 meichel 00443 * Changed include path schema for all DCMTK header files 00444 * 00445 * Revision 1.26 2004/10/19 12:58:24 joergr 00446 * Enhanced API documentation. 00447 * 00448 * Revision 1.25 2004/02/06 11:07:50 joergr 00449 * Distinguish more clearly between const and non-const access to pixel data. 00450 * 00451 * Revision 1.24 2004/01/05 14:52:20 joergr 00452 * Removed acknowledgements with e-mail addresses from CVS log. 00453 * 00454 * Revision 1.23 2003/12/23 15:53:22 joergr 00455 * Replaced post-increment/decrement operators by pre-increment/decrement 00456 * operators where appropriate (e.g. 'i++' by '++i'). 00457 * 00458 * Revision 1.22 2003/12/09 10:02:04 joergr 00459 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00460 * Removed leading underscore characters from preprocessor symbols (reserved 00461 * symbols). Updated copyright header. 00462 * 00463 * Revision 1.21 2002/12/09 13:32:54 joergr 00464 * Renamed parameter/local variable to avoid name clashes with global 00465 * declaration left and/or right (used for as iostream manipulators). 00466 * 00467 * Revision 1.20 2002/10/21 10:13:51 joergr 00468 * Corrected wrong calculation of min/max pixel value in cases where the 00469 * stored pixel data exceeds the expected size. 00470 * 00471 * Revision 1.19 2002/06/26 16:05:43 joergr 00472 * Enhanced handling of corrupted pixel data and/or length. 00473 * 00474 * Revision 1.18 2001/11/19 12:56:27 joergr 00475 * Added parameter 'frame' to setRoiWindow(). 00476 * 00477 * Revision 1.17 2001/09/28 13:09:30 joergr 00478 * Added method setRoiWindow() which automatically calculates a min-max VOI 00479 * window for a specified rectangular region of the image. 00480 * Made min-max window calculation consistent with latest release of the DICOM 00481 * standard (supplement 33). 00482 * 00483 * Revision 1.16 2001/06/01 15:49:47 meichel 00484 * Updated copyright header 00485 * 00486 * Revision 1.15 2000/05/03 09:46:29 joergr 00487 * Removed most informational and some warning messages from release built 00488 * (#ifndef DEBUG). 00489 * 00490 * Revision 1.14 2000/04/28 12:32:32 joergr 00491 * DebugLevel - global for the module - now derived from OFGlobal (MF-safe). 00492 * 00493 * Revision 1.13 2000/04/27 13:08:41 joergr 00494 * Dcmimgle library code now consistently uses ofConsole for error output. 00495 * 00496 * Revision 1.12 2000/03/08 16:24:21 meichel 00497 * Updated copyright header. 00498 * 00499 * Revision 1.11 2000/03/03 14:09:14 meichel 00500 * Implemented library support for redirecting error messages into memory 00501 * instead of printing them to stdout/stderr for GUI applications. 00502 * 00503 * Revision 1.10 1999/10/06 13:44:35 joergr 00504 * Corrected creation of PrintBitmap pixel data: VOI windows should be applied 00505 * before clipping to avoid that the region outside the image (border) is also 00506 * windowed (this requires a new method in dcmimgle to create a DicomImage 00507 * with the grayscale transformations already applied). 00508 * 00509 * Revision 1.9 1999/09/17 12:42:40 joergr 00510 * Added/changed/completed DOC++ style comments in the header files. 00511 * Enhanced efficiency of the implementation to determine min/max values of 00512 * the input pixels. 00513 * 00514 * Revision 1.8 1999/05/31 12:35:16 joergr 00515 * Corrected bug concerning the conversion of color images to grayscale. 00516 * 00517 * Revision 1.7 1999/04/30 16:10:51 meichel 00518 * Minor code purifications to keep IBM xlC quiet 00519 * 00520 * Revision 1.6 1999/04/28 14:52:12 joergr 00521 * Introduced new scheme for the debug level variable: now each level can be 00522 * set separately (there is no "include" relationship). 00523 * 00524 * Revision 1.5 1999/03/24 17:20:16 joergr 00525 * Added/Modified comments and formatting. 00526 * 00527 * Revision 1.4 1999/01/20 15:11:38 joergr 00528 * Replaced invocation of getCount() by member variable Count where possible. 00529 * 00530 * Revision 1.3 1999/01/11 09:36:13 joergr 00531 * Corrected some typos and formatting. 00532 * 00533 * Revision 1.2 1998/12/22 14:34:30 joergr 00534 * Corrected some typos and formatting. 00535 * 00536 * Revision 1.1 1998/11/27 15:36:43 joergr 00537 * Added copyright message. 00538 * Replaced delete by delete[] for array types. 00539 * Added method to give direct (non-const) access to internal data buffer. 00540 * Added support for new bit manipulation class. 00541 * 00542 * Revision 1.7 1998/07/01 08:39:25 joergr 00543 * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional 00544 * options), e.g. add copy constructors. 00545 * 00546 * Revision 1.6 1998/05/11 14:53:23 joergr 00547 * Added CVS/RCS header to each file. 00548 * 00549 * 00550 */