00001 /* 00002 * 00003 * Copyright (C) 1996-2005, OFFIS 00004 * 00005 * This software and supporting documentation were developed by 00006 * 00007 * Kuratorium OFFIS e.V. 00008 * Healthcare Information and Communication Systems 00009 * Escherweg 2 00010 * D-26121 Oldenburg, Germany 00011 * 00012 * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY 00013 * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR 00014 * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR 00015 * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND 00016 * PERFORMANCE OF THE SOFTWARE IS WITH THE USER. 00017 * 00018 * Module: dcmimage 00019 * 00020 * Author: Joerg Riesmeier 00021 * 00022 * Purpose: DicomHSVPixelTemplate (Header) 00023 * 00024 * Last Update: $Author: meichel $ 00025 * Update Date: $Date: 2005/12/08 16:01:39 $ 00026 * CVS/RCS Revision: $Revision: 1.19 $ 00027 * Status: $State: Exp $ 00028 * 00029 * CVS/RCS Log at end of file 00030 * 00031 */ 00032 00033 00034 #ifndef DIHSVPXT_H 00035 #define DIHSVPXT_H 00036 00037 #include "dcmtk/config/osconfig.h" 00038 00039 #include "dcmtk/ofstd/ofconsol.h" /* for ofConsole */ 00040 #include "dcmtk/dcmimage/dicopxt.h" 00041 #include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ 00042 00043 00044 /*---------------------* 00045 * class declaration * 00046 *---------------------*/ 00047 00050 template<class T1, class T2> 00051 class DiHSVPixelTemplate 00052 : public DiColorPixelTemplate<T2> 00053 { 00054 00055 public: 00056 00065 DiHSVPixelTemplate(const DiDocument *docu, 00066 const DiInputPixel *pixel, 00067 EI_Status &status, 00068 const unsigned long planeSize, 00069 const int bits) 00070 : DiColorPixelTemplate<T2>(docu, pixel, 3, status) 00071 { 00072 if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) 00073 convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), planeSize, bits); 00074 } 00075 00078 virtual ~DiHSVPixelTemplate() 00079 { 00080 } 00081 00082 00083 private: 00084 00091 void convert(const T1 *pixel, 00092 const unsigned long planeSize, 00093 const int bits) 00094 { 00095 if (Init(pixel)) 00096 { 00097 register T2 *r = this->Data[0]; 00098 register T2 *g = this->Data[1]; 00099 register T2 *b = this->Data[2]; 00100 const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); 00101 const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); 00102 // use the number of input pixels derived from the length of the 'PixelData' 00103 // attribute), but not more than the size of the intermediate buffer 00104 const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; 00105 if (this->PlanarConfiguration) 00106 { 00107 /* 00108 register const T1 *h = pixel; 00109 register const T1 *s = h + this->InputCount; 00110 register const T1 *v = s + this->InputCount; 00111 for (i = count; i != 0; --i) 00112 convertValue(*(r++), *(g++), *(b++), removeSign(*(h++), offset), removeSign(*(s++), offset), 00113 removeSign(*(v++), offset), maxvalue); 00114 */ 00115 register unsigned long l; 00116 register unsigned long i = count; 00117 register const T1 *h = pixel; 00118 register const T1 *s = h + planeSize; 00119 register const T1 *v = s + planeSize; 00120 while (i != 0) 00121 { 00122 /* convert a single frame */ 00123 for (l = planeSize; (l != 0) && (i != 0); --l, --i) 00124 { 00125 convertValue(*(r++), *(g++), *(b++), removeSign(*(h++), offset), removeSign(*(s++), offset), 00126 removeSign(*(v++), offset), maxvalue); 00127 } 00128 /* jump to next frame start (skip 2 planes) */ 00129 h += 2 * planeSize; 00130 s += 2 * planeSize; 00131 v += 2 * planeSize; 00132 } 00133 } 00134 else 00135 { 00136 register const T1 *p = pixel; 00137 register T2 h; 00138 register T2 s; 00139 register T2 v; 00140 register unsigned long i; 00141 for (i = count; i != 0; --i) 00142 { 00143 h = removeSign(*(p++), offset); 00144 s = removeSign(*(p++), offset); 00145 v = removeSign(*(p++), offset); 00146 convertValue(*(r++), *(g++), *(b++), h, s, v, maxvalue); 00147 } 00148 } 00149 } 00150 } 00151 00154 void convertValue(T2 &red, 00155 T2 &green, 00156 T2 &blue, 00157 const T2 hue, 00158 const T2 saturation, 00159 const T2 value, 00160 const T2 maxvalue) 00161 { 00162 /* 00163 * conversion algorithm taken from Foley et al.: 'Computer Graphics: Principles and Practice' (1990) 00164 */ 00165 00166 if (saturation == 0) 00167 { 00168 red = value; 00169 green = value; 00170 blue = value; 00171 } 00172 else 00173 { 00174 const double h = (OFstatic_cast(double, hue) * 6) / (OFstatic_cast(double, maxvalue) + 1); // '... + 1' to assert h < 6 00175 const double s = OFstatic_cast(double, saturation) / OFstatic_cast(double, maxvalue); 00176 const double v = OFstatic_cast(double, value) / OFstatic_cast(double, maxvalue); 00177 const T2 hi = OFstatic_cast(T2, h); 00178 const double hf = h - hi; 00179 const T2 p = OFstatic_cast(T2, maxvalue * v * (1 - s)); 00180 const T2 q = OFstatic_cast(T2, maxvalue * v * (1 - s * hf)); 00181 const T2 t = OFstatic_cast(T2, maxvalue * v * (1 - s * (1 - hf))); 00182 switch (hi) 00183 { 00184 case 0: 00185 red = value; 00186 green = t; 00187 blue = p; 00188 break; 00189 case 1: 00190 red = q; 00191 green = value; 00192 blue = p; 00193 break; 00194 case 2: 00195 red = p; 00196 green = value; 00197 blue = t; 00198 break; 00199 case 3: 00200 red = p; 00201 green = q; 00202 blue = value; 00203 break; 00204 case 4: 00205 red = t; 00206 green = p; 00207 blue = value; 00208 break; 00209 case 5: 00210 red = value; 00211 green = p; 00212 blue = q; 00213 break; 00214 default: 00215 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Warnings)) 00216 { 00217 ofConsole.lockCerr() << "WARNING: invalid value for 'hi' while converting HSV to RGB !" << endl; 00218 ofConsole.unlockCerr(); 00219 } 00220 } 00221 } 00222 } 00223 }; 00224 00225 00226 #endif 00227 00228 00229 /* 00230 * 00231 * CVS/RCS Log: 00232 * $Log: dihsvpxt.h,v $ 00233 * Revision 1.19 2005/12/08 16:01:39 meichel 00234 * Changed include path schema for all DCMTK header files 00235 * 00236 * Revision 1.18 2004/04/21 10:00:31 meichel 00237 * Minor modifications for compilation with gcc 3.4.0 00238 * 00239 * Revision 1.17 2003/12/23 11:48:23 joergr 00240 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00241 * Removed leading underscore characters from preprocessor symbols (reserved 00242 * symbols). Updated copyright header. 00243 * Replaced post-increment/decrement operators by pre-increment/decrement 00244 * operators where appropriate (e.g. 'i++' by '++i'). 00245 * 00246 * Revision 1.16 2002/06/26 16:18:10 joergr 00247 * Enhanced handling of corrupted pixel data and/or length. 00248 * Corrected decoding of multi-frame, planar images. 00249 * 00250 * Revision 1.15 2001/11/09 16:47:01 joergr 00251 * Removed 'inline' specifier from certain methods. 00252 * 00253 * Revision 1.14 2001/06/01 15:49:30 meichel 00254 * Updated copyright header 00255 * 00256 * Revision 1.13 2000/04/28 12:39:32 joergr 00257 * DebugLevel - global for the module - now derived from OFGlobal (MF-safe). 00258 * 00259 * Revision 1.12 2000/04/27 13:15:13 joergr 00260 * Dcmimage library code now consistently uses ofConsole for error output. 00261 * 00262 * Revision 1.11 2000/03/08 16:21:52 meichel 00263 * Updated copyright header. 00264 * 00265 * Revision 1.10 2000/03/03 14:07:52 meichel 00266 * Implemented library support for redirecting error messages into memory 00267 * instead of printing them to stdout/stderr for GUI applications. 00268 * 00269 * Revision 1.9 1999/09/17 14:03:45 joergr 00270 * Enhanced efficiency of some "for" loops. 00271 * 00272 * Revision 1.8 1999/04/28 12:47:04 joergr 00273 * Introduced new scheme for the debug level variable: now each level can be 00274 * set separately (there is no "include" relationship). 00275 * 00276 * Revision 1.7 1999/02/03 16:54:27 joergr 00277 * Moved global functions maxval() and determineRepresentation() to class 00278 * DicomImageClass (as static methods). 00279 * 00280 * Revision 1.6 1999/01/20 14:46:15 joergr 00281 * Replaced invocation of getCount() by member variable Count where possible. 00282 * 00283 * Revision 1.5 1998/11/27 13:51:50 joergr 00284 * Added copyright message. 00285 * 00286 * Revision 1.4 1998/05/11 14:53:16 joergr 00287 * Added CVS/RCS header to each file. 00288 * 00289 * 00290 */