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