diybrpxt.h

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  */


Generated on 20 Dec 2005 for OFFIS DCMTK Version 3.5.4 by Doxygen 1.4.5