dicopxt.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:  dcmimage
00019  *
00020  *  Author:  Joerg Riesmeier
00021  *
00022  *  Purpose: DicomColorPixelTemplate (Header)
00023  *
00024  *  Last Update:      $Author: meichel $
00025  *  Update Date:      $Date: 2005/12/08 16:01:35 $
00026  *  CVS/RCS Revision: $Revision: 1.25 $
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 "dcmtk/config/osconfig.h"
00038 #include "dcmtk/dcmdata/dctypes.h"
00039 #include "dcmtk/ofstd/ofbmanip.h"
00040 
00041 #include "dcmtk/dcmimage/dicopx.h"
00042 #include "dcmtk/dcmimgle/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 
00159     inline const void *getData() const
00160     {
00161         return OFstatic_cast(const void *, Data);
00162     }
00163 
00169     inline void *getDataPtr()
00170     {
00171         return OFstatic_cast(void *, Data);
00172     }
00173 
00179     inline void *getDataArrayPtr()
00180     {
00181         return OFstatic_cast(void *, Data);
00182     }
00183 
00193     OFBool getPixelData(void *data,
00194                         const size_t count) const
00195     {
00196         OFBool result = OFFalse;
00197         /* check parameters and internal data */
00198         if ((data != NULL) && (count >= Count * 3) &&
00199             (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL))
00200         {
00201             /* copy all three planes to the given memory block */
00202             OFBitmanipTemplate<T>::copyMem(Data[0], OFstatic_cast(T *, data), Count);
00203             OFBitmanipTemplate<T>::copyMem(Data[1], OFstatic_cast(T *, data) + Count, Count);
00204             OFBitmanipTemplate<T>::copyMem(Data[2], OFstatic_cast(T *, data) + 2 * Count, Count);
00205             result = OFTrue;
00206         }
00207         return result;
00208     }
00209 
00225     unsigned long createDIB(void *&data,
00226                             const unsigned long size,
00227                             const Uint16 width,
00228                             const Uint16 height,
00229                             const unsigned long frame,
00230                             const int fromBits,
00231                             const int toBits,
00232                             const int mode,
00233                             const int upsideDown,
00234                             const int padding) const
00235     {
00236         unsigned long bytes = 0;
00237         if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
00238         {
00239             const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
00240             const unsigned long start = count * frame + ((upsideDown) ?
00241                 OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0);
00242             const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0;
00243             register const T *r = Data[0] + start;
00244             register const T *g = Data[1] + start;
00245             register const T *b = Data[2] + start;
00246             register Uint16 x;
00247             register Uint16 y;
00248             if (mode == 24)     // 24 bits per pixel
00249             {
00250                 const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3;
00251                 // each line has to start at 32-bit-address, if 'padding' is true
00252                 const int gap = (padding) ? OFstatic_cast(int, (4 - wid3 & 0x3) & 0x3) : 0;
00253                 unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height);
00254                 if ((data == NULL) || (size >= fsize))
00255                 {
00256                     if (data == NULL)
00257                         data = new Uint8[fsize];
00258                     if (data != NULL)
00259                     {
00260                         register Uint8 *q = OFstatic_cast(Uint8 *, data);
00261                         if (fromBits == toBits)
00262                         {
00263                             /* copy pixel data as is */
00264                             for (y = height; y != 0; y--)
00265                             {
00266                                 for (x = width; x != 0; x--)
00267                                 {
00268                                     /* reverse sample order: B-G-R */
00269                                     *(q++) = OFstatic_cast(Uint8, *(b++));
00270                                     *(q++) = OFstatic_cast(Uint8, *(g++));
00271                                     *(q++) = OFstatic_cast(Uint8, *(r++));
00272                                 }
00273                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00274                                 q += gap;                                           // new line: jump to next 32-bit address
00275                             }
00276                         }
00277                         else if (fromBits < toBits)
00278                         {
00279                             /* increase color depth: multiply with factor */
00280                             const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00281                                                      OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00282                             const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1);
00283                             if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00284                             {
00285                                 for (y = height; y != 0; y--)
00286                                 {
00287                                     for (x = width; x != 0; x--)
00288                                     {
00289                                         /* reverse sample order: B-G-R */
00290                                         *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2);
00291                                         *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2);
00292                                         *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2);
00293                                     }
00294                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00295                                     q += gap;                                       // new line: jump to next 32-bit address
00296                                 }
00297                             } else {
00298                                 for (y = height; y != 0; y--)
00299                                 {
00300                                     for (x = width; x != 0; x--)
00301                                     {
00302                                         /* reverse sample order: B-G-R */
00303                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1);
00304                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1);
00305                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1);
00306                                     }
00307                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00308                                     q += gap;                                       // new line: jump to next 32-bit address
00309                                 }
00310                             }
00311                         }
00312                         else /* fromBits > toBits */
00313                         {
00314                             /* reduce color depth: right shift */
00315                             const int shift = fromBits - toBits;
00316                             for (y = height; y != 0; y--)
00317                             {
00318                                 for (x = width; x != 0; x--)
00319                                 {
00320                                     /* reverse sample order: B-G-R */
00321                                     *(q++) = OFstatic_cast(Uint8, *(b++) >> shift);
00322                                     *(q++) = OFstatic_cast(Uint8, *(g++) >> shift);
00323                                     *(q++) = OFstatic_cast(Uint8, *(r++) >> shift);
00324                                 }
00325                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00326                                 q += gap;                                           // new line: jump to next 32-bit address
00327                             }
00328                         }
00329                         bytes = fsize;
00330                     }
00331                 }
00332             }
00333             else if (mode == 32)     // 32 bits per pixel
00334             {
00335                 const unsigned long fsize = count * 4;
00336                 if ((data == NULL) || (size >= fsize))
00337                 {
00338                     if (data == NULL)
00339                         data = new Uint32[count];
00340                     if (data != NULL)
00341                     {
00342                         register Uint32 *q = OFstatic_cast(Uint32 *, data);
00343                         if (fromBits == toBits)
00344                         {
00345                             /* copy pixel data as is */
00346                             for (y = height; y != 0; y--)
00347                             {
00348                                 for (x = width; x != 0; x--)
00349                                 {
00350                                     /* reverse sample order: B-G-R-0 */
00351                                     *(q++) = (OFstatic_cast(Uint32, *(b++)) << 24) |
00352                                              (OFstatic_cast(Uint32, *(g++)) << 16) |
00353                                              (OFstatic_cast(Uint32, *(r++)) << 8);
00354                                 }
00355                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00356                             }
00357                         }
00358                         else if (fromBits < toBits)
00359                         {
00360                             /* increase color depth: multiply with factor */
00361                             const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00362                                                      OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00363                             const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
00364                             if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00365                             {
00366                                 for (y = height; y != 0; y--)
00367                                 {
00368                                     for (x = width; x != 0; x--)
00369                                     {
00370                                         /* reverse sample order: B-G-R-0 */
00371                                         *(q++) = (OFstatic_cast(Uint32, *(b++) * gradient2) << 24) |
00372                                                  (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) |
00373                                                  (OFstatic_cast(Uint32, *(r++) * gradient2) << 8);
00374                                     }
00375                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00376                                 }
00377                             } else {
00378                                 for (y = height; y != 0; y--)
00379                                 {
00380                                     for (x = width; x != 0; x--)
00381                                     {
00382                                         /* reverse sample order: B-G-R-0 */
00383                                         *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 24) |
00384                                                  (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) |
00385                                                  (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 8);
00386                                     }
00387                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00388                                 }
00389                             }
00390                         }
00391                         else /* fromBits > toBits */
00392                         {
00393                             /* reduce color depth: right shift */
00394                             const int shift = fromBits - toBits;
00395                             for (y = height; y != 0; y--)
00396                             {
00397                                 for (x = width; x != 0; x--)
00398                                 {
00399                                     /* reverse sample order: B-G-R-0 */
00400                                     *(q++) = (OFstatic_cast(Uint32, *(b++) >> shift) << 24) |
00401                                              (OFstatic_cast(Uint32, *(g++) >> shift) << 16) |
00402                                              (OFstatic_cast(Uint32, *(r++) >> shift) << 8);
00403                                 }
00404                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00405                             }
00406                         }
00407                         bytes = fsize;
00408                     }
00409                 }
00410             }
00411         }
00412         return bytes;
00413     }
00414 
00426     unsigned long createAWTBitmap(void *&data,
00427                                   const Uint16 width,
00428                                   const Uint16 height,
00429                                   const unsigned long frame,
00430                                   const int fromBits,
00431                                   const int toBits) const
00432     {
00433         data = NULL;
00434         unsigned long bytes = 0;
00435         if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
00436         {
00437             const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
00438             data = new Uint32[count];
00439             if (data != NULL)
00440             {
00441                 const unsigned long start = count * frame;
00442                 register const T *r = Data[0] + start;
00443                 register const T *g = Data[1] + start;
00444                 register const T *b = Data[2] + start;
00445                 register Uint32 *q = OFstatic_cast(Uint32 *, data);
00446                 register unsigned long i;
00447                 if (fromBits == toBits)
00448                 {
00449                     /* copy pixel data as is */
00450                     for (i = count; i != 0; --i)
00451                     {
00452                         /* sample order: R-G-B */
00453                         *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) |
00454                                  (OFstatic_cast(Uint32, *(g++)) << 16) |
00455                                  (OFstatic_cast(Uint32, *(b++)) << 8);
00456                     }
00457                 }
00458                 else if (fromBits < toBits)
00459                 {
00460                     /* increase color depth: multiply with factor */
00461                     const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00462                                              OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00463                     const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
00464                     if (gradient1 == OFstatic_cast(double, gradient2))         // integer multiplication?
00465                     {
00466                         for (i = count; i != 0; --i)
00467                         {
00468                             /* sample order: R-G-B */
00469                             *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) |
00470                                      (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) |
00471                                      (OFstatic_cast(Uint32, *(b++) * gradient2) << 8);
00472                         }
00473                     } else {
00474                         for (i = count; i != 0; --i)
00475                         {
00476                             /* sample order: R-G-B */
00477                             *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) |
00478                                      (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) |
00479                                      (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8);
00480                         }
00481                     }
00482                 }
00483                 else /* fromBits > toBits */
00484                 {
00485                     /* reduce color depth: right shift */
00486                     const int shift = fromBits - toBits;
00487                     for (i = count; i != 0; --i)
00488                     {
00489                         /* sample order: R-G-B */
00490                         *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) |
00491                                  (OFstatic_cast(Uint32, *(g++) >> shift) << 16) |
00492                                  (OFstatic_cast(Uint32, *(b++) >> shift) << 8);
00493                     }
00494                 }
00495                 bytes = count * 4;
00496             }
00497         }
00498         return bytes;
00499     }
00500 
00501 
00502  protected:
00503 
00509     DiColorPixelTemplate(const DiColorPixel *pixel,
00510                          const unsigned long count)
00511       : DiColorPixel(pixel, count)
00512     {
00513         Data[0] = NULL;
00514         Data[1] = NULL;
00515         Data[2] = NULL;
00516     }
00517 
00524     inline int Init(const void *pixel)
00525     {
00526         int result = 0;
00527         if (pixel != NULL)
00528         {
00529             result = 1;
00530             /* allocate data buffer for the 3 planes */
00531             for (int j = 0; j < 3; j++)
00532             {
00533                 Data[j] = new T[Count];
00534                 if (Data[j] != NULL)
00535                 {
00536                     /* erase empty part of the buffer (=blacken the background) */
00537                     if (InputCount < Count)
00538                         OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount);
00539                 } else
00540                     result = 0;     // at least one buffer could not be allocated!
00541             }
00542         }
00543         return result;
00544     }
00545 
00546 
00548     T *Data[3];
00549 
00550 
00551  private:
00552 
00553  // --- declarations to avoid compiler warnings
00554 
00555     DiColorPixelTemplate(const DiColorPixelTemplate<T> &);
00556     DiColorPixelTemplate<T> &operator=(const DiColorPixelTemplate<T> &);
00557 };
00558 
00559 
00560 #endif
00561 
00562 
00563 /*
00564  *
00565  * CVS/RCS Log:
00566  * $Log: dicopxt.h,v $
00567  * Revision 1.25  2005/12/08 16:01:35  meichel
00568  * Changed include path schema for all DCMTK header files
00569  *
00570  * Revision 1.24  2004/10/19 12:57:47  joergr
00571  * Enhanced API documentation.
00572  *
00573  * Revision 1.23  2004/02/06 11:18:18  joergr
00574  * Distinguish more clearly between const and non-const access to pixel data.
00575  *
00576  * Revision 1.22  2004/01/21 12:59:43  meichel
00577  * Added OFconst_cast, needed for Visual C++ 6
00578  *
00579  * Revision 1.21  2003/12/23 11:43:03  joergr
00580  * Adapted type casts to new-style typecast operators defined in ofcast.h.
00581  * Removed leading underscore characters from preprocessor symbols (reserved
00582  * symbols). Updated copyright header. Added missing API documentation.
00583  * Replaced post-increment/decrement operators by pre-increment/decrement
00584  * operators where appropriate (e.g. 'i++' by '++i').
00585  *
00586  * Revision 1.20  2002/12/10 17:39:50  meichel
00587  * Added explicit type cast to avoid compilation error on gcc 3.2
00588  *
00589  * Revision 1.19  2002/12/09 13:37:24  joergr
00590  * Added private undefined copy constructor and/or assignment operator.
00591  * Fixed bug that caused method createAWTBitmap() to return always empty pixel
00592  * data.
00593  *
00594  * Revision 1.18  2002/09/12 14:10:37  joergr
00595  * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata
00596  * routine and is therefore more efficient.
00597  *
00598  * Revision 1.17  2002/08/29 12:57:49  joergr
00599  * Added method that creates pixel data in DICOM format.
00600  *
00601  * Revision 1.16  2002/06/26 16:17:41  joergr
00602  * Enhanced handling of corrupted pixel data and/or length.
00603  *
00604  * Revision 1.15  2002/01/29 17:07:08  joergr
00605  * Added optional flag to the "Windows DIB" methods allowing to switch off the
00606  * scanline padding.
00607  *
00608  * Revision 1.14  2001/12/11 14:23:44  joergr
00609  * Added type cast to keep old Sun compilers quiet.
00610  *
00611  * Revision 1.13  2001/11/09 16:44:35  joergr
00612  * Enhanced and renamed createTrueColorDIB() method.
00613  *
00614  * Revision 1.12  2001/06/01 15:49:29  meichel
00615  * Updated copyright header
00616  *
00617  * Revision 1.11  2000/03/08 16:21:51  meichel
00618  * Updated copyright header.
00619  *
00620  * Revision 1.10  1999/09/17 14:03:44  joergr
00621  * Enhanced efficiency of some "for" loops.
00622  *
00623  * Revision 1.9  1999/07/23 13:22:29  joergr
00624  * emoved inline method 'removeSign'which is no longer needed.
00625  *
00626  * Revision 1.8  1999/04/28 12:51:58  joergr
00627  * Corrected some typos, comments and formatting.
00628  *
00629  * Revision 1.7  1999/01/20 14:44:49  joergr
00630  * Corrected some typos and formatting.
00631  *
00632  * Revision 1.6  1998/11/27 13:50:20  joergr
00633  * Added copyright message. Replaced delete by delete[] for array types.
00634  * Added method to give direct (non const) access to internal data buffer.
00635  *
00636  * Revision 1.5  1998/05/11 14:53:13  joergr
00637  * Added CVS/RCS header to each file.
00638  *
00639  *
00640  */


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