Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | Related Pages

dicopxt.h

00001 /*
00002  *
00003  *  Copyright (C) 1996-2004, 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: DicomColorPixelTemplate (Header)
00023  *
00024  *  Last Update:      $Author: joergr $
00025  *  Update Date:      $Date: 2004/02/06 11:18:18 $
00026  *  CVS/RCS Revision: $Revision: 1.23 $
00027  *  Status:           $State: Exp $
00028  *
00029  *  CVS/RCS Log at end of file
00030  *
00031  */
00032 
00033 
00034 #ifndef DICOPXT_H
00035 #define DICOPXT_H
00036 
00037 #include "osconfig.h"
00038 #include "dctypes.h"
00039 #include "ofbmanip.h"
00040 
00041 #include "dicopx.h"
00042 #include "dipxrept.h"
00043 
00044 
00045 /********************************************************************/
00046 
00047 
00048 inline Uint8 removeSign(const Uint8 value, const Uint8)
00049 {
00050     return value;
00051 }
00052 
00053 
00054 inline Uint16 removeSign(const Uint16 value, const Uint16)
00055 {
00056     return value;
00057 }
00058 
00059 
00060 inline Uint32 removeSign(const Uint32 value, const Uint32)
00061 {
00062     return value;
00063 }
00064 
00065 
00066 inline Uint8 removeSign(const Sint8 value, const Sint8 offset)
00067 {
00068     return OFstatic_cast(Uint8, OFstatic_cast(Sint16, value) + OFstatic_cast(Sint16, offset) + 1);
00069 }
00070 
00071 
00072 inline Uint16 removeSign(const Sint16 value, const Sint16 offset)
00073 {
00074     return OFstatic_cast(Uint16, OFstatic_cast(Sint32, value) + OFstatic_cast(Sint32, offset) + 1);
00075 }
00076 
00077 /*
00078 inline Uint32 removeSign(const Sint32 value, const Sint32 offset)
00079 {
00080     return (value < 0) ? OFstatic_cast(Uint32, value + offset + 1) : OFstatic_cast(Uint32, value) + OFstatic_cast(Uint32, offset) + 1;
00081 }
00082 
00083 
00084 inline Uint8 removeSign(const Sint8 value, const Uint8 mask)
00085 {
00086     return OFstatic_cast(Uint8, value) ^ mask;
00087 }
00088 
00089 
00090 inline Uint16 removeSign(const Sint16 value, const Uint16 mask)
00091 {
00092     return OFstatic_cast(Uint16, value) ^ mask;
00093 }
00094 */
00095 
00096 inline Uint32 removeSign(const Sint32 value, const Uint32 mask)
00097 {
00098     return OFstatic_cast(Uint32, value) ^ mask;
00099 }
00100 
00101 
00102 /*---------------------*
00103  *  class declaration  *
00104  *---------------------*/
00105 
00108 template<class T>
00109 class DiColorPixelTemplate
00110   : public DiColorPixel,
00111     public DiPixelRepresentationTemplate<T>
00112 {
00113 
00114  public:
00115 
00124     DiColorPixelTemplate(const DiDocument *docu,
00125                          const DiInputPixel *pixel,
00126                          const Uint16 samples,
00127                          EI_Status &status,
00128                          const Uint16 sample_rate = 0)
00129       : DiColorPixel(docu, pixel, samples, status, sample_rate)
00130     {
00131         Data[0] = NULL;
00132         Data[1] = NULL;
00133         Data[2] = NULL;
00134     }
00135 
00138     virtual ~DiColorPixelTemplate()
00139     {
00140         delete[] Data[0];
00141         delete[] Data[1];
00142         delete[] Data[2];
00143     }
00144 
00149     inline EP_Representation getRepresentation() const
00150     {
00151         return DiPixelRepresentationTemplate<T>::getRepresentation();
00152     }
00153 
00158     inline const void *getData() const
00159     {
00160         return OFstatic_cast(const void *, Data);
00161     }
00162 
00167     inline void *getDataPtr()
00168     {
00169         return OFstatic_cast(void *, Data);
00170     }
00171 
00176     inline void *getDataArrayPtr()
00177     {
00178         return OFstatic_cast(void *, Data);
00179     }
00180 
00190     OFBool getPixelData(void *data,
00191                         const size_t count) const
00192     {
00193         OFBool result = OFFalse;
00194         /* check parameters and internal data */
00195         if ((data != NULL) && (count >= Count * 3) &&
00196             (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL))
00197         {
00198             /* copy all three planes to the given memory block */
00199             OFBitmanipTemplate<T>::copyMem(Data[0], OFstatic_cast(T *, data), Count);
00200             OFBitmanipTemplate<T>::copyMem(Data[1], OFstatic_cast(T *, data) + Count, Count);
00201             OFBitmanipTemplate<T>::copyMem(Data[2], OFstatic_cast(T *, data) + 2 * Count, Count);
00202             result = OFTrue;
00203         }
00204         return result;
00205     }
00206 
00222     unsigned long createDIB(void *&data,
00223                             const unsigned long size,
00224                             const Uint16 width,
00225                             const Uint16 height,
00226                             const unsigned long frame,
00227                             const int fromBits,
00228                             const int toBits,
00229                             const int mode,
00230                             const int upsideDown,
00231                             const int padding) const
00232     {
00233         unsigned long bytes = 0;
00234         if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
00235         {
00236             const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
00237             const unsigned long start = count * frame + ((upsideDown) ?
00238                 OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0);
00239             const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0;
00240             register const T *r = Data[0] + start;
00241             register const T *g = Data[1] + start;
00242             register const T *b = Data[2] + start;
00243             register Uint16 x;
00244             register Uint16 y;
00245             if (mode == 24)     // 24 bits per pixel
00246             {
00247                 const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3;
00248                 // each line has to start at 32-bit-address, if 'padding' is true
00249                 const int gap = (padding) ? OFstatic_cast(int, (4 - wid3 & 0x3) & 0x3) : 0;
00250                 unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height);
00251                 if ((data == NULL) || (size >= fsize))
00252                 {
00253                     if (data == NULL)
00254                         data = new Uint8[fsize];
00255                     if (data != NULL)
00256                     {
00257                         register Uint8 *q = OFstatic_cast(Uint8 *, data);
00258                         if (fromBits == toBits)
00259                         {
00260                             /* copy pixel data as is */
00261                             for (y = height; y != 0; y--)
00262                             {
00263                                 for (x = width; x != 0; x--)
00264                                 {
00265                                     /* reverse sample order: B-G-R */
00266                                     *(q++) = OFstatic_cast(Uint8, *(b++));
00267                                     *(q++) = OFstatic_cast(Uint8, *(g++));
00268                                     *(q++) = OFstatic_cast(Uint8, *(r++));
00269                                 }
00270                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00271                                 q += gap;                                           // new line: jump to next 32-bit address
00272                             }
00273                         }
00274                         else if (fromBits < toBits)
00275                         {
00276                             /* increase color depth: multiply with factor */
00277                             const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00278                                                      OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00279                             const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1);
00280                             if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00281                             {
00282                                 for (y = height; y != 0; y--)
00283                                 {
00284                                     for (x = width; x != 0; x--)
00285                                     {
00286                                         /* reverse sample order: B-G-R */
00287                                         *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2);
00288                                         *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2);
00289                                         *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2);
00290                                     }
00291                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00292                                     q += gap;                                       // new line: jump to next 32-bit address
00293                                 }
00294                             } else {
00295                                 for (y = height; y != 0; y--)
00296                                 {
00297                                     for (x = width; x != 0; x--)
00298                                     {
00299                                         /* reverse sample order: B-G-R */
00300                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1);
00301                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1);
00302                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1);
00303                                     }
00304                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00305                                     q += gap;                                       // new line: jump to next 32-bit address
00306                                 }
00307                             }
00308                         }
00309                         else /* fromBits > toBits */
00310                         {
00311                             /* reduce color depth: right shift */
00312                             const int shift = fromBits - toBits;
00313                             for (y = height; y != 0; y--)
00314                             {
00315                                 for (x = width; x != 0; x--)
00316                                 {
00317                                     /* reverse sample order: B-G-R */
00318                                     *(q++) = OFstatic_cast(Uint8, *(b++) >> shift);
00319                                     *(q++) = OFstatic_cast(Uint8, *(g++) >> shift);
00320                                     *(q++) = OFstatic_cast(Uint8, *(r++) >> shift);
00321                                 }
00322                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00323                                 q += gap;                                           // new line: jump to next 32-bit address
00324                             }
00325                         }
00326                         bytes = fsize;
00327                     }
00328                 }
00329             }
00330             else if (mode == 32)     // 32 bits per pixel
00331             {
00332                 const unsigned long fsize = count * 4;
00333                 if ((data == NULL) || (size >= fsize))
00334                 {
00335                     if (data == NULL)
00336                         data = new Uint32[count];
00337                     if (data != NULL)
00338                     {
00339                         register Uint32 *q = OFstatic_cast(Uint32 *, data);
00340                         if (fromBits == toBits)
00341                         {
00342                             /* copy pixel data as is */
00343                             for (y = height; y != 0; y--)
00344                             {
00345                                 for (x = width; x != 0; x--)
00346                                 {
00347                                     /* reverse sample order: B-G-R-0 */
00348                                     *(q++) = (OFstatic_cast(Uint32, *(b++)) << 24) |
00349                                              (OFstatic_cast(Uint32, *(g++)) << 16) |
00350                                              (OFstatic_cast(Uint32, *(r++)) << 8);
00351                                 }
00352                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00353                             }
00354                         }
00355                         else if (fromBits < toBits)
00356                         {
00357                             /* increase color depth: multiply with factor */
00358                             const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00359                                                      OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00360                             const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
00361                             if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00362                             {
00363                                 for (y = height; y != 0; y--)
00364                                 {
00365                                     for (x = width; x != 0; x--)
00366                                     {
00367                                         /* reverse sample order: B-G-R-0 */
00368                                         *(q++) = (OFstatic_cast(Uint32, *(b++) * gradient2) << 24) |
00369                                                  (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) |
00370                                                  (OFstatic_cast(Uint32, *(r++) * gradient2) << 8);
00371                                     }
00372                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00373                                 }
00374                             } else {
00375                                 for (y = height; y != 0; y--)
00376                                 {
00377                                     for (x = width; x != 0; x--)
00378                                     {
00379                                         /* reverse sample order: B-G-R-0 */
00380                                         *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 24) |
00381                                                  (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) |
00382                                                  (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 8);
00383                                     }
00384                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00385                                 }
00386                             }
00387                         }
00388                         else /* fromBits > toBits */
00389                         {
00390                             /* reduce color depth: right shift */
00391                             const int shift = fromBits - toBits;
00392                             for (y = height; y != 0; y--)
00393                             {
00394                                 for (x = width; x != 0; x--)
00395                                 {
00396                                     /* reverse sample order: B-G-R-0 */
00397                                     *(q++) = (OFstatic_cast(Uint32, *(b++) >> shift) << 24) |
00398                                              (OFstatic_cast(Uint32, *(g++) >> shift) << 16) |
00399                                              (OFstatic_cast(Uint32, *(r++) >> shift) << 8);
00400                                 }
00401                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00402                             }
00403                         }
00404                         bytes = fsize;
00405                     }
00406                 }
00407             }
00408         }
00409         return bytes;
00410     }
00411 
00423     unsigned long createAWTBitmap(void *&data,
00424                                   const Uint16 width,
00425                                   const Uint16 height,
00426                                   const unsigned long frame,
00427                                   const int fromBits,
00428                                   const int toBits) const
00429     {
00430         data = NULL;
00431         unsigned long bytes = 0;
00432         if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
00433         {
00434             const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
00435             data = new Uint32[count];
00436             if (data != NULL)
00437             {
00438                 const unsigned long start = count * frame;
00439                 register const T *r = Data[0] + start;
00440                 register const T *g = Data[1] + start;
00441                 register const T *b = Data[2] + start;
00442                 register Uint32 *q = OFstatic_cast(Uint32 *, data);
00443                 register unsigned long i;
00444                 if (fromBits == toBits)
00445                 {
00446                     /* copy pixel data as is */
00447                     for (i = count; i != 0; --i)
00448                     {
00449                         /* sample order: R-G-B */
00450                         *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) |
00451                                  (OFstatic_cast(Uint32, *(g++)) << 16) |
00452                                  (OFstatic_cast(Uint32, *(b++)) << 8);
00453                     }
00454                 }
00455                 else if (fromBits < toBits)
00456                 {
00457                     /* increase color depth: multiply with factor */
00458                     const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00459                                              OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00460                     const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
00461                     if (gradient1 == OFstatic_cast(double, gradient2))         // integer multiplication?
00462                     {
00463                         for (i = count; i != 0; --i)
00464                         {
00465                             /* sample order: R-G-B */
00466                             *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) |
00467                                      (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) |
00468                                      (OFstatic_cast(Uint32, *(b++) * gradient2) << 8);
00469                         }
00470                     } else {
00471                         for (i = count; i != 0; --i)
00472                         {
00473                             /* sample order: R-G-B */
00474                             *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) |
00475                                      (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) |
00476                                      (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8);
00477                         }
00478                     }
00479                 }
00480                 else /* fromBits > toBits */
00481                 {
00482                     /* reduce color depth: right shift */
00483                     const int shift = fromBits - toBits;
00484                     for (i = count; i != 0; --i)
00485                     {
00486                         /* sample order: R-G-B */
00487                         *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) |
00488                                  (OFstatic_cast(Uint32, *(g++) >> shift) << 16) |
00489                                  (OFstatic_cast(Uint32, *(b++) >> shift) << 8);
00490                     }
00491                 }
00492                 bytes = count * 4;
00493             }
00494         }
00495         return bytes;
00496     }
00497 
00498 
00499  protected:
00500 
00506     DiColorPixelTemplate(const DiColorPixel *pixel,
00507                          const unsigned long count)
00508       : DiColorPixel(pixel, count)
00509     {
00510         Data[0] = NULL;
00511         Data[1] = NULL;
00512         Data[2] = NULL;
00513     }
00514 
00521     inline int Init(const void *pixel)
00522     {
00523         int result = 0;
00524         if (pixel != NULL)
00525         {
00526             result = 1;
00527             /* allocate data buffer for the 3 planes */
00528             for (int j = 0; j < 3; j++)
00529             {
00530                 Data[j] = new T[Count];
00531                 if (Data[j] != NULL)
00532                 {
00533                     /* erase empty part of the buffer (=blacken the background) */
00534                     if (InputCount < Count)
00535                         OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount);
00536                 } else
00537                     result = 0;     // at least one buffer could not be allocated!
00538             }
00539         }
00540         return result;
00541     }
00542 
00543 
00545     T *Data[3];
00546 
00547 
00548  private:
00549 
00550  // --- declarations to avoid compiler warnings
00551 
00552     DiColorPixelTemplate(const DiColorPixelTemplate<T> &);
00553     DiColorPixelTemplate<T> &operator=(const DiColorPixelTemplate<T> &);
00554 };
00555 
00556 
00557 #endif
00558 
00559 
00560 /*
00561  *
00562  * CVS/RCS Log:
00563  * $Log: dicopxt.h,v $
00564  * Revision 1.23  2004/02/06 11:18:18  joergr
00565  * Distinguish more clearly between const and non-const access to pixel data.
00566  *
00567  * Revision 1.22  2004/01/21 12:59:43  meichel
00568  * Added OFconst_cast, needed for Visual C++ 6
00569  *
00570  * Revision 1.21  2003/12/23 11:43:03  joergr
00571  * Adapted type casts to new-style typecast operators defined in ofcast.h.
00572  * Removed leading underscore characters from preprocessor symbols (reserved
00573  * symbols). Updated copyright header. Added missing API documentation.
00574  * Replaced post-increment/decrement operators by pre-increment/decrement
00575  * operators where appropriate (e.g. 'i++' by '++i').
00576  *
00577  * Revision 1.20  2002/12/10 17:39:50  meichel
00578  * Added explicit type cast to avoid compilation error on gcc 3.2
00579  *
00580  * Revision 1.19  2002/12/09 13:37:24  joergr
00581  * Added private undefined copy constructor and/or assignment operator.
00582  * Fixed bug that caused method createAWTBitmap() to return always empty pixel
00583  * data.
00584  *
00585  * Revision 1.18  2002/09/12 14:10:37  joergr
00586  * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata
00587  * routine and is therefore more efficient.
00588  *
00589  * Revision 1.17  2002/08/29 12:57:49  joergr
00590  * Added method that creates pixel data in DICOM format.
00591  *
00592  * Revision 1.16  2002/06/26 16:17:41  joergr
00593  * Enhanced handling of corrupted pixel data and/or length.
00594  *
00595  * Revision 1.15  2002/01/29 17:07:08  joergr
00596  * Added optional flag to the "Windows DIB" methods allowing to switch off the
00597  * scanline padding.
00598  *
00599  * Revision 1.14  2001/12/11 14:23:44  joergr
00600  * Added type cast to keep old Sun compilers quiet.
00601  *
00602  * Revision 1.13  2001/11/09 16:44:35  joergr
00603  * Enhanced and renamed createTrueColorDIB() method.
00604  *
00605  * Revision 1.12  2001/06/01 15:49:29  meichel
00606  * Updated copyright header
00607  *
00608  * Revision 1.11  2000/03/08 16:21:51  meichel
00609  * Updated copyright header.
00610  *
00611  * Revision 1.10  1999/09/17 14:03:44  joergr
00612  * Enhanced efficiency of some "for" loops.
00613  *
00614  * Revision 1.9  1999/07/23 13:22:29  joergr
00615  * emoved inline method 'removeSign'which is no longer needed.
00616  *
00617  * Revision 1.8  1999/04/28 12:51:58  joergr
00618  * Corrected some typos, comments and formatting.
00619  *
00620  * Revision 1.7  1999/01/20 14:44:49  joergr
00621  * Corrected some typos and formatting.
00622  *
00623  * Revision 1.6  1998/11/27 13:50:20  joergr
00624  * Added copyright message. Replaced delete by delete[] for array types.
00625  * Added method to give direct (non const) access to internal data buffer.
00626  *
00627  * Revision 1.5  1998/05/11 14:53:13  joergr
00628  * Added CVS/RCS header to each file.
00629  *
00630  *
00631  */


Generated on 26 Apr 2005 for OFFIS DCMTK Version 3.5.3 by Doxygen 1.4.2