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

pl2passscale.h

00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: pl2passscale_8h-source.html,v 1.4 2004/09/15 15:26:24 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   typedef _DataType* _RowType;
00048   class _Accumulator {
00049   public:
00050       _Accumulator ()
00051       {
00052         val [0] = val [1] = val [2] = 0;
00053       };
00054       void Accumulate (int Weight, _DataType &value)
00055       {
00056         val [0] += (Weight * value [0]);
00057         val [1] += (Weight * value [1]);
00058         val [2] += (Weight * value [2]);
00059       };
00060       void Store (_DataType &value)
00061       {
00062         value [0] = (unsigned char) ((val [0] + 128)/256);
00063         value [1] = (unsigned char) ((val [1] + 128)/256);
00064         value [2] = (unsigned char) ((val [2] + 128)/256);
00065       };
00066       int val [3];
00067   };
00068 };
00069 
00070 class CDataRGBA_UBYTE {
00071 public:
00072   typedef unsigned char _DataType[4];
00073   typedef _DataType* _RowType;
00074   class _Accumulator {
00075   public:
00076       _Accumulator ()
00077       {
00078         val [0] = val [1] = val [2] = val [3] = 0;
00079       };
00080       void Accumulate (int dWeight, _DataType &value)
00081       {
00082         val [0] += (dWeight * (value [0]));
00083         val [1] += (dWeight * (value [1]));
00084         val [2] += (dWeight * (value [2]));
00085         val [3] += (dWeight * (value [3]));
00086       };
00087       void Store (_DataType &value)
00088       {
00089         value [0] = (unsigned char) ((val [0] + 128)/256);
00090         value [1] = (unsigned char) ((val [1] + 128)/256);
00091         value [2] = (unsigned char) ((val [2] + 128)/256);
00092         value [3] = (unsigned char) ((val [3] + 128)/256);
00093       };
00094       int val [4];
00095   };
00096 };
00097 
00098 template <class DataClass>
00099 class C2PassScale
00100 {
00101 public:
00102     typedef typename DataClass::_DataType _DataType;
00103     typedef typename DataClass::_RowType _RowType;
00104 
00105     C2PassScale (const PLContribDef& ContribDef,
00106                  ProgressAndAbortCallBack callback = NULL)
00107         : m_Callback (callback), m_ContribDef (ContribDef)
00108     {};
00109 
00110     virtual ~C2PassScale() {};
00111 
00112    _RowType * Scale (
00113         _RowType   *pOrigImage,
00114         PLUINT        uOrigWidth,
00115         PLUINT        uOrigHeight,
00116         _RowType   *pDstImage,
00117         PLUINT        uNewWidth,
00118         PLUINT        uNewHeight);
00119 
00120 private:
00121 
00122     ProgressAndAbortCallBack    m_Callback;
00123     bool                        m_bCanceled;
00124 
00125     LineContribType *AllocContributions (PLUINT uLineLength,
00126                                          PLUINT uWindowSize);
00127 
00128     void FreeContributions (LineContribType * p);
00129 
00130     LineContribType *CalcContributions (PLUINT    uLineSize,
00131                                         PLUINT    uSrcSize,
00132                                         double  dScale);
00133 
00134     void ScaleRow (_RowType           *pSrc,
00135                    PLUINT                uSrcWidth,
00136                    _RowType           *pRes,
00137                    PLUINT                uResWidth,
00138                    PLUINT                uRow,
00139                    LineContribType    *Contrib);
00140 
00141     void HorizScale (_RowType           *pSrc,
00142                      PLUINT                uSrcWidth,
00143                      PLUINT                uSrcHeight,
00144                      _RowType           *pDst,
00145                      PLUINT                uResWidth,
00146                      PLUINT                uResHeight);
00147 
00148     void VertScale (_RowType           *pSrc,
00149                     PLUINT                uSrcWidth,
00150                     PLUINT                uSrcHeight,
00151                     _RowType           *pDst,
00152                     PLUINT                uResWidth,
00153                     PLUINT                uResHeight);
00154 
00155     const PLContribDef& m_ContribDef;
00156 };
00157 
00158 template <class DataClass>
00159 LineContribType *
00160 C2PassScale<DataClass>::AllocContributions (PLUINT uLineLength, PLUINT uWindowSize)
00161 {
00162     LineContribType *res = new LineContribType;
00163         // Init structure header
00164     res->WindowSize = uWindowSize;
00165     res->LineLength = uLineLength;
00166         // Allocate list of contributions
00167     res->ContribRow = new ContributionType[uLineLength];
00168     for (PLUINT u = 0 ; u < uLineLength ; u++)
00169     {
00170         // Allocate contributions for every pixel
00171         res->ContribRow[u].Weights = new int[uWindowSize];
00172     }
00173     return res;
00174 }
00175 
00176 template <class DataClass>
00177 void
00178 C2PassScale<DataClass>::FreeContributions (LineContribType * p)
00179 {
00180     for (int u = 0; u < p->LineLength; u++)
00181     {
00182         // Free contribs for every pixel
00183         delete [] p->ContribRow[u].Weights;
00184     }
00185     delete [] p->ContribRow;    // Free list of pixels contribs
00186     delete p;                   // Free contribs header
00187 }
00188 
00189 template <class DataClass>
00190 LineContribType *
00191 C2PassScale<DataClass>::CalcContributions
00192     (PLUINT uLineSize, PLUINT uSrcSize, double dScale)
00193 {
00194     double dWidth;
00195     double dFScale = 1.0;
00196     double dFilterWidth = m_ContribDef.GetWidth();
00197 
00198     if (dScale < 1.0)
00199     {    // Minification
00200         dWidth = dFilterWidth / dScale;
00201         dFScale = dScale;
00202     }
00203     else
00204     {    // Magnification
00205         dWidth= dFilterWidth;
00206     }
00207 
00208     // Window size is the number of sampled pixels
00209     int iWindowSize = 2 * (int)ceil(dWidth) + 1;
00210 
00211     // Allocate a new line contributions strucutre
00212     LineContribType *res = AllocContributions (uLineSize, iWindowSize);
00213 
00214     for (PLUINT u = 0; u < uLineSize; u++)
00215     {   // Scan through line of contributions
00216         double dCenter = (u+0.5)/dScale-0.5;   // Reverse mapping
00217         // Find the significant edge points that affect the pixel
00218         int iLeft = max (0, (int)floor (dCenter - dWidth));
00219         int iRight = min ((int)ceil (dCenter + dWidth), int(uSrcSize) - 1);
00220 
00221         // Cut edge points to fit in filter window in case of spill-off
00222         if (iRight - iLeft + 1 > iWindowSize)
00223         {
00224             if (iLeft < (int(uSrcSize) - 1 / 2))
00225             {
00226                 iLeft++;
00227             }
00228             else
00229             {
00230                 iRight--;
00231             }
00232         }
00233   //ets+++ adjusted ileft and iright values not stored in contrib array
00234         res->ContribRow[u].Left = iLeft;
00235         res->ContribRow[u].Right = iRight;
00236   //ets
00237         int dTotalWeight = 0;  // Zero sum of weights
00238         for (int iSrc = iLeft; iSrc <= iRight; iSrc++)
00239         {   // Calculate weights
00240             int CurWeight = int (dFScale * (m_ContribDef.Filter (dFScale * (dCenter - (double)iSrc)))*256);
00241             res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00242             dTotalWeight += CurWeight;
00243         }
00244         PLASSERT (dTotalWeight >= 0);   // An error in the filter function can cause this
00245         int UsedWeight = 0;
00246         if (dTotalWeight > 0)
00247         {   // Normalize weight of neighbouring points
00248             for (int iSrc = iLeft; iSrc < iRight; iSrc++)
00249             {   // Normalize point
00250               int CurWeight = (res->ContribRow[u].Weights[iSrc-iLeft]*256)/dTotalWeight;
00251               res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00252               UsedWeight += CurWeight;
00253             }
00254             // The last point gets everything that's left over so the sum is
00255             // always correct.
00256             res->ContribRow[u].Weights[iRight-iLeft] = 256 - UsedWeight;
00257         }
00258    }
00259    return res;
00260 }
00261 
00262 
00263 template <class DataClass>
00264 void
00265 C2PassScale<DataClass>::ScaleRow (_RowType *pSrc, PLUINT uSrcWidth,
00266                                   _RowType *pRes, PLUINT uResWidth,
00267                                   PLUINT uRow, LineContribType *Contrib)
00268 {
00269     _DataType *pSrcRow = pSrc[uRow];
00270     _DataType *pDstRow = pRes[uRow];
00271     for (PLUINT x = 0; x < uResWidth; x++)
00272     {   // Loop through row
00273         typename DataClass::_Accumulator a;
00274         int iLeft = Contrib->ContribRow[x].Left;    // Retrieve left boundries
00275         int iRight = Contrib->ContribRow[x].Right;  // Retrieve right boundries
00276         for (int i = iLeft; i <= iRight; i++)
00277         {   // Scan between boundries
00278             // Accumulate weighted effect of each neighboring pixel
00279             a .Accumulate (Contrib->ContribRow[x].Weights[i-iLeft], pSrcRow[i]);
00280         }
00281         a .Store (pDstRow [x]);
00282     }
00283 }
00284 
00285 template <class DataClass>
00286 void
00287 C2PassScale<DataClass>::HorizScale (_RowType *pSrc, PLUINT uSrcWidth, PLUINT uSrcHeight,
00288                                     _RowType *pDst, PLUINT uResWidth, PLUINT uResHeight)
00289 {
00290     if (uResWidth == uSrcWidth)
00291     { // No scaling required, just copy
00292       for (PLUINT u = 0; u < uResHeight; u++)
00293         memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00294 
00295     }
00296     // Allocate and calculate the contributions
00297     LineContribType * Contrib;
00298     Contrib = CalcContributions (uResWidth, uSrcWidth,
00299                                  double(uResWidth) / double(uSrcWidth));
00300     for (PLUINT u = 0; u < uResHeight; u++)
00301     {   // Step through rows
00302         if (NULL != m_Callback)
00303         {
00304             //
00305             // Progress and report callback supplied
00306             //
00307             if (!m_Callback (PLBYTE(double(u) / double (uResHeight) * 50.0)))
00308             {
00309                 //
00310                 // User wished to abort now
00311                 //
00312                 m_bCanceled = true;
00313                 FreeContributions (Contrib);  // Free contributions structure
00314                 return;
00315             }
00316         }
00317 
00318         ScaleRow (  pSrc,
00319                     uSrcWidth,
00320                     pDst,
00321                     uResWidth,
00322                     u,
00323                     Contrib);    // Scale each row
00324     }
00325     FreeContributions (Contrib);  // Free contributions structure
00326 }
00327 
00328 
00329 template <class DataClass>
00330 void
00331 C2PassScale<DataClass>::VertScale (_RowType *pSrc, PLUINT uSrcWidth, PLUINT uSrcHeight,
00332                                    _RowType *pDst, PLUINT uResWidth, PLUINT uResHeight)
00333 {
00334     PLUINT u;
00335 
00336     if (uSrcHeight == uResHeight)
00337     {   // No scaling required, just copy
00338       for (u = 0; u < uResHeight; u++)
00339         memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00340     }
00341     // Allocate and calculate the contributions
00342     LineContribType * Contrib = CalcContributions (uResHeight, uSrcHeight, double(uResHeight) / double(uSrcHeight));
00343     for (PLUINT y = 0; y < uResHeight; y++)
00344     {    // Loop through column
00345         if (NULL != m_Callback)
00346         {
00347             //
00348             // Progress and report callback supplied
00349             //
00350             if (!m_Callback (PLBYTE(double(y) / double (uResHeight) * 50.0) + 50))
00351             {
00352                 //
00353                 // User wished to abort now
00354                 //
00355                 m_bCanceled = true;
00356                 FreeContributions (Contrib);  // Free contributions structure
00357                 return;
00358             }
00359         }
00360         for (u = 0; u < uResWidth; u++)
00361         {   // Step through columns
00362             typename DataClass::_Accumulator a;
00363             int iLeft = Contrib->ContribRow[y].Left;    // Retrieve left boundries
00364             int iRight = Contrib->ContribRow[y].Right;  // Retrieve right boundries
00365             for (int i = iLeft; i <= iRight; i++)
00366             {   // Scan between boundries
00367                 // Accumulate weighted effect of each neighboring pixel
00368                 a.Accumulate (Contrib->ContribRow[y].Weights[i-iLeft], pSrc[i][u]);
00369             }
00370             a .Store (pDst[y][u]);
00371         }
00372 
00373     }
00374     FreeContributions (Contrib);     // Free contributions structure
00375 }
00376 
00377 
00378 template <class DataClass>
00379 typename C2PassScale<DataClass>::_RowType *
00380 C2PassScale<DataClass>::Scale (_RowType *pOrigImage, PLUINT uOrigWidth, PLUINT uOrigHeight,
00381                                _RowType *pDstImage, PLUINT uNewWidth, PLUINT uNewHeight)
00382 {
00383     // Scale source image horizontally into temporary image
00384     m_bCanceled = false;
00385     PLUINT u;
00386 
00387     // Allocate temp image
00388     _RowType *pTemp = new _RowType[uOrigHeight];
00389     for (u = 0; u < uOrigHeight; u++)
00390       pTemp[u] = new _DataType[uNewWidth];
00391 
00392     HorizScale (pOrigImage,
00393                 uOrigWidth,
00394                 uOrigHeight,
00395                 pTemp,
00396                 uNewWidth,
00397                 uOrigHeight);
00398     if (m_bCanceled)
00399     {
00400       for (u = 0; u < uOrigHeight; u++)
00401         delete [] pTemp[u];
00402       delete [] pTemp;
00403       return NULL;
00404     }
00405 
00406     // Scale temporary image vertically into result image
00407     VertScale ( pTemp,
00408                 uNewWidth,
00409                 uOrigHeight,
00410                 pDstImage,
00411                 uNewWidth,
00412                 uNewHeight);
00413     for (u = 0; u < uOrigHeight; u++)
00414       delete [] pTemp[u];
00415     delete [] pTemp;
00416     if (m_bCanceled)
00417     {
00418         return NULL;
00419     }
00420     return pDstImage;
00421 }
00422 
00423 
00424 #endif //   _2_PASS_SCALE_H_
00425 
00426 /*
00427 /--------------------------------------------------------------------
00428 |
00429 |      $Log: pl2passscale_8h-source.html,v $
00429 |      Revision 1.4  2004/09/15 15:26:24  uzadow
00429 |      Linux compatibility changes, doc update.
00429 |
00430 |      Revision 1.9  2004/07/28 13:55:48  artcom
00431 |      Added 24 bpp support to plfilterresizebilinear.
00432 |
00433 |      Revision 1.8  2002/11/04 22:40:13  uzadow
00434 |      Updated for gcc 3.1
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 Mon Sep 13 16:16:40 2004 for paintlib by doxygen 1.3.2