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

pl2passscale.h

Go to the documentation of this file.
00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: pl2passscale.h,v 1.2 2004/10/02 22:23:32 maxx Exp $
00005 |
00006 |      Copyright (c) 1996-2002 Ulrich von Zadow
00007 |
00008 \--------------------------------------------------------------------
00009 */
00010 
00011 #ifndef _2_PASS_SCALE_H_
00012 #define _2_PASS_SCALE_H_
00013 
00014 #include <math.h>
00015 
00016 #include "plcontribdefs.h"
00017 #include "plpaintlibdefs.h"
00018 #include "../minmax.h"
00019 
00020 typedef struct
00021 {
00022    int *Weights;     // Normalized weights of neighboring pixels
00023    int Left,Right;   // Bounds of source pixels window
00024 } ContributionType;  // Contirbution information for a single pixel
00025 
00026 typedef struct
00027 {
00028    ContributionType *ContribRow; // Row (or column) of contribution weights
00029    int WindowSize,               // Filter window size (of affecting source pixels)
00030        LineLength;               // Length of line (no. or rows / cols)
00031 } LineContribType;               // Contribution information for an entire line (row or column)
00032 
00033 typedef bool (*ProgressAndAbortCallBack)(PLBYTE bPercentComplete);
00034 
00035 class CDataRGB_UBYTE
00036 {
00037 public:
00038   typedef unsigned char _DataType[3];
00039   class _Accumulator {
00040   public:
00041       _Accumulator ()
00042       {
00043         val [0] = val [1] = val [2] = 0;
00044       };
00045       void Accumulate (int Weight, _DataType &value)
00046       {
00047         val [0] += (Weight * value [0]);
00048         val [1] += (Weight * value [1]);
00049         val [2] += (Weight * value [2]);
00050       };
00051       void Store (_DataType &value)
00052       {
00053         value [0] = (unsigned char) ((val [0] + 128)/256);
00054         value [1] = (unsigned char) ((val [1] + 128)/256);
00055         value [2] = (unsigned char) ((val [2] + 128)/256);
00056       };
00057       int val [3];
00058   };
00059 };
00060 
00061 class CDataRGBA_UBYTE {
00062 public:
00063   typedef unsigned char _DataType[4];
00064   typedef _DataType* _RowType;
00065   class _Accumulator {
00066   public:
00067       _Accumulator ()
00068       {
00069         val [0] = val [1] = val [2] = val [3] = 0;
00070       };
00071       void Accumulate (int dWeight, _DataType &value)
00072       {
00073         val [0] += (dWeight * (value [0]));
00074         val [1] += (dWeight * (value [1]));
00075         val [2] += (dWeight * (value [2]));
00076         val [3] += (dWeight * (value [3]));
00077       };
00078       void Store (_DataType &value)
00079       {
00080         value [0] = (unsigned char) ((val [0] + 128)/256);
00081         value [1] = (unsigned char) ((val [1] + 128)/256);
00082         value [2] = (unsigned char) ((val [2] + 128)/256);
00083         value [3] = (unsigned char) ((val [3] + 128)/256);
00084       };
00085       int val [4];
00086   };
00087 };
00088 
00089 template <class DataClass>
00090 class C2PassScale
00091 {
00092 public:
00093     typedef typename DataClass::_DataType _DataType;
00094     typedef typename DataClass::_RowType _RowType;
00095 
00096     C2PassScale (const PLContribDef& ContribDef, 
00097                  ProgressAndAbortCallBack callback = NULL)
00098         : m_Callback (callback), m_ContribDef (ContribDef)
00099     {};
00100 
00101     virtual ~C2PassScale() {};
00102 
00103    _RowType * Scale (
00104         _RowType   *pOrigImage,
00105         PLUINT        uOrigWidth,
00106         PLUINT        uOrigHeight,
00107         _RowType   *pDstImage,
00108         PLUINT        uNewWidth,
00109         PLUINT        uNewHeight);
00110 
00111 private:
00112 
00113     ProgressAndAbortCallBack    m_Callback;
00114     bool                        m_bCanceled;
00115 
00116     LineContribType *AllocContributions (PLUINT uLineLength,
00117                                          PLUINT uWindowSize);
00118 
00119     void FreeContributions (LineContribType * p);
00120 
00121     LineContribType *CalcContributions (PLUINT    uLineSize,
00122                                         PLUINT    uSrcSize,
00123                                         double  dScale);
00124 
00125     void ScaleRow (_RowType           *pSrc,
00126                    PLUINT                uSrcWidth,
00127                    _RowType           *pRes,
00128                    PLUINT                uResWidth,
00129                    PLUINT                uRow,
00130                    LineContribType    *Contrib);
00131 
00132     void HorizScale (_RowType           *pSrc,
00133                      PLUINT                uSrcWidth,
00134                      PLUINT                uSrcHeight,
00135                      _RowType           *pDst,
00136                      PLUINT                uResWidth,
00137                      PLUINT                uResHeight);
00138 
00139     void VertScale (_RowType           *pSrc,
00140                     PLUINT                uSrcWidth,
00141                     PLUINT                uSrcHeight,
00142                     _RowType           *pDst,
00143                     PLUINT                uResWidth,
00144                     PLUINT                uResHeight);
00145 
00146     const PLContribDef& m_ContribDef;
00147 };
00148 
00149 template <class DataClass>
00150 LineContribType *
00151 C2PassScale<DataClass>::AllocContributions (PLUINT uLineLength, PLUINT uWindowSize)
00152 {
00153     LineContribType *res = new LineContribType;
00154         // Init structure header
00155     res->WindowSize = uWindowSize;
00156     res->LineLength = uLineLength;
00157         // Allocate list of contributions
00158     res->ContribRow = new ContributionType[uLineLength];
00159     for (PLUINT u = 0 ; u < uLineLength ; u++)
00160     {
00161         // Allocate contributions for every pixel
00162         res->ContribRow[u].Weights = new int[uWindowSize];
00163     }
00164     return res;
00165 }
00166 
00167 template <class DataClass>
00168 void
00169 C2PassScale<DataClass>::FreeContributions (LineContribType * p)
00170 {
00171     for (int u = 0; u < p->LineLength; u++)
00172     {
00173         // Free contribs for every pixel
00174         delete [] p->ContribRow[u].Weights;
00175     }
00176     delete [] p->ContribRow;    // Free list of pixels contribs
00177     delete p;                   // Free contribs header
00178 }
00179 
00180 template <class DataClass>
00181 LineContribType *
00182 C2PassScale<DataClass>::CalcContributions 
00183     (PLUINT uLineSize, PLUINT uSrcSize, double dScale)
00184 {
00185     double dWidth;
00186     double dFScale = 1.0;
00187     double dFilterWidth = m_ContribDef.GetWidth();
00188 
00189     if (dScale < 1.0)
00190     {    // Minification
00191         dWidth = dFilterWidth / dScale;
00192         dFScale = dScale;
00193     }
00194     else
00195     {    // Magnification
00196         dWidth= dFilterWidth;
00197     }
00198 
00199     // Window size is the number of sampled pixels
00200     int iWindowSize = 2 * (int)ceil(dWidth) + 1;
00201 
00202     // Allocate a new line contributions strucutre
00203     LineContribType *res = AllocContributions (uLineSize, iWindowSize);
00204 
00205     for (PLUINT u = 0; u < uLineSize; u++)
00206     {   // Scan through line of contributions
00207         double dCenter = (u+0.5)/dScale-0.5;   // Reverse mapping
00208         // Find the significant edge points that affect the pixel
00209         int iLeft = max (0, (int)floor (dCenter - dWidth));
00210         int iRight = min ((int)ceil (dCenter + dWidth), int(uSrcSize) - 1);
00211 
00212         // Cut edge points to fit in filter window in case of spill-off
00213         if (iRight - iLeft + 1 > iWindowSize)
00214         {
00215             if (iLeft < (int(uSrcSize) - 1 / 2))
00216             {
00217                 iLeft++;
00218             }
00219             else
00220             {
00221                 iRight--;
00222             }
00223         }
00224   //ets+++ adjusted ileft and iright values not stored in contrib array
00225         res->ContribRow[u].Left = iLeft;
00226         res->ContribRow[u].Right = iRight;
00227   //ets
00228         int dTotalWeight = 0;  // Zero sum of weights
00229         for (int iSrc = iLeft; iSrc <= iRight; iSrc++)
00230         {   // Calculate weights
00231             int CurWeight = int (dFScale * (m_ContribDef.Filter (dFScale * (dCenter - (double)iSrc)))*256);
00232             res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00233             dTotalWeight += CurWeight;
00234         }
00235         PLASSERT (dTotalWeight >= 0);   // An error in the filter function can cause this
00236         int UsedWeight = 0;
00237         if (dTotalWeight > 0)
00238         {   // Normalize weight of neighbouring points
00239             for (int iSrc = iLeft; iSrc < iRight; iSrc++)
00240             {   // Normalize point
00241               int CurWeight = (res->ContribRow[u].Weights[iSrc-iLeft]*256)/dTotalWeight;
00242               res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00243               UsedWeight += CurWeight;
00244             }
00245             // The last point gets everything that's left over so the sum is 
00246             // always correct.
00247             res->ContribRow[u].Weights[iRight-iLeft] = 256 - UsedWeight;
00248         }
00249    }
00250    return res;
00251 }
00252 
00253 
00254 template <class DataClass>
00255 void
00256 C2PassScale<DataClass>::ScaleRow (_RowType *pSrc, PLUINT uSrcWidth,
00257                                   _RowType *pRes, PLUINT uResWidth,
00258                                   PLUINT uRow, LineContribType *Contrib)
00259 {
00260     _DataType *pSrcRow = pSrc[uRow];
00261     _DataType *pDstRow = pRes[uRow];
00262     for (PLUINT x = 0; x < uResWidth; x++)
00263     {   // Loop through row
00264         typename DataClass::_Accumulator a;
00265         int iLeft = Contrib->ContribRow[x].Left;    // Retrieve left boundries
00266         int iRight = Contrib->ContribRow[x].Right;  // Retrieve right boundries
00267         for (int i = iLeft; i <= iRight; i++)
00268         {   // Scan between boundries
00269             // Accumulate weighted effect of each neighboring pixel
00270             a .Accumulate (Contrib->ContribRow[x].Weights[i-iLeft], pSrcRow[i]);
00271         }
00272         a .Store (pDstRow [x]);
00273     }
00274 }
00275 
00276 template <class DataClass>
00277 void
00278 C2PassScale<DataClass>::HorizScale (_RowType *pSrc, PLUINT uSrcWidth, PLUINT uSrcHeight,      
00279                                     _RowType *pDst, PLUINT uResWidth, PLUINT uResHeight)
00280 {
00281     if (uResWidth == uSrcWidth)
00282     { // No scaling required, just copy
00283       for (PLUINT u = 0; u < uResHeight; u++)
00284         memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00285 
00286     }
00287     // Allocate and calculate the contributions
00288     LineContribType * Contrib;
00289     Contrib = CalcContributions (uResWidth, uSrcWidth, 
00290                                  double(uResWidth) / double(uSrcWidth));
00291     for (PLUINT u = 0; u < uResHeight; u++)
00292     {   // Step through rows
00293         if (NULL != m_Callback)
00294         {
00295             //
00296             // Progress and report callback supplied
00297             //
00298             if (!m_Callback (PLBYTE(double(u) / double (uResHeight) * 50.0)))
00299             {
00300                 //
00301                 // User wished to abort now
00302                 //
00303                 m_bCanceled = true;
00304                 FreeContributions (Contrib);  // Free contributions structure
00305                 return;
00306             }
00307         }
00308 
00309         ScaleRow (  pSrc,
00310                     uSrcWidth,
00311                     pDst,
00312                     uResWidth,
00313                     u,
00314                     Contrib);    // Scale each row
00315     }
00316     FreeContributions (Contrib);  // Free contributions structure
00317 }
00318 
00319 
00320 template <class DataClass>
00321 void
00322 C2PassScale<DataClass>::VertScale (_RowType *pSrc, PLUINT uSrcWidth, PLUINT uSrcHeight,      
00323                                    _RowType *pDst, PLUINT uResWidth, PLUINT uResHeight)
00324 {
00325     PLUINT u;
00326 
00327     if (uSrcHeight == uResHeight)
00328     {   // No scaling required, just copy
00329       for (u = 0; u < uResHeight; u++)
00330         memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00331     }
00332     // Allocate and calculate the contributions
00333     LineContribType * Contrib = CalcContributions (uResHeight, uSrcHeight, double(uResHeight) / double(uSrcHeight));
00334     for (PLUINT y = 0; y < uResHeight; y++)
00335     {    // Loop through column
00336         if (NULL != m_Callback)
00337         {
00338             //
00339             // Progress and report callback supplied
00340             //
00341             if (!m_Callback (PLBYTE(double(y) / double (uResHeight) * 50.0) + 50))
00342             {
00343                 //
00344                 // User wished to abort now
00345                 //
00346                 m_bCanceled = true;
00347                 FreeContributions (Contrib);  // Free contributions structure
00348                 return;
00349             }
00350         }
00351         for (u = 0; u < uResWidth; u++)
00352         {   // Step through columns
00353             typename DataClass::_Accumulator a;
00354             int iLeft = Contrib->ContribRow[y].Left;    // Retrieve left boundries
00355             int iRight = Contrib->ContribRow[y].Right;  // Retrieve right boundries
00356             for (int i = iLeft; i <= iRight; i++)
00357             {   // Scan between boundries
00358                 // Accumulate weighted effect of each neighboring pixel
00359                 a.Accumulate (Contrib->ContribRow[y].Weights[i-iLeft], pSrc[i][u]);
00360             }
00361             a .Store (pDst[y][u]);
00362         }
00363 
00364     }
00365     FreeContributions (Contrib);     // Free contributions structure
00366 }
00367 
00368 
00369 /*
00370 template <class DataClass>
00371 C2PassScale<DataClass>::_RowType *
00372 C2PassScale<DataClass>::Scale (_RowType *pOrigImage, PLUINT uOrigWidth, PLUINT uOrigHeight,
00373                                _RowType *pDstImage, PLUINT uNewWidth, PLUINT uNewHeight)
00374 {
00375     // Scale source image horizontally into temporary image
00376     m_bCanceled = false;
00377     PLUINT u;
00378 
00379     // Allocate temp image
00380     _RowType *pTemp = new _RowType[uOrigHeight];
00381     for (u = 0; u < uOrigHeight; u++)
00382       pTemp[u] = new _DataType[uNewWidth];
00383 
00384     HorizScale (pOrigImage,
00385                 uOrigWidth,
00386                 uOrigHeight,
00387                 pTemp,
00388                 uNewWidth,
00389                 uOrigHeight);
00390     if (m_bCanceled)
00391     {
00392       for (u = 0; u < uOrigHeight; u++)
00393         delete [] pTemp[u];
00394       delete [] pTemp;
00395       return NULL;
00396     }
00397 
00398     // Scale temporary image vertically into result image
00399     VertScale ( pTemp,
00400                 uNewWidth,
00401                 uOrigHeight,
00402                 pDstImage,
00403                 uNewWidth,
00404                 uNewHeight);
00405     for (u = 0; u < uOrigHeight; u++)
00406       delete [] pTemp[u];
00407     delete [] pTemp;
00408     if (m_bCanceled)
00409     {
00410         return NULL;
00411     }
00412     return pDstImage;
00413 }
00414 */
00415 
00416 
00417 #endif //   _2_PASS_SCALE_H_
00418 
00419 /*
00420 /--------------------------------------------------------------------
00421 |
00422 |      $Log: pl2passscale.h,v $
00423 |      Revision 1.2  2004/10/02 22:23:32  maxx
00424 |
00425 |      These changes are needed to make vuVolume compile with gcc-3.4.
00426 |
00427 |      Revision 1.1  2004/05/21 21:02:53  maxx
00428 |      Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine.
00429 |
00430 |      Revision 1.2  2002/11/20 09:04:54  sbergner
00431 |      modified syntax for compliance with gcc 3.0.4 (onyx)
00432 |
00433 |      Revision 1.1  2002/11/13 01:59:47  mspindle
00434 |      *** empty log message ***
00435 |
00436 |      Revision 1.7  2002/02/24 13:00:45  uzadow
00437 |      Documentation update; removed buggy PLFilterRotate.
00438 |
00439 |      Revision 1.6  2001/10/06 22:03:26  uzadow
00440 |      Added PL prefix to basic data types.
00441 |
00442 |      Revision 1.5  2001/10/03 14:00:29  uzadow
00443 |      Much improved quality in FilterResizeBilinear.
00444 |
00445 |      Revision 1.4  2001/09/30 17:19:16  uzadow
00446 |      Removed lots of floating-point calculations.
00447 |
00448 |      Revision 1.3  2001/09/30 16:57:25  uzadow
00449 |      Improved speed of 2passfilter.h, code readability changes.
00450 |
00451 |      Revision 1.2  2001/09/16 20:57:17  uzadow
00452 |      Linux version name prefix changes
00453 |
00454 |      Revision 1.1  2001/09/16 19:03:23  uzadow
00455 |      Added global name prefix PL, changed most filenames.
00456 |
00457 |      Revision 1.8  2000/12/04 23:56:11  uzadow
00458 |      no message
00459 |
00460 |      Revision 1.7  2000/08/13 12:11:43  Administrator
00461 |      Added experimental DirectDraw-Support
00462 |
00463 |      Revision 1.6  2000/05/27 16:34:05  Ulrich von Zadow
00464 |      Linux compatibility changes
00465 |
00466 |      Revision 1.5  2000/01/16 20:43:15  anonymous
00467 |      Removed MFC dependencies
00468 |
00469 |      Revision 1.4  1999/12/31 17:55:08  Ulrich von Zadow
00470 |      Corrected rounding error.
00471 |
00472 |      Revision 1.3  1999/12/08 16:31:40  Ulrich von Zadow
00473 |      Unix compatibility
00474 |
00475 |      Revision 1.2  1999/10/22 21:21:34  Ulrich von Zadow
00476 |      no message
00477 |
00478 |      Revision 1.1  1999/10/21 16:05:17  Ulrich von Zadow
00479 |      Moved filters to separate directory. Added Crop, Grayscale and
00480 |      GetAlpha filters.
00481 |
00482 |      Revision 1.1  1999/10/19 21:29:55  Ulrich von Zadow
00483 |      Added filters.
00484 |
00485 |
00486 \--------------------------------------------------------------------
00487 */

Generated on Wed Dec 15 21:20:30 2004 for vuVolume by  doxygen 1.3.9.1