discalet.h

00001 /*
00002  *
00003  *  Copyright (C) 1996-2005, OFFIS
00004  *
00005  *  This software and supporting documentation were developed by
00006  *
00007  *    Kuratorium OFFIS e.V.
00008  *    Healthcare Information and Communication Systems
00009  *    Escherweg 2
00010  *    D-26121 Oldenburg, Germany
00011  *
00012  *  THIS SOFTWARE IS MADE AVAILABLE,  AS IS,  AND OFFIS MAKES NO  WARRANTY
00013  *  REGARDING  THE  SOFTWARE,  ITS  PERFORMANCE,  ITS  MERCHANTABILITY  OR
00014  *  FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES  OR
00015  *  ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
00016  *  PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
00017  *
00018  *  Module:  dcmimgle
00019  *
00020  *  Author:  Joerg Riesmeier
00021  *
00022  *  Purpose: DicomScaleTemplates (Header)
00023  *
00024  *  Last Update:      $Author: meichel $
00025  *  Update Date:      $Date: 2005/12/08 16:48:09 $
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 DISCALET_H
00035 #define DISCALET_H
00036 
00037 #include "dcmtk/config/osconfig.h"
00038 #include "dcmtk/dcmdata/dctypes.h"
00039 #include "dcmtk/ofstd/ofconsol.h"
00040 #include "dcmtk/ofstd/ofcast.h"
00041 #include "dcmtk/ofstd/ofstream.h"
00042 
00043 #include "dcmtk/dcmimgle/ditranst.h"
00044 #include "dcmtk/dcmimgle/dipxrept.h"
00045 #include "dcmtk/dcmimgle/diutils.h"
00046 
00047 
00048 /*---------------------*
00049  *  macro definitions  *
00050  *---------------------*/
00051 
00052 #define SCALE_FACTOR 4096
00053 #define HALFSCALE_FACTOR 2048
00054 
00055 
00056 /*--------------------*
00057  *  helper functions  *
00058  *--------------------*/
00059 
00060 // help function to set scaling values
00061 
00062 static inline void setScaleValues(Uint16 data[],
00063                                   const Uint16 min,
00064                                   const Uint16 max)
00065 {
00066     register Uint16 remainder = max % min;
00067     Uint16 step0 = max / min;
00068     Uint16 step1 = max / min;
00069     if (remainder > OFstatic_cast(Uint16, min / 2))
00070     {
00071         remainder = min - remainder;
00072         ++step0;
00073     } else
00074         ++step1;
00075     const double count = OFstatic_cast(double, min) / (OFstatic_cast(double, remainder) + 1);
00076     register Uint16 i;
00077     register double c = count;
00078     for (i = 0; i < min; ++i)
00079     {
00080         if ((i >= OFstatic_cast(Uint16, c)) && (remainder > 0))
00081         {
00082             --remainder;
00083             c += count;
00084             data[i] = step1;
00085         }
00086         else
00087             data[i] = step0;
00088     }
00089 }
00090 
00091 
00092 /*---------------------*
00093  *  class declaration  *
00094  *---------------------*/
00095 
00099 template<class T>
00100 class DiScaleTemplate
00101   : public DiTransTemplate<T>
00102 {
00103 
00104  public:
00105 
00120     DiScaleTemplate(const int planes,
00121                     const Uint16 columns,           /* resolution of source image */
00122                     const Uint16 rows,
00123                     const signed long left_pos,     /* origin of clipping area */
00124                     const signed long top_pos,
00125                     const Uint16 src_cols,          /* extension of clipping area */
00126                     const Uint16 src_rows,
00127                     const Uint16 dest_cols,         /* extension of destination image */
00128                     const Uint16 dest_rows,
00129                     const Uint32 frames,            /* number of frames */
00130                     const int bits = 0)
00131       : DiTransTemplate<T>(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits),
00132         Left(left_pos),
00133         Top(top_pos),
00134         Columns(columns),
00135         Rows(rows)
00136     {
00137     }
00138 
00149     DiScaleTemplate(const int planes,
00150                     const Uint16 src_cols,          /* resolution of source image */
00151                     const Uint16 src_rows,
00152                     const Uint16 dest_cols,         /* resolution of destination image */
00153                     const Uint16 dest_rows,
00154                     const Uint32 frames,            /* number of frames */
00155                     const int bits = 0)
00156       : DiTransTemplate<T>(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits),
00157         Left(0),
00158         Top(0),
00159         Columns(src_cols),
00160         Rows(src_rows)
00161     {
00162     }
00163 
00166     virtual ~DiScaleTemplate()
00167     {
00168     }
00169 
00177     void scaleData(const T *src[],               // combined clipping and scaling UNTESTED for multi-frame images !!
00178                    T *dest[],
00179                    const int interpolate,
00180                    const T value = 0)
00181     {
00182         if ((src != NULL) && (dest != NULL))
00183         {
00184 #ifdef DEBUG
00185             if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_DebugMessages))
00186             {
00187                 ofConsole.lockCout() << "C/R: " << Columns << " " << Rows << endl
00188                                      << "L/T: " << Left << " " << Top << endl
00189                                      << "SX/Y: " << this->Src_X << " " << this->Src_Y << endl
00190                                      << "DX/Y: " << this->Dest_X << " " << this->Dest_Y << endl;
00191                 ofConsole.unlockCout();
00192             }
00193 #endif
00194             if ((Left + OFstatic_cast(signed long, this->Src_X) <= 0) || (Top + OFstatic_cast(signed long, this->Src_Y) <= 0) ||
00195                 (Left >= OFstatic_cast(signed long, Columns)) || (Top >= OFstatic_cast(signed long, Rows)))
00196             {                                                                   // no image to be displayed
00197 #ifdef DEBUG
00198                 if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Informationals))
00199                 {
00200                     ofConsole.lockCerr() << "INFO: clipping area is fully outside the image boundaries !" << endl;
00201                     ofConsole.unlockCerr();
00202                 }
00203 #endif
00204                 fillPixel(dest, value);                                         // ... fill bitmap
00205             }
00206             else if ((this->Src_X == this->Dest_X) && (this->Src_Y == this->Dest_Y))                    // no scaling
00207             {
00208                 if ((Left == 0) && (Top == 0) && (Columns == this->Src_X) && (Rows == this->Src_Y))
00209                     copyPixel(src, dest);                                       // copying
00210                 else if ((Left >= 0) && (OFstatic_cast(Uint16, Left + this->Src_X) <= Columns) &&
00211                          (Top >= 0) && (OFstatic_cast(Uint16, Top + this->Src_Y) <= Rows))
00212                     clipPixel(src, dest);                                       // clipping
00213                 else
00214                     clipBorderPixel(src, dest, value);                          // clipping (with border)
00215             }
00216             else if ((interpolate == 1) && (this->Bits <= MAX_INTERPOLATION_BITS))    // interpolation (pbmplus)
00217                 interpolatePixel(src, dest);
00218             else if ((interpolate == 2) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y))    // interpolated expansion (c't)
00219                 expandPixel(src, dest);
00220             else if ((interpolate == 2) && (this->Src_X >= this->Dest_X) && (this->Src_Y >= this->Dest_Y))    // interpolated reduction (c't)
00221                 reducePixel(src, dest);
00222             else if ((this->Dest_X % this->Src_X == 0) && (this->Dest_Y % this->Src_Y == 0))            // replication
00223                 replicatePixel(src, dest);
00224             else if ((this->Src_X % this->Dest_X == 0) && (this->Src_Y % this->Dest_Y == 0))            // supression
00225                 suppressPixel(src, dest);
00226             else                                                                // general scaling
00227                 scalePixel(src, dest);
00228         }
00229     }
00230 
00231  protected:
00232 
00234     const signed long Left;
00236     const signed long Top;
00238     const Uint16 Columns;
00240     const Uint16 Rows;
00241 
00242 
00243  private:
00244 
00251     void clipPixel(const T *src[],
00252                    T *dest[])
00253     {
00254         const unsigned long x_feed = Columns - this->Src_X;
00255         const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns);
00256         register Uint16 x;
00257         register Uint16 y;
00258         register const T *p;
00259         register T *q;
00260         for (int j = 0; j < this->Planes; ++j)
00261         {
00262             p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
00263             q = dest[j];
00264             for (unsigned long f = this->Frames; f != 0; --f)
00265             {
00266                 for (y = this->Dest_Y; y != 0; --y)
00267                 {
00268                     for (x = this->Dest_X; x != 0; --x)
00269                         *(q++) = *(p++);
00270                     p += x_feed;
00271                 }
00272                 p += y_feed;
00273             }
00274         }
00275     }
00276 
00284     void clipBorderPixel(const T *src[],
00285                          T *dest[],
00286                          const T value)
00287     {
00288         const Uint16 s_left = (Left > 0) ? OFstatic_cast(Uint16, Left) : 0;
00289         const Uint16 s_top = (Top > 0) ? OFstatic_cast(Uint16, Top) : 0;
00290         const Uint16 d_left = (Left < 0 ? OFstatic_cast(Uint16, -Left) : 0);
00291         const Uint16 d_top = (Top < 0) ? OFstatic_cast(Uint16, -Top) : 0;
00292         const Uint16 d_right = (OFstatic_cast(unsigned long, this->Src_X) + OFstatic_cast(unsigned long, s_left) <
00293                                 OFstatic_cast(unsigned long, Columns) + OFstatic_cast(unsigned long, d_left)) ?
00294                                (this->Src_X - 1) : (Columns + d_left - s_left - 1);
00295         const Uint16 d_bottom = (OFstatic_cast(unsigned long, this->Src_Y) + OFstatic_cast(unsigned long, s_top) <
00296                                  OFstatic_cast(unsigned long, Rows) + OFstatic_cast(unsigned long, d_top)) ?
00297                                 (this->Src_Y - 1) : (Rows + d_top - s_top - 1);
00298         const Uint16 x_count = d_right - d_left + 1;
00299         const Uint16 y_count = d_bottom - d_top + 1;
00300         const unsigned long s_start = OFstatic_cast(unsigned long, s_top) * OFstatic_cast(unsigned long, Columns) + s_left;
00301         const unsigned long x_feed = Columns - x_count;
00302         const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - y_count) * Columns;
00303         const unsigned long t_feed = OFstatic_cast(unsigned long, d_top) * OFstatic_cast(unsigned long, this->Src_X);
00304         const unsigned long b_feed = OFstatic_cast(unsigned long, this->Src_Y - d_bottom - 1) * OFstatic_cast(unsigned long, this->Src_X);
00305 
00306         /*
00307          *  The approach is to divide the destination image in up to four areas outside the source image
00308          *  plus one area for the source image. The for and while loops are scanning linearly over the
00309          *  destination image and setting the appropriate value depending on the current area. This is
00310          *  different from most of the other algorithms in this toolkit where the source image is scanned
00311          *  linearly.
00312          */
00313         register Uint16 x;
00314         register Uint16 y;
00315         register unsigned long i;
00316         register const T *p;
00317         register T *q;
00318         for (int j = 0; j < this->Planes; ++j)
00319         {
00320             p = src[j] + s_start;
00321             q = dest[j];
00322             for (unsigned long f = this->Frames; f != 0; --f)
00323             {
00324                 for (i = t_feed; i != 0; --i)               // top
00325                     *(q++) = value;
00326                 for (y = y_count; y != 0; --y)              // middle part:
00327                 {
00328                     x = 0;
00329                     while (x < d_left)                      // - left
00330                     {
00331                         *(q++) = value;
00332                         ++x;
00333                     }
00334                     while (x <= d_right)                    // - middle
00335                     {
00336                         *(q++) = *(p++);
00337                         ++x;
00338                     }
00339                     while (x < this->Src_X)                       // - right
00340                     {
00341                         *(q++) = value;
00342                         ++x;
00343                     }
00344                     p += x_feed;
00345                 }
00346                 for (i = b_feed; i != 0; --i)               // bottom
00347                     *(q++) = value;
00348                 p += y_feed;
00349             }
00350         }
00351     }
00352 
00359     void replicatePixel(const T *src[],
00360                         T *dest[])
00361     {
00362         const Uint16 x_factor = this->Dest_X / this->Src_X;
00363         const Uint16 y_factor = this->Dest_Y / this->Src_Y;
00364         const unsigned long x_feed = Columns;
00365         const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns);
00366         const T *sp;
00367         register Uint16 x;
00368         register Uint16 y;
00369         register Uint16 dx;
00370         register Uint16 dy;
00371         register const T *p;
00372         register T *q;
00373         register T value;
00374         for (int j = 0; j < this->Planes; ++j)
00375         {
00376             sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
00377             q = dest[j];
00378             for (Uint32 f = this->Frames; f != 0; --f)
00379             {
00380                 for (y = this->Src_Y; y != 0; --y)
00381                 {
00382                     for (dy = y_factor; dy != 0; --dy)
00383                     {
00384                         for (x = this->Src_X, p = sp; x != 0; --x)
00385                         {
00386                             value = *(p++);
00387                             for (dx = x_factor; dx != 0; --dx)
00388                                 *(q++) = value;
00389                         }
00390                     }
00391                     sp += x_feed;
00392                 }
00393                 sp += y_feed;
00394             }
00395         }
00396     }
00397 
00404     void suppressPixel(const T *src[],
00405                        T *dest[])
00406     {
00407         const unsigned int x_divisor = this->Src_X / this->Dest_X;
00408         const unsigned long x_feed = OFstatic_cast(unsigned long, this->Src_Y / this->Dest_Y) * OFstatic_cast(unsigned long, Columns) - this->Src_X;
00409         const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns);
00410         register Uint16 x;
00411         register Uint16 y;
00412         register const T *p;
00413         register T *q;
00414         for (int j = 0; j < this->Planes; ++j)
00415         {
00416             p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
00417             q = dest[j];
00418             for (Uint32 f = this->Frames; f != 0; --f)
00419             {
00420                 for (y = this->Dest_Y; y != 0; --y)
00421                 {
00422                     for (x = this->Dest_X; x != 0; --x)
00423                     {
00424                         *(q++) = *p;
00425                         p += x_divisor;
00426                     }
00427                     p += x_feed;
00428                 }
00429                 p += y_feed;
00430             }
00431         }
00432     }
00433 
00440     void scalePixel(const T *src[],
00441                     T *dest[])
00442     {
00443         const Uint16 xmin = (this->Dest_X < this->Src_X) ? this->Dest_X : this->Src_X;      // minimum width
00444         const Uint16 ymin = (this->Dest_Y < this->Src_Y) ? this->Dest_Y : this->Src_Y;      // minimum height
00445         Uint16 *x_step = new Uint16[xmin];
00446         Uint16 *y_step = new Uint16[ymin];
00447         Uint16 *x_fact = new Uint16[xmin];
00448         Uint16 *y_fact = new Uint16[ymin];
00449 
00450        /*
00451         *  Approach: If one pixel line has to be added or removed it is taken from the middle of the image (1/2).
00452         *  For two lines it is at 1/3 and 2/3 of the image and so on. It sounds easy but it was a hard job ;-)
00453         */
00454 
00455         if ((x_step != NULL) && (y_step != NULL) && (x_fact != NULL) && (y_fact != NULL))
00456         {
00457             register Uint16 x;
00458             register Uint16 y;
00459             if (this->Dest_X < this->Src_X)
00460                 setScaleValues(x_step, this->Dest_X, this->Src_X);
00461             else if (this->Dest_X > this->Src_X)
00462                 setScaleValues(x_fact, this->Src_X, this->Dest_X);
00463             if (this->Dest_X <= this->Src_X)
00464                 OFBitmanipTemplate<Uint16>::setMem(x_fact, 1, xmin);  // initialize with default values
00465             if (this->Dest_X >= this->Src_X)
00466                 OFBitmanipTemplate<Uint16>::setMem(x_step, 1, xmin);  // initialize with default values
00467             x_step[xmin - 1] += Columns - this->Src_X;                      // skip to next line
00468             if (this->Dest_Y < this->Src_Y)
00469                 setScaleValues(y_step, this->Dest_Y, this->Src_Y);
00470             else if (this->Dest_Y > this->Src_Y)
00471                 setScaleValues(y_fact, this->Src_Y, this->Dest_Y);
00472             if (this->Dest_Y <= this->Src_Y)
00473                 OFBitmanipTemplate<Uint16>::setMem(y_fact, 1, ymin);  // initialize with default values
00474             if (this->Dest_Y >= this->Src_Y)
00475                 OFBitmanipTemplate<Uint16>::setMem(y_step, 1, ymin);  // initialize with default values
00476             y_step[ymin - 1] += Rows - this->Src_Y;                         // skip to next frame
00477             const T *sp;
00478             register Uint16 dx;
00479             register Uint16 dy;
00480             register const T *p;
00481             register T *q;
00482             register T value;
00483             for (int j = 0; j < this->Planes; ++j)
00484             {
00485                 sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
00486                 q = dest[j];
00487                 for (Uint32 f = 0; f < this->Frames; ++f)
00488                 {
00489                     for (y = 0; y < ymin; ++y)
00490                     {
00491                         for (dy = 0; dy < y_fact[y]; ++dy)
00492                         {
00493                             for (x = 0, p = sp; x < xmin; ++x)
00494                             {
00495                                 value = *p;
00496                                 for (dx = 0; dx < x_fact[x]; ++dx)
00497                                     *(q++) = value;
00498                                 p += x_step[x];
00499                             }
00500                         }
00501                         sp += OFstatic_cast(unsigned long, y_step[y]) * OFstatic_cast(unsigned long, Columns);
00502                     }
00503                 }
00504             }
00505         }
00506         delete[] x_step;
00507         delete[] y_step;
00508         delete[] x_fact;
00509         delete[] y_fact;
00510     }
00511 
00512 
00518     void interpolatePixel(const T *src[],
00519                           T *dest[])
00520     {
00521         if ((this->Src_X != Columns) || (this->Src_Y != Rows))
00522         {
00523             if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Errors))
00524             {
00525                ofConsole.lockCerr() << "ERROR: interpolated scaling and clipping at the same time not implemented" << endl
00526                                     << "       ... ignoring clipping region !" << endl;
00527                ofConsole.unlockCerr();
00528             }
00529             this->Src_X = Columns;            // temporarily removed 'const' for 'Src_X' in class 'DiTransTemplate'
00530             this->Src_Y = Rows;               //                             ... 'Src_Y' ...
00531         }
00532 
00533         /*
00534          *   based on scaling algorithm from "Extended Portable Bitmap Toolkit" (pbmplus10dec91)
00535          *   (adapted to be used with signed pixel representation and inverse images - mono2)
00536          */
00537 
00538         register Uint16 x;
00539         register Uint16 y;
00540         register const T *p;
00541         register T *q;
00542         T const *sp = NULL;                         // initialization avoids compiler warning
00543         T const *fp;
00544         T *sq;
00545 
00546         const unsigned long sxscale = OFstatic_cast(unsigned long, (OFstatic_cast(double, this->Dest_X) / OFstatic_cast(double, this->Src_X)) * SCALE_FACTOR);
00547         const unsigned long syscale = OFstatic_cast(unsigned long, (OFstatic_cast(double, this->Dest_Y) / OFstatic_cast(double, this->Src_Y)) * SCALE_FACTOR);
00548         DiPixelRepresentationTemplate<T> rep;
00549         const signed long maxvalue = DicomImageClass::maxval(this->Bits - rep.isSigned());
00550 
00551         T *xtemp = new T[this->Src_X];
00552         signed long *xvalue = new signed long[this->Src_X];
00553 
00554         if ((xtemp == NULL) || (xvalue == NULL))
00555         {
00556             if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Errors))
00557             {
00558                 ofConsole.lockCerr() << "ERROR: can't allocate temporary buffers for interpolation scaling !" << endl;
00559                 ofConsole.unlockCerr();
00560             }
00561 
00562             const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y) * this->Frames;
00563             for (int j = 0; j < this->Planes; ++j)
00564                 OFBitmanipTemplate<T>::zeroMem(dest[j], count);     // delete destination buffer
00565         }
00566         else
00567         {
00568             for (int j = 0; j < this->Planes; ++j)
00569             {
00570                 fp = src[j];
00571                 sq = dest[j];
00572                 for (Uint32 f = this->Frames; f != 0; --f)
00573                 {
00574                     for (x = 0; x < this->Src_X; ++x)
00575                         xvalue[x] = HALFSCALE_FACTOR;
00576                     register unsigned long yfill = SCALE_FACTOR;
00577                     register unsigned long yleft = syscale;
00578                     register int yneed = 1;
00579                     int ysrc = 0;
00580                     for (y = 0; y < this->Dest_Y; ++y)
00581                     {
00582                         if (this->Src_Y == this->Dest_Y)
00583                         {
00584                             sp = fp;
00585                             for (x = this->Src_X, p = sp, q = xtemp; x != 0; --x)
00586                                 *(q++) = *(p++);
00587                             fp += this->Src_X;
00588                         }
00589                         else
00590                         {
00591                             while (yleft < yfill)
00592                             {
00593                                 if (yneed && (ysrc < OFstatic_cast(int, this->Src_Y)))
00594                                 {
00595                                     sp = fp;
00596                                     fp += this->Src_X;
00597                                     ++ysrc;
00598                                 }
00599                                 for (x = 0, p = sp; x < this->Src_X; ++x)
00600                                     xvalue[x] += yleft * OFstatic_cast(signed long, *(p++));
00601                                 yfill -= yleft;
00602                                 yleft = syscale;
00603                                 yneed = 1;
00604                             }
00605                             if (yneed && (ysrc < OFstatic_cast(int, this->Src_Y)))
00606                             {
00607                                 sp = fp;
00608                                 fp += this->Src_X;
00609                                 ++ysrc;
00610                                 yneed = 0;
00611                             }
00612                             for (x = 0, p = sp, q = xtemp; x < this->Src_X; ++x)
00613                             {
00614                                 register signed long v = xvalue[x] + yfill * OFstatic_cast(signed long, *(p++));
00615                                 v /= SCALE_FACTOR;
00616                                 *(q++) = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v);
00617                                 xvalue[x] = HALFSCALE_FACTOR;
00618                             }
00619                             yleft -= yfill;
00620                             if (yleft == 0)
00621                             {
00622                                 yleft = syscale;
00623                                 yneed = 1;
00624                             }
00625                             yfill = SCALE_FACTOR;
00626                         }
00627                         if (this->Src_X == this->Dest_X)
00628                         {
00629                             for (x = this->Dest_X, p = xtemp, q = sq; x != 0; --x)
00630                                 *(q++) = *(p++);
00631                             sq += this->Dest_X;
00632                         }
00633                         else
00634                         {
00635                             register signed long v = HALFSCALE_FACTOR;
00636                             register unsigned long xfill = SCALE_FACTOR;
00637                             register unsigned long xleft;
00638                             register int xneed = 0;
00639                             q = sq;
00640                             for (x = 0, p = xtemp; x < this->Src_X; ++x, ++p)
00641                             {
00642                                 xleft = sxscale;
00643                                 while (xleft >= xfill)
00644                                 {
00645                                     if (xneed)
00646                                     {
00647                                         ++q;
00648                                         v = HALFSCALE_FACTOR;
00649                                     }
00650                                     v += xfill * OFstatic_cast(signed long, *p);
00651                                     v /= SCALE_FACTOR;
00652                                     *q = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v);
00653                                     xleft -= xfill;
00654                                     xfill = SCALE_FACTOR;
00655                                     xneed = 1;
00656                                 }
00657                                 if (xleft > 0)
00658                                 {
00659                                     if (xneed)
00660                                     {
00661                                         ++q;
00662                                         v = HALFSCALE_FACTOR;
00663                                         xneed = 0;
00664                                     }
00665                                     v += xleft * OFstatic_cast(signed long, *p);
00666                                     xfill -= xleft;
00667                                 }
00668                             }
00669                             if (xfill > 0)
00670                                 v += xfill * OFstatic_cast(signed long, *(--p));
00671                             if (!xneed)
00672                             {
00673                                 v /= SCALE_FACTOR;
00674                                 *q = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v);
00675                             }
00676                             sq += this->Dest_X;
00677                         }
00678                     }
00679                 }
00680             }
00681         }
00682         delete[] xtemp;
00683         delete[] xvalue;
00684     }
00685 
00686 
00692     void expandPixel(const T *src[],
00693                      T *dest[])
00694     {
00695 #ifdef DEBUG
00696         if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Informationals))
00697         {
00698             ofConsole.lockCerr() << "INFO: expandPixel with interpolated c't algorithm" << endl;
00699             ofConsole.unlockCerr();
00700         }
00701 #endif
00702         const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X);
00703         const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y);
00704         const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns);
00705         const T *sp;
00706         double bx, ex;
00707         double by, ey;
00708         int bxi, exi;
00709         int byi, eyi;
00710         unsigned long offset;
00711         double value, sum;
00712         double x_part, y_part;
00713         double l_factor, r_factor;
00714         double t_factor, b_factor;
00715         register int xi;
00716         register int yi;
00717         register Uint16 x;
00718         register Uint16 y;
00719         register const T *p;
00720         register T *q;
00721 
00722         /*
00723          *   based on scaling algorithm from "c't - Magazin fuer Computertechnik" (c't 11/94)
00724          *   (adapted to be used with signed pixel representation and inverse images - mono1)
00725          */
00726 
00727         for (int j = 0; j < this->Planes; ++j)
00728         {
00729             sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
00730             q = dest[j];
00731             for (Uint32 f = 0; f < this->Frames; ++f)
00732             {
00733                 for (y = 0; y < this->Dest_Y; ++y)
00734                 {
00735                     by = y_factor * OFstatic_cast(double, y);
00736                     ey = y_factor * (OFstatic_cast(double, y) + 1.0);
00737                     byi = OFstatic_cast(int, by);
00738                     eyi = OFstatic_cast(int, ey);
00739                     if (OFstatic_cast(double, eyi) == ey)
00740                         --eyi;
00741                     y_part = OFstatic_cast(double, eyi) / y_factor;
00742                     b_factor = y_part - OFstatic_cast(double, y);
00743                     t_factor = (OFstatic_cast(double, y) + 1.0) - y_part;
00744                     for (x = 0; x < this->Dest_X; ++x)
00745                     {
00746                         value = 0;
00747                         bx = x_factor * OFstatic_cast(double, x);
00748                         ex = x_factor * (OFstatic_cast(double, x) + 1.0);
00749                         bxi = OFstatic_cast(int, bx);
00750                         exi = OFstatic_cast(int, ex);
00751                         if (OFstatic_cast(double, exi) == ex)
00752                             --exi;
00753                         x_part = OFstatic_cast(double, exi) / x_factor;
00754                         l_factor = x_part - OFstatic_cast(double, x);
00755                         r_factor = (OFstatic_cast(double, x) + 1.0) - x_part;
00756                         offset = OFstatic_cast(unsigned long, byi - 1) * OFstatic_cast(unsigned long, Columns);
00757                         for (yi = byi; yi <= eyi; ++yi)
00758                         {
00759                             offset += Columns;
00760                             p = sp + offset + OFstatic_cast(unsigned long, bxi);
00761                             for (xi = bxi; xi <= exi; ++xi)
00762                             {
00763                                 sum = OFstatic_cast(double, *(p++));
00764                                 if (bxi != exi)
00765                                 {
00766                                     if (xi == bxi)
00767                                         sum *= l_factor;
00768                                     else
00769                                         sum *= r_factor;
00770                                 }
00771                                 if (byi != eyi)
00772                                 {
00773                                     if (yi == byi)
00774                                         sum *= b_factor;
00775                                     else
00776                                         sum *= t_factor;
00777                                 }
00778                                 value += sum;
00779                             }
00780                         }
00781                         *(q++) = OFstatic_cast(T, value + 0.5);
00782                     }
00783                 }
00784                 sp += f_size;                                        // skip to next frame start: UNTESTED
00785             }
00786         }
00787     }
00788 
00789 
00795     void reducePixel(const T *src[],
00796                           T *dest[])
00797     {
00798 #ifdef DEBUG
00799         if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Informationals | DicomImageClass::DL_Warnings))
00800         {
00801             ofConsole.lockCerr() << "INFO: reducePixel with interpolated c't algorithm ... still a little BUGGY !" << endl;
00802             ofConsole.unlockCerr();
00803         }
00804 #endif
00805         const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X);
00806         const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y);
00807         const double xy_factor = x_factor * y_factor;
00808         const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns);
00809         const T *sp;
00810         double bx, ex;
00811         double by, ey;
00812         int bxi, exi;
00813         int byi, eyi;
00814         unsigned long offset;
00815         double value, sum;
00816         double l_factor, r_factor;
00817         double t_factor, b_factor;
00818         register int xi;
00819         register int yi;
00820         register Uint16 x;
00821         register Uint16 y;
00822         register const T *p;
00823         register T *q;
00824 
00825         /*
00826          *   based on scaling algorithm from "c't - Magazin fuer Computertechnik" (c't 11/94)
00827          *   (adapted to be used with signed pixel representation and inverse images - mono1)
00828          */
00829 
00830         for (int j = 0; j < this->Planes; ++j)
00831         {
00832             sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
00833             q = dest[j];
00834             for (Uint32 f = 0; f < this->Frames; ++f)
00835             {
00836                 for (y = 0; y < this->Dest_Y; ++y)
00837                 {
00838                     by = y_factor * OFstatic_cast(double, y);
00839                     ey = y_factor * (OFstatic_cast(double, y) + 1.0);
00840                     byi = OFstatic_cast(int, by);
00841                     eyi = OFstatic_cast(int, ey);
00842                     if (OFstatic_cast(double, eyi) == ey)
00843                         --eyi;
00844                     b_factor = 1 + OFstatic_cast(double, byi) - by;
00845                     t_factor = ey - OFstatic_cast(double, eyi);
00846                     for (x = 0; x < this->Dest_X; ++x)
00847                     {
00848                         value = 0;
00849                         bx = x_factor * OFstatic_cast(double, x);
00850                         ex = x_factor * (OFstatic_cast(double, x) + 1.0);
00851                         bxi = OFstatic_cast(int, bx);
00852                         exi = OFstatic_cast(int, ex);
00853                         if (OFstatic_cast(double, exi) == ex)
00854                             --exi;
00855                         l_factor = 1 + OFstatic_cast(double, bxi) - bx;
00856                         r_factor = ex - OFstatic_cast(double, exi);
00857                         offset = OFstatic_cast(unsigned long, byi - 1) * OFstatic_cast(unsigned long, Columns);
00858                         for (yi = byi; yi <= eyi; ++yi)
00859                         {
00860                             offset += Columns;
00861                             p = sp + offset + OFstatic_cast(unsigned long, bxi);
00862                             for (xi = bxi; xi <= exi; ++xi)
00863                             {
00864                                 sum = OFstatic_cast(double, *(p++)) / xy_factor;
00865                                 if (xi == bxi)
00866                                     sum *= l_factor;
00867                                 else if (xi == exi)
00868                                     sum *= r_factor;
00869                                 if (yi == byi)
00870                                     sum *= b_factor;
00871                                 else if (yi == eyi)
00872                                     sum *= t_factor;
00873                                 value += sum;
00874                             }
00875                         }
00876                         *(q++) = OFstatic_cast(T, value + 0.5);
00877                     }
00878                 }
00879                 sp += f_size;                                        // skip to next frame start: UNTESTED
00880             }
00881         }
00882     }
00883 };
00884 
00885 #endif
00886 
00887 
00888 /*
00889  *
00890  * CVS/RCS Log:
00891  * $Log: discalet.h,v $
00892  * Revision 1.25  2005/12/08 16:48:09  meichel
00893  * Changed include path schema for all DCMTK header files
00894  *
00895  * Revision 1.24  2004/04/21 10:00:36  meichel
00896  * Minor modifications for compilation with gcc 3.4.0
00897  *
00898  * Revision 1.23  2004/01/05 14:52:20  joergr
00899  * Removed acknowledgements with e-mail addresses from CVS log.
00900  *
00901  * Revision 1.22  2003/12/23 15:53:22  joergr
00902  * Replaced post-increment/decrement operators by pre-increment/decrement
00903  * operators where appropriate (e.g. 'i++' by '++i').
00904  *
00905  * Revision 1.21  2003/12/09 10:25:06  joergr
00906  * Adapted type casts to new-style typecast operators defined in ofcast.h.
00907  * Removed leading underscore characters from preprocessor symbols (reserved
00908  * symbols). Updated copyright header.
00909  *
00910  * Revision 1.20  2002/12/09 13:32:56  joergr
00911  * Renamed parameter/local variable to avoid name clashes with global
00912  * declaration left and/or right (used for as iostream manipulators).
00913  *
00914  * Revision 1.19  2002/04/16 13:53:12  joergr
00915  * Added configurable support for C++ ANSI standard includes (e.g. streams).
00916  *
00917  * Revision 1.18  2001/06/01 15:49:51  meichel
00918  * Updated copyright header
00919  *
00920  * Revision 1.17  2000/05/03 09:46:29  joergr
00921  * Removed most informational and some warning messages from release built
00922  * (#ifndef DEBUG).
00923  *
00924  * Revision 1.16  2000/04/28 12:32:33  joergr
00925  * DebugLevel - global for the module - now derived from OFGlobal (MF-safe).
00926  *
00927  * Revision 1.15  2000/04/27 13:08:42  joergr
00928  * Dcmimgle library code now consistently uses ofConsole for error output.
00929  *
00930  * Revision 1.14  2000/03/08 16:24:24  meichel
00931  * Updated copyright header.
00932  *
00933  * Revision 1.13  2000/03/07 16:15:13  joergr
00934  * Added explicit type casts to make Sun CC 2.0.1 happy.
00935  *
00936  * Revision 1.12  2000/03/03 14:09:14  meichel
00937  * Implemented library support for redirecting error messages into memory
00938  *   instead of printing them to stdout/stderr for GUI applications.
00939  *
00940  * Revision 1.11  1999/11/19 12:37:19  joergr
00941  * Fixed bug in scaling method "reducePixel" (reported by gcc 2.7.2.1).
00942  *
00943  * Revision 1.10  1999/09/17 13:07:20  joergr
00944  * Added/changed/completed DOC++ style comments in the header files.
00945  * Enhanced efficiency of some "for" loops.
00946  *
00947  * Revision 1.9  1999/08/25 16:41:55  joergr
00948  * Added new feature: Allow clipping region to be outside the image
00949  * (overlapping).
00950  *
00951  * Revision 1.8  1999/07/23 14:09:24  joergr
00952  * Added new interpolation algorithm for scaling.
00953  *
00954  * Revision 1.7  1999/04/28 14:55:05  joergr
00955  * Introduced new scheme for the debug level variable: now each level can be
00956  * set separately (there is no "include" relationship).
00957  *
00958  * Revision 1.6  1999/03/24 17:20:24  joergr
00959  * Added/Modified comments and formatting.
00960  *
00961  * Revision 1.5  1999/02/11 16:42:10  joergr
00962  * Removed inline declarations from several methods.
00963  *
00964  * Revision 1.4  1999/02/03 17:35:14  joergr
00965  * Moved global functions maxval() and determineRepresentation() to class
00966  * DicomImageClass (as static methods).
00967  *
00968  * Revision 1.3  1998/12/22 14:39:44  joergr
00969  * Added some preparation to enhance interpolated scaling (clipping and
00970  * scaling) in the future.
00971  *
00972  * Revision 1.2  1998/12/16 16:39:45  joergr
00973  * Implemented combined clipping and scaling for pixel replication and
00974  * suppression.
00975  *
00976  * Revision 1.1  1998/11/27 15:47:11  joergr
00977  * Added copyright message.
00978  * Combined clipping and scaling methods.
00979  *
00980  * Revision 1.4  1998/05/11 14:53:29  joergr
00981  * Added CVS/RCS header to each file.
00982  *
00983  *
00984  */


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