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: DicomInputPixelTemplate (Header) 00019 * 00020 * Last Update: $Author: joergr $ 00021 * Update Date: $Date: 2010-10-14 13:16:26 $ 00022 * CVS/RCS Revision: $Revision: 1.42 $ 00023 * Status: $State: Exp $ 00024 * 00025 * CVS/RCS Log at end of file 00026 * 00027 */ 00028 00029 00030 #ifndef DIINPXT_H 00031 #define DIINPXT_H 00032 00033 #include "dcmtk/config/osconfig.h" 00034 #include "dcmtk/dcmdata/dcpixel.h" 00035 00036 #include "dcmtk/ofstd/ofbmanip.h" 00037 #include "dcmtk/ofstd/ofcast.h" 00038 00039 #include "dcmtk/dcmimgle/diinpx.h" 00040 #include "dcmtk/dcmimgle/didocu.h" 00041 #include "dcmtk/dcmimgle/dipxrept.h" 00042 00043 00044 /*--------------------* 00045 * helper functions * 00046 *--------------------*/ 00047 00048 static inline Uint8 expandSign(const Uint8 Value, 00049 const Uint8, 00050 const Uint8) 00051 { 00052 return Value; 00053 } 00054 00055 00056 static inline Uint16 expandSign(const Uint16 Value, 00057 const Uint16, 00058 const Uint16) 00059 { 00060 return Value; 00061 } 00062 00063 00064 static inline Uint32 expandSign(const Uint32 Value, 00065 const Uint32, 00066 const Uint32) 00067 { 00068 return Value; 00069 } 00070 00071 00072 static inline Sint8 expandSign(const Sint8 Value, 00073 const Sint8 SignBit, 00074 const Sint8 SignMask) 00075 { 00076 return (Value & SignBit) ? (Value | SignMask) : Value; 00077 } 00078 00079 00080 static inline Sint16 expandSign(const Sint16 Value, 00081 const Sint16 SignBit, 00082 const Sint16 SignMask) 00083 { 00084 return (Value & SignBit) ? (Value | SignMask) : Value; 00085 } 00086 00087 00088 static inline Sint32 expandSign(const Sint32 Value, 00089 const Sint32 SignBit, 00090 const Sint32 SignMask) 00091 { 00092 return (Value & SignBit) ? (Value | SignMask) : Value; 00093 } 00094 00095 00096 static Uint32 getPixelData(DcmPixelData *PixelData, 00097 Uint8 *&pixel) 00098 { 00099 PixelData->getUint8Array(pixel); 00100 return PixelData->getLength(); 00101 } 00102 00103 00104 static Uint32 getPixelData(DcmPixelData *PixelData, 00105 Uint16 *&pixel) 00106 { 00107 PixelData->getUint16Array(pixel); 00108 return PixelData->getLength(); 00109 } 00110 00111 00112 /*---------------------* 00113 * class declaration * 00114 *---------------------*/ 00115 00118 template<class T1, class T2> 00119 class DiInputPixelTemplate 00120 : public DiInputPixel, 00121 public DiPixelRepresentationTemplate<T2> 00122 { 00123 00124 public: 00125 00138 DiInputPixelTemplate(const DiDocument *document, 00139 const Uint16 alloc, 00140 const Uint16 stored, 00141 const Uint16 high, 00142 const unsigned long first, 00143 const unsigned long number, 00144 const unsigned long fsize, 00145 DcmFileCache *fileCache, 00146 Uint32 &fragment) 00147 : DiInputPixel(stored, first, number, fsize), 00148 Data(NULL) 00149 { 00150 MinValue[0] = 0; 00151 MinValue[1] = 0; 00152 MaxValue[0] = 0; 00153 MaxValue[1] = 0; 00154 if (this->isSigned()) 00155 { 00156 AbsMinimum = -OFstatic_cast(double, DicomImageClass::maxval(Bits - 1, 0)); 00157 AbsMaximum = OFstatic_cast(double, DicomImageClass::maxval(Bits - 1)); 00158 } else { 00159 AbsMinimum = 0; 00160 AbsMaximum = OFstatic_cast(double, DicomImageClass::maxval(Bits)); 00161 } 00162 if ((document != NULL) && (document->getPixelData() != NULL)) 00163 convert(document, alloc, stored, high, fileCache, fragment); 00164 if ((PixelCount == 0) || (PixelStart + PixelCount > Count)) // check for corrupt pixel length 00165 { 00166 PixelCount = Count - PixelStart; 00167 DCMIMGLE_DEBUG("setting number of pixels to be processed (PixelCount) to: " << PixelCount); 00168 } 00169 } 00170 00173 virtual ~DiInputPixelTemplate() 00174 { 00175 delete[] Data; 00176 } 00177 00182 int determineMinMax() 00183 { 00184 if (Data != NULL) 00185 { 00186 DCMIMGLE_DEBUG("determining minimum and maximum pixel values for input data"); 00187 register T2 *p = Data; 00188 register unsigned long i; 00189 const unsigned long ocnt = OFstatic_cast(unsigned long, getAbsMaxRange()); 00190 Uint8 *lut = NULL; 00191 if ((sizeof(T2) <= 2) && (Count > 3 * ocnt)) // optimization criteria 00192 { 00193 lut = new Uint8[ocnt]; 00194 if (lut != NULL) 00195 { 00196 DCMIMGLE_DEBUG("using optimized routine with additional LUT"); 00197 OFBitmanipTemplate<Uint8>::zeroMem(lut, ocnt); 00198 register Uint8 *q = lut - OFstatic_cast(T2, getAbsMinimum()); 00199 for (i = Count; i != 0; --i) // fill lookup table 00200 *(q + *(p++)) = 1; 00201 q = lut; 00202 for (i = 0; i < ocnt; ++i) // search for minimum 00203 { 00204 if (*(q++) != 0) 00205 { 00206 MinValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i) + getAbsMinimum()); 00207 break; 00208 } 00209 } 00210 q = lut + ocnt; 00211 for (i = ocnt; i != 0; --i) // search for maximum 00212 { 00213 if (*(--q) != 0) 00214 { 00215 MaxValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + getAbsMinimum()); 00216 break; 00217 } 00218 } 00219 if (Count >= PixelCount) // use global min/max value 00220 { 00221 MinValue[1] = MinValue[0]; 00222 MaxValue[1] = MaxValue[0]; 00223 } else { // calculate min/max for selected range 00224 OFBitmanipTemplate<Uint8>::zeroMem(lut, ocnt); 00225 p = Data + PixelStart; 00226 q = lut - OFstatic_cast(T2, getAbsMinimum()); 00227 for (i = PixelCount; i != 0; --i) // fill lookup table 00228 *(q + *(p++)) = 1; 00229 q = lut; 00230 for (i = 0; i < ocnt; ++i) // search for minimum 00231 { 00232 if (*(q++) != 0) 00233 { 00234 MinValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i) + getAbsMinimum()); 00235 break; 00236 } 00237 } 00238 q = lut + ocnt; 00239 for (i = ocnt; i != 0; --i) // search for maximum 00240 { 00241 if (*(--q) != 0) 00242 { 00243 MaxValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + getAbsMinimum()); 00244 break; 00245 } 00246 } 00247 } 00248 } 00249 } 00250 if (lut == NULL) // use conventional method 00251 { 00252 register T2 value = *p; 00253 MinValue[0] = value; 00254 MaxValue[0] = value; 00255 for (i = Count; i > 1; --i) 00256 { 00257 value = *(++p); 00258 if (value < MinValue[0]) 00259 MinValue[0] = value; 00260 else if (value > MaxValue[0]) 00261 MaxValue[0] = value; 00262 } 00263 if (Count <= PixelCount) // use global min/max value 00264 { 00265 MinValue[1] = MinValue[0]; 00266 MaxValue[1] = MaxValue[0]; 00267 } else { // calculate min/max for selected range 00268 p = Data + PixelStart; 00269 value = *p; 00270 MinValue[1] = value; 00271 MaxValue[1] = value; 00272 for (i = PixelCount; i > 1; --i) 00273 { 00274 value = *(++p); 00275 if (value < MinValue[1]) 00276 MinValue[1] = value; 00277 else if (value > MaxValue[1]) 00278 MaxValue[1] = value; 00279 } 00280 } 00281 } 00282 delete[] lut; 00283 return 1; 00284 } 00285 return 0; 00286 } 00287 00292 inline EP_Representation getRepresentation() const 00293 { 00294 return DiPixelRepresentationTemplate<T2>::getRepresentation(); 00295 } 00296 00301 inline const void *getData() const 00302 { 00303 return OFstatic_cast(const void *, Data); 00304 } 00305 00310 virtual void *getDataPtr() 00311 { 00312 return OFstatic_cast(void *, Data); 00313 } 00314 00317 inline void removeDataReference() 00318 { 00319 Data = NULL; 00320 } 00321 00329 inline double getMinValue(const int idx) const 00330 { 00331 return (idx == 0) ? OFstatic_cast(double, MinValue[0]) : OFstatic_cast(double, MinValue[1]); 00332 } 00333 00341 inline double getMaxValue(const int idx) const 00342 { 00343 return (idx == 0) ? OFstatic_cast(double, MaxValue[0]) : OFstatic_cast(double, MaxValue[1]); 00344 } 00345 00346 00347 private: 00348 00358 void convert(const DiDocument *document, 00359 const Uint16 bitsAllocated, 00360 const Uint16 bitsStored, 00361 const Uint16 highBit, 00362 DcmFileCache *fileCache, 00363 Uint32 &fragment) 00364 { 00365 T1 *pixel = NULL; 00366 OFBool deletePixel = OFFalse; 00367 Uint32 lengthBytes = 0; 00368 DcmPixelData *pixelData = document->getPixelData(); 00369 const Uint16 bitsof_T1 = bitsof(T1); 00370 const Uint16 bitsof_T2 = bitsof(T2); 00371 const OFBool uncompressed = pixelData->canWriteXfer(EXS_LittleEndianExplicit, EXS_Unknown); 00372 /* check whether to use partial read */ 00373 if ((document->getFlags() & CIF_UsePartialAccessToPixelData) && (PixelCount > 0) && 00374 (!uncompressed || !pixelData->valueLoaded()) && (bitsAllocated % 8 == 0)) 00375 { 00376 /* Bits Allocated is always a multiple of 8 (see above), same for bits of T1 */ 00377 const Uint32 byteFactor = bitsAllocated / 8; 00378 const Uint32 bytes_T1 = bitsof_T1 / 8; 00379 const Uint32 count_T1 = (byteFactor == bytes_T1) ? PixelCount : (PixelCount * byteFactor + bytes_T1 - 1) / bytes_T1; 00380 #ifdef DEBUG 00381 DCMIMGLE_TRACE("PixelCount: " << PixelCount << ", byteFactor: " << byteFactor << ", bytes_T1: " << bytes_T1 << ", count_T1: " << count_T1); 00382 #endif 00383 /* allocate temporary buffer, even number of bytes required for getUncompressedFrame() */ 00384 const Uint32 extraByte = ((sizeof(T1) == 1) && (count_T1 & 1)) ? 1 : 0; 00385 pixel = new T1[count_T1 + extraByte]; 00386 if (pixel != NULL) 00387 { 00388 if (uncompressed) 00389 { 00390 DCMIMGLE_DEBUG("using partial read access to uncompressed pixel data"); 00391 const Uint32 offset = PixelStart * byteFactor; 00392 const Uint32 bufSize = PixelCount * byteFactor; 00393 const OFCondition status = pixelData->getPartialValue(pixel, offset, bufSize, fileCache); 00394 if (status.good()) 00395 { 00396 PixelStart = 0; 00397 lengthBytes = bufSize; 00398 } else { 00399 DCMIMGLE_ERROR("can't access partial value from byte offset " << offset << " to " 00400 << (offset + bufSize - 1) << ": " << status.text()); 00401 } 00402 } else { 00403 DCMIMGLE_DEBUG("using partial read access to compressed pixel data"); 00404 OFCondition status = EC_IllegalCall; 00405 OFString decompressedColorModel; 00406 const Uint32 fsize = FrameSize * byteFactor; 00407 for (Uint32 frame = 0; frame < NumberOfFrames; ++frame) 00408 { 00409 /* make sure that the buffer always has an even number of bytes as required for getUncompressedFrame() */ 00410 const Uint32 bufSize = (fsize & 1) ? fsize + 1 : fsize; 00411 status = pixelData->getUncompressedFrame(document->getDataset(), FirstFrame + frame, fragment, 00412 OFreinterpret_cast(Uint8 *, pixel) + lengthBytes, bufSize, decompressedColorModel, fileCache); 00413 if (status.good()) 00414 { 00415 DCMIMGLE_TRACE("successfully decompressed frame " << FirstFrame + frame); 00416 lengthBytes += fsize; 00417 } else { 00418 DCMIMGLE_ERROR("can't decompress frame " << FirstFrame + frame << ": " << status.text()); 00419 break; 00420 } 00421 } 00422 if (status.good()) 00423 PixelStart = 0; 00424 /* check whether color model changed during decompression */ 00425 if (!decompressedColorModel.empty() && (decompressedColorModel != document->getPhotometricInterpretation())) 00426 { 00427 DCMIMGLE_WARN("Photometric Interpretation of decompressed pixel data deviates from original image: " 00428 << decompressedColorModel); 00429 } 00430 } 00431 deletePixel = OFTrue; 00432 } 00433 } else { 00434 DCMIMGLE_DEBUG("reading uncompressed pixel data completely into memory"); 00435 /* always access complete pixel data */ 00436 lengthBytes = getPixelData(pixelData, pixel); 00437 } 00438 if ((pixel != NULL) && (lengthBytes > 0)) 00439 { 00440 const Uint32 length_T1 = lengthBytes / sizeof(T1); 00441 /* need to split 'length' in order to avoid integer overflow for large pixel data */ 00442 const Uint32 length_B1 = lengthBytes / bitsAllocated; 00443 const Uint32 length_B2 = lengthBytes % bitsAllocated; 00444 // # old code: Count = ((lengthBytes * 8) + bitsAllocated - 1) / bitsAllocated; 00445 Count = 8 * length_B1 + (8 * length_B2 + bitsAllocated - 1) / bitsAllocated; 00446 register unsigned long i; 00447 Data = new T2[Count]; 00448 if (Data != NULL) 00449 { 00450 DCMIMGLE_TRACE("Input length: " << lengthBytes << " bytes, Pixel count: " << Count 00451 << " (" << PixelCount << "), In: " << bitsof_T1 << " bits, Out: " << bitsof_T2 00452 << " bits (" << (this->isSigned() ? "signed" : "unsigned") << ")"); 00453 register const T1 *p = pixel; 00454 register T2 *q = Data; 00455 if (bitsof_T1 == bitsAllocated) // case 1: equal 8/16 bit 00456 { 00457 if (bitsStored == bitsAllocated) 00458 { 00459 DCMIMGLE_DEBUG("convert input pixel data: case 1a (single copy)"); 00460 for (i = Count; i != 0; --i) 00461 *(q++) = OFstatic_cast(T2, *(p++)); 00462 } 00463 else /* bitsStored < bitsAllocated */ 00464 { 00465 register T1 mask = 0; 00466 for (i = 0; i < bitsStored; ++i) 00467 mask |= OFstatic_cast(T1, 1 << i); 00468 const T2 sign = 1 << (bitsStored - 1); 00469 T2 smask = 0; 00470 for (i = bitsStored; i < bitsof_T2; ++i) 00471 smask |= OFstatic_cast(T2, 1 << i); 00472 const Uint16 shift = highBit + 1 - bitsStored; 00473 if (shift == 0) 00474 { 00475 DCMIMGLE_DEBUG("convert input pixel data: case 1b (mask & sign)"); 00476 for (i = length_T1; i != 0; --i) 00477 *(q++) = expandSign(OFstatic_cast(T2, *(p++) & mask), sign, smask); 00478 } 00479 else /* shift > 0 */ 00480 { 00481 DCMIMGLE_DEBUG("convert input pixel data: case 1c (shift & mask & sign)"); 00482 for (i = length_T1; i != 0; --i) 00483 *(q++) = expandSign(OFstatic_cast(T2, (*(p++) >> shift) & mask), sign, smask); 00484 } 00485 } 00486 } 00487 else if ((bitsof_T1 > bitsAllocated) && (bitsof_T1 % bitsAllocated == 0)) // case 2: divisor of 8/16 bit 00488 { 00489 const Uint16 times = bitsof_T1 / bitsAllocated; 00490 register T1 mask = 0; 00491 for (i = 0; i < bitsStored; ++i) 00492 mask |= OFstatic_cast(T1, 1 << i); 00493 register Uint16 j; 00494 register T1 value; 00495 if ((bitsStored == bitsAllocated) && (bitsStored == bitsof_T2)) 00496 { 00497 if (times == 2) 00498 { 00499 DCMIMGLE_DEBUG("convert input pixel data: case 2a (simple mask)"); 00500 for (i = length_T1; i != 0; --i, ++p) 00501 { 00502 *(q++) = OFstatic_cast(T2, *p & mask); 00503 *(q++) = OFstatic_cast(T2, *p >> bitsAllocated); 00504 } 00505 } 00506 else 00507 { 00508 DCMIMGLE_DEBUG("convert input pixel data: case 2b (mask)"); 00509 for (i = length_T1; i != 0; --i) 00510 { 00511 value = *(p++); 00512 for (j = times; j != 0; --j) 00513 { 00514 *(q++) = OFstatic_cast(T2, value & mask); 00515 value >>= bitsAllocated; 00516 } 00517 } 00518 } 00519 } 00520 else 00521 { 00522 DCMIMGLE_DEBUG("convert input pixel data: case 2c (shift & mask & sign)"); 00523 const T2 sign = 1 << (bitsStored - 1); 00524 T2 smask = 0; 00525 for (i = bitsStored; i < bitsof_T2; ++i) 00526 smask |= OFstatic_cast(T2, 1 << i); 00527 const Uint16 shift = highBit + 1 - bitsStored; 00528 for (i = length_T1; i != 0; --i) 00529 { 00530 value = *(p++) >> shift; 00531 for (j = times; j != 0; --j) 00532 { 00533 *(q++) = expandSign(OFstatic_cast(T2, value & mask), sign, smask); 00534 value >>= bitsAllocated; 00535 } 00536 } 00537 } 00538 } 00539 else if ((bitsof_T1 < bitsAllocated) && (bitsAllocated % bitsof_T1 == 0) // case 3: multiplicant of 8/16 00540 && (bitsStored == bitsAllocated)) 00541 { 00542 DCMIMGLE_DEBUG("convert input pixel data: case 3 (multi copy)"); 00543 const Uint16 times = bitsAllocated / bitsof_T1; 00544 register Uint16 j; 00545 register Uint16 shift; 00546 register T2 value; 00547 for (i = length_T1; i != 0; --i) 00548 { 00549 shift = 0; 00550 value = OFstatic_cast(T2, *(p++)); 00551 for (j = times; j > 1; --j, --i) 00552 { 00553 shift += bitsof_T1; 00554 value |= OFstatic_cast(T2, *(p++)) << shift; 00555 } 00556 *(q++) = value; 00557 } 00558 } 00559 else // case 4: anything else 00560 { 00561 DCMIMGLE_DEBUG("convert input pixel data: case 4 (general)"); 00562 register T2 value = 0; 00563 register Uint16 bits = 0; 00564 register Uint32 skip = highBit + 1 - bitsStored; 00565 register Uint32 times; 00566 T1 mask[bitsof_T1]; 00567 mask[0] = 1; 00568 for (i = 1; i < bitsof_T1; ++i) 00569 mask[i] = (mask[i - 1] << 1) | 1; 00570 T2 smask = 0; 00571 for (i = bitsStored; i < bitsof_T2; ++i) 00572 smask |= OFstatic_cast(T2, 1 << i); 00573 const T2 sign = 1 << (bitsStored - 1); 00574 const Uint32 gap = bitsAllocated - bitsStored; 00575 i = 0; 00576 while (i < length_T1) 00577 { 00578 if (skip < bitsof_T1) 00579 { 00580 if (skip + bitsStored - bits < bitsof_T1) // -++- --++ 00581 { 00582 value |= (OFstatic_cast(T2, (*p >> skip) & mask[bitsStored - bits - 1]) << bits); 00583 skip += bitsStored - bits + gap; 00584 bits = bitsStored; 00585 } 00586 else // ++-- ++++ 00587 { 00588 value |= (OFstatic_cast(T2, (*p >> skip) & mask[bitsof_T1 - skip - 1]) << bits); 00589 bits += bitsof_T1 - OFstatic_cast(Uint16, skip); 00590 skip = (bits == bitsStored) ? gap : 0; 00591 ++i; 00592 ++p; 00593 } 00594 if (bits == bitsStored) 00595 { 00596 *(q++) = expandSign(value, sign, smask); 00597 value = 0; 00598 bits = 0; 00599 } 00600 } 00601 else 00602 { 00603 times = skip / bitsof_T1; 00604 i += times; 00605 p += times; 00606 skip -= times * bitsof_T1; 00607 } 00608 } 00609 } 00610 } 00611 } else { 00612 // in case of error, reset pixel count variable 00613 Count = 0; 00614 } 00615 if (deletePixel) 00616 { 00617 // delete temporary buffer 00618 delete[] pixel; 00619 } 00620 } 00621 00623 T2 *Data; 00624 00626 T2 MinValue[2]; 00628 T2 MaxValue[2]; 00629 00630 // --- declarations to avoid compiler warnings 00631 00632 DiInputPixelTemplate(const DiInputPixelTemplate<T1,T2> &); 00633 DiInputPixelTemplate<T1,T2> &operator=(const DiInputPixelTemplate<T1,T2> &); 00634 }; 00635 00636 00637 #endif 00638 00639 00640 /* 00641 * 00642 * CVS/RCS Log: 00643 * $Log: diinpxt.h,v $ 00644 * Revision 1.42 2010-10-14 13:16:26 joergr 00645 * Updated copyright header. Added reference to COPYRIGHT file. 00646 * 00647 * Revision 1.41 2010-07-22 10:27:30 joergr 00648 * Made sure that the size of the buffer for partial access to pixel data is 00649 * always an even number of bytes. 00650 * 00651 * Revision 1.40 2010-04-16 12:56:46 joergr 00652 * Further enhanced computation of buffer size when using partial read access 00653 * to pixel data. Now also some rare cases of BitsAllocated are supported. 00654 * 00655 * Revision 1.39 2010-04-15 14:18:36 joergr 00656 * Fixed possibly wrong computation of a buffer size when using partial read 00657 * access to pixel data. This could lead to a crash under certain conditions. 00658 * 00659 * Revision 1.38 2010-03-01 09:08:46 uli 00660 * Removed some unnecessary include directives in the headers. 00661 * 00662 * Revision 1.37 2009-11-25 16:05:40 joergr 00663 * Adapted code for new approach to access individual frames of a DICOM image. 00664 * Added more logging messages. Revised logging messages. 00665 * 00666 * Revision 1.36 2009-10-28 14:38:16 joergr 00667 * Fixed minor issues in log output. 00668 * 00669 * Revision 1.35 2009-10-28 09:53:40 uli 00670 * Switched to logging mechanism provided by the "new" oflog module. 00671 * 00672 * Revision 1.34 2007-08-30 13:39:30 joergr 00673 * Added further check on pixel pointer (possibly avoids crash under certain 00674 * conditions). 00675 * 00676 * Revision 1.33 2006/10/27 14:59:26 joergr 00677 * Fixed possible integer overflow for images with very large pixel data. 00678 * 00679 * Revision 1.32 2006/08/15 16:30:11 meichel 00680 * Updated the code in module dcmimgle to correctly compile when 00681 * all standard C++ classes remain in namespace std. 00682 * 00683 * Revision 1.31 2006/01/17 18:35:42 joergr 00684 * Fixed compilation problem with gcc 4.0 on Linux x86_64. 00685 * 00686 * Revision 1.30 2005/12/08 16:47:44 meichel 00687 * Changed include path schema for all DCMTK header files 00688 * 00689 * Revision 1.29 2004/04/21 10:00:36 meichel 00690 * Minor modifications for compilation with gcc 3.4.0 00691 * 00692 * Revision 1.28 2004/02/06 11:07:50 joergr 00693 * Distinguish more clearly between const and non-const access to pixel data. 00694 * 00695 * Revision 1.27 2004/01/05 14:52:20 joergr 00696 * Removed acknowledgements with e-mail addresses from CVS log. 00697 * 00698 * Revision 1.26 2003/12/23 15:53:22 joergr 00699 * Replaced post-increment/decrement operators by pre-increment/decrement 00700 * operators where appropriate (e.g. 'i++' by '++i'). 00701 * 00702 * Revision 1.25 2003/12/08 19:10:52 joergr 00703 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00704 * Removed leading underscore characters from preprocessor symbols (reserved 00705 * symbols). Updated copyright header. 00706 * 00707 * Revision 1.24 2002/10/21 10:13:50 joergr 00708 * Corrected wrong calculation of min/max pixel value in cases where the 00709 * stored pixel data exceeds the expected size. 00710 * 00711 * Revision 1.23 2001/11/13 18:07:36 joergr 00712 * Fixed bug occurring when processing monochrome images with an odd number of 00713 * pixels. 00714 * 00715 * Revision 1.22 2001/10/10 15:25:09 joergr 00716 * Removed redundant variable declarations to avoid compiler warnings 00717 * ("declaration of ... shadows previous local"). 00718 * 00719 * Revision 1.21 2001/09/28 13:04:59 joergr 00720 * Enhanced algorithm to determine the min and max value. 00721 * 00722 * Revision 1.20 2001/06/01 15:49:42 meichel 00723 * Updated copyright header 00724 * 00725 * Revision 1.19 2000/05/03 09:46:28 joergr 00726 * Removed most informational and some warning messages from release built 00727 * (#ifndef DEBUG). 00728 * 00729 * Revision 1.18 2000/04/28 12:32:30 joergr 00730 * DebugLevel - global for the module - now derived from OFGlobal (MF-safe). 00731 * 00732 * Revision 1.17 2000/04/27 13:08:39 joergr 00733 * Dcmimgle library code now consistently uses ofConsole for error output. 00734 * 00735 * Revision 1.16 2000/03/08 16:24:17 meichel 00736 * Updated copyright header. 00737 * 00738 * Revision 1.15 2000/03/03 14:09:12 meichel 00739 * Implemented library support for redirecting error messages into memory 00740 * instead of printing them to stdout/stderr for GUI applications. 00741 * 00742 * Revision 1.14 1999/09/17 12:21:57 joergr 00743 * Added/changed/completed DOC++ style comments in the header files. 00744 * Enhanced efficiency of some "for" loops and of the implementation to 00745 * determine min/max values of the input pixels. 00746 * 00747 * Revision 1.13 1999/07/23 13:54:38 joergr 00748 * Optimized memory usage for converting input pixel data (reference instead 00749 * of copying where possible). 00750 * 00751 * Revision 1.12 1999/05/04 09:20:39 meichel 00752 * Minor code purifications to keep IBM xlC quiet 00753 * 00754 * Revision 1.11 1999/04/30 16:23:59 meichel 00755 * Minor code purifications to keep IBM xlC quiet 00756 * 00757 * Revision 1.10 1999/04/28 14:48:39 joergr 00758 * Introduced new scheme for the debug level variable: now each level can be 00759 * set separately (there is no "include" relationship). 00760 * 00761 * Revision 1.9 1999/03/24 17:20:03 joergr 00762 * Added/Modified comments and formatting. 00763 * 00764 * Revision 1.8 1999/02/11 16:00:54 joergr 00765 * Removed inline declarations from several methods. 00766 * 00767 * Revision 1.7 1999/02/03 17:04:37 joergr 00768 * Moved global functions maxval() and determineRepresentation() to class 00769 * DicomImageClass (as static methods). 00770 * 00771 * Revision 1.6 1999/01/20 15:01:31 joergr 00772 * Replaced invocation of getCount() by member variable Count where possible. 00773 * 00774 * Revision 1.5 1999/01/11 09:34:28 joergr 00775 * Corrected bug in determing 'AbsMaximum' (removed '+ 1'). 00776 * 00777 * Revision 1.4 1998/12/22 14:23:16 joergr 00778 * Added calculation of member variables AbsMinimum/AbsMaximum. 00779 * Replaced method copyMem by for-loop copying each item. 00780 * Removed some '#ifdef DEBUG'. 00781 * 00782 * Revision 1.3 1998/12/16 16:30:34 joergr 00783 * Added methods to determine absolute minimum and maximum value for given 00784 * value representation. 00785 * 00786 * Revision 1.2 1998/12/14 17:18:23 joergr 00787 * Reformatted source code. 00788 * 00789 * Revision 1.1 1998/11/27 15:08:21 joergr 00790 * Added copyright message. 00791 * Introduced global debug level for dcmimage module to control error output. 00792 * Added support for new bit manipulation class. 00793 * 00794 * Revision 1.8 1998/07/01 08:39:21 joergr 00795 * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional 00796 * options), e.g. add copy constructors. 00797 * 00798 * Revision 1.7 1998/05/11 14:53:17 joergr 00799 * Added CVS/RCS header to each file. 00800 * 00801 * 00802 */