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