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