00001 /* 00002 * 00003 * Copyright (C) 1998-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: DicomYBRPixelTemplate (Header) 00023 * 00024 * Last Update: $Author: meichel $ 00025 * Update Date: $Date: 2005/12/08 16:02:01 $ 00026 * CVS/RCS Revision: $Revision: 1.17 $ 00027 * Status: $State: Exp $ 00028 * 00029 * CVS/RCS Log at end of file 00030 * 00031 */ 00032 00033 00034 #ifndef DIYBRPXT_H 00035 #define DIYBRPXT_H 00036 00037 #include "dcmtk/config/osconfig.h" 00038 00039 #include "dcmtk/dcmimage/dicopxt.h" 00040 #include "dcmtk/dcmimgle/dipxrept.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 DiYBRPixelTemplate 00052 : public DiColorPixelTemplate<T2> 00053 { 00054 00055 public: 00056 00066 DiYBRPixelTemplate(const DiDocument *docu, 00067 const DiInputPixel *pixel, 00068 EI_Status &status, 00069 const unsigned long planeSize, 00070 const int bits, 00071 const OFBool rgb) 00072 : DiColorPixelTemplate<T2>(docu, pixel, 3, status) 00073 { 00074 if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) 00075 convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), planeSize, bits, rgb); 00076 } 00077 00080 virtual ~DiYBRPixelTemplate() 00081 { 00082 } 00083 00084 00085 private: 00086 00094 void convert(const T1 *pixel, 00095 const unsigned long planeSize, 00096 const int bits, 00097 const OFBool rgb) 00098 { 00099 if (Init(pixel)) 00100 { 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 (rgb) /* convert to RGB model */ 00106 { 00107 register T2 *r = this->Data[0]; 00108 register T2 *g = this->Data[1]; 00109 register T2 *b = this->Data[2]; 00110 const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); 00111 DiPixelRepresentationTemplate<T1> rep; 00112 if (bits == 8 && !rep.isSigned()) // only for unsigned 8 bit 00113 { 00114 Sint16 rcr_tab[256]; 00115 Sint16 gcb_tab[256]; 00116 Sint16 gcr_tab[256]; 00117 Sint16 bcb_tab[256]; 00118 const double r_const = 0.7010 * OFstatic_cast(double, maxvalue); 00119 const double g_const = 0.5291 * OFstatic_cast(double, maxvalue); 00120 const double b_const = 0.8859 * OFstatic_cast(double, maxvalue); 00121 register unsigned long l; 00122 for (l = 0; l < 256; ++l) 00123 { 00124 rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * OFstatic_cast(double, l) - r_const); 00125 gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * OFstatic_cast(double, l)); 00126 gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * OFstatic_cast(double, l) - g_const); 00127 bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * OFstatic_cast(double, l) - b_const); 00128 } 00129 register Sint32 sr; 00130 register Sint32 sg; 00131 register Sint32 sb; 00132 if (this->PlanarConfiguration) 00133 { 00134 /* 00135 register const T1 *y = pixel; 00136 register const T1 *cb = y + this->InputCount; 00137 register const T1 *cr = cb + this->InputCount; 00138 for (i = count; i != 0; --i, ++y, ++cb, ++cr) 00139 { 00140 sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]); 00141 sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]); 00142 sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]); 00143 *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr); 00144 *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg); 00145 *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb); 00146 } 00147 */ 00148 register const T1 *y = pixel; 00149 register const T1 *cb = y + planeSize; 00150 register const T1 *cr = cb + planeSize; 00151 register unsigned long i = count; 00152 while (i != 0) 00153 { 00154 /* convert a single frame */ 00155 for (l = planeSize; (l != 0) && (i != 0); --l, --i, ++y, ++cb, ++cr) 00156 { 00157 sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, *cr)]); 00158 sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, *cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, *cr)]); 00159 sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, *cb)]); 00160 *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr); 00161 *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg); 00162 *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb); 00163 } 00164 /* jump to next frame start (skip 2 planes) */ 00165 y += 2 * planeSize; 00166 cb += 2 * planeSize; 00167 cr += 2 * planeSize; 00168 } 00169 } 00170 else 00171 { 00172 register const T1 *p = pixel; 00173 register T1 y; 00174 register T1 cb; 00175 register T1 cr; 00176 register unsigned long i; 00177 for (i = count; i != 0; --i) 00178 { 00179 y = *(p++); 00180 cb = *(p++); 00181 cr = *(p++); 00182 sr = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, cr)]); 00183 sg = OFstatic_cast(Sint32, y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, cr)]); 00184 sb = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, cb)]); 00185 *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr); 00186 *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg); 00187 *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb); 00188 } 00189 } 00190 } 00191 else 00192 { 00193 if (this->PlanarConfiguration) 00194 { 00195 /* 00196 register const T1 *y = pixel; 00197 register const T1 *cb = y + this->InputCount; 00198 register const T1 *cr = cb + this->InputCount; 00199 for (i = count; i != 0; --i) 00200 convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset), 00201 removeSign(*(cr++), offset), maxvalue); 00202 */ 00203 register unsigned long l; 00204 register unsigned long i = count; 00205 register const T1 *y = pixel; 00206 register const T1 *cb = y + planeSize; 00207 register const T1 *cr = cb + planeSize; 00208 while (i != 0) 00209 { 00210 /* convert a single frame */ 00211 for (l = planeSize; (l != 0) && (i != 0); --l, --i) 00212 { 00213 convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset), 00214 removeSign(*(cr++), offset), maxvalue); 00215 } 00216 /* jump to next frame start (skip 2 planes) */ 00217 y += 2 * planeSize; 00218 cb += 2 * planeSize; 00219 cr += 2 * planeSize; 00220 } 00221 } 00222 else 00223 { 00224 register const T1 *p = pixel; 00225 register T2 y; 00226 register T2 cb; 00227 register T2 cr; 00228 register unsigned long i; 00229 for (i = count; i != 0; --i) 00230 { 00231 y = removeSign(*(p++), offset); 00232 cb = removeSign(*(p++), offset); 00233 cr = removeSign(*(p++), offset); 00234 convertValue(*(r++), *(g++), *(b++), y, cb, cr, maxvalue); 00235 } 00236 } 00237 } 00238 } else { /* retain YCbCr model */ 00239 register const T1 *p = pixel; 00240 if (this->PlanarConfiguration) 00241 { 00242 /* 00243 register T2 *q; 00244 // number of pixels to be skipped (only applicable if 'PixelData' contains more 00245 // pixels than expected) 00246 const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0; 00247 for (int j = 0; j < 3; ++j) 00248 { 00249 q = this->Data[j]; 00250 for (i = count; i != 0; --i) 00251 *(q++) = removeSign(*(p++), offset); 00252 // skip to beginning of next plane 00253 p += skip; 00254 } 00255 */ 00256 register unsigned long l; 00257 register unsigned long i = 0; 00258 while (i < count) 00259 { 00260 /* store current pixel index */ 00261 const unsigned long iStart = i; 00262 for (int j = 0; j < 3; ++j) 00263 { 00264 /* convert a single plane */ 00265 for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i) 00266 this->Data[j][i] = removeSign(*(p++), offset); 00267 } 00268 } 00269 } 00270 else 00271 { 00272 register int j; 00273 register unsigned long i; 00274 for (i = 0; i < count; ++i) /* for all pixel ... */ 00275 for (j = 0; j < 3; ++j) 00276 this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */ 00277 } 00278 } 00279 } 00280 } 00281 00284 inline void convertValue(T2 &red, T2 &green, T2 &blue, const T2 y, const T2 cb, const T2 cr, const T2 maxvalue) 00285 { 00286 double dr = OFstatic_cast(double, y) + 1.4020 * OFstatic_cast(double, cr) - 0.7010 * OFstatic_cast(double, maxvalue); 00287 double dg = OFstatic_cast(double, y) - 0.3441 * OFstatic_cast(double, cb) - 0.7141 * OFstatic_cast(double, cr) + 0.5291 * OFstatic_cast(double, maxvalue); 00288 double db = OFstatic_cast(double, y) + 1.7720 * OFstatic_cast(double, cb) - 0.8859 * OFstatic_cast(double, maxvalue); 00289 red = (dr < 0.0) ? 0 : (dr > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dr); 00290 green = (dg < 0.0) ? 0 : (dg > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dg); 00291 blue = (db < 0.0) ? 0 : (db > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, db); 00292 } 00293 }; 00294 00295 00296 #endif 00297 00298 00299 /* 00300 * 00301 * CVS/RCS Log: 00302 * $Log: diybrpxt.h,v $ 00303 * Revision 1.17 2005/12/08 16:02:01 meichel 00304 * Changed include path schema for all DCMTK header files 00305 * 00306 * Revision 1.16 2004/04/21 10:00:31 meichel 00307 * Minor modifications for compilation with gcc 3.4.0 00308 * 00309 * Revision 1.15 2004/02/06 11:16:35 joergr 00310 * Added typecast to array indexes to avoid warning messages on MacOS X 10.3 00311 * with gcc 3.3. 00312 * 00313 * Revision 1.14 2003/12/23 12:30:34 joergr 00314 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00315 * Removed leading underscore characters from preprocessor symbols (reserved 00316 * symbols). Updated copyright header. 00317 * Replaced post-increment/decrement operators by pre-increment/decrement 00318 * operators where appropriate (e.g. 'i++' by '++i'). 00319 * 00320 * Revision 1.13 2002/06/26 16:20:19 joergr 00321 * Enhanced handling of corrupted pixel data and/or length. 00322 * Corrected decoding of multi-frame, planar images. 00323 * 00324 * Revision 1.12 2001/11/09 16:47:03 joergr 00325 * Removed 'inline' specifier from certain methods. 00326 * 00327 * Revision 1.11 2001/09/28 13:55:41 joergr 00328 * Added new flag (CIF_KeepYCbCrColorModel) which avoids conversion of YCbCr 00329 * color models to RGB. 00330 * 00331 * Revision 1.10 2001/06/01 15:49:32 meichel 00332 * Updated copyright header 00333 * 00334 * Revision 1.9 2000/04/27 13:15:15 joergr 00335 * Dcmimage library code now consistently uses ofConsole for error output. 00336 * 00337 * Revision 1.8 2000/03/08 16:21:54 meichel 00338 * Updated copyright header. 00339 * 00340 * Revision 1.7 1999/09/17 14:03:46 joergr 00341 * Enhanced efficiency of some "for" loops. 00342 * 00343 * Revision 1.6 1999/04/28 12:52:04 joergr 00344 * Corrected some typos, comments and formatting. 00345 * 00346 * Revision 1.5 1999/02/03 16:55:29 joergr 00347 * Moved global functions maxval() and determineRepresentation() to class 00348 * DicomImageClass (as static methods). 00349 * 00350 * Revision 1.4 1999/01/20 14:47:20 joergr 00351 * Replaced invocation of getCount() by member variable Count where possible. 00352 * 00353 * Revision 1.3 1998/11/27 14:18:56 joergr 00354 * Added copyright message. 00355 * 00356 * Revision 1.2 1998/05/11 14:53:32 joergr 00357 * Added CVS/RCS header to each file. 00358 * 00359 * 00360 */