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 <math.h>
00015
00016 #include "plcontribdefs.h"
00017 #include "plpaintlibdefs.h"
00018 #include "../minmax.h"
00019
00020 typedef struct
00021 {
00022 int *Weights;
00023 int Left,Right;
00024 } ContributionType;
00025
00026 typedef struct
00027 {
00028 ContributionType *ContribRow;
00029 int WindowSize,
00030 LineLength;
00031 } LineContribType;
00032
00033 typedef bool (*ProgressAndAbortCallBack)(PLBYTE bPercentComplete);
00034
00035 class CDataRGB_UBYTE
00036 {
00037 public:
00038 typedef unsigned char _DataType[3];
00039 class _Accumulator {
00040 public:
00041 _Accumulator ()
00042 {
00043 val [0] = val [1] = val [2] = 0;
00044 };
00045 void Accumulate (int Weight, _DataType &value)
00046 {
00047 val [0] += (Weight * value [0]);
00048 val [1] += (Weight * value [1]);
00049 val [2] += (Weight * value [2]);
00050 };
00051 void Store (_DataType &value)
00052 {
00053 value [0] = (unsigned char) ((val [0] + 128)/256);
00054 value [1] = (unsigned char) ((val [1] + 128)/256);
00055 value [2] = (unsigned char) ((val [2] + 128)/256);
00056 };
00057 int val [3];
00058 };
00059 };
00060
00061 class CDataRGBA_UBYTE {
00062 public:
00063 typedef unsigned char _DataType[4];
00064 typedef _DataType* _RowType;
00065 class _Accumulator {
00066 public:
00067 _Accumulator ()
00068 {
00069 val [0] = val [1] = val [2] = val [3] = 0;
00070 };
00071 void Accumulate (int dWeight, _DataType &value)
00072 {
00073 val [0] += (dWeight * (value [0]));
00074 val [1] += (dWeight * (value [1]));
00075 val [2] += (dWeight * (value [2]));
00076 val [3] += (dWeight * (value [3]));
00077 };
00078 void Store (_DataType &value)
00079 {
00080 value [0] = (unsigned char) ((val [0] + 128)/256);
00081 value [1] = (unsigned char) ((val [1] + 128)/256);
00082 value [2] = (unsigned char) ((val [2] + 128)/256);
00083 value [3] = (unsigned char) ((val [3] + 128)/256);
00084 };
00085 int val [4];
00086 };
00087 };
00088
00089 template <class DataClass>
00090 class C2PassScale
00091 {
00092 public:
00093 typedef typename DataClass::_DataType _DataType;
00094 typedef typename DataClass::_RowType _RowType;
00095
00096 C2PassScale (const PLContribDef& ContribDef,
00097 ProgressAndAbortCallBack callback = NULL)
00098 : m_Callback (callback), m_ContribDef (ContribDef)
00099 {};
00100
00101 virtual ~C2PassScale() {};
00102
00103 _RowType * Scale (
00104 _RowType *pOrigImage,
00105 PLUINT uOrigWidth,
00106 PLUINT uOrigHeight,
00107 _RowType *pDstImage,
00108 PLUINT uNewWidth,
00109 PLUINT uNewHeight);
00110
00111 private:
00112
00113 ProgressAndAbortCallBack m_Callback;
00114 bool m_bCanceled;
00115
00116 LineContribType *AllocContributions (PLUINT uLineLength,
00117 PLUINT uWindowSize);
00118
00119 void FreeContributions (LineContribType * p);
00120
00121 LineContribType *CalcContributions (PLUINT uLineSize,
00122 PLUINT uSrcSize,
00123 double dScale);
00124
00125 void ScaleRow (_RowType *pSrc,
00126 PLUINT uSrcWidth,
00127 _RowType *pRes,
00128 PLUINT uResWidth,
00129 PLUINT uRow,
00130 LineContribType *Contrib);
00131
00132 void HorizScale (_RowType *pSrc,
00133 PLUINT uSrcWidth,
00134 PLUINT uSrcHeight,
00135 _RowType *pDst,
00136 PLUINT uResWidth,
00137 PLUINT uResHeight);
00138
00139 void VertScale (_RowType *pSrc,
00140 PLUINT uSrcWidth,
00141 PLUINT uSrcHeight,
00142 _RowType *pDst,
00143 PLUINT uResWidth,
00144 PLUINT uResHeight);
00145
00146 const PLContribDef& m_ContribDef;
00147 };
00148
00149 template <class DataClass>
00150 LineContribType *
00151 C2PassScale<DataClass>::AllocContributions (PLUINT uLineLength, PLUINT uWindowSize)
00152 {
00153 LineContribType *res = new LineContribType;
00154
00155 res->WindowSize = uWindowSize;
00156 res->LineLength = uLineLength;
00157
00158 res->ContribRow = new ContributionType[uLineLength];
00159 for (PLUINT u = 0 ; u < uLineLength ; u++)
00160 {
00161
00162 res->ContribRow[u].Weights = new int[uWindowSize];
00163 }
00164 return res;
00165 }
00166
00167 template <class DataClass>
00168 void
00169 C2PassScale<DataClass>::FreeContributions (LineContribType * p)
00170 {
00171 for (int u = 0; u < p->LineLength; u++)
00172 {
00173
00174 delete [] p->ContribRow[u].Weights;
00175 }
00176 delete [] p->ContribRow;
00177 delete p;
00178 }
00179
00180 template <class DataClass>
00181 LineContribType *
00182 C2PassScale<DataClass>::CalcContributions
00183 (PLUINT uLineSize, PLUINT uSrcSize, double dScale)
00184 {
00185 double dWidth;
00186 double dFScale = 1.0;
00187 double dFilterWidth = m_ContribDef.GetWidth();
00188
00189 if (dScale < 1.0)
00190 {
00191 dWidth = dFilterWidth / dScale;
00192 dFScale = dScale;
00193 }
00194 else
00195 {
00196 dWidth= dFilterWidth;
00197 }
00198
00199
00200 int iWindowSize = 2 * (int)ceil(dWidth) + 1;
00201
00202
00203 LineContribType *res = AllocContributions (uLineSize, iWindowSize);
00204
00205 for (PLUINT u = 0; u < uLineSize; u++)
00206 {
00207 double dCenter = (u+0.5)/dScale-0.5;
00208
00209 int iLeft = max (0, (int)floor (dCenter - dWidth));
00210 int iRight = min ((int)ceil (dCenter + dWidth), int(uSrcSize) - 1);
00211
00212
00213 if (iRight - iLeft + 1 > iWindowSize)
00214 {
00215 if (iLeft < (int(uSrcSize) - 1 / 2))
00216 {
00217 iLeft++;
00218 }
00219 else
00220 {
00221 iRight--;
00222 }
00223 }
00224
00225 res->ContribRow[u].Left = iLeft;
00226 res->ContribRow[u].Right = iRight;
00227
00228 int dTotalWeight = 0;
00229 for (int iSrc = iLeft; iSrc <= iRight; iSrc++)
00230 {
00231 int CurWeight = int (dFScale * (m_ContribDef.Filter (dFScale * (dCenter - (double)iSrc)))*256);
00232 res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00233 dTotalWeight += CurWeight;
00234 }
00235 PLASSERT (dTotalWeight >= 0);
00236 int UsedWeight = 0;
00237 if (dTotalWeight > 0)
00238 {
00239 for (int iSrc = iLeft; iSrc < iRight; iSrc++)
00240 {
00241 int CurWeight = (res->ContribRow[u].Weights[iSrc-iLeft]*256)/dTotalWeight;
00242 res->ContribRow[u].Weights[iSrc-iLeft] = CurWeight;
00243 UsedWeight += CurWeight;
00244 }
00245
00246
00247 res->ContribRow[u].Weights[iRight-iLeft] = 256 - UsedWeight;
00248 }
00249 }
00250 return res;
00251 }
00252
00253
00254 template <class DataClass>
00255 void
00256 C2PassScale<DataClass>::ScaleRow (_RowType *pSrc, PLUINT uSrcWidth,
00257 _RowType *pRes, PLUINT uResWidth,
00258 PLUINT uRow, LineContribType *Contrib)
00259 {
00260 _DataType *pSrcRow = pSrc[uRow];
00261 _DataType *pDstRow = pRes[uRow];
00262 for (PLUINT x = 0; x < uResWidth; x++)
00263 {
00264 typename DataClass::_Accumulator a;
00265 int iLeft = Contrib->ContribRow[x].Left;
00266 int iRight = Contrib->ContribRow[x].Right;
00267 for (int i = iLeft; i <= iRight; i++)
00268 {
00269
00270 a .Accumulate (Contrib->ContribRow[x].Weights[i-iLeft], pSrcRow[i]);
00271 }
00272 a .Store (pDstRow [x]);
00273 }
00274 }
00275
00276 template <class DataClass>
00277 void
00278 C2PassScale<DataClass>::HorizScale (_RowType *pSrc, PLUINT uSrcWidth, PLUINT uSrcHeight,
00279 _RowType *pDst, PLUINT uResWidth, PLUINT uResHeight)
00280 {
00281 if (uResWidth == uSrcWidth)
00282 {
00283 for (PLUINT u = 0; u < uResHeight; u++)
00284 memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00285
00286 }
00287
00288 LineContribType * Contrib;
00289 Contrib = CalcContributions (uResWidth, uSrcWidth,
00290 double(uResWidth) / double(uSrcWidth));
00291 for (PLUINT u = 0; u < uResHeight; u++)
00292 {
00293 if (NULL != m_Callback)
00294 {
00295
00296
00297
00298 if (!m_Callback (PLBYTE(double(u) / double (uResHeight) * 50.0)))
00299 {
00300
00301
00302
00303 m_bCanceled = true;
00304 FreeContributions (Contrib);
00305 return;
00306 }
00307 }
00308
00309 ScaleRow ( pSrc,
00310 uSrcWidth,
00311 pDst,
00312 uResWidth,
00313 u,
00314 Contrib);
00315 }
00316 FreeContributions (Contrib);
00317 }
00318
00319
00320 template <class DataClass>
00321 void
00322 C2PassScale<DataClass>::VertScale (_RowType *pSrc, PLUINT uSrcWidth, PLUINT uSrcHeight,
00323 _RowType *pDst, PLUINT uResWidth, PLUINT uResHeight)
00324 {
00325 PLUINT u;
00326
00327 if (uSrcHeight == uResHeight)
00328 {
00329 for (u = 0; u < uResHeight; u++)
00330 memcpy (pDst[u], pSrc[u], sizeof (_DataType) * uSrcWidth);
00331 }
00332
00333 LineContribType * Contrib = CalcContributions (uResHeight, uSrcHeight, double(uResHeight) / double(uSrcHeight));
00334 for (PLUINT y = 0; y < uResHeight; y++)
00335 {
00336 if (NULL != m_Callback)
00337 {
00338
00339
00340
00341 if (!m_Callback (PLBYTE(double(y) / double (uResHeight) * 50.0) + 50))
00342 {
00343
00344
00345
00346 m_bCanceled = true;
00347 FreeContributions (Contrib);
00348 return;
00349 }
00350 }
00351 for (u = 0; u < uResWidth; u++)
00352 {
00353 typename DataClass::_Accumulator a;
00354 int iLeft = Contrib->ContribRow[y].Left;
00355 int iRight = Contrib->ContribRow[y].Right;
00356 for (int i = iLeft; i <= iRight; i++)
00357 {
00358
00359 a.Accumulate (Contrib->ContribRow[y].Weights[i-iLeft], pSrc[i][u]);
00360 }
00361 a .Store (pDst[y][u]);
00362 }
00363
00364 }
00365 FreeContributions (Contrib);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 #endif // _2_PASS_SCALE_H_
00418
00419
00420
00421
00422
00423
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
00484
00485
00486
00487