dicoopxt.h

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:  dcmimgle
00019  *
00020  *  Author:  Joerg Riesmeier
00021  *
00022  *  Purpose: DicomColorOutputPixelTemplate (Header)
00023  *
00024  *  Last Update:      $Author: meichel $
00025  *  Update Date:      $Date: 2005/12/08 16:01:33 $
00026  *  CVS/RCS Revision: $Revision: 1.24 $
00027  *  Status:           $State: Exp $
00028  *
00029  *  CVS/RCS Log at end of file
00030  *
00031  */
00032 
00033 
00034 #ifndef DICOOPXT_H
00035 #define DICOOPXT_H
00036 
00037 #include "dcmtk/config/osconfig.h"
00038 #include "dcmtk/dcmdata/dctypes.h"
00039 
00040 #include "dcmtk/dcmimage/dicoopx.h"
00041 #include "dcmtk/dcmimage/dicopx.h"
00042 #include "dcmtk/dcmimgle/dipxrept.h"
00043 #include "dcmtk/dcmimgle/diutils.h"
00044 
00045 
00046 /*---------------------*
00047  *  class declaration  *
00048  *---------------------*/
00049 
00052 template<class T1, class T2>
00053 class DiColorOutputPixelTemplate
00054   : public DiColorOutputPixel,
00055     public DiPixelRepresentationTemplate<T2>
00056 {
00057 
00058  public:
00059 
00071     DiColorOutputPixelTemplate(void *buffer,
00072                                const DiColorPixel *pixel,
00073                                const unsigned long count,
00074                                const unsigned long frame,
00075                                const int bits1, /* input depth */
00076                                const int bits2, /* output depth */
00077                                const int planar,
00078                                const int inverse)
00079       : DiColorOutputPixel(pixel, count, frame),
00080         Data(NULL),
00081         DeleteData(buffer == NULL),
00082         isPlanar(planar)
00083     {
00084         if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
00085         {
00086             Data = OFstatic_cast(T2 *, buffer);
00087             convert(OFstatic_cast(const T1 **, OFconst_cast(void *, pixel->getData())), frame * FrameSize, bits1, bits2, planar, inverse);
00088         }
00089     }
00090 
00100     DiColorOutputPixelTemplate(void *buffer,
00101                                const DiPixel *pixel,
00102                                const unsigned long count,
00103                                const unsigned long frame,
00104                                const unsigned long /*frames*/,
00105                                const int planar)
00106       : DiColorOutputPixel(pixel, count, frame),
00107         Data(NULL),
00108         DeleteData(buffer == NULL),
00109         isPlanar(planar)
00110     {
00111         if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
00112             Data = OFstatic_cast(T2 *, buffer);
00113     }
00114 
00117     virtual ~DiColorOutputPixelTemplate()
00118     {
00119         if (DeleteData)
00120             delete[] Data;
00121     }
00122 
00127     inline EP_Representation getRepresentation() const
00128     {
00129         return DiPixelRepresentationTemplate<T2>::getRepresentation();
00130     }
00131 
00136     inline size_t getItemSize() const
00137     {
00138         return sizeof(T2) * 3;
00139     }
00140 
00145     inline const void *getData() const
00146     {
00147         return OFstatic_cast(const void *, Data);
00148     }
00149 
00154     virtual void *getDataPtr()
00155     {
00156         return OFstatic_cast(void *, Data);
00157     }
00158 
00165     inline const void *getPlane(const int plane) const
00166     {
00167         void *result = NULL;
00168         if (Data != NULL)
00169         {
00170             if (plane <= 0)
00171                 result = OFstatic_cast(void *, Data);
00172             else
00173             {
00174                 if (isPlanar)
00175                     result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2) * FrameSize);
00176                 else
00177                     result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2));
00178             }
00179         }
00180         return result;
00181     }
00182 
00189     int writePPM(ostream &stream) const
00190     {
00191         if (Data != NULL)
00192         {
00193             register T2 *p = Data;
00194             register unsigned long i;
00195             register int j;
00196             for (i = FrameSize; i != 0; --i)
00197                 for (j = 3; j != 0; --j)
00198                     stream << OFstatic_cast(unsigned long, *(p++)) << " ";     // typecast to resolve problems with 'char'
00199             return 1;
00200         }
00201         return 0;
00202     }
00203 
00210     int writePPM(FILE *stream) const
00211     {
00212         if (Data != NULL)
00213         {
00214             register T2 *p = Data;
00215             register unsigned long i;
00216             register int j;
00217             for (i = FrameSize; i != 0; --i)
00218                 for (j = 3; j != 0; --j)
00219                     fprintf(stream, "%lu ", OFstatic_cast(unsigned long, *(p++)));
00220             return 1;
00221         }
00222         return 0;
00223     }
00224 
00225 
00226  protected:
00227 
00229     T2 *Data;
00230 
00231 
00232  private:
00233 
00243     void convert(const T1 *pixel[3],
00244                  const unsigned long start,
00245                  const int bits1,
00246                  const int bits2,
00247                  const int planar,
00248                  const int inverse)
00249     {
00250         if ((pixel[0] != NULL) && (pixel[1] != NULL) && (pixel[2] != NULL))
00251         {
00252             if (Data == NULL)
00253                 Data = new T2[FrameSize * 3];
00254             if (Data != NULL)
00255             {
00256                 register T2 *q = Data;
00257                 register unsigned long i;
00258                 const T2 max2 = OFstatic_cast(T2, DicomImageClass::maxval(bits2));
00259                 if (planar)
00260                 {
00261                     register const T1 *p;
00262                     if (bits1 == bits2)
00263                     {
00264                         for (int j = 0; j < 3; ++j)
00265                         {
00266                             p = pixel[j] + start;
00267                             /* invert output data */
00268                             if (inverse)
00269                             {
00270                                 for (i = Count; i != 0; --i)                        // copy inverted data
00271                                     *(q++) = max2 - OFstatic_cast(T2, *(p++));
00272                             } else {
00273                                 for (i = Count; i != 0; --i)                        // copy
00274                                     *(q++) = OFstatic_cast(T2, *(p++));
00275                             }
00276                             if (Count < FrameSize)
00277                             {
00278                                 OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count);  // set remaining pixels of frame to zero
00279                                 q += (FrameSize - Count);
00280                             }
00281                         }
00282                     }
00283                     else if (bits1 < bits2)                                     // optimization possible using LUT
00284                     {
00285                         const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) /
00286                                                  OFstatic_cast(double, DicomImageClass::maxval(bits1));
00287                         const T2 gradient2 = OFstatic_cast(T2, gradient1);
00288                         for (int j = 0; j < 3; ++j)
00289                         {
00290                             p = pixel[j] + start;
00291                             if (gradient1 == OFstatic_cast(double, gradient2))  // integer multiplication?
00292                             {
00293                                 /* invert output data */
00294                                 if (inverse)
00295                                 {
00296                                     for (i = Count; i != 0; --i)                            // expand depth & invert
00297                                         *(q++) = max2 - OFstatic_cast(T2, *(p++)) * gradient2;
00298                                 } else {
00299                                     for (i = Count; i != 0; --i)                            // expand depth
00300                                         *(q++) = OFstatic_cast(T2, *(p++)) * gradient2;
00301                                 }
00302                             } else {
00303                                 /* invert output data */
00304                                 if (inverse)
00305                                 {
00306                                     for (i = Count; i != 0; --i)                            // expand depth & invert
00307                                         *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1);
00308                                 } else {
00309                                     for (i = Count; i != 0; --i)                            // expand depth
00310                                         *(q++) = OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1);
00311                                 }
00312                             }
00313                             if (Count < FrameSize)
00314                             {
00315                                 OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count);  // set remaining pixels of frame to zero
00316                                 q += (FrameSize - Count);
00317                             }
00318                         }                                                       // ... to be enhanced !
00319                     }
00320                     else /* bits1 > bits2 */
00321                     {
00322                         const int shift = bits1 - bits2;
00323                         for (int j = 0; j < 3; ++j)
00324                         {
00325                             p = pixel[j] + start;
00326                             /* invert output data */
00327                             if (inverse)
00328                             {
00329                                 for (i = Count; i != 0; --i)                            // reduce depth & invert
00330                                     *(q++) = max2 - OFstatic_cast(T2, *(p++) >> shift);
00331                             } else {
00332                                 for (i = Count; i != 0; --i)                            // reduce depth
00333                                     *(q++) = OFstatic_cast(T2, *(p++) >> shift);
00334                             }
00335                             if (Count < FrameSize)
00336                             {
00337                                 OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count);  // set remaining pixels of frame to zero
00338                                 q += (FrameSize - Count);
00339                             }
00340                         }
00341                     }
00342                 }
00343                 else /* not planar */
00344                 {
00345                     register int j;
00346                     if (bits1 == bits2)
00347                     {
00348                         /* invert output data */
00349                         if (inverse)
00350                         {
00351                             for (i = start; i < start + Count; ++i)
00352                                 for (j = 0; j < 3; ++j)                         // copy inverted data
00353                                     *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]);
00354                         } else {
00355                             for (i = start; i < start + Count; ++i)
00356                                 for (j = 0; j < 3; ++j)                         // copy
00357                                     *(q++) = OFstatic_cast(T2, pixel[j][i]);
00358                         }
00359                     }
00360                     else if (bits1 < bits2)                                     // optimization possible using LUT
00361                     {
00362                         const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) /
00363                                                  OFstatic_cast(double, DicomImageClass::maxval(bits1));
00364                         const T2 gradient2 = OFstatic_cast(T2, gradient1);
00365                         if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00366                         {
00367                             /* invert output data */
00368                             if (inverse)
00369                             {
00370                                 for (i = start; i < start + Count; ++i)                 // expand depth & invert
00371                                     for (j = 0; j < 3; ++j)
00372                                         *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]) * gradient2;
00373                             } else {
00374                                 for (i = start; i < start + Count; ++i)
00375                                     for (j = 0; j < 3; ++j)                             // expand depth
00376                                         *(q++) = OFstatic_cast(T2, pixel[j][i]) * gradient2;
00377                             }
00378                         } else {
00379                             /* invert output data */
00380                             if (inverse)
00381                             {
00382                                 for (i = start; i < start + Count; ++i)
00383                                     for (j = 0; j < 3; ++j)                             // expand depth & invert
00384                                         *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1);
00385                             } else {
00386                                 for (i = start; i < start + Count; ++i)
00387                                     for (j = 0; j < 3; ++j)                             // expand depth
00388                                         *(q++) = OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1);
00389                             }
00390                         }
00391                     }
00392                     else /* bits1 > bits2 */
00393                     {
00394                         const int shift = bits1 - bits2;
00395                         /* invert output data */
00396                         if (inverse)
00397                         {
00398                             for (i = start; i < start + Count; ++i)
00399                                 for (j = 0; j < 3; ++j)                                 // reduce depth & invert
00400                                     *(q++) = max2 - OFstatic_cast(T2, pixel[j][i] >> shift);
00401                         } else {
00402                             for (i = start; i < start + Count; ++i)
00403                                 for (j = 0; j < 3; ++j)                                 // reduce depth
00404                                     *(q++) = OFstatic_cast(T2, pixel[j][i] >> shift);
00405                         }
00406                     }
00407                     if (Count < FrameSize)
00408                         OFBitmanipTemplate<T2>::zeroMem(q, 3 * (FrameSize - Count));  // set remaining pixels of frame to zero
00409                 }
00410             }
00411         } else
00412             Data = NULL;
00413     }
00414 
00416     int DeleteData;
00418     int isPlanar;
00419 
00420  // --- declarations to avoid compiler warnings
00421 
00422     DiColorOutputPixelTemplate(const DiColorOutputPixelTemplate<T1,T2> &);
00423     DiColorOutputPixelTemplate<T1,T2> &operator=(const DiColorOutputPixelTemplate<T1,T2> &);
00424 };
00425 
00426 
00427 #endif
00428 
00429 
00430 /*
00431  *
00432  * CVS/RCS Log:
00433  * $Log: dicoopxt.h,v $
00434  * Revision 1.24  2005/12/08 16:01:33  meichel
00435  * Changed include path schema for all DCMTK header files
00436  *
00437  * Revision 1.23  2004/02/06 11:18:18  joergr
00438  * Distinguish more clearly between const and non-const access to pixel data.
00439  *
00440  * Revision 1.22  2003/12/23 16:06:21  joergr
00441  * Replaced additional post-increment/decrement operators by pre-increment/
00442  * decrement operators.
00443  *
00444  * Revision 1.21  2003/12/23 11:36:24  joergr
00445  * Adapted type casts to new-style typecast operators defined in ofcast.h.
00446  * Removed leading underscore characters from preprocessor symbols (reserved
00447  * symbols). Updated copyright header.
00448  * Replaced post-increment/decrement operators by pre-increment/decrement
00449  * operators where appropriate (e.g. 'i++' by '++i').
00450  *
00451  * Revision 1.20  2002/06/26 17:20:31  joergr
00452  * Added type cast to keep MSVC6 quiet.
00453  *
00454  * Revision 1.19  2002/06/26 16:17:16  joergr
00455  * Added support for polarity flag to color images.
00456  *
00457  * Revision 1.18  2001/11/09 16:42:04  joergr
00458  * Removed 'inline' specifier from certain methods.
00459  *
00460  * Revision 1.17  2001/06/01 15:49:29  meichel
00461  * Updated copyright header
00462  *
00463  * Revision 1.16  2000/03/30 14:15:44  joergr
00464  * Corrected wrong bit expansion of output pixel data (left shift is not
00465  * correct).
00466  *
00467  * Revision 1.15  2000/03/08 16:21:50  meichel
00468  * Updated copyright header.
00469  *
00470  * Revision 1.14  1999/09/17 14:03:43  joergr
00471  * Enhanced efficiency of some "for" loops.
00472  *
00473  * Revision 1.13  1999/08/17 10:28:47  joergr
00474  * Commented unused parameter name to avoid compiler warnings.
00475  * Removed unused parameter.
00476  *
00477  * Revision 1.12  1999/07/23 13:20:45  joergr
00478  * Enhanced handling of corrupted pixel data (wrong length).
00479  *
00480  * Revision 1.11  1999/04/30 16:12:03  meichel
00481  * Minor code purifications to keep IBM xlC quiet
00482  *
00483  * Revision 1.10  1999/04/29 09:31:13  joergr
00484  * Moved color related image files back to non-public part.
00485  *
00486  * Revision 1.1  1999/04/28 14:57:31  joergr
00487  * Moved files from dcmimage module to dcmimgle to support new pastel color
00488  * output format.
00489  *
00490  * Revision 1.8  1999/01/20 14:43:12  joergr
00491  * Replaced invocation of getCount() by member variable Count where possible.
00492  * Added new output method to fill external memory buffer with rendered pixel
00493  * data.
00494  *
00495  * Revision 1.7  1998/12/22 13:23:57  joergr
00496  * Added comments that the routines for expanding pixel's depth have to be
00497  * enhanced in the future (replicate bit pattern instead of shifting). Same
00498  * question for reducing depth.
00499  *
00500  * Revision 1.6  1998/11/27 13:46:00  joergr
00501  * Added copyright message. Replaced delete by delete[] for array types.
00502  *
00503  * Revision 1.5  1998/07/01 08:39:19  joergr
00504  * Minor changes to avoid compiler warnings (gcc 2.8.1 with additional
00505  * options), e.g. add copy constructors.
00506  *
00507  * Revision 1.4  1998/05/11 14:53:12  joergr
00508  * Added CVS/RCS header to each file.
00509  *
00510  *
00511  */


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