dcmimage/include/dcmtk/dcmimage/dicoopxt.h

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


Generated on 6 Jan 2011 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.5.1