def save_png(surf, filename): alpha = bool(surf.format.Amask) if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = 0xff, 0xff00, 0xff0000, 0xff000000 else: rmask, gmask, bmask, amask = 0xff00, 0xff0000, 0xff, 0x000000ff ss_surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SWSURFACE | sdl.SDL_SRCALPHA, surf.w, surf.h, 32 if alpha else 24, rmask, gmask, bmask, amask) if not ss_surf: return -1 with opaque(surf): rect = ffi.new('SDL_Rect*') rect.w = surf.w rect.h = surf.h sdl.SDL_BlitSurface(surf, rect, ss_surf, ffi.NULL) ss_rows = ffi.new('unsigned char*[]', surf.h) ss_pixels = ffi.cast('unsigned char*', ss_surf.pixels) for i in range(surf.h): ss_rows[i] = ss_pixels + i * ss_surf.pitch err_msg = ffi.new('char**') result = pnglib.write_png(filename, ss_rows, surf.w, surf.h, (pnglib.PNG_COLOR_TYPE_RGB_ALPHA if alpha else pnglib.PNG_COLOR_TYPE_RGB), 8, err_msg) sdl.SDL_FreeSurface(ss_surf) if result == -1: raise IOError("PNGError: %s" % ffi.string(err_msg[0])) return result
def save_jpg(surf, filename): if (surf.format.BytesPerPixel == 3 and not (surf.flags & sdl.SDL_SRCALPHA) and surf.format.Rshift == 0): ss_surf = surf else: if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = 0xff, 0xff00, 0xff0000, 0xff000000 else: rmask, gmask, bmask, amask = 0xff00, 0xff, 0xff0000, 0xff000000 ss_surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SWSURFACE, surf.w, surf.h, 24, rmask, gmask, bmask, amask) if not ss_surf: return -1 rect = ffi.new('SDL_Rect*') rect.w = surf.w rect.h = surf.h sdl.SDL_BlitSurface(surf, rect, ss_surf, ffi.NULL) ss_rows = ffi.new('unsigned char*[]', surf.h) ss_pixels = ffi.cast('unsigned char*', ss_surf.pixels) for i in range(surf.h): ss_rows[i] = ss_pixels + i * ss_surf.pitch err_msg = ffi.new('char**') result = jpglib.write_jpeg(filename, ss_rows, surf.w, surf.h, 85, err_msg) if ss_surf is not surf: sdl.SDL_FreeSurface(ss_surf) if result == -1: raise IOError("JPGError: %s" % ffi.string(err_msg[0])) return result
def new_surface_from_surface(c_surface, w, h): if 4 < c_surface.format.BytesPerPixel <= 0: raise ValueError("unsupported Surface bit depth for transform") format = c_surface.format newsurf = sdl.SDL_CreateRGBSurface(c_surface.flags, w, h, format.BitsPerPixel, format.Rmask, format.Gmask, format.Bmask, format.Amask) if not newsurf: SDLError.from_sdl_error() if format.BytesPerPixel == 1 and format.palette: sdl.SDL_SetColors(newsurf, format.palette.colors, 0, format.palette.ncolors) if c_surface.flags & sdl.SDL_SRCCOLORKEY: sdl.SDL_SetColorKey(newsurf, (c_surface.flags & sdl.SDL_RLEACCEL) | sdl.SDL_SRCCOLORKEY, format.colorkey) if c_surface.flags & sdl.SDL_SRCALPHA: result = sdl.SDL_SetAlpha(newsurf, c_surface.flags, format.alpha) if result == -1: raise SDLError.from_sdl_error() return newsurf
def rotozoom(surface, angle, scale): """ rotozoom(Surface, angle, scale) -> Surface filtered scale and rotation """ c_surf = surface._c_surface if scale == 0.0: new_surf = new_surface_from_surface(c_surf, c_surf.w, c_surf.h) return Surface._from_sdl_surface(new_surf) if c_surf.format.BitsPerPixel == 32: surf32 = c_surf else: surf32 = sdl.SDL_CreateRGBSurface(sdl.SDL_SWSURFACE, surf.w, surf.h, 32, 0xff, 0xff00, 0xff0000, 0xff000000) sdl.SDL_BlitSurface(surf, ffi.NULL, surf32, ffi.NULL) new_surf = sdl.rotozoomSurface(surf32, angle, scale, 1) return Surface._from_sdl_surface(new_surf)
def fromstring(string, size, format, flipped=False): w, h = size if w < 1 or h < 1: raise ValueError("Resolution must be positive values") if format == "P": if len(string) != w * h: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast('char*', surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w if flipped else y * w pixels[dest:dest + w] = string[src_start:src_start + w] elif format == "RGB": if len(string) != w * h * 3: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 24, 0xff, 0xff << 16, 0xff << 8, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w * 3 if flipped else y * w * 3 row = string[src_start:src_start + w * 3] for x in range(0, w * 3, 3): # BYTE0, BYTE1 and BYTE2 are determined by byte order pixels[dest + x + BYTE0] = row[x + BYTE0] pixels[dest + x + BYTE1] = row[x + BYTE1] pixels[dest + x + BYTE2] = row[x + BYTE2] elif format in ("RGBA", "RGBAX", "ARGB"): if len(string) != w * h * 4: raise ValueError("String length does not equal format and " "resolution size") if format == "ARGB": if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = (0xff << 8, 0xff << 16, 0xff << 24, 0xff) else: rmask, gmask, bmask, amask = (0xff << 16, 0xff << 8, 0xff, 0xff << 24) surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SRCALPHA, w, h, 32, rmask, gmask, bmask, amask) else: alphamult = format == "RGBA" if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask = 0xff, 0xff << 8, 0xff << 16 amask = 0xff << 24 if alphamult else 0 else: rmask, gmask, bmask = 0xff << 24, 0xff << 16, 0xff << 8 amask = 0xff if alphamult else 0 surf = sdl.SDL_CreateRGBSurface( sdl.SDL_SRCALPHA if alphamult else 0, w, h, 32, rmask, gmask, bmask, amask) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w * 4 if flipped else y * w * 4 pixels[dest:dest + w * 4] = string[src_start:src_start + w * 4] else: raise ValueError("Unrecognized type of format") return Surface._from_sdl_surface(surf)
def __init__(self, size, flags=0, depth=0, masks=None): w, h = unpack_rect(size) if isinstance(depth, Surface): if masks: raise ValueError( "cannot pass surface for depth and color masks") surface = depth depth = 0 else: surface = None depth = int(depth) if depth and masks: Rmask, Gmask, Bmask, Amask = masks bpp = depth elif surface is None: if depth: bpp = depth Rmask, Gmask, Bmask, Amask = \ self._get_default_masks(bpp, False) elif sdl.SDL_GetVideoSurface(): pix = sdl.SDL_GetVideoSurface().format bpp = pix.BitsPerPixel Amask = pix.Amask Rmask = pix.Rmask Gmask = pix.Gmask Bmask = pix.Bmask elif sdl.SDL_WasInit(sdl.SDL_INIT_VIDEO): pix = sdl.SDL_GetVideoInfo().vfmt bpp = pix.BitsPerPixel Amask = pix.Amask Rmask = pix.Rmask Gmask = pix.Gmask Bmask = pix.Bmask else: bpp = 32 Rmask, Gmask, Bmask, Amask = \ self._get_default_masks(32, False) # the alpha mask might be different - must update if flags & sdl.SDL_SRCALPHA: Rmask, Gmask, Bmask, Amask = \ self._get_default_masks(bpp, True) # depth argument was a Surface object else: pix = surface._c_surface.format bpp = pix.BitsPerPixel if flags & sdl.SDL_SRCALPHA: Rmask, Gmask, Bmask, Amask = \ self._get_default_masks(bpp, True) else: Amask = pix.Amask Rmask = pix.Rmask Gmask = pix.Gmask Bmask = pix.Bmask self._c_surface = sdl.SDL_CreateRGBSurface(flags, w, h, bpp, Rmask, Gmask, Bmask, Amask) self._format = self._c_surface.format self._w = self._c_surface.w self._h = self._c_surface.h if not self._c_surface: raise SDLError.from_sdl_error() if masks: """ Confirm the surface was created correctly (masks were valid). Also ensure that 24 and 32 bit surfaces have 8 bit fields (no losses). """ format = self._format Rmask = (0xFF >> format.Rloss) << format.Rshift Gmask = (0xFF >> format.Gloss) << format.Gshift Bmask = (0xFF >> format.Bloss) << format.Bshift Amask = (0xFF >> format.Aloss) << format.Ashift bad_loss = format.Rloss or format.Gloss or format.Bloss if flags & sdl.SDL_SRCALPHA: bad_loss = bad_loss or format.Aloss else: bad_loss = bad_loss or format.Aloss != 8 if (format.Rmask != Rmask or format.Gmask != Gmask or format.Bmask != Bmask or format.Amask != Amask or (format.BytesPerPixel >= 3 and bad_loss)): # Note: don't free _c_surface here. It will # be done in __del__. raise ValueError("Invalid mask values")
sdl.SDL_FreeSurface(ss_surf) if result == -1: raise IOError("PNGError: %s" % ffi.string(err_msg[0])) return result def fromstring(string, (w, h), format, flipped=False): if w < 1 or h < 1: raise ValueError("Resolution must be positive values") if format == "P": if len(string) != w * h: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast('char*', surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w if flipped else y * w pixels[dest:dest + w] = string[src_start:src_start + w] elif format == "RGB": if len(string) != w * h * 3: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 24, 0xff, 0xff << 16, 0xff << 8, 0)