📄 rleaccel.c
字号:
* highly optimised. *//* encode 32bpp rgb + a into 16bpp rgb, losing alpha */static int copy_opaque_16(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint16 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b; RGB_FROM_PIXEL(*src, sfmt, r, g, b); PIXEL_FROM_RGB(*d, dfmt, r, g, b); src++; d++; } return n * 2;}/* decode opaque pixels from 16bpp to 32bpp rgb + a */static int uncopy_opaque_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint16 *s = src; unsigned alpha = dfmt->Amask ? 255 : 0; for(i = 0; i < n; i++) { unsigned r, g, b; RGB_FROM_PIXEL(*s, sfmt, r, g, b); PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha); s++; dst++; } return n * 2;}/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */static int copy_transl_565(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint16 pix; RGBA_FROM_8888(*src, sfmt, r, g, b, a); PIXEL_FROM_RGB(pix, dfmt, r, g, b); *d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0); src++; d++; } return n * 4;}/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */static int copy_transl_555(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint16 pix; RGBA_FROM_8888(*src, sfmt, r, g, b, a); PIXEL_FROM_RGB(pix, dfmt, r, g, b); *d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0); src++; d++; } return n * 4;}/* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */static int uncopy_transl_16(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *s = src; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint32 pix = *s++; a = (pix & 0x3e0) >> 2; pix = (pix & ~0x3e0) | pix >> 16; RGB_FROM_PIXEL(pix, sfmt, r, g, b); PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); dst++; } return n * 4;}/* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */static int copy_32(void *dst, Uint32 *src, int n, GAL_PixelFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *d = dst; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint32 pixel; RGBA_FROM_8888(*src, sfmt, r, g, b, a); PIXEL_FROM_RGB(pixel, dfmt, r, g, b); *d++ = pixel | a << 24; src++; } return n * 4;}/* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */static int uncopy_32(Uint32 *dst, void *src, int n, RLEDestFormat *sfmt, GAL_PixelFormat *dfmt){ int i; Uint32 *s = src; for(i = 0; i < n; i++) { unsigned r, g, b, a; Uint32 pixel = *s++; RGB_FROM_PIXEL(pixel, sfmt, r, g, b); a = pixel >> 24; PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); dst++; } return n * 4;}#define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255)#define ISTRANSL(pixel, fmt) \ ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U)/* convert surface to be quickly alpha-blittable onto dest, if possible */static int RLEAlphaSurface(GAL_Surface *surface){ GAL_Surface *dest; GAL_PixelFormat *df; int maxsize = 0; int max_opaque_run; int max_transl_run = 65535; unsigned masksum; Uint8 *rlebuf, *dst; int (*copy_opaque)(void *, Uint32 *, int, GAL_PixelFormat *, GAL_PixelFormat *); int (*copy_transl)(void *, Uint32 *, int, GAL_PixelFormat *, GAL_PixelFormat *); dest = surface->map->dst; if(!dest) return -1; df = dest->format; if(surface->format->BitsPerPixel != 32) return -1; /* only 32bpp source supported */ /* find out whether the destination is one we support, and determine the max size of the encoded result */ masksum = df->Rmask | df->Gmask | df->Bmask; switch(df->BytesPerPixel) { case 2: /* 16bpp: only support 565 and 555 formats */ switch(masksum) { case 0xffff: if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) { copy_opaque = copy_opaque_16; copy_transl = copy_transl_565; } else return -1; break; case 0x7fff: if(df->Gmask == 0x03e0 || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) { copy_opaque = copy_opaque_16; copy_transl = copy_transl_555; } else return -1; break; default: return -1; } max_opaque_run = 255; /* runs stored as bytes */ /* worst case is alternating opaque and translucent pixels, with room for alignment padding between lines */ maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2; break; case 4: if(masksum != 0x00ffffff) return -1; /* requires unused high byte */ copy_opaque = copy_32; copy_transl = copy_32; max_opaque_run = 255; /* runs stored as short ints */ /* worst case is alternating opaque and translucent pixels */ maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4; break; default: return -1; /* anything else unsupported right now */ } maxsize += sizeof(RLEDestFormat); rlebuf = (Uint8 *)malloc(maxsize); if(!rlebuf) { GAL_OutOfMemory(); return -1; } { /* save the destination format so we can undo the encoding later */ RLEDestFormat *r = (RLEDestFormat *)rlebuf; r->BytesPerPixel = df->BytesPerPixel; r->Rloss = df->Rloss; r->Gloss = df->Gloss; r->Bloss = df->Bloss; r->Rshift = df->Rshift; r->Gshift = df->Gshift; r->Bshift = df->Bshift; r->Ashift = df->Ashift; r->Rmask = df->Rmask; r->Gmask = df->Gmask; r->Bmask = df->Bmask; r->Amask = df->Amask; } dst = rlebuf + sizeof(RLEDestFormat); /* Do the actual encoding */ { int x, y; int h = surface->h, w = surface->w; GAL_PixelFormat *sf = surface->format; Uint32 *src = (Uint32 *)((Uint8 *)surface->pixels + surface->offset); Uint8 *lastline = dst; /* end of last non-blank line */ /* opaque counts are 8 or 16 bits, depending on target depth */#define ADD_OPAQUE_COUNTS(n, m) \ if(df->BytesPerPixel == 4) { \ ((Uint16 *)dst)[0] = n; \ ((Uint16 *)dst)[1] = m; \ dst += 4; \ } else { \ dst[0] = n; \ dst[1] = m; \ dst += 2; \ } /* translucent counts are always 16 bit */#define ADD_TRANSL_COUNTS(n, m) \ (((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4) for(y = 0; y < h; y++) { int runstart, skipstart; int blankline = 0; /* First encode all opaque pixels of a scan line */ x = 0; do { int run, skip, len; skipstart = x; while(x < w && !ISOPAQUE(src[x], sf)) x++; runstart = x; while(x < w && ISOPAQUE(src[x], sf)) x++; skip = runstart - skipstart; if(skip == w) blankline = 1; run = x - runstart; while(skip > max_opaque_run) { ADD_OPAQUE_COUNTS(max_opaque_run, 0); skip -= max_opaque_run; } len = MIN(run, max_opaque_run); ADD_OPAQUE_COUNTS(skip, len); dst += copy_opaque(dst, src + runstart, len, sf, df); runstart += len; run -= len; while(run) { len = MIN(run, max_opaque_run); ADD_OPAQUE_COUNTS(0, len); dst += copy_opaque(dst, src + runstart, len, sf, df); runstart += len; run -= len; } } while(x < w); /* Make sure the next output address is 32-bit aligned */ dst += (unsigned long)dst & 2; /* Next, encode all translucent pixels of the same scan line */ x = 0; do { int run, skip, len; skipstart = x; while(x < w && !ISTRANSL(src[x], sf)) x++; runstart = x; while(x < w && ISTRANSL(src[x], sf)) x++; skip = runstart - skipstart; blankline &= (skip == w);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -