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
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483