00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "pgdraw.h"
00030
00031 #include <cstdio>
00032 #include <cstring>
00033 #include <cstdlib>
00034 #include <cmath>
00035
00036 #if ! defined( macintosh ) && ! defined( __MWERKS__ )
00037
00038
00039
00040
00041 #endif // not defined macintosh nor __MWERKS__
00042
00043 #define sign(x) ((x)>0 ? 1:-1)
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 inline void LockSurface(SDL_Surface* s) {
00057 if ( SDL_MUSTLOCK(s) ) {
00058 if ( SDL_LockSurface(s) < 0 )
00059 return ;
00060 }
00061 }
00062
00063 inline void UnlockSurface(SDL_Surface* s) {
00064 if ( SDL_MUSTLOCK(s) ) {
00065 SDL_UnlockSurface(s);
00066 return ;
00067 }
00068 }
00069
00070 template < class ST, class DT >
00071 inline void StretchTemplateLUT(int x1, int x2, int y1, int y2, int yr, int yw, ST src_pixels, DT dst_pixels, Uint32* lut) {
00072 int dx, dy, e, d, dx2;
00073
00074 register Uint32 p;
00075
00076 dx = (x2 - x1);
00077 dy = (y2 - y1);
00078
00079 dy <<= 1;
00080 e = dy - dx;
00081 dx2 = dx << 1;
00082
00083 for (d = 0; d < dx; d++) {
00084 p = lut[*src_pixels];
00085 *dst_pixels++ = p;
00086
00087 while (e >= 0) {
00088 src_pixels ++;
00089 e -= dx2;
00090 }
00091
00092 e += dy;
00093 }
00094 }
00095
00096 template < class ST, class DT >
00097 inline void StretchTemplate(int x1, int x2, int y1, int y2, int yr, int yw, ST src_pixels, DT dst_pixels) {
00098 int dx, dy, e, d, dx2;
00099
00100
00101
00102
00103
00104 dx = (x2 - x1);
00105 dy = (y2 - y1);
00106
00107 dy <<= 1;
00108 e = dy - dx;
00109 dx2 = dx << 1;
00110
00111 for (d = 0; d < dx; d++) {
00112
00113
00114
00115 *dst_pixels++ = *((DT)src_pixels);
00116
00117
00118
00119
00120
00121 while (e >= 0) {
00122 src_pixels ++;
00123 e -= dx2;
00124 }
00125
00126 e += dy;
00127 }
00128 }
00129
00130 template < class ST, class DT >
00131 inline void RectStretchTemplate(SDL_Surface* src_surface, ST src, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, DT dst, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI) {
00132 int dx, dy, e, d, dx2;
00133 int sx, sy;
00134 dx = abs((int)(yd2 - yd1));
00135 dy = abs((int)(ys2 - ys1));
00136 sx = sign(yd2 - yd1);
00137 sy = sign(ys2 - ys1);
00138 e = (dy << 1)-dx;
00139 dx2 = dx << 1;
00140 dy <<= 1;
00141
00142 Uint16 src_pitch = src_surface->pitch;
00143 Uint16 dst_pitch = dst_surface->pitch;
00144
00145 int src_bpp = src_surface->format->BytesPerPixel;
00146 int dst_bpp = dst_surface->format->BytesPerPixel;
00147
00148 SDL_Rect clip;
00149 SDL_GetClipRect(dst_surface, &clip);
00150
00151 register long src_pixels = ((long)src + ys1 * src_pitch + xs1 * src_bpp);
00152 register long dst_pixels = ((long)dst + yd1 * dst_pitch + xd1 * dst_bpp);
00153 register Uint32* lut = lutVOI;
00154
00155 if (lut == NULL) {
00156 for (d = 0; (d <= dx) && (yd1 < dst_surface->h) && (ys1 < src_surface->h); d++) {
00157
00158 if(yd1 < clip.y || yd1 > clip.y+clip.h-1) {
00159 continue;
00160 }
00161
00162 StretchTemplate(xd1, xd2, xs1, xs2, ys1, yd1, (ST)src_pixels, (DT)dst_pixels);
00163
00164 while (e >= 0) {
00165 src_pixels += src_pitch;
00166 ys1++;
00167 e -= dx2;
00168 }
00169 dst_pixels += dst_pitch;
00170 yd1++;
00171 e += dy;
00172 }
00173 } else {
00174 for (d = 0; (d <= dx) && (yd1 < dst_surface->h) && (ys1 < src_surface->h); d++) {
00175 StretchTemplateLUT(xd1, xd2, xs1, xs2, ys1, yd1, (ST)src_pixels, (DT)dst_pixels, lut);
00176
00177 while (e >= 0) {
00178 src_pixels += src_pitch;
00179 ys1++;
00180 e -= dx2;
00181 }
00182 dst_pixels += dst_pitch;
00183 yd1++;
00184 e += dy;
00185 }
00186 }
00187
00188 }
00189
00190 inline void StretchTemplate24to32(int x1, int x2, int y1, int y2, int yr, int yw, Uint8* src_pixels, Uint32* dst_pixels, Uint32* lut) {
00191 int dx, dy, e, d, dx2;
00192
00193 register Uint8 pr;
00194 register Uint8 pg;
00195 register Uint8 pb;
00196 register Uint32 r;
00197
00198 dx = (x2 - x1);
00199 dy = (y2 - y1);
00200
00201 dy <<= 1;
00202 e = dy - dx;
00203 dx2 = dx << 1;
00204
00205 for (d = 0; d < dx; d++) {
00206 pr = lut[*(src_pixels)];
00207 pg = lut[*(src_pixels+1)];
00208 pb = lut[*(src_pixels+2)];
00209
00210 r = pr << 16 | pg << 8 | pb;
00211 *dst_pixels++ = r;
00212
00213 while (e >= 0) {
00214 src_pixels+=3;
00215 e -= dx2;
00216 }
00217
00218 e += dy;
00219 }
00220 }
00221
00222 inline void RectStretch24to32(SDL_Surface* src_surface, Uint8* src, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, Uint32* dst, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI) {
00223 int dx, dy, e, d, dx2;
00224 int sx, sy;
00225 dx = abs((int)(yd2 - yd1));
00226 dy = abs((int)(ys2 - ys1));
00227 sx = sign(yd2 - yd1);
00228 sy = sign(ys2 - ys1);
00229 e = (dy << 1)-dx;
00230 dx2 = dx << 1;
00231 dy <<= 1;
00232
00233 Uint16 src_pitch = src_surface->pitch;
00234 Uint16 dst_pitch = dst_surface->pitch;
00235
00236 int src_bpp = src_surface->format->BytesPerPixel;
00237 int dst_bpp = dst_surface->format->BytesPerPixel;
00238
00239 SDL_Rect clip;
00240 SDL_GetClipRect(dst_surface, &clip);
00241
00242 register long src_pixels = ((long)src + ys1 * src_pitch + xs1 * src_bpp);
00243 register long dst_pixels = ((long)dst + yd1 * dst_pitch + xd1 * dst_bpp);
00244 register Uint32* lut = lutVOI;
00245
00246 for (d = 0; (d <= dx) && (yd1 < dst_surface->h) && (ys1 < src_surface->h); d++) {
00247 StretchTemplate24to32(xd1, xd2, xs1, xs2, ys1, yd1, (Uint8*)src_pixels, (Uint32*)dst_pixels, lut);
00248
00249 while (e >= 0) {
00250 src_pixels += src_pitch;
00251 ys1++;
00252 e -= dx2;
00253 }
00254 dst_pixels += dst_pitch;
00255 yd1++;
00256 e += dy;
00257 }
00258
00259 }
00260
00261 void PG_Draw::RectStretch(SDL_Surface* src_surface, int xs1, int ys1, int xs2, int ys2, SDL_Surface* dst_surface, int xd1, int yd1, int xd2, int yd2, Uint32* lutVOI) {
00262 int src_bpp = src_surface->format->BytesPerPixel;
00263 int dst_bpp = dst_surface->format->BytesPerPixel;
00264
00265 switch (dst_bpp) {
00266
00267 case 1:
00268 switch (src_bpp) {
00269
00270 case 1:
00271 if(src_surface->format->palette != NULL) {
00272 SDL_SetColors(dst_surface, src_surface->format->palette->colors, 0, 256);
00273 }
00274 RectStretchTemplate(src_surface, (Uint8*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint8*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00275 break;
00276
00277 case 2:
00278 RectStretchTemplate(src_surface, (Uint16*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint8*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00279 break;
00280 }
00281 break;
00282
00283 case 2:
00284 switch (src_bpp) {
00285
00286 case 2:
00287 RectStretchTemplate(src_surface, (Uint16*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint16*)dst_surface->pixels, xd1, yd1, xd2, yd2, NULL);
00288 break;
00289 }
00290 break;
00291
00292 case 4:
00293 switch (src_bpp) {
00294
00295 case 1:
00296 RectStretchTemplate(src_surface, (Uint8*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00297 break;
00298
00299 case 3:
00300 RectStretch24to32(src_surface, (Uint8*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00301 break;
00302
00303 case 2:
00304 RectStretchTemplate(src_surface, (Uint16*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, lutVOI);
00305 break;
00306
00307 case 4:
00308 RectStretchTemplate(src_surface, (Uint32*)src_surface->pixels, xs1, ys1, xs2, ys2, dst_surface, (Uint32*)dst_surface->pixels, xd1, yd1, xd2, yd2, NULL);
00309 break;
00310
00311 }
00312 break;
00313 }
00314
00315
00316
00317 }
00318
00319
00320 typedef Uint8 Pixel;
00321
00322 #define WHITE_PIXEL (255)
00323 #define BLACK_PIXEL (0)
00324
00325
00326 inline SDL_Surface* new_image(int xsize, int ysize)
00327 {
00328 return SDL_CreateRGBSurface(
00329 SDL_SWSURFACE,
00330 xsize,
00331 ysize,
00332 8,
00333 0, 0, 0, 0);
00334 }
00335
00336 inline void free_image(SDL_Surface* image) {
00337 SDL_FreeSurface(image);
00338 }
00339
00340 inline void get_row(Pixel* row, SDL_Surface* image, int y) {
00341 memcpy(row, (Uint8*)image->pixels + (y * image->pitch), (sizeof(Pixel) * image->w));
00342 }
00343
00344 inline void get_column(Pixel* column, SDL_Surface* image, int x) {
00345 register int i, d;
00346 register Pixel *p;
00347 d = image->pitch;
00348
00349 register Uint8* pixels = (Uint8*)image->pixels + x;
00350
00351 for (i = image->h, p = pixels; i-- > 0; p += d) {
00352 *column++ = *p;
00353 }
00354 }
00355
00356
00357
00358
00359
00360 #define filter_support (1.0)
00361
00362 inline double filter(double t) {
00363
00364 if (t < 0.0)
00365 t = -t;
00366 if (t < 1.0)
00367 return ((2.0 * t - 3.0) * t * t + 1.0);
00368 return (0.0);
00369 }
00370
00371 #define box_support (0.5)
00372
00373 inline double box_filter(double t) {
00374 if ((t > -0.5) && (t <= 0.5))
00375 return (1.0);
00376 return (0.0);
00377 }
00378
00379 #define triangle_support (1.0)
00380
00381 inline double triangle_filter(double t) {
00382 if (t < 0.0)
00383 t = -t;
00384 if (t < 1.0)
00385 return (1.0 - t);
00386 return (0.0);
00387 }
00388
00389 #define bell_support (1.5)
00390
00391 inline double bell_filter(double t)
00392 {
00393 if (t < 0)
00394 t = -t;
00395 if (t < .5)
00396 return (.75 - (t * t));
00397 if (t < 1.5) {
00398 t = (t - 1.5);
00399 return (.5 * (t * t));
00400 }
00401 return (0.0);
00402 }
00403
00404 #define B_spline_support (2.0)
00405
00406 inline double B_spline_filter(double t)
00407 {
00408 static double tt;
00409
00410 if (t < 0)
00411 t = -t;
00412 if (t < 1) {
00413 tt = t * t;
00414 return ((.5 * tt * t) - tt + (2.0 / 3.0));
00415 } else if (t < 2) {
00416 t = 2 - t;
00417 return ((1.0 / 6.0) * (t * t * t));
00418 }
00419 return (0.0);
00420 }
00421
00422 inline double sinc(double x) {
00423 x *= M_PI;
00424
00425 if (x != 0)
00426 return (sin(x) / x);
00427 return (1.0);
00428 }
00429
00430 #define Lanczos3_support (3.0)
00431
00432 inline double Lanczos3_filter(double t) {
00433 if (t < 0)
00434 t = -t;
00435 if (t < 3.0)
00436 return (sinc(t) * sinc(t / 3.0));
00437 return (0.0);
00438 }
00439
00440 #define Mitchell_support (2.0)
00441
00442 #define B (1.0 / 3.0)
00443 #define C (1.0 / 3.0)
00444
00445 inline double Mitchell_filter(double t) {
00446 double tt;
00447
00448 tt = t * t;
00449 if (t < 0)
00450 t = -t;
00451 if (t < 1.0) {
00452 t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
00453 + (( -18.0 + 12.0 * B + 6.0 * C) * tt)
00454 + (6.0 - 2 * B));
00455 return (t / 6.0);
00456 } else if (t < 2.0) {
00457 t = ((( -1.0 * B - 6.0 * C) * (t * tt))
00458 + ((6.0 * B + 30.0 * C) * tt)
00459 + (( -12.0 * B - 48.0 * C) * t)
00460 + (8.0 * B + 24 * C));
00461 return (t / 6.0);
00462 }
00463 return (0.0);
00464 }
00465
00466
00467
00468 typedef struct {
00469 int pixel;
00470 double weight;
00471 }
00472 CONTRIB;
00473
00474 typedef struct {
00475 int n;
00476 CONTRIB *p;
00477 }
00478 CLIST;
00479
00480 CLIST *contrib;
00481 static double filterLUT[4001];
00482
00483 void PG_Draw::CreateFilterLUT() {
00484 static bool bCreated = false;
00485 double v;
00486
00487 if(bCreated) {
00488 return;
00489 }
00490
00491 for (int i = -2000; i < 2001; i++) {
00492 v = (double)i / 1000.0;
00493 filterLUT[i + 2000] = B_spline_filter(v);
00494 }
00495
00496 bCreated = true;
00497 }
00498
00499 typedef double (*filterfunc)(double);
00500
00501
00502 #define CLAMP(v,l,h) ((Uint32)v & 0xFF)
00503 #define FLTIDX(v) (int)(v*1000 + 2000)
00504
00505 void zoom(SDL_Surface* dst, SDL_Surface* src, double fwidth) {
00506 SDL_Surface *tmp;
00507 double xscale, yscale;
00508 register int i, j, k;
00509 double n;
00510 double center, left, right;
00511 double width, fscale, weight;
00512 Pixel *raster;
00513 register Uint8* tmp_pixels;
00514 int tmp_pitch;
00515 register double tmp_w, tmp_h, src_w;
00516
00517 if (!src || !dst)
00518 return;
00519
00520 if (!src->w || !src->h || !dst->w || !dst->h)
00521 return;
00522
00523 LockSurface(src);
00524 LockSurface(dst);
00525
00526
00527 tmp = new_image(dst->w, src->h);
00528 LockSurface(tmp);
00529
00530 xscale = (double) dst->w / (double) src->w;
00531 yscale = (double) dst->h / (double) src->h;
00532
00533
00534 contrib = (CLIST *)calloc(dst->w, sizeof(CLIST));
00535 src_w = (double)src->w;
00536 if (xscale < 1.0) {
00537 width = (double)(fwidth / xscale);
00538 fscale = (double)(1.0 / xscale);
00539 tmp_w = (double)dst->w;
00540 for (i = 0; i < tmp_w; ++i) {
00541 contrib[i].n = 0;
00542 contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
00543 sizeof(CONTRIB));
00544 center = i / xscale;
00545 left = ceil(center - width);
00546 right = floor(center + width);
00547 for (j = (int)left; j <= (int)right; ++j) {
00548 weight = center - j;
00549
00550 weight = filterLUT[FLTIDX(weight / fscale)] / fscale;
00551 if (j < 0) {
00552 n = -j;
00553 } else if (j >= src_w) {
00554 n = (src_w - j) + src_w - 1;
00555 } else {
00556 n = j;
00557 }
00558 k = contrib[i].n++;
00559 contrib[i].p[k].pixel = (int)n;
00560 contrib[i].p[k].weight = weight;
00561 }
00562 }
00563 } else {
00564 tmp_w = dst->w;
00565 for (i = 0; i < tmp_w; ++i) {
00566 contrib[i].n = 0;
00567 contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
00568 sizeof(CONTRIB));
00569 center = i / xscale;
00570 left = ceil(center - fwidth);
00571 right = floor(center + fwidth);
00572 for (j = (int)left; j <= (int)right; ++j) {
00573 weight = center - j;
00574
00575 weight = filterLUT[FLTIDX(weight)];
00576 if (j < 0) {
00577 n = -j;
00578 } else if (j >= src_w) {
00579 n = (src_w - j) + src_w - 1;
00580 } else {
00581 n = j;
00582 }
00583 k = contrib[i].n++;
00584 contrib[i].p[k].pixel = (int)n;
00585 contrib[i].p[k].weight = weight;
00586 }
00587 }
00588 }
00589
00590
00591 tmp_pitch = tmp->pitch;
00592 tmp_pixels = (Uint8*)tmp->pixels;
00593
00594 raster = (Pixel *)calloc(src->w, sizeof(Pixel));
00595 tmp_h = tmp->h;
00596 tmp_w = tmp->w;
00597
00598 int offset = (int)(tmp_pitch - tmp_w);
00599
00600 for (k = 0; k < tmp_h; ++k) {
00601
00602 memcpy(raster, (Uint8*)src->pixels + (k * src->pitch), (sizeof(Pixel) * src->w));
00603 for (i = 0; i < tmp_w; ++i) {
00604 weight = 0.0;
00605 for (j = 0; j < contrib[i].n; ++j) {
00606 weight += raster[contrib[i].p[j].pixel]
00607 * contrib[i].p[j].weight;
00608 }
00609 *((Uint8 *)tmp_pixels++) = (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);
00610 }
00611
00612 tmp_pixels += offset;
00613 }
00614
00615 free(raster);
00616
00617
00618 for (i = 0; i < tmp_w; ++i) {
00619 free(contrib[i].p);
00620 }
00621 free(contrib);
00622
00623
00624 contrib = (CLIST *)calloc(dst->h, sizeof(CLIST));
00625 if (yscale < 1.0) {
00626 width = fwidth / yscale;
00627 fscale = 1.0 / yscale;
00628 tmp_h = dst->h;
00629 for (i = 0; i < tmp_h; ++i) {
00630 contrib[i].n = 0;
00631 contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
00632 sizeof(CONTRIB));
00633 center = i / yscale;
00634 left = ceil(center - width);
00635 right = floor(center + width);
00636 for (j = (int)left; j <= (int)right; ++j) {
00637 weight = center - j;
00638
00639 weight = filterLUT[FLTIDX(weight / fscale)] / fscale;
00640 if (j < 0) {
00641 n = -j;
00642 } else if (j >= tmp->h) {
00643 n = (tmp->h - j) + tmp->h - 1;
00644 } else {
00645 n = j;
00646 }
00647 k = contrib[i].n++;
00648 contrib[i].p[k].pixel = (int)n;
00649 contrib[i].p[k].weight = weight;
00650 }
00651 }
00652 } else {
00653 tmp_h = dst->h;
00654 for (i = 0; i < tmp_h; ++i) {
00655 contrib[i].n = 0;
00656 contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
00657 sizeof(CONTRIB));
00658 center = i / yscale;
00659 left = ceil(center - fwidth);
00660 right = floor(center + fwidth);
00661 for (j = (int)left; j <= (int)right; ++j) {
00662 weight = center - j;
00663
00664 weight = filterLUT[FLTIDX(weight)];
00665 if (j < 0) {
00666 n = -j;
00667 } else if (j >= tmp->h) {
00668 n = (tmp->h - j) + tmp->h - 1;
00669 } else {
00670 n = j;
00671 }
00672 k = contrib[i].n++;
00673 contrib[i].p[k].pixel = (int)n;
00674 contrib[i].p[k].weight = weight;
00675 }
00676 }
00677 }
00678
00679
00680 tmp_pitch = dst->pitch;
00681 tmp_pixels = (Uint8*)dst->pixels;
00682
00683 raster = (Pixel *)calloc(tmp->h, sizeof(Pixel));
00684 tmp_w = dst->w;
00685 tmp_h = dst->h;
00686
00687 offset = 1 - (int)(tmp_w * tmp_pitch);
00688
00689 for (k = 0; k < tmp_w; ++k) {
00690 get_column(raster, tmp, k);
00691 for (i = 0; i < tmp_h; ++i) {
00692 weight = 0.0;
00693 for (j = 0; j < contrib[i].n; ++j) {
00694 weight += raster[contrib[i].p[j].pixel]
00695 * contrib[i].p[j].weight;
00696 }
00697 *(((Uint8 *)tmp_pixels) + i*tmp_pitch + k) = (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);
00698 }
00699
00700 }
00701
00702 free(raster);
00703
00704
00705 for (i = 0; i < tmp_h; ++i) {
00706 free(contrib[i].p);
00707 }
00708 free(contrib);
00709
00710 UnlockSurface(src);
00711 UnlockSurface(dst);
00712 UnlockSurface(tmp);
00713 free_image(tmp);
00714 }
00715
00716
00717 void PG_Draw::PG_SmoothFast(SDL_Surface* src, SDL_Surface* dst) {
00718 zoom(dst, src, B_spline_support);
00719 }
00720
00721 SDL_Surface* PG_CopyRect(SDL_Surface* s, int x, int y, int w, int h) {
00722 SDL_Surface* image = new_image(w, h);
00723
00724 for (int i = 0; i < h; i++) {
00725 memcpy(
00726 (Uint8*)image->pixels + i*image->pitch,
00727 (Uint8*)s->pixels + (y + i)*s->pitch + x,
00728 w);
00729 }
00730
00731 return image;
00732 }
00733
00734
00735 #define SCALE 1024
00736 #define HALFSCALE 512
00737
00738
00739
00740
00741
00742 void PG_Draw::InterpolatePixel(SDL_Surface* src, SDL_Surface* dest) {
00743
00744 register Uint16 x;
00745 register Uint16 y;
00746 register const Uint8 *p;
00747 register Uint8 *q;
00748 Uint8 const *sp = NULL;
00749 Uint8 const *fp;
00750 Uint8 *sq;
00751
00752 if (!src || !dest)
00753 return;
00754
00755 if (!src->w || !src->h || !dest->w || !dest->h)
00756 return;
00757
00758 int Dest_X = dest->w;
00759 int Dest_Y = dest->h;
00760 int Src_X = src->w;
00761 int Src_Y = src->h;
00762
00763 const unsigned long sxscale = (unsigned long)(((double)Dest_X / (double)Src_X) * SCALE);
00764 const unsigned long syscale = (unsigned long)(((double)Dest_Y / (double)Src_Y) * SCALE);
00765
00766 Uint8 *xtemp = new Uint8[Src_X];
00767 signed long *xvalue = new signed long[Src_X];
00768
00769 fp = (Uint8*)src->pixels;
00770 sq = (Uint8*)dest->pixels;
00771 for (x = 0; x < Src_X; x++)
00772 xvalue[x] = HALFSCALE;
00773
00774 register unsigned long yfill = SCALE;
00775 register unsigned long yleft = syscale;
00776 register int yneed = 1;
00777 int ysrc = 0;
00778
00779 for (y = 0; y < Dest_Y; y++) {
00780 if (Src_Y == Dest_Y) {
00781 sp = fp;
00782
00783 for (x = 0, p = sp, q = xtemp; x < Src_X; x++)
00784 *(q++) = *(p++);
00785
00786 fp += src->pitch;
00787 } else {
00788 while (yleft < yfill) {
00789 if (yneed && (ysrc < (int)Src_Y)) {
00790 sp = fp;
00791 fp += src->pitch;
00792 ysrc++;
00793 }
00794
00795 for (x = 0, p = sp; x < Src_X; x++)
00796 xvalue[x] += yleft * (signed long)(*(p++));
00797
00798 yfill -= yleft;
00799 yleft = syscale;
00800 yneed = 1;
00801 }
00802
00803 if (yneed && (ysrc < (int)Src_Y)) {
00804 sp = fp;
00805 fp += src->pitch;
00806 ysrc++;
00807 yneed = 0;
00808 }
00809
00810 for (x = 0, p = sp, q = xtemp; x < Src_X; x++) {
00811 register signed long v = xvalue[x] + yfill * (signed long)(*(p++));
00812 v /= SCALE;
00813 *(q++) = (unsigned char)v;
00814 xvalue[x] = HALFSCALE;
00815 }
00816 yleft -= yfill;
00817 if (yleft == 0) {
00818 yleft = syscale;
00819 yneed = 1;
00820 }
00821 yfill = SCALE;
00822 }
00823 if (Src_X == Dest_X) {
00824
00825 for (x = 0, p = xtemp, q = sq; x < Dest_X; x++)
00826 *(q++) = *(p++);
00827
00828 sq += dest->pitch;
00829 } else {
00830 register signed long v = HALFSCALE;
00831 register unsigned long xfill = SCALE;
00832 register unsigned long xleft;
00833 register int xneed = 0;
00834 q = sq;
00835
00836 for (x = 0, p = xtemp; x < Src_X; x++, p++) {
00837 xleft = sxscale;
00838
00839 while (xleft >= xfill) {
00840 if (xneed) {
00841 q++;
00842 v = HALFSCALE;
00843 }
00844 v += xfill * (signed long)(*p);
00845 v /= SCALE;
00846 *q = (unsigned char)v;
00847 xleft -= xfill;
00848 xfill = SCALE;
00849 xneed = 1;
00850 }
00851 if (xleft > 0) {
00852 if (xneed) {
00853 q++;
00854 v = HALFSCALE;
00855 xneed = 0;
00856 }
00857 v += xleft * (signed long)(*p);
00858 xfill -= xleft;
00859 }
00860 }
00861
00862 if (xfill > 0)
00863 v += xfill * (signed long)(*(--p));
00864
00865 if (!xneed) {
00866 v /= SCALE;
00867 *q = (unsigned char)v;
00868 }
00869
00870 sq += dest->pitch;
00871 }
00872 }
00873
00874 delete[] xtemp;
00875 delete[] xvalue;
00876 }