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 __del__(self): if self._c_surface and (sdl.SDL_WasInit(sdl.SDL_INIT_VIDEO) or not \ (self._c_surface.flags & sdl.SDL_HWSURFACE)): sdl.SDL_FreeSurface(self._c_surface) self._c_surface = None self._format = None self._w = None self._h = None
def blit(self, source, dest, area=None, special_flags=0): """ blit(source, dest, area=None, special_flags = 0) -> Rect draw one image onto another """ if not self._c_surface or not source._c_surface: raise SDLError("display Surface quit") if self.is_pure_opengl(): raise SDLError("Cannot blit to OPENGL Surfaces (OPENGLBLIT is ok)") srcrect = ffi.new('SDL_Rect*') destrect = ffi.new('SDL_Rect*') if area is not None: srcrect.x, srcrect.y, srcrect.w, srcrect.h = \ rect_vals_from_obj(area) else: srcrect.w = source._w srcrect.h = source._h if isinstance(dest, tuple) and len(dest) == 2: destrect.x = int(dest[0]) destrect.y = int(dest[1]) destrect.w = source._w destrect.h = source._h else: destrect.x, destrect.y, destrect.w, destrect.h = \ rect_vals_from_obj(dest) c_dest = self._c_surface c_src = source._c_surface c_subsurface = None flags = special_flags if self.subsurfacedata: owner = self.subsurfacedata.owner c_subsurface = owner._c_surface suboffsetx = self.subsurfacedata.xoffset suboffsety = self.subsurfacedata.yoffset while owner.subsurfacedata: subdata = owner.subsurfacedata owner = subdata.owner c_subsurface = owner._c_surface suboffsetx += subdata.xoffset suboffsety += subdata.yoffset orig_clip = ffi.new('SDL_Rect*') sub_clip = ffi.new('SDL_Rect*') sdl.SDL_GetClipRect(c_subsurface, orig_clip) sdl.SDL_GetClipRect(self._c_surface, sub_clip) sub_clip[0].x += suboffsetx sub_clip[0].y += suboffsety sdl.SDL_SetClipRect(c_subsurface, sub_clip) destrect.x += suboffsetx destrect.y += suboffsety c_dest = c_subsurface # TODO: implement special blend flags # these checks come straight from pygame - copied comments if (c_dest.format.Amask and (c_dest.flags & sdl.SDL_SRCALPHA) and not (c_src.format.Amask and not (c_src.flags & sdl.SDL_SRCALPHA)) and (c_dest.format.BytesPerPixel == 2 or c_dest.format.BytesPerPixel == 4)): # SDL works for 2 and 4 bytes res = sdl.pygame_Blit(c_src, srcrect, c_dest, destrect, flags) elif flags or (c_src.flags & (sdl.SDL_SRCALPHA | sdl.SDL_SRCCOLORKEY) and c_dest.pixels == c_src.pixels and check_surface_overlap(c_src, srcrect, c_dest, destrect)): ''' This simplification is possible because a source subsurface is converted to its owner with a clip rect and a dst subsurface cannot be blitted to its owner because the owner is locked. ''' res = sdl.pygame_Blit(c_src, srcrect, c_dest, destrect, flags) # can't blit alpha to 8bit, crashes SDL elif (c_dest.format.BytesPerPixel == 1 and (c_src.format.Amask or c_src.flags & sdl.SDL_SRCALPHA)): if c_src.format.BytesPerPixel == 1: res = sdl.pygame_Blit(c_src, srcrect, c_dest, destrect, 0) elif sdl.SDL_WasInit(sdl.SDL_INIT_VIDEO): # TODO: SDL_DisplayFormat segfaults c_src = sdl.SDL_DisplayFormat(c_src) if c_src: res = sdl.SDL_BlitSurface(c_src, srcrect, c_dest, destrect) sdl.SDL_FreeSurface(c_src) else: res = -1 else: raise NotImplementedError() else: res = sdl.SDL_BlitSurface(c_src, srcrect, c_dest, destrect) if c_subsurface: sdl.SDL_SetClipRect(c_subsurface, orig_clip) destrect.x -= suboffsetx destrect.y -= suboffsety else: # TODO: prep/unprep pass if res == -1: raise SDLError.from_sdl_error() elif res == -2: raise SDLError("Surface was lost") return Rect._from4(destrect.x, destrect.y, destrect.w, destrect.h)