dcmimage/include/dcmtk/dcmimage/dicopxt.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:  dcmimage
00015  *
00016  *  Author:  Joerg Riesmeier
00017  *
00018  *  Purpose: DicomColorPixelTemplate (Header)
00019  *
00020  *  Last Update:      $Author: joergr $
00021  *  Update Date:      $Date: 2010-10-14 13:16:29 $
00022  *  CVS/RCS Revision: $Revision: 1.30 $
00023  *  Status:           $State: Exp $
00024  *
00025  *  CVS/RCS Log at end of file
00026  *
00027  */
00028 
00029 
00030 #ifndef DICOPXT_H
00031 #define DICOPXT_H
00032 
00033 #include "dcmtk/config/osconfig.h"
00034 #include "dcmtk/ofstd/ofbmanip.h"
00035 
00036 #include "dcmtk/dcmimage/dicopx.h"
00037 #include "dcmtk/dcmimgle/dipxrept.h"
00038 
00039 
00040 /********************************************************************/
00041 
00042 
00043 inline Uint8 removeSign(const Uint8 value, const Uint8)
00044 {
00045     return value;
00046 }
00047 
00048 
00049 inline Uint16 removeSign(const Uint16 value, const Uint16)
00050 {
00051     return value;
00052 }
00053 
00054 
00055 inline Uint32 removeSign(const Uint32 value, const Uint32)
00056 {
00057     return value;
00058 }
00059 
00060 
00061 inline Uint8 removeSign(const Sint8 value, const Sint8 offset)
00062 {
00063     return OFstatic_cast(Uint8, OFstatic_cast(Sint16, value) + OFstatic_cast(Sint16, offset) + 1);
00064 }
00065 
00066 
00067 inline Uint16 removeSign(const Sint16 value, const Sint16 offset)
00068 {
00069     return OFstatic_cast(Uint16, OFstatic_cast(Sint32, value) + OFstatic_cast(Sint32, offset) + 1);
00070 }
00071 
00072 /*
00073 inline Uint32 removeSign(const Sint32 value, const Sint32 offset)
00074 {
00075     return (value < 0) ? OFstatic_cast(Uint32, value + offset + 1) : OFstatic_cast(Uint32, value) + OFstatic_cast(Uint32, offset) + 1;
00076 }
00077 
00078 
00079 inline Uint8 removeSign(const Sint8 value, const Uint8 mask)
00080 {
00081     return OFstatic_cast(Uint8, value) ^ mask;
00082 }
00083 
00084 
00085 inline Uint16 removeSign(const Sint16 value, const Uint16 mask)
00086 {
00087     return OFstatic_cast(Uint16, value) ^ mask;
00088 }
00089 */
00090 
00091 inline Uint32 removeSign(const Sint32 value, const Uint32 mask)
00092 {
00093     return OFstatic_cast(Uint32, value) ^ mask;
00094 }
00095 
00096 
00097 /*---------------------*
00098  *  class declaration  *
00099  *---------------------*/
00100 
00103 template<class T>
00104 class DiColorPixelTemplate
00105   : public DiColorPixel,
00106     public DiPixelRepresentationTemplate<T>
00107 {
00108 
00109  public:
00110 
00119     DiColorPixelTemplate(const DiDocument *docu,
00120                          const DiInputPixel *pixel,
00121                          const Uint16 samples,
00122                          EI_Status &status,
00123                          const Uint16 sample_rate = 0)
00124       : DiColorPixel(docu, pixel, samples, status, sample_rate)
00125     {
00126         Data[0] = NULL;
00127         Data[1] = NULL;
00128         Data[2] = NULL;
00129     }
00130 
00133     virtual ~DiColorPixelTemplate()
00134     {
00135         delete[] Data[0];
00136         delete[] Data[1];
00137         delete[] Data[2];
00138     }
00139 
00144     inline EP_Representation getRepresentation() const
00145     {
00146         return DiPixelRepresentationTemplate<T>::getRepresentation();
00147     }
00148 
00154     inline const void *getData() const
00155     {
00156         return OFstatic_cast(const void *, Data);
00157     }
00158 
00164     inline void *getDataPtr()
00165     {
00166         return OFstatic_cast(void *, Data);
00167     }
00168 
00174     inline void *getDataArrayPtr()
00175     {
00176         return OFstatic_cast(void *, Data);
00177     }
00178 
00189     OFBool getPixelData(void *data,
00190                         const unsigned long count,
00191                         const unsigned long fcount,
00192                         const unsigned long frames,
00193                         const int planar) const
00194     {
00195         OFBool result = OFFalse;
00196         /* check parameters and internal data */
00197         if ((data != NULL) && (count >= Count * 3) && (frames > 0) && (frames * fcount <= Count) &&
00198             (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL))
00199         {
00200             register T *q = OFstatic_cast(T *, data);
00201             register int j;
00202             register unsigned long k;
00203             register unsigned long offset = 0;
00204             if (planar)
00205             {
00206                 /* for all frames ... */
00207                 for (k = 0; k < frames; ++k)
00208                 {
00209                     /* copy all three planes to the given memory block */
00210                     for (j = 0; j < 3; ++j)
00211                     {
00212                         OFBitmanipTemplate<T>::copyMem(Data[j] + offset, q, fcount);
00213                         q += fcount;
00214                     }
00215                     offset += fcount;
00216                 }
00217             } else {
00218                 register unsigned long i;
00219                 /* for all frames ... */
00220                 for (k = 0; k < frames; ++k)
00221                 {
00222                     /* copy pixel data values from internal representation */
00223                     for (i = 0; i < fcount; ++i)
00224                     {
00225                         for (j = 0; j < 3; ++j)
00226                             *(q++) = Data[j][i + offset];
00227                     }
00228                     offset += fcount;
00229                 }
00230             }
00231             result = OFTrue;
00232         }
00233         return result;
00234     }
00235 
00251     unsigned long createDIB(void *&data,
00252                             const unsigned long size,
00253                             const Uint16 width,
00254                             const Uint16 height,
00255                             const unsigned long frame,
00256                             const int fromBits,
00257                             const int toBits,
00258                             const int mode,
00259                             const int upsideDown,
00260                             const int padding) const
00261     {
00262         unsigned long bytes = 0;
00263         if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
00264         {
00265             const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
00266             const unsigned long start = count * frame + ((upsideDown) ?
00267                 OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0);
00268             const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0;
00269             register const T *r = Data[0] + start;
00270             register const T *g = Data[1] + start;
00271             register const T *b = Data[2] + start;
00272             register Uint16 x;
00273             register Uint16 y;
00274             if (mode == 24)     // 24 bits per pixel
00275             {
00276                 const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3;
00277                 // each line has to start at 32-bit-address, if 'padding' is true
00278                 const int gap = (padding) ? OFstatic_cast(int, (4 - (wid3 & 0x3)) & 0x3) : 0;
00279                 unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height);
00280                 if ((data == NULL) || (size >= fsize))
00281                 {
00282                     if (data == NULL)
00283                         data = new Uint8[fsize];
00284                     if (data != NULL)
00285                     {
00286                         register Uint8 *q = OFstatic_cast(Uint8 *, data);
00287                         if (fromBits == toBits)
00288                         {
00289                             /* copy pixel data as is */
00290                             for (y = height; y != 0; y--)
00291                             {
00292                                 for (x = width; x != 0; x--)
00293                                 {
00294                                     /* reverse sample order: B-G-R */
00295                                     *(q++) = OFstatic_cast(Uint8, *(b++));
00296                                     *(q++) = OFstatic_cast(Uint8, *(g++));
00297                                     *(q++) = OFstatic_cast(Uint8, *(r++));
00298                                 }
00299                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00300                                 q += gap;                                           // new line: jump to next 32-bit address
00301                             }
00302                         }
00303                         else if (fromBits < toBits)
00304                         {
00305                             /* increase color depth: multiply with factor */
00306                             const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00307                                                      OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00308                             const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1);
00309                             if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00310                             {
00311                                 for (y = height; y != 0; y--)
00312                                 {
00313                                     for (x = width; x != 0; x--)
00314                                     {
00315                                         /* reverse sample order: B-G-R */
00316                                         *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2);
00317                                         *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2);
00318                                         *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2);
00319                                     }
00320                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00321                                     q += gap;                                       // new line: jump to next 32-bit address
00322                                 }
00323                             } else {
00324                                 for (y = height; y != 0; y--)
00325                                 {
00326                                     for (x = width; x != 0; x--)
00327                                     {
00328                                         /* reverse sample order: B-G-R */
00329                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1);
00330                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1);
00331                                         *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1);
00332                                     }
00333                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00334                                     q += gap;                                       // new line: jump to next 32-bit address
00335                                 }
00336                             }
00337                         }
00338                         else /* fromBits > toBits */
00339                         {
00340                             /* reduce color depth: right shift */
00341                             const int shift = fromBits - toBits;
00342                             for (y = height; y != 0; y--)
00343                             {
00344                                 for (x = width; x != 0; x--)
00345                                 {
00346                                     /* reverse sample order: B-G-R */
00347                                     *(q++) = OFstatic_cast(Uint8, *(b++) >> shift);
00348                                     *(q++) = OFstatic_cast(Uint8, *(g++) >> shift);
00349                                     *(q++) = OFstatic_cast(Uint8, *(r++) >> shift);
00350                                 }
00351                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00352                                 q += gap;                                           // new line: jump to next 32-bit address
00353                             }
00354                         }
00355                         bytes = fsize;
00356                     }
00357                 }
00358             }
00359             else if (mode == 32)     // 32 bits per pixel
00360             {
00361                 const unsigned long fsize = count * 4;
00362                 if ((data == NULL) || (size >= fsize))
00363                 {
00364                     if (data == NULL)
00365                         data = new Uint32[count];
00366                     if (data != NULL)
00367                     {
00368                         register Uint32 *q = OFstatic_cast(Uint32 *, data);
00369                         if (fromBits == toBits)
00370                         {
00371                             /* copy pixel data as is */
00372                             for (y = height; y != 0; y--)
00373                             {
00374                                 for (x = width; x != 0; x--)
00375                                 {
00376                                     /* normal sample order: 0-R-G-B */
00377                                     *(q++) = (OFstatic_cast(Uint32, *(r++)) << 16) |
00378                                              (OFstatic_cast(Uint32, *(g++)) << 8) |
00379                                              OFstatic_cast(Uint32, *(b++));
00380                                 }
00381                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00382                             }
00383                         }
00384                         else if (fromBits < toBits)
00385                         {
00386                             /* increase color depth: multiply with factor */
00387                             const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00388                                                      OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00389                             const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
00390                             if (gradient1 == OFstatic_cast(double, gradient2))      // integer multiplication?
00391                             {
00392                                 for (y = height; y != 0; y--)
00393                                 {
00394                                     for (x = width; x != 0; x--)
00395                                     {
00396                                         /* normal sample order: 0-R-G-B */
00397                                         *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 16) |
00398                                                  (OFstatic_cast(Uint32, *(g++) * gradient2) << 8) |
00399                                                  OFstatic_cast(Uint32, *(b++) * gradient2);
00400                                     }
00401                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00402                                 }
00403                             } else {
00404                                 for (y = height; y != 0; y--)
00405                                 {
00406                                     for (x = width; x != 0; x--)
00407                                     {
00408                                         /* normal sample order: 0-R-G-B */
00409                                         *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 16) |
00410                                                  (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 8) |
00411                                                  OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1);
00412                                     }
00413                                     r += nextRow; g += nextRow; b += nextRow;       // go backwards if 'upsideDown'
00414                                 }
00415                             }
00416                         }
00417                         else /* fromBits > toBits */
00418                         {
00419                             /* reduce color depth: right shift */
00420                             const int shift = fromBits - toBits;
00421                             for (y = height; y != 0; y--)
00422                             {
00423                                 for (x = width; x != 0; x--)
00424                                 {
00425                                     /* normal sample order: 0-R-G-B */
00426                                     *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 16) |
00427                                              (OFstatic_cast(Uint32, *(g++) >> shift) << 8) |
00428                                              OFstatic_cast(Uint32, *(b++) >> shift);
00429                                 }
00430                                 r += nextRow; g += nextRow; b += nextRow;           // go backwards if 'upsideDown'
00431                             }
00432                         }
00433                         bytes = fsize;
00434                     }
00435                 }
00436             }
00437         }
00438         return bytes;
00439     }
00440 
00452     unsigned long createAWTBitmap(void *&data,
00453                                   const Uint16 width,
00454                                   const Uint16 height,
00455                                   const unsigned long frame,
00456                                   const int fromBits,
00457                                   const int toBits) const
00458     {
00459         data = NULL;
00460         unsigned long bytes = 0;
00461         if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8))
00462         {
00463             const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height);
00464             data = new Uint32[count];
00465             if (data != NULL)
00466             {
00467                 const unsigned long start = count * frame;
00468                 register const T *r = Data[0] + start;
00469                 register const T *g = Data[1] + start;
00470                 register const T *b = Data[2] + start;
00471                 register Uint32 *q = OFstatic_cast(Uint32 *, data);
00472                 register unsigned long i;
00473                 if (fromBits == toBits)
00474                 {
00475                     /* copy pixel data as is */
00476                     for (i = count; i != 0; --i)
00477                     {
00478                         /* sample order: R-G-B */
00479                         *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) |
00480                                  (OFstatic_cast(Uint32, *(g++)) << 16) |
00481                                  (OFstatic_cast(Uint32, *(b++)) << 8);
00482                     }
00483                 }
00484                 else if (fromBits < toBits)
00485                 {
00486                     /* increase color depth: multiply with factor */
00487                     const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) /
00488                                              OFstatic_cast(double, DicomImageClass::maxval(fromBits));
00489                     const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1);
00490                     if (gradient1 == OFstatic_cast(double, gradient2))         // integer multiplication?
00491                     {
00492                         for (i = count; i != 0; --i)
00493                         {
00494                             /* sample order: R-G-B */
00495                             *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) |
00496                                      (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) |
00497                                      (OFstatic_cast(Uint32, *(b++) * gradient2) << 8);
00498                         }
00499                     } else {
00500                         for (i = count; i != 0; --i)
00501                         {
00502                             /* sample order: R-G-B */
00503                             *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) |
00504                                      (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) |
00505                                      (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8);
00506                         }
00507                     }
00508                 }
00509                 else /* fromBits > toBits */
00510                 {
00511                     /* reduce color depth: right shift */
00512                     const int shift = fromBits - toBits;
00513                     for (i = count; i != 0; --i)
00514                     {
00515                         /* sample order: R-G-B */
00516                         *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) |
00517                                  (OFstatic_cast(Uint32, *(g++) >> shift) << 16) |
00518                                  (OFstatic_cast(Uint32, *(b++) >> shift) << 8);
00519                     }
00520                 }
00521                 bytes = count * 4;
00522             }
00523         }
00524         return bytes;
00525     }
00526 
00527 
00528  protected:
00529 
00535     DiColorPixelTemplate(const DiColorPixel *pixel,
00536                          const unsigned long count)
00537       : DiColorPixel(pixel, count)
00538     {
00539         Data[0] = NULL;
00540         Data[1] = NULL;
00541         Data[2] = NULL;
00542     }
00543 
00550     inline int Init(const void *pixel)
00551     {
00552         int result = 0;
00553         if (pixel != NULL)
00554         {
00555             result = 1;
00556             /* allocate data buffer for the 3 planes */
00557             for (int j = 0; j < 3; j++)
00558             {
00559                 Data[j] = new T[Count];
00560                 if (Data[j] != NULL)
00561                 {
00562                     /* erase empty part of the buffer (=blacken the background) */
00563                     if (InputCount < Count)
00564                         OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount);
00565                 } else
00566                     result = 0;     // at least one buffer could not be allocated!
00567             }
00568         }
00569         return result;
00570     }
00571 
00572 
00574     T *Data[3];
00575 
00576 
00577  private:
00578 
00579  // --- declarations to avoid compiler warnings
00580 
00581     DiColorPixelTemplate(const DiColorPixelTemplate<T> &);
00582     DiColorPixelTemplate<T> &operator=(const DiColorPixelTemplate<T> &);
00583 };
00584 
00585 
00586 #endif
00587 
00588 
00589 /*
00590  *
00591  * CVS/RCS Log:
00592  * $Log: dicopxt.h,v $
00593  * Revision 1.30  2010-10-14 13:16:29  joergr
00594  * Updated copyright header. Added reference to COPYRIGHT file.
00595  *
00596  * Revision 1.29  2010-03-01 09:08:46  uli
00597  * Removed some unnecessary include directives in the headers.
00598  *
00599  * Revision 1.28  2009-08-26 07:51:31  joergr
00600  * Added parentheses around + or - in operand of & in order to avoid warnings
00601  * reported by gcc 4.3.2.
00602  *
00603  * Revision 1.27  2008-05-13 10:03:34  joergr
00604  * Fixed issue with multi-frame color images: writeImageToDataset() used wrong
00605  * format for color-by-plane output.
00606  *
00607  * Revision 1.26  2006/07/10 10:59:26  joergr
00608  * Fixed incorrect order of sample values in 32-bit DIB images.
00609  *
00610  * Revision 1.25  2005/12/08 16:01:35  meichel
00611  * Changed include path schema for all DCMTK header files
00612  *
00613  * Revision 1.24  2004/10/19 12:57:47  joergr
00614  * Enhanced API documentation.
00615  *
00616  * Revision 1.23  2004/02/06 11:18:18  joergr
00617  * Distinguish more clearly between const and non-const access to pixel data.
00618  *
00619  * Revision 1.22  2004/01/21 12:59:43  meichel
00620  * Added OFconst_cast, needed for Visual C++ 6
00621  *
00622  * Revision 1.21  2003/12/23 11:43:03  joergr
00623  * Adapted type casts to new-style typecast operators defined in ofcast.h.
00624  * Removed leading underscore characters from preprocessor symbols (reserved
00625  * symbols). Updated copyright header. Added missing API documentation.
00626  * Replaced post-increment/decrement operators by pre-increment/decrement
00627  * operators where appropriate (e.g. 'i++' by '++i').
00628  *
00629  * Revision 1.20  2002/12/10 17:39:50  meichel
00630  * Added explicit type cast to avoid compilation error on gcc 3.2
00631  *
00632  * Revision 1.19  2002/12/09 13:37:24  joergr
00633  * Added private undefined copy constructor and/or assignment operator.
00634  * Fixed bug that caused method createAWTBitmap() to return always empty pixel
00635  * data.
00636  *
00637  * Revision 1.18  2002/09/12 14:10:37  joergr
00638  * Replaced "createPixelData" by "getPixelData" which uses a new dcmdata
00639  * routine and is therefore more efficient.
00640  *
00641  * Revision 1.17  2002/08/29 12:57:49  joergr
00642  * Added method that creates pixel data in DICOM format.
00643  *
00644  * Revision 1.16  2002/06/26 16:17:41  joergr
00645  * Enhanced handling of corrupted pixel data and/or length.
00646  *
00647  * Revision 1.15  2002/01/29 17:07:08  joergr
00648  * Added optional flag to the "Windows DIB" methods allowing to switch off the
00649  * scanline padding.
00650  *
00651  * Revision 1.14  2001/12/11 14:23:44  joergr
00652  * Added type cast to keep old Sun compilers quiet.
00653  *
00654  * Revision 1.13  2001/11/09 16:44:35  joergr
00655  * Enhanced and renamed createTrueColorDIB() method.
00656  *
00657  * Revision 1.12  2001/06/01 15:49:29  meichel
00658  * Updated copyright header
00659  *
00660  * Revision 1.11  2000/03/08 16:21:51  meichel
00661  * Updated copyright header.
00662  *
00663  * Revision 1.10  1999/09/17 14:03:44  joergr
00664  * Enhanced efficiency of some "for" loops.
00665  *
00666  * Revision 1.9  1999/07/23 13:22:29  joergr
00667  * emoved inline method 'removeSign'which is no longer needed.
00668  *
00669  * Revision 1.8  1999/04/28 12:51:58  joergr
00670  * Corrected some typos, comments and formatting.
00671  *
00672  * Revision 1.7  1999/01/20 14:44:49  joergr
00673  * Corrected some typos and formatting.
00674  *
00675  * Revision 1.6  1998/11/27 13:50:20  joergr
00676  * Added copyright message. Replaced delete by delete[] for array types.
00677  * Added method to give direct (non const) access to internal data buffer.
00678  *
00679  * Revision 1.5  1998/05/11 14:53:13  joergr
00680  * Added CVS/RCS header to each file.
00681  *
00682  *
00683  */


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