00001
00002
00003
00004
00005
00006
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
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;
00031 int Left,Right;
00032 } ContributionType;
00033
00034 typedef struct
00035 {
00036 ContributionType *ContribRow;
00037 int WindowSize,
00038 LineLength;
00039 } LineContribType;
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
00163 res->WindowSize = uWindowSize;
00164 res->LineLength = uLineLength;
00165
00166 res->ContribRow = new ContributionType[uLineLength];
00167 for (PLUINT u = 0 ; u < uLineLength ; u++)
00168 {
00169
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
00182 delete [] p->ContribRow[u].Weights;
00183 }
00184 delete [] p->ContribRow;
00185 delete p;
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 {
00199 dWidth = dFilterWidth / dScale;
00200 dFScale = dScale;
00201 }
00202 else
00203 {
00204 dWidth= dFilterWidth;
00205 }
00206
00207
00208 int iWindowSize = 2 * (int)ceil(dWidth) + 1;
00209
00210
00211 LineContribType *res = AllocContributions (uLineSize, iWindowSize);
00212
00213 for (PLUINT u = 0; u < uLineSize; u++)
00214 {
00215 double dCenter = (u+0.5)/dScale-0.5;
00216
00217 int iLeft = max (0, (int)floor (dCenter - dWidth));
00218 int iRight = min ((int)ceil (dCenter + dWidth), int(uSrcSize) - 1);
00219
00220
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
00233 res->ContribRow[u].Left = iLeft;
00234 res->ContribRow[u].Right = iRight;
00235
00236 int dTotalWeight = 0;
00237 for (int iSrc = iLeft; iSrc <= iRight; iSrc++)
00238 {
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);
00244 int UsedWeight = 0;
00245 if (dTotalWeight > 0)
00246 {
00247 for (int iSrc = iLeft; iSrc < iRight; iSrc++)
00248 {
00249 int CurWeight = (res->ContribRow[u].Weights[iSrc-iLeft]*256)/dTotalWeight;
00250 res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00251 UsedWeight += CurWeight;
00252 }
00253
00254
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 {
00272 typename DataClass::_Accumulator a;
00273 int iLeft = Contrib->ContribRow[x].Left;
00274 int iRight = Contrib->ContribRow[x].Right;
00275 for (int i = iLeft; i <= iRight; i++)
00276 {
00277
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 {
00291 for (PLUINT u = 0; u < uResHeight; u++)
00292 memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00293
00294 }
00295
00296 LineContribType * Contrib;
00297 Contrib = CalcContributions (uResWidth, uSrcWidth,
00298 double(uResWidth) / double(uSrcWidth));
00299 for (PLUINT u = 0; u < uResHeight; u++)
00300 {
00301 if (NULL != m_Callback)
00302 {
00303
00304
00305
00306 if (!m_Callback (PLBYTE(double(u) / double (uResHeight) * 50.0)))
00307 {
00308
00309
00310
00311 m_bCanceled = true;
00312 FreeContributions (Contrib);
00313 return;
00314 }
00315 }
00316
00317 ScaleRow ( pSrc,
00318 uSrcWidth,
00319 pDst,
00320 uResWidth,
00321 u,
00322 Contrib);
00323 }
00324 FreeContributions (Contrib);
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 {
00337 for (u = 0; u < uResHeight; u++)
00338 memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00339 }
00340
00341 LineContribType * Contrib = CalcContributions (uResHeight, uSrcHeight, double(uResHeight) / double(uSrcHeight));
00342 for (PLUINT y = 0; y < uResHeight; y++)
00343 {
00344 if (NULL != m_Callback)
00345 {
00346
00347
00348
00349 if (!m_Callback (PLBYTE(double(y) / double (uResHeight) * 50.0) + 50))
00350 {
00351
00352
00353
00354 m_bCanceled = true;
00355 FreeContributions (Contrib);
00356 return;
00357 }
00358 }
00359 for (u = 0; u < uResWidth; u++)
00360 {
00361 typename DataClass::_Accumulator a;
00362 int iLeft = Contrib->ContribRow[y].Left;
00363 int iRight = Contrib->ContribRow[y].Right;
00364 for (int i = iLeft; i <= iRight; i++)
00365 {
00366
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);
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
00383 m_bCanceled = false;
00384 PLUINT u;
00385
00386
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
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