📄 sdl_rotozoom.c
字号:
/* SDL_rotozoom.c - rotozoomer for 32bit or 8bit surfaces LGPL (c) A. Schiffler*/#ifdef WIN32#include <windows.h>#endif#include <stdlib.h>#include <string.h>#include "SDL_rotozoom.h"#define MAX(a,b) (((a) > (b)) ? (a) : (b))/* 32bit Zoomer with optional anti-aliasing by bilinear interpolation. Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. */int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth){ int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep; tColorRGBA *c00, *c01, *c10, *c11; tColorRGBA *sp, *csp, *dp; int sgap, dgap; /* * Variable setup */ if (smooth) { /* * For interpolation: assume source dimension is one pixel */ /* * smaller to avoid overflow on right and bottom edge. */ sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); } else { sx = (int) (65536.0 * (float) src->w / (float) dst->w); sy = (int) (65536.0 * (float) src->h / (float) dst->h); } /* * Allocate memory for row increments */ if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { return (-1); } if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { free(sax); return (-1); } /* * Precalculate row increments */ csx = 0; csax = sax; for (x = 0; x <= dst->w; x++) { *csax = csx; csax++; csx &= 0xffff; csx += sx; } csy = 0; csay = say; for (y = 0; y <= dst->h; y++) { *csay = csy; csay++; csy &= 0xffff; csy += sy; } /* * Pointer setup */ sp = csp = (tColorRGBA *) src->pixels; dp = (tColorRGBA *) dst->pixels; sgap = src->pitch - src->w * 4; dgap = dst->pitch - dst->w * 4; /* * Switch between interpolating and non-interpolating code */ if (smooth) { /* * Interpolating Zoom */ /* * Scan destination */ csay = say; for (y = 0; y < dst->h; y++) { /* * Setup color source pointers */ c00 = csp; c01 = csp; c01++; c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); c11 = c10; c11++; csax = sax; for (x = 0; x < dst->w; x++) { /* * Interpolate colors */ ex = (*csax & 0xffff); ey = (*csay & 0xffff); t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; dp->r = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; dp->g = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; dp->b = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; dp->a = (((t2 - t1) * ey) >> 16) + t1; /* * Advance source pointers */ csax++; sstep = (*csax >> 16); c00 += sstep; c01 += sstep; c10 += sstep; c11 += sstep; /* * Advance destination pointer */ dp++; } /* * Advance source pointer */ csay++; csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); /* * Advance destination pointers */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } } else { /* * Non-Interpolating Zoom */ csay = say; for (y = 0; y < dst->h; y++) { sp = csp; csax = sax; for (x = 0; x < dst->w; x++) { /* * Draw */ *dp = *sp; /* * Advance source pointers */ csax++; sp += (*csax >> 16); /* * Advance destination pointer */ dp++; } /* * Advance source pointer */ csay++; csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); /* * Advance destination pointers */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } } /* * Remove temp arrays */ free(sax); free(say); return (0);}/* 8bit Zoomer without smoothing. Zoomes 8bit palette/Y 'src' surface to 'dst' surface. */int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst){ Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy; Uint8 *sp, *dp, *csp; int dgap; /* * Variable setup */ sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); /* * Allocate memory for row increments */ if ((sax = (Uint32 *) malloc(dst->w * sizeof(Uint32))) == NULL) { return (-1); } if ((say = (Uint32 *) malloc(dst->h * sizeof(Uint32))) == NULL) { if (sax != NULL) { free(sax); } return (-1); } /* * Precalculate row increments */ csx = 0; csax = sax; for (x = 0; x < dst->w; x++) { csx += sx; *csax = (csx >> 16); csx &= 0xffff; csax++; } csy = 0; csay = say; for (y = 0; y < dst->h; y++) { csy += sy; *csay = (csy >> 16); csy &= 0xffff; csay++; } csx = 0; csax = sax; for (x = 0; x < dst->w; x++) { csx += (*csax); csax++; } csy = 0; csay = say; for (y = 0; y < dst->h; y++) { csy += (*csay); csay++; } /* * Pointer setup */ sp = csp = (Uint8 *) src->pixels; dp = (Uint8 *) dst->pixels; dgap = dst->pitch - dst->w; /* * Draw */ csay = say; for (y = 0; y < dst->h; y++) { csax = sax; sp = csp; for (x = 0; x < dst->w; x++) { /* * Draw */ *dp = *sp; /* * Advance source pointers */ sp += (*csax); csax++; /* * Advance destination pointer */ dp++; } /* * Advance source pointer (for row) */ csp += ((*csay) * src->pitch); csay++; /* * Advance destination pointers */ dp += dgap; } /* * Remove temp arrays */ free(sax); free(say); return (0);}/* 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation. Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. */void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int smooth){ int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; tColorRGBA c00, c01, c10, c11; tColorRGBA *pc, *sp; int gap; /* * Variable setup */ xd = ((src->w - dst->w) << 15); yd = ((src->h - dst->h) << 15); ax = (cx << 16) - (icos * cx); ay = (cy << 16) - (isin * cx); sw = src->w - 1; sh = src->h - 1; pc = dst->pixels; gap = dst->pitch - dst->w * 4; /* * Switch between interpolating and non-interpolating code */ if (smooth) { for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (sdx >> 16); dy = (sdy >> 16); if ((dx >= -1) && (dy >= -1) && (dx < src->w) && (dy < src->h)) { if ((dx >= 0) && (dy >= 0) && (dx < sw) && (dy < sh)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; sp += 1; c01 = *sp; sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); sp -= 1; c10 = *sp; sp += 1; c11 = *sp; } else if ((dx == sw) && (dy == sh)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if ((dx == -1) && (dy == -1)) { sp = (tColorRGBA *) (src->pixels); c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if ((dx == -1) && (dy == sh)) { sp = (tColorRGBA *) (src->pixels); sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if ((dx == sw) && (dy == -1)) { sp = (tColorRGBA *) (src->pixels); sp += dx; c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if (dx == -1) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); c00 = *sp; c01 = *sp; c10 = *sp; sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); c11 = *sp; } else if (dy == -1) { sp = (tColorRGBA *) (src->pixels); sp += dx; c00 = *sp; c01 = *sp; c10 = *sp; sp += 1; c11 = *sp; } else if (dx == sw) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; c01 = *sp; sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); c10 = *sp; c11 = *sp; } else if (dy == sh) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; sp += 1; c01 = *sp; c10 = *sp; c11 = *sp; } /* * Interpolate colors */ ex = (sdx & 0xffff); ey = (sdy & 0xffff); t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; pc->r = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; pc->g = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; pc->b = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; pc->a = (((t2 - t1) * ey) >> 16) + t1; } sdx += icos; sdy += isin; pc++; } pc = (tColorRGBA *) ((Uint8 *) pc + gap); } } else { for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (short) (sdx >> 16); dy = (short) (sdy >> 16); if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; *pc = *sp; } sdx += icos; sdy += isin; pc++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -