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: DicomMonoOutputPixelTemplate (Header) 00019 * 00020 * Last Update: $Author: joergr $ 00021 * Update Date: $Date: 2010-10-28 10:58:38 $ 00022 * CVS/RCS Revision: $Revision: 1.54 $ 00023 * Status: $State: Exp $ 00024 * 00025 * CVS/RCS Log at end of file 00026 * 00027 */ 00028 00029 00030 #ifndef DIMOOPXT_H 00031 #define DIMOOPXT_H 00032 00033 #include "dcmtk/config/osconfig.h" 00034 00035 #include "dcmtk/ofstd/ofcast.h" 00036 #include "dcmtk/ofstd/ofbmanip.h" 00037 00038 #include "dcmtk/dcmimgle/dimoopx.h" 00039 #include "dcmtk/dcmimgle/dimopx.h" 00040 #include "dcmtk/dcmimgle/diluptab.h" 00041 #include "dcmtk/dcmimgle/diovlay.h" 00042 #include "dcmtk/dcmimgle/dipxrept.h" 00043 #include "dcmtk/dcmimgle/didispfn.h" 00044 #include "dcmtk/dcmimgle/didislut.h" 00045 00046 #ifdef PASTEL_COLOR_OUTPUT 00047 #include "dimcopxt.h" 00048 #endif 00049 00050 #define INCLUDE_CMATH 00051 #include "dcmtk/ofstd/ofstdinc.h" 00052 00053 00054 /*---------------------* 00055 * class declaration * 00056 *---------------------*/ 00057 00060 template<class T1, class T2, class T3> 00061 class DiMonoOutputPixelTemplate 00062 : public DiMonoOutputPixel, 00063 public DiPixelRepresentationTemplate<T3> 00064 { 00065 00066 public: 00067 00087 DiMonoOutputPixelTemplate(void *buffer, 00088 const DiMonoPixel *pixel, 00089 DiOverlay *overlays[2], 00090 const DiLookupTable *vlut, 00091 const DiLookupTable *plut, 00092 DiDisplayFunction *disp, 00093 const EF_VoiLutFunction vfunc, 00094 const double center, 00095 const double width, 00096 const Uint32 low, 00097 const Uint32 high, 00098 const Uint16 columns, 00099 const Uint16 rows, 00100 const unsigned long frame, 00101 #ifdef PASTEL_COLOR_OUTPUT 00102 const unsigned long frames, 00103 #else 00104 const unsigned long /*frames*/, 00105 #endif 00106 const int pastel = 0) 00107 : DiMonoOutputPixel(pixel, OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows), frame, 00108 OFstatic_cast(unsigned long, fabs(OFstatic_cast(double, high - low)))), 00109 Data(NULL), 00110 DeleteData(buffer == NULL), 00111 ColorData(NULL) 00112 { 00113 if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count)) 00114 { 00115 if (pastel) 00116 #ifdef PASTEL_COLOR_OUTPUT 00117 color(buffer, pixel, frame, frames); 00118 #else 00119 DCMIMGLE_ERROR("pastel color output not supported"); 00120 #endif 00121 else 00122 { 00123 DCMIMGLE_TRACE("monochrome output image - columns: " << columns << ", rows: " << rows << ", frame: " << frame); 00124 DCMIMGLE_TRACE("monochrome output values - low: " << OFstatic_cast(unsigned long, low) << ", high: " 00125 << OFstatic_cast(unsigned long, high) << ((low > high) ? " (inverted)" : "")); 00126 Data = OFstatic_cast(T3 *, buffer); 00127 if ((vlut != NULL) && (vlut->isValid())) // valid VOI LUT ? 00128 voilut(pixel, frame * FrameSize, vlut, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); 00129 else 00130 { 00131 if (width < 1) // no valid window according to supplement 33 00132 nowindow(pixel, frame * FrameSize, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); 00133 else if (vfunc == EFV_Sigmoid) 00134 sigmoid(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); 00135 else // linear 00136 window(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); 00137 } 00138 overlay(overlays, disp, columns, rows, frame); // add (visible) overlay planes to output bitmap 00139 } 00140 } 00141 } 00142 00145 virtual ~DiMonoOutputPixelTemplate() 00146 { 00147 if (DeleteData) 00148 delete[] Data; 00149 delete ColorData; 00150 } 00151 00156 inline EP_Representation getRepresentation() const 00157 { 00158 return DiPixelRepresentationTemplate<T3>::getRepresentation(); 00159 } 00160 00165 inline size_t getItemSize() const 00166 { 00167 return (ColorData != NULL) ? ColorData->getItemSize() : sizeof(T3); 00168 } 00169 00174 inline const void *getData() const 00175 { 00176 return (ColorData != NULL) ? ColorData->getData() : OFstatic_cast(const void *, Data); 00177 } 00178 00183 virtual void *getDataPtr() 00184 { 00185 return (ColorData != NULL) ? ColorData->getDataPtr() : OFstatic_cast(void *, Data); 00186 } 00187 00190 inline void removeDataReference() 00191 { 00192 Data = NULL; 00193 DeleteData = 0; 00194 } 00195 00202 inline int writePPM(STD_NAMESPACE ostream& stream) const 00203 { 00204 if (Data != NULL) 00205 { 00206 register unsigned long i; 00207 for (i = 0; i < FrameSize; ++i) 00208 stream << OFstatic_cast(unsigned long, Data[i]) << " "; // typecast to resolve problems with 'char' 00209 return 1; 00210 } 00211 if (ColorData != NULL) 00212 return ColorData->writePPM(stream); 00213 return 0; 00214 } 00215 00222 inline int writePPM(FILE *stream) const 00223 { 00224 if (Data != NULL) 00225 { 00226 register unsigned long i; 00227 for (i = 0; i < FrameSize; ++i) 00228 fprintf(stream, "%lu ", OFstatic_cast(unsigned long, Data[i])); 00229 return 1; 00230 } 00231 if (ColorData != NULL) 00232 return ColorData->writePPM(stream); 00233 return 0; 00234 } 00235 00236 00237 protected: 00238 00241 inline void determineUsedValues() 00242 { 00243 if ((UsedValues == NULL) && (MaxValue > 0) && (MaxValue < MAX_TABLE_ENTRY_COUNT)) 00244 { 00245 UsedValues = new Uint8[MaxValue + 1]; 00246 if (UsedValues != NULL) 00247 { 00248 OFBitmanipTemplate<Uint8>::zeroMem(UsedValues, MaxValue + 1); // initialize array 00249 register const T3 *p = Data; 00250 register Uint8 *q = UsedValues; 00251 register unsigned long i; 00252 for (i = Count; i != 0; --i) 00253 *(q + *(p++)) = 1; // mark used entries 00254 } 00255 } 00256 } 00257 00258 00259 private: 00260 00267 inline void createDisplayLUT(const DiDisplayLUT *&dlut, 00268 DiDisplayFunction *disp, 00269 const int bits) 00270 { 00271 if ((disp != NULL) && (disp->isValid())) 00272 { // create Display LUT 00273 dlut = disp->getLookupTable(bits); 00274 if ((dlut != NULL) && (dlut->isValid())) // LUT is valid 00275 { 00276 DCMIMGLE_DEBUG("using display transformation"); 00277 } else { 00278 DCMIMGLE_WARN("can't create display LUT ... ignoring display transformation"); 00279 dlut = NULL; 00280 } 00281 } 00282 } 00283 00289 inline int initOptimizationLUT(T3 *&lut, 00290 const unsigned long ocnt) 00291 { 00292 int result = 0; 00293 if ((sizeof(T1) <= 2) && (Count > 3 * ocnt)) // optimization criteria 00294 { // use LUT for optimization 00295 lut = new T3[ocnt]; 00296 if (lut != NULL) 00297 { 00298 DCMIMGLE_DEBUG("using optimized routine with additional LUT (" << ocnt << " entries)"); 00299 result = 1; 00300 } 00301 } 00302 return result; 00303 } 00304 00305 #ifdef PASTEL_COLOR_OUTPUT 00306 void color(void *buffer, // create true color pastel image 00307 const DiMonoPixel *inter, 00308 const unsigned long frame, 00309 const unsigned long frames) 00310 { 00311 ColorData = new DiMonoColorOutputPixelTemplate<T1, T3>(buffer, inter, frame, frames); 00312 if (ColorData != NULL) 00313 DCMIMGLE_DEBUG(">>> COLOR <<<"); 00314 } 00315 #endif 00316 00327 void voilut(const DiMonoPixel *inter, 00328 const Uint32 start, 00329 const DiLookupTable *vlut, 00330 const DiLookupTable *plut, 00331 DiDisplayFunction *disp, 00332 const T3 low, 00333 const T3 high) 00334 { 00335 const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); 00336 if ((pixel != NULL) && (vlut != NULL)) 00337 { 00338 if (Data == NULL) 00339 Data = new T3[FrameSize]; 00340 if (Data != NULL) 00341 { 00342 DCMIMGLE_DEBUG("applying VOI transformation with LUT (" << vlut->getCount() << " entries)"); 00343 const DiDisplayLUT *dlut = NULL; 00344 const double minvalue = vlut->getMinValue(); 00345 const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1; 00346 register unsigned long i; 00347 if (minvalue == vlut->getMaxValue()) // LUT has only one entry or all entries are equal 00348 { 00349 T3 value; 00350 if ((plut != NULL) && (plut->isValid())) // has presentation LUT 00351 { 00352 DCMIMGLE_DEBUG("applying presentation LUT transformation"); 00353 createDisplayLUT(dlut, disp, plut->getBits()); 00354 const Uint32 value2 = OFstatic_cast(Uint32, (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * plut->getCount()); 00355 if (dlut != NULL) // perform display transformation 00356 { 00357 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #1 - UNTESTED"); 00358 if (low > high) // invers 00359 value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getAbsMaxRange() - plut->getValue(value2) - 1))); 00360 else // normal 00361 value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getValue(value2)))); 00362 } else { // don't use display: invalid or absent 00363 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #2"); 00364 value = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * outrange / OFstatic_cast(double, plut->getAbsMaxRange())); 00365 } 00366 } else { // has no presentation LUT 00367 createDisplayLUT(dlut, disp, vlut->getBits()); 00368 if (dlut != NULL) // perform display transformation 00369 { 00370 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #3 - UNTESTED"); 00371 if (low > high) // invers 00372 value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, vlut->getAbsMaxRange() - minvalue - 1))); 00373 else // normal 00374 value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, minvalue))); 00375 } else { // don't use display: invalid or absent 00376 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #4"); 00377 value = OFstatic_cast(T3, OFstatic_cast(double, low) + (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * outrange); 00378 } 00379 } 00380 OFBitmanipTemplate<T3>::setMem(Data, value, Count); // set output pixels to LUT value 00381 } else { 00382 register T2 value = 0; 00383 const T2 absmin = OFstatic_cast(T2, inter->getAbsMinimum()); 00384 const T2 firstentry = vlut->getFirstEntry(value); // choose signed/unsigned method 00385 const T2 lastentry = vlut->getLastEntry(value); 00386 const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries 00387 register const T1 *p = pixel + start; 00388 register T3 *q = Data; 00389 T3 *lut = NULL; 00390 if ((plut != NULL) && (plut->isValid())) // has presentation LUT 00391 { 00392 DCMIMGLE_DEBUG("applying presentation LUT transformation"); 00393 createDisplayLUT(dlut, disp, plut->getBits()); 00394 register Uint32 value2; // presentation LUT is always unsigned 00395 const Uint32 pcnt = plut->getCount(); 00396 const double gradient1 = OFstatic_cast(double, pcnt) / OFstatic_cast(double, vlut->getAbsMaxRange()); 00397 const Uint32 firstvalue = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getFirstValue()) * gradient1); 00398 const Uint32 lastvalue = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getLastValue()) * gradient1); 00399 if (initOptimizationLUT(lut, ocnt)) 00400 { // use LUT for optimization 00401 q = lut; 00402 if (dlut != NULL) // perform display transformation 00403 { 00404 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #5"); 00405 if (low > high) // inverse 00406 { 00407 const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1); 00408 for (i = 0; i < ocnt; ++i) 00409 { 00410 value = OFstatic_cast(T2, i) + absmin; 00411 if (value <= firstentry) 00412 value2 = firstvalue; 00413 else if (value >= lastentry) 00414 value2 = lastvalue; 00415 else 00416 value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); 00417 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value2)))); 00418 } 00419 } else { // normal 00420 for (i = 0; i < ocnt; ++i) 00421 { 00422 value = OFstatic_cast(T2, i) + absmin; 00423 if (value <= firstentry) 00424 value2 = firstvalue; 00425 else if (value >= lastentry) 00426 value2 = lastvalue; 00427 else 00428 value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); 00429 *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value2))); 00430 } 00431 } 00432 } else { // don't use display: invalid or absent 00433 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #6"); 00434 const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange()); 00435 for (i = 0; i < ocnt; ++i) 00436 { 00437 value = OFstatic_cast(T2, i) + absmin; 00438 if (value <= firstentry) 00439 value2 = firstvalue; 00440 else if (value >= lastentry) 00441 value2 = lastvalue; 00442 else 00443 value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); 00444 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); 00445 } 00446 } 00447 const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry 00448 q = Data; 00449 for (i = Count; i != 0; --i) // apply LUT 00450 *(q++) = *(lut0 + (*(p++))); 00451 } 00452 if (lut == NULL) // use "normal" transformation 00453 { 00454 if (dlut != NULL) // perform display transformation 00455 { 00456 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #7"); 00457 if (low > high) // inverse 00458 { 00459 const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1); 00460 for (i = Count; i != 0; --i) 00461 { 00462 value = OFstatic_cast(T2, *(p++)); // pixel value 00463 if (value <= firstentry) 00464 value2 = firstvalue; 00465 else if (value >= lastentry) 00466 value2 = lastvalue; 00467 else 00468 value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); 00469 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value2)))); 00470 } 00471 } else { // normal 00472 for (i = Count; i != 0; --i) 00473 { 00474 value = OFstatic_cast(T2, *(p++)); // pixel value 00475 if (value <= firstentry) 00476 value2 = firstvalue; 00477 else if (value >= lastentry) 00478 value2 = lastvalue; 00479 else 00480 value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); 00481 *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value2))); 00482 } 00483 } 00484 } else { // don't use display: invalid or absent 00485 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #8"); 00486 const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange()); 00487 for (i = Count; i != 0; --i) 00488 { 00489 value = OFstatic_cast(T2, *(p++)); // pixel value 00490 if (value <= firstentry) 00491 value2 = firstvalue; 00492 else if (value >= lastentry) 00493 value2 = lastvalue; 00494 else 00495 value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); 00496 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); 00497 } 00498 } 00499 } 00500 } else { // has no presentation LUT 00501 createDisplayLUT(dlut, disp, vlut->getBits()); 00502 const double gradient = outrange / OFstatic_cast(double, vlut->getAbsMaxRange()); 00503 const T3 firstvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getFirstValue()) * gradient); 00504 const T3 lastvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getLastValue()) * gradient); 00505 if (initOptimizationLUT(lut, ocnt)) 00506 { // use LUT for optimization 00507 q = lut; 00508 if (dlut != NULL) // perform display transformation 00509 { 00510 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #9"); 00511 if (low > high) // inverse 00512 { 00513 const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1); 00514 for (i = 0; i < ocnt; ++i) 00515 { 00516 value = OFstatic_cast(T2, i) + absmin; 00517 if (value < firstentry) 00518 value = firstentry; 00519 else if (value > lastentry) 00520 value = lastentry; 00521 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - vlut->getValue(value)))); 00522 } 00523 } else { // normal 00524 for (i = 0; i < ocnt; ++i) 00525 { 00526 value = OFstatic_cast(T2, i) + absmin; 00527 if (value < firstentry) 00528 value = firstentry; 00529 else if (value > lastentry) 00530 value = lastentry; 00531 *(q++) = OFstatic_cast(T3, dlut->getValue(vlut->getValue(value))); 00532 } 00533 } 00534 } else { // don't use display: invalid or absent 00535 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #10"); 00536 for (i = 0; i < ocnt; ++i) // calculating LUT entries 00537 { 00538 value = OFstatic_cast(T2, i) + absmin; 00539 if (value <= firstentry) 00540 *(q++) = firstvalue; 00541 else if (value >= lastentry) 00542 *(q++) = lastvalue; 00543 else 00544 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient); 00545 } 00546 } 00547 const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry 00548 q = Data; 00549 for (i = Count; i != 0; --i) // apply LUT 00550 *(q++) = *(lut0 + (*(p++))); 00551 } 00552 if (lut == NULL) // use "normal" transformation 00553 { 00554 if (dlut != NULL) // perform display transformation 00555 { 00556 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #11"); 00557 if (low > high) // inverse 00558 { 00559 const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1); 00560 for (i = Count; i != 0; --i) 00561 { 00562 value = OFstatic_cast(T2, *(p++)); 00563 if (value < firstentry) 00564 value = firstentry; 00565 else if (value > lastentry) 00566 value = lastentry; 00567 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - vlut->getValue(value)))); 00568 } 00569 } else { // normal 00570 for (i = Count; i != 0; --i) 00571 { 00572 value = OFstatic_cast(T2, *(p++)); 00573 if (value < firstentry) 00574 value = firstentry; 00575 else if (value > lastentry) 00576 value = lastentry; 00577 *(q++) = OFstatic_cast(T3, dlut->getValue(vlut->getValue(value))); 00578 } 00579 } 00580 } else { // don't use display: invalid or absent 00581 DCMIMGLE_TRACE("monochrome rendering: VOI LUT #12"); 00582 for (i = 0; i < Count; ++i) 00583 { 00584 value = OFstatic_cast(T2, *(p++)); 00585 if (value <= firstentry) 00586 *(q++) = firstvalue; 00587 else if (value >= lastentry) 00588 *(q++) = lastvalue; 00589 else 00590 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient); 00591 } 00592 } 00593 } 00594 } 00595 delete[] lut; 00596 } 00597 if (Count < FrameSize) 00598 OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero 00599 } 00600 } else 00601 Data = NULL; 00602 } 00603 00613 void nowindow(const DiMonoPixel *inter, 00614 const Uint32 start, 00615 const DiLookupTable *plut, 00616 DiDisplayFunction *disp, 00617 const T3 low, 00618 const T3 high) 00619 { 00620 const DiDisplayLUT *dlut = NULL; 00621 const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); 00622 if (pixel != NULL) 00623 { 00624 if (Data == NULL) // create new output buffer 00625 Data = new T3[FrameSize]; 00626 if (Data != NULL) 00627 { 00628 DCMIMGLE_DEBUG("applying no VOI transformation (linear scaling)"); 00629 const double absmin = inter->getAbsMinimum(); 00630 const double absmax = inter->getAbsMaximum(); 00631 const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1; 00632 const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries 00633 register const T1 *p = pixel + start; 00634 register T3 *q = Data; 00635 register unsigned long i; 00636 T3 *lut = NULL; 00637 if ((plut != NULL) && (plut->isValid())) // has presentation LUT 00638 { 00639 DCMIMGLE_DEBUG("applying presentation LUT transformation"); 00640 createDisplayLUT(dlut, disp, plut->getBits()); 00641 register Uint32 value; // presentation LUT is always unsigned 00642 const double gradient1 = OFstatic_cast(double, plut->getCount()) / inter->getAbsMaxRange(); 00643 const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange()); 00644 if (initOptimizationLUT(lut, ocnt)) 00645 { // use LUT for optimization 00646 q = lut; 00647 if (dlut != NULL) // perform display transformation 00648 { 00649 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #1"); 00650 if (low > high) // inverse 00651 { 00652 const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1); 00653 for (i = 0; i < ocnt; ++i) 00654 { 00655 value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); 00656 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value)))); 00657 } 00658 } else { // normal 00659 for (i = 0; i < ocnt; ++i) 00660 { 00661 value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); 00662 *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value))); 00663 } 00664 } 00665 } else { // don't use display: invalid or absent 00666 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #2"); 00667 for (i = 0; i < ocnt; ++i) 00668 { 00669 value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); 00670 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2); 00671 } 00672 } 00673 const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry 00674 q = Data; 00675 for (i = Count; i != 0; --i) // apply LUT 00676 *(q++) = *(lut0 + (*(p++))); 00677 } 00678 if (lut == NULL) // use "normal" transformation 00679 { 00680 if (dlut != NULL) // perform display transformation 00681 { 00682 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #3"); 00683 if (low > high) // inverse 00684 { 00685 const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1); 00686 for (i = Count; i != 0; --i) 00687 { 00688 value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); 00689 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value)))); 00690 } 00691 } else { // normal 00692 for (i = Count; i != 0; --i) 00693 { 00694 value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); 00695 *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value))); 00696 } 00697 } 00698 } else { // don't use display: invalid or absent 00699 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #4"); 00700 for (i = Count; i != 0; --i) 00701 { 00702 value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); 00703 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2); 00704 } 00705 } 00706 } 00707 } else { // has no presentation LUT 00708 createDisplayLUT(dlut, disp, inter->getBits()); 00709 register const double gradient = outrange / (inter->getAbsMaxRange()); 00710 if (initOptimizationLUT(lut, ocnt)) 00711 { // use LUT for optimization 00712 q = lut; 00713 if (dlut != NULL) // perform display transformation 00714 { 00715 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #5"); 00716 if (low > high) // inverse 00717 { 00718 for (i = ocnt; i != 0; --i) // calculating LUT entries 00719 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, i - 1))); 00720 } else { // normal 00721 for (i = 0; i < ocnt; ++i) // calculating LUT entries 00722 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, i))); 00723 } 00724 } else { // don't use display: invalid or absent 00725 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #6"); 00726 for (i = 0; i < ocnt; ++i) // calculating LUT entries 00727 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, i) * gradient); 00728 } 00729 const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry 00730 q = Data; 00731 for (i = Count; i != 0; --i) // apply LUT 00732 *(q++) = *(lut0 + (*(p++))); 00733 } 00734 if (lut == NULL) // use "normal" transformation 00735 { 00736 if (dlut != NULL) // perform display transformation 00737 { 00738 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #7"); 00739 if (low > high) // inverse 00740 { 00741 for (i = Count; i != 0; --i) 00742 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, absmax - (OFstatic_cast(double, *(p++)) - absmin)))); 00743 } else { // normal 00744 for (i = Count; i != 0; --i) 00745 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, OFstatic_cast(double, *(p++)) - absmin))); 00746 } 00747 } else { // don't use display: invalid or absent 00748 DCMIMGLE_TRACE("monochrome rendering: VOI NONE #8"); 00749 for (i = Count; i != 0; --i) 00750 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + (OFstatic_cast(double, *(p++)) - absmin) * gradient); 00751 } 00752 } 00753 } 00754 delete[] lut; 00755 if (Count < FrameSize) 00756 OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero 00757 } 00758 } else 00759 Data = NULL; 00760 } 00761 00773 void sigmoid(const DiMonoPixel *inter, 00774 const Uint32 start, 00775 const DiLookupTable *plut, 00776 DiDisplayFunction *disp, 00777 const double center, 00778 const double width, 00779 const T3 low, 00780 const T3 high) 00781 { 00782 const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); 00783 if (pixel != NULL) 00784 { 00785 if (Data == NULL) 00786 Data = new T3[FrameSize]; // create new output buffer 00787 if (Data != NULL) 00788 { 00789 DCMIMGLE_DEBUG("applying sigmoid VOI transformation with window center = " << center << ", width = " << width); 00790 const DiDisplayLUT *dlut = NULL; 00791 const double absmin = inter->getAbsMinimum(); 00792 const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range 00793 const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries 00794 register const T1 *p = pixel + start; 00795 register T3 *q = Data; 00796 register unsigned long i; 00797 register double value; 00798 T3 *lut = NULL; 00799 if ((plut != NULL) && (plut->isValid())) // has presentation LUT 00800 { 00801 DCMIMGLE_DEBUG("applying presentation LUT transformation"); 00802 createDisplayLUT(dlut, disp, plut->getBits()); 00803 register Uint32 value2; // presentation LUT is always unsigned 00804 const double plutcnt_1 = OFstatic_cast(double, plut->getCount() - 1); 00805 const double plutmax_1 = OFstatic_cast(double, plut->getAbsMaxRange() - 1); 00806 if (initOptimizationLUT(lut, ocnt)) 00807 { // use LUT for optimization 00808 q = lut; 00809 if (dlut != NULL) // perform display transformation 00810 { 00811 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #1"); 00812 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 00813 const double offset = (low > high) ? maxvalue : 0; 00814 const double gradient = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); 00815 for (i = 0; i < ocnt; ++i) 00816 { 00817 value = OFstatic_cast(double, i) + absmin; 00818 value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); 00819 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient))); 00820 } 00821 } else { // don't use display: invalid or absent 00822 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #2"); 00823 const double gradient = outrange / plutmax_1; 00824 for (i = 0; i < ocnt; ++i) 00825 { 00826 value = OFstatic_cast(double, i) + absmin; 00827 value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); 00828 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient); 00829 } 00830 } 00831 const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry 00832 q = Data; 00833 for (i = Count; i != 0; --i) // apply LUT 00834 *(q++) = *(lut0 + (*(p++))); 00835 } 00836 if (lut == NULL) // use "normal" transformation 00837 { 00838 if (dlut != NULL) // perform display transformation 00839 { 00840 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #3"); 00841 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 00842 const double offset = (low > high) ? maxvalue : 0; 00843 const double gradient = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); 00844 for (i = Count; i != 0; --i) 00845 { 00846 value = OFstatic_cast(double, *(p++)); 00847 value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); 00848 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient))); 00849 } 00850 } else { // don't use display: invalid or absent 00851 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #4"); 00852 const double gradient = outrange / plutmax_1; 00853 for (i = Count; i != 0; --i) 00854 { 00855 value = OFstatic_cast(double, *(p++)); 00856 value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); 00857 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient); 00858 } 00859 } 00860 } 00861 } else { // has no presentation LUT 00862 createDisplayLUT(dlut, disp, bitsof(T1)); 00863 if (initOptimizationLUT(lut, ocnt)) 00864 { // use LUT for optimization 00865 q = lut; 00866 if (dlut != NULL) // perform display transformation 00867 { 00868 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #5"); 00869 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 00870 const double outrange2 = (low > high) ? -maxvalue : maxvalue; 00871 const double offset = (low > high) ? maxvalue : 0; 00872 for (i = 0; i < ocnt; ++i) // calculating LUT entries 00873 { 00874 value = OFstatic_cast(double, i) + absmin; 00875 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + outrange2 / (1 + exp(-4 * (value - center) / width))))); 00876 } 00877 } else { // don't use display: invalid or absent 00878 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #6"); 00879 for (i = 0; i < ocnt; ++i) // calculating LUT entries 00880 { 00881 value = OFstatic_cast(double, i) + absmin; 00882 *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width))); 00883 } 00884 } 00885 const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry 00886 q = Data; 00887 for (i = Count; i != 0; --i) // apply LUT 00888 *(q++) = *(lut0 + (*(p++))); 00889 } 00890 if (lut == NULL) // use "normal" transformation 00891 { 00892 if (dlut != NULL) // perform display transformation 00893 { 00894 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #7"); 00895 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 00896 const double outrange2 = (low > high) ? -maxvalue : maxvalue; 00897 const double offset = (low > high) ? maxvalue : 0; 00898 for (i = Count; i != 0; --i) 00899 { 00900 value = OFstatic_cast(double, *(p++)); 00901 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + outrange2 / (1 + exp(-4 * (value - center) / width))))); 00902 } 00903 } else { // don't use display: invalid or absent 00904 DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #8"); 00905 for (i = Count; i != 0; --i) 00906 { 00907 value = OFstatic_cast(double, *(p++)); 00908 *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width))); 00909 } 00910 } 00911 } 00912 } 00913 delete[] lut; 00914 if (Count < FrameSize) 00915 OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero 00916 } 00917 } else 00918 Data = NULL; 00919 } 00920 00932 void window(const DiMonoPixel *inter, 00933 const Uint32 start, 00934 const DiLookupTable *plut, 00935 DiDisplayFunction *disp, 00936 const double center, 00937 const double width, 00938 const T3 low, 00939 const T3 high) 00940 { 00941 const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); 00942 if (pixel != NULL) 00943 { 00944 if (Data == NULL) 00945 Data = new T3[FrameSize]; // create new output buffer 00946 if (Data != NULL) 00947 { 00948 DCMIMGLE_DEBUG("applying linear VOI transformation with window center = " << center << ", width = " << width); 00949 const DiDisplayLUT *dlut = NULL; 00950 const double absmin = inter->getAbsMinimum(); 00951 const double width_1 = width - 1; 00952 const double leftBorder = center - 0.5 - width_1 / 2; // window borders, according to supplement 33 00953 const double rightBorder = center - 0.5 + width_1 / 2; 00954 const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range 00955 const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries 00956 register const T1 *p = pixel + start; 00957 register T3 *q = Data; 00958 register unsigned long i; 00959 register double value; 00960 T3 *lut = NULL; 00961 if ((plut != NULL) && (plut->isValid())) // has presentation LUT 00962 { 00963 DCMIMGLE_DEBUG("applying presentation LUT transformation"); 00964 createDisplayLUT(dlut, disp, plut->getBits()); 00965 register Uint32 value2; // presentation LUT is always unsigned 00966 const Uint32 pcnt = plut->getCount(); 00967 const double plutmax_1 = OFstatic_cast(double, plut->getAbsMaxRange()) - 1; 00968 const double gradient1 = (width_1 == 0) ? 0 : OFstatic_cast(double, pcnt - 1) / width_1; 00969 if (initOptimizationLUT(lut, ocnt)) 00970 { // use LUT for optimization 00971 q = lut; 00972 if (dlut != NULL) // perform display transformation 00973 { 00974 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #1"); 00975 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 00976 const double offset = (low > high) ? maxvalue : 0; 00977 const double gradient2 = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); 00978 for (i = 0; i < ocnt; ++i) 00979 { 00980 value = OFstatic_cast(double, i) + absmin; // pixel value 00981 if (value <= leftBorder) 00982 value2 = 0; // first LUT index 00983 else if (value > rightBorder) 00984 value2 = pcnt - 1; // last LUT index 00985 else 00986 value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); 00987 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient2))); 00988 } 00989 } else { // don't use display: invalid or absent 00990 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #2"); 00991 const double gradient2 = outrange / plutmax_1; 00992 for (i = 0; i < ocnt; ++i) 00993 { 00994 value = OFstatic_cast(double, i) + absmin; // pixel value 00995 if (value <= leftBorder) 00996 value2 = 0; // first LUT index 00997 else if (value > rightBorder) 00998 value2 = pcnt - 1; // last LUT index 00999 else 01000 value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); 01001 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); 01002 } 01003 } 01004 const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry 01005 q = Data; 01006 for (i = Count; i != 0; --i) // apply LUT 01007 *(q++) = *(lut0 + (*(p++))); 01008 } 01009 if (lut == NULL) // use "normal" transformation 01010 { 01011 if (dlut != NULL) // perform display transformation 01012 { 01013 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #3"); 01014 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 01015 const double offset = (low > high) ? maxvalue : 0; 01016 const double gradient2 = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); 01017 for (i = Count; i != 0; --i) 01018 { 01019 value = OFstatic_cast(double, *(p++)); // pixel value 01020 if (value <= leftBorder) 01021 value2 = 0; // first LUT index 01022 else if (value > rightBorder) 01023 value2 = pcnt - 1; // last LUT index 01024 else 01025 value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); 01026 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient2))); 01027 } 01028 } else { // don't use display: invalid or absent 01029 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #4"); 01030 const double gradient2 = outrange / plutmax_1; 01031 for (i = Count; i != 0; --i) 01032 { 01033 value = OFstatic_cast(double, *(p++)); // pixel value 01034 if (value <= leftBorder) 01035 value2 = 0; // first LUT index 01036 else if (value > rightBorder) 01037 value2 = pcnt - 1; // last LUT index 01038 else 01039 value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); 01040 *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); 01041 } 01042 } 01043 } 01044 } else { // has no presentation LUT 01045 createDisplayLUT(dlut, disp, bitsof(T1)); 01046 if (initOptimizationLUT(lut, ocnt)) 01047 { // use LUT for optimization 01048 q = lut; 01049 if (dlut != NULL) // perform display transformation 01050 { 01051 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #5"); 01052 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 01053 const double offset = (low > high) ? maxvalue : 0; 01054 const double gradient = (width_1 == 0) ? 0 : ((low > high) ? (-maxvalue / width_1) : (maxvalue / width_1)); 01055 for (i = 0; i < ocnt; ++i) // calculating LUT entries 01056 { 01057 value = OFstatic_cast(double, i) + absmin - leftBorder; 01058 if (value < 0) // left border 01059 value = 0; 01060 else if (value > width_1) // right border 01061 value = width_1; 01062 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + value * gradient))); // calculate value 01063 } 01064 } else { // don't use display: invalid or absent 01065 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #6"); 01066 const double offset = (width_1 == 0) ? 0 : (high - ((center - 0.5) / width_1 + 0.5) * outrange); 01067 const double gradient = (width_1 == 0) ? 0 : outrange / width_1; 01068 for (i = 0; i < ocnt; ++i) // calculating LUT entries 01069 { 01070 value = OFstatic_cast(double, i) + absmin; 01071 if (value <= leftBorder) 01072 *(q++) = low; // black/white 01073 else if (value > rightBorder) 01074 *(q++) = high; // white/black 01075 else 01076 *(q++) = OFstatic_cast(T3, offset + value * gradient); // gray value 01077 } 01078 } 01079 const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry 01080 q = Data; 01081 for (i = Count; i != 0; --i) // apply LUT 01082 *(q++) = *(lut0 + (*(p++))); 01083 } 01084 if (lut == NULL) // use "normal" transformation 01085 { 01086 if (dlut != NULL) // perform display transformation 01087 { 01088 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #7"); 01089 const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); 01090 const double offset = (low > high) ? maxvalue : 0; 01091 const double gradient = (width_1 == 0) ? 0 : ((low > high) ? (-maxvalue / width_1) : (maxvalue / width_1)); 01092 for (i = Count; i != 0; --i) // calculating LUT entries 01093 { 01094 value = OFstatic_cast(double, *(p++)) - leftBorder; 01095 if (value < 0) // left border 01096 value = 0; 01097 else if (value > width_1) // right border 01098 value = width_1; 01099 *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + value * gradient))); // calculate value 01100 } 01101 } else { // don't use display: invalid or absent 01102 DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #8"); 01103 const double offset = (width_1 == 0) ? 0 : (high - ((center - 0.5) / width_1 + 0.5) * outrange); 01104 const double gradient = (width_1 == 0) ? 0 : outrange / width_1; 01105 for (i = Count; i != 0; --i) 01106 { 01107 value = OFstatic_cast(double, *(p++)); 01108 if (value <= leftBorder) 01109 *(q++) = low; // black/white 01110 else if (value > rightBorder) 01111 *(q++) = high; // white/black 01112 else 01113 *(q++) = OFstatic_cast(T3, offset + value * gradient); // gray value 01114 } 01115 } 01116 } 01117 } 01118 delete[] lut; 01119 if (Count < FrameSize) 01120 OFBitmanipTemplate<T3>::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero 01121 } 01122 } else 01123 Data = NULL; 01124 } 01125 01126 01135 void overlay(DiOverlay *overlays[2], 01136 DiDisplayFunction *disp, 01137 const Uint16 columns, 01138 const Uint16 rows, 01139 const unsigned long frame) 01140 { 01141 if ((Data != NULL) && (overlays != NULL)) 01142 { 01143 for (unsigned int j = 0; j < 2; ++j) 01144 { 01145 if (overlays[j] != NULL) 01146 { 01147 if (overlays[j]->getCount() > 0) 01148 DCMIMGLE_DEBUG("applying " << ((j == 0) ? "built-in" : "additional") << " overlay planes"); 01149 const signed long left_pos = overlays[j]->getLeft(); 01150 const signed long top_pos = overlays[j]->getTop(); 01151 register DiOverlayPlane *plane; 01152 for (unsigned int i = 0; i < overlays[j]->getCount(); ++i) 01153 { 01154 plane = overlays[j]->getPlane(i); 01155 if ((plane != NULL) && plane->isVisible() && plane->reset(frame)) 01156 { 01157 register T3 *q; 01158 register Uint16 x; 01159 register Uint16 y; 01160 const Uint16 xmin = (plane->getLeft(left_pos) > 0) ? plane->getLeft(left_pos) : 0; 01161 const Uint16 ymin = (plane->getTop(top_pos) > 0) ? plane->getTop(top_pos) : 0; 01162 const Uint16 xmax = (plane->getRight(left_pos) < columns) ? plane->getRight(left_pos) : columns; 01163 const Uint16 ymax = (plane->getBottom(top_pos) < rows) ? plane->getBottom(top_pos) : rows; 01164 const T3 maxvalue = OFstatic_cast(T3, DicomImageClass::maxval(bitsof(T3))); 01165 switch (plane->getMode()) 01166 { 01167 case EMO_Replace: 01168 { 01169 DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'replace' mode"); 01170 const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue); 01171 for (y = ymin; y < ymax; ++y) 01172 { 01173 plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); 01174 q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); 01175 for (x = xmin; x < xmax; ++x, ++q) 01176 { 01177 if (plane->getNextBit()) 01178 *q = fore; 01179 } 01180 } 01181 break; 01182 } 01183 case EMO_ThresholdReplace: 01184 { 01185 DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'threshold replace' mode"); 01186 const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue); 01187 const T3 thresh = OFstatic_cast(T3, plane->getThreshold() * maxvalue); 01188 for (y = ymin; y < ymax; ++y) 01189 { 01190 plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); 01191 q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); 01192 for (x = xmin; x < xmax; ++x, ++q) 01193 { 01194 if (plane->getNextBit()) 01195 *q = (*q <= thresh) ? fore : 1; 01196 } 01197 } 01198 break; 01199 } 01200 case EMO_Complement: 01201 { 01202 DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'complement' mode"); 01203 const T3 thresh = OFstatic_cast(T3, DicomImageClass::maxval(bitsof(T3) / 2)); 01204 for (y = ymin; y < ymax; ++y) 01205 { 01206 plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); 01207 q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); 01208 for (x = xmin; x < xmax; ++x, ++q) 01209 { 01210 if (plane->getNextBit()) 01211 *q = (*q <= thresh) ? maxvalue : 0; 01212 } 01213 } 01214 break; 01215 } 01216 case EMO_InvertBitmap: 01217 { 01218 DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'invert bitmap' mode"); 01219 const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue); 01220 for (y = ymin; y < ymax; ++y) 01221 { 01222 plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); 01223 q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); 01224 for (x = xmin; x < xmax; ++x, ++q) 01225 { 01226 if (!plane->getNextBit()) 01227 *q = fore; 01228 } 01229 } 01230 break; 01231 } 01232 case EMO_RegionOfInterest: 01233 { 01234 DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'region of interest' mode"); 01235 const int dim = bitsof(T3) / 2; 01236 for (y = ymin; y < ymax; ++y) 01237 { 01238 plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); 01239 q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); 01240 for (x = xmin; x < xmax; ++x, ++q) 01241 { 01242 if (!plane->getNextBit()) 01243 *q = *q >> dim; 01244 } 01245 } 01246 break; 01247 } 01248 case EMO_BitmapShutter: 01249 { 01250 DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'bitmap shutter' mode"); 01251 register T3 fore = OFstatic_cast(T3, OFstatic_cast(double, maxvalue) * OFstatic_cast(double, plane->getPValue()) / OFstatic_cast(double, DicomImageClass::maxval(WIDTH_OF_PVALUES))); 01252 if ((disp != NULL) && (disp->isValid())) 01253 { 01254 const DiDisplayLUT *dlut = disp->getLookupTable(WIDTH_OF_PVALUES); 01255 if ((dlut != NULL) && (dlut->isValid())) 01256 fore = OFstatic_cast(T3, dlut->getValue(plane->getPValue())); 01257 } 01258 for (y = ymin; y < ymax; ++y) 01259 { 01260 plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); 01261 q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); 01262 for (x = xmin; x < xmax; ++x, ++q) 01263 { 01264 if (plane->getNextBit()) 01265 *q = fore; 01266 } 01267 } 01268 break; 01269 } 01270 default: /* e.g. EMO_Default */ 01271 DCMIMGLE_WARN("unhandled overlay mode (" << OFstatic_cast(int, plane->getMode()) << ")"); 01272 } 01273 } 01274 } 01275 } 01276 } 01277 } 01278 } 01279 01280 01282 T3 *Data; 01284 int DeleteData; 01285 01286 #ifdef PASTEL_COLOR_OUTPUT 01287 DiMonoColorOutputPixelTemplate<T1, T3> *ColorData; 01288 #else 01289 // dummy variable 01290 DiMonoOutputPixel *ColorData; 01291 #endif 01292 01293 // --- declarations to avoid compiler warnings 01294 01295 DiMonoOutputPixelTemplate(const DiMonoOutputPixelTemplate<T1,T2,T3> &); 01296 DiMonoOutputPixelTemplate<T1,T2,T3> &operator=(const DiMonoOutputPixelTemplate<T1,T2,T3> &); 01297 }; 01298 01299 01300 #endif 01301 01302 01303 /* 01304 * 01305 * CVS/RCS Log: 01306 * $Log: dimoopxt.h,v $ 01307 * Revision 1.54 2010-10-28 10:58:38 joergr 01308 * Implemented missing rendering code for sigmoid VOI LUT function. 01309 * Added more trace log messages which might be helpful for detailed debugging. 01310 * 01311 * Revision 1.53 2010-10-14 13:16:26 joergr 01312 * Updated copyright header. Added reference to COPYRIGHT file. 01313 * 01314 * Revision 1.52 2010-10-05 15:25:10 joergr 01315 * Added preliminary support for VOI LUT function. Please note, however, that 01316 * the sigmoid transformation is not yet implemented. 01317 * In debug mode, output more details on overlay plane to the logger. 01318 * 01319 * Revision 1.51 2010-03-01 09:08:47 uli 01320 * Removed some unnecessary include directives in the headers. 01321 * 01322 * Revision 1.50 2009-11-25 16:08:26 joergr 01323 * Removed inclusion of header file "ofconsol.h". 01324 * Revised logging messages. Added more logging messages. 01325 * 01326 * Revision 1.49 2009-10-28 14:38:16 joergr 01327 * Fixed minor issues in log output. 01328 * 01329 * Revision 1.48 2009-10-28 09:53:40 uli 01330 * Switched to logging mechanism provided by the "new" oflog module. 01331 * 01332 * Revision 1.47 2006-08-15 16:30:11 meichel 01333 * Updated the code in module dcmimgle to correctly compile when 01334 * all standard C++ classes remain in namespace std. 01335 * 01336 * Revision 1.46 2005/12/08 16:47:54 meichel 01337 * Changed include path schema for all DCMTK header files 01338 * 01339 * Revision 1.45 2005/03/09 17:30:42 joergr 01340 * Added support for new overlay mode "invert bitmap". 01341 * 01342 * Revision 1.44 2004/02/06 11:07:50 joergr 01343 * Distinguish more clearly between const and non-const access to pixel data. 01344 * 01345 * Revision 1.43 2003/12/23 15:53:22 joergr 01346 * Replaced post-increment/decrement operators by pre-increment/decrement 01347 * operators where appropriate (e.g. 'i++' by '++i'). 01348 * 01349 * Revision 1.42 2003/12/23 10:51:52 joergr 01350 * Updated documentation to get rid of doxygen warnings. 01351 * 01352 * Revision 1.41 2003/12/09 16:49:11 joergr 01353 * Adapted type casts to new-style typecast operators defined in ofcast.h. 01354 * Removed leading underscore characters from preprocessor symbols (reserved 01355 * symbols). Updated copyright header. 01356 * 01357 * Revision 1.40 2003/06/12 15:08:34 joergr 01358 * Fixed inconsistent API documentation reported by Doxygen. 01359 * 01360 * Revision 1.39 2002/12/09 13:32:53 joergr 01361 * Renamed parameter/local variable to avoid name clashes with global 01362 * declaration left and/or right (used for as iostream manipulators). 01363 * 01364 * Revision 1.38 2002/11/27 14:08:06 meichel 01365 * Adapted module dcmimgle to use of new header file ofstdinc.h 01366 * 01367 * Revision 1.37 2002/06/19 08:12:01 meichel 01368 * Added typecasts to avoid ambiguity with built-in functions on gcc 3.2 01369 * 01370 * Revision 1.36 2001/06/01 15:49:46 meichel 01371 * Updated copyright header 01372 * 01373 * Revision 1.35 2000/05/03 09:46:28 joergr 01374 * Removed most informational and some warning messages from release built 01375 * (#ifndef DEBUG). 01376 * 01377 * Revision 1.34 2000/04/28 12:32:31 joergr 01378 * DebugLevel - global for the module - now derived from OFGlobal (MF-safe). 01379 * 01380 * Revision 1.33 2000/04/27 13:08:40 joergr 01381 * Dcmimgle library code now consistently uses ofConsole for error output. 01382 * 01383 * Revision 1.32 2000/03/08 16:24:20 meichel 01384 * Updated copyright header. 01385 * 01386 * Revision 1.31 2000/03/07 16:15:12 joergr 01387 * Added explicit type casts to make Sun CC 2.0.1 happy. 01388 * 01389 * Revision 1.30 2000/03/06 18:19:36 joergr 01390 * Moved get-method to base class, renamed method and made method virtual to 01391 * avoid hiding of methods (reported by Sun CC 4.2). 01392 * 01393 * Revision 1.29 2000/03/03 14:09:13 meichel 01394 * Implemented library support for redirecting error messages into memory 01395 * instead of printing them to stdout/stderr for GUI applications. 01396 * 01397 * Revision 1.28 2000/02/01 10:52:37 meichel 01398 * Avoiding to include <stdlib.h> as extern "C" on Borland C++ Builder 4, 01399 * workaround for bug in compiler header files. 01400 * 01401 * Revision 1.27 1999/10/11 20:14:14 joergr 01402 * Fixed bug in window() routine for cases where presentation LUT is active. 01403 * 01404 * Revision 1.26 1999/10/06 13:42:03 joergr 01405 * Added method to remove reference to (internally handled) pixel data. 01406 * 01407 * Revision 1.25 1999/09/17 12:40:45 joergr 01408 * Added/changed/completed DOC++ style comments in the header files. 01409 * Enhanced efficiency of some "for" loops. 01410 * 01411 * Revision 1.24 1999/09/10 08:45:19 joergr 01412 * Added support for CIELAB display function. 01413 * 01414 * Revision 1.23 1999/08/25 16:41:53 joergr 01415 * Added new feature: Allow clipping region to be outside the image 01416 * (overlapping). 01417 * 01418 * Revision 1.22 1999/08/17 10:26:08 joergr 01419 * Commented unused parameter names to avoid compiler warnings. 01420 * 01421 * Revision 1.21 1999/07/23 14:08:44 joergr 01422 * Changed implementation/interpretation of windows center/width (according to 01423 * new letter ballot of supplement 33). 01424 * Enhanced handling of corrupted pixel data (wrong length). 01425 * 01426 * Revision 1.20 1999/05/03 15:43:21 joergr 01427 * Replaced method applyOptimizationLUT by its contents (method body) to avoid 01428 * warnings (and possible errors) on Sun CC 2.0.1 :-/ 01429 * 01430 * Revision 1.18 1999/04/30 16:10:50 meichel 01431 * Minor code purifications to keep IBM xlC quiet 01432 * 01433 * Revision 1.17 1999/04/29 16:46:46 meichel 01434 * Minor code purifications to keep DEC cxx 6 quiet. 01435 * 01436 * Revision 1.16 1999/04/29 09:38:34 joergr 01437 * Changed position of "#ifdef" to avoid compiler warnings. 01438 * 01439 * Revision 1.15 1999/04/29 09:20:01 joergr 01440 * Removed color related image files from public toolkit part. 01441 * 01442 * Revision 1.14 1999/04/28 18:56:07 joergr 01443 * Removed support for pastel color output from public DCMTK part. 01444 * 01445 * Revision 1.13 1999/04/28 14:51:44 joergr 01446 * Added experimental support to create grayscale images with more than 256 01447 * shades of gray to be displayed on a consumer monitor (use pastel colors). 01448 * Introduced new scheme for the debug level variable: now each level can be 01449 * set separately (there is no "include" relationship). 01450 * 01451 * Revision 1.12 1999/03/24 17:20:14 joergr 01452 * Added/Modified comments and formatting. 01453 * 01454 * Revision 1.11 1999/03/02 12:03:52 joergr 01455 * Corrected bug in output routine of monochrome pixel data (wrong scaling when 01456 * Barten transformation and windowing are active). 01457 * 01458 * Revision 1.10 1999/02/28 16:41:01 joergr 01459 * Corrected bug: the output bits for bitmaps shutters were inverted (this was 01460 * done due to an error in the used test images). 01461 * 01462 * Revision 1.9 1999/02/11 16:40:19 joergr 01463 * Added routine to check whether particular grayscale values are unused in 01464 * the output data. 01465 * Removed two small memory leaks reported by dmalloc library. 01466 * 01467 * Revision 1.8 1999/02/05 16:44:52 joergr 01468 * Corrected calculation of DDL value for bitmaps shutters (overlays). 01469 * 01470 * Revision 1.7 1999/02/05 15:13:36 joergr 01471 * Added conversion P-Value to DDL when display function is absent. 01472 * 01473 * Revision 1.6 1999/02/03 17:32:43 joergr 01474 * Added optimization LUT to transform pixel data. 01475 * Added support for calibration according to Barten transformation (incl. 01476 * a DISPLAY file describing the monitor characteristic). 01477 * 01478 * Revision 1.5 1999/01/20 15:11:05 joergr 01479 * Replaced invocation of getCount() by member variable Count where possible. 01480 * Added new output method to fill external memory buffer with rendered pixel 01481 * data. 01482 * Added new overlay plane mode for bitmap shutters. 01483 * Added optimization to modality and VOI transformation (using additional 01484 * LUTs). 01485 * 01486 * Revision 1.4 1998/12/23 12:40:01 joergr 01487 * Removed unused parameter (BitsPerSample). 01488 * 01489 * Revision 1.3 1998/12/22 14:32:49 joergr 01490 * Improved implementation of presentation LUT application (and other gray 01491 * scale transformations). Tested with ECR test images from David Clunie. 01492 * 01493 * Revision 1.2 1998/12/14 17:25:55 joergr 01494 * Added support for correct scaling of input/output values for grayscale 01495 * transformations. 01496 * 01497 * Revision 1.1 1998/11/27 15:29:53 joergr 01498 * Added copyright message. 01499 * Introduced global debug level for dcmimage module to control error output. 01500 * Corrected bug in VOI LUT transformation method. 01501 * Changed behaviour: now window width of 0 is valid and negative width 01502 * is invalid. 01503 * 01504 * Revision 1.6 1998/07/01 08:39:24 joergr 01505 * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional 01506 * options), e.g. add copy constructors. 01507 * 01508 * Revision 1.5 1998/05/11 14:53:22 joergr 01509 * Added CVS/RCS header to each file. 01510 * 01511 * 01512 */