Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members

pl2passscale.h

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

Generated on Sun Jun 6 13:42:21 2004 for paintlib by doxygen 1.3.2