表面(Surface)子系统(CategorySurface)
SDL Surface 是系统内存(RAM) 中的像素缓冲区,适用于处理未存储在 GPU 显存中的图像数据——可便捷地传递、修改图像,无需依赖硬件加速。
SDL_Surface 提供了完善的多格式图像管理能力,以及一套实用的像素数据操作工具集,包括:表面间像素拷贝、图像矩形填充、格式转换等。
SDL 内置了简易的图片加载函数:
- BMP 加载:
SDL_LoadBMP() - PNG 加载:
SDL_LoadPNG()
SDL 本身不支持其他格式(如 JPG/PNG 以外),但可通过外部优秀库扩展(如官方配套的 SDL_image)。
线程安全说明
这些函数整体线程安全:不同线程可操作不同 Surface;禁止两个线程同时修改同一个 Surface。
函数
- SDL_AddSurfaceAlternateImage:为 Surface 添加备用图像(多分辨率/格式适配)
- SDL_BlitSurface:基础表面拷贝(将源 Surface 绘制到目标 Surface,支持裁剪)
- SDL_BlitSurface9Grid:9宫格模式拷贝 Surface(拉伸时边缘不变形)
- SDL_BlitSurfaceScaled:缩放拷贝 Surface(自动适配目标尺寸)
- SDL_BlitSurfaceTiled:平铺拷贝 Surface(重复绘制填满目标区域)
- SDL_BlitSurfaceTiledWithScale:带缩放的平铺拷贝 Surface
- SDL_BlitSurfaceUnchecked:无参数校验的快速表面拷贝(性能更高,需确保参数合法)
- SDL_BlitSurfaceUncheckedScaled:无校验的缩放表面拷贝
- SDL_ClearSurface:清空 Surface(用预设颜色填充整个表面)
- SDL_ConvertPixels:像素格式转换(直接处理像素缓冲区,不依赖 Surface)
- SDL_ConvertPixelsAndColorspace:像素格式+颜色空间双重转换
- SDL_ConvertSurface:转换 Surface 的像素格式(生成新 Surface)
- SDL_ConvertSurfaceAndColorspace:转换 Surface 的像素格式+颜色空间
- SDL_CreateSurface:创建空 Surface(指定尺寸、像素格式)
- SDL_CreateSurfaceFrom:从已有像素缓冲区创建 Surface(复用内存)
- SDL_CreateSurfacePalette:为 Surface 创建调色板(索引色格式专用)
- SDL_DestroySurface:销毁 Surface(释放内存和资源)
- SDL_DuplicateSurface:复制 Surface(生成独立的新 Surface)
- SDL_FillSurfaceRect:填充 Surface 中的单个矩形区域
- SDL_FillSurfaceRects:批量填充 Surface 中的多个矩形区域
- SDL_FlipSurface:翻转 Surface(水平/垂直/180度,参考 SDL_FlipMode)
- SDL_GetSurfaceAlphaMod:获取 Surface 的透明度调制值(0-255)
- SDL_GetSurfaceBlendMode:获取 Surface 的混合模式
- SDL_GetSurfaceClipRect:获取 Surface 的裁剪矩形(仅绘制矩形内区域)
- SDL_GetSurfaceColorKey:获取 Surface 的颜色键(透明色)
- SDL_GetSurfaceColorMod:获取 Surface 的颜色调制值(RGB 偏移)
- SDL_GetSurfaceColorspace:获取 Surface 的颜色空间(如 sRGB、BT.709)
- SDL_GetSurfaceImages:获取 Surface 关联的所有备用图像
- SDL_GetSurfacePalette:获取 Surface 的调色板(索引色格式)
- SDL_GetSurfaceProperties:获取 Surface 的属性集合(格式、标志位等)
- SDL_LoadBMP:从文件加载 BMP 图像到 Surface
- SDL_LoadBMP_IO:从自定义 IO 流加载 BMP 图像到 Surface
- SDL_LoadPNG:从文件加载 PNG 图像到 Surface
- SDL_LoadPNG_IO:从自定义 IO 流加载 PNG 图像到 Surface
- SDL_LoadSurface:通用图像加载(自动识别格式,需 SDL_image 支持)
- SDL_LoadSurface_IO:从自定义 IO 流通用加载图像到 Surface
- SDL_LockSurface:锁定 Surface(获取可读写的像素缓冲区,修改前必须调用)
- SDL_MapSurfaceRGB:将 RGB 颜色转换为 Surface 格式的像素值(无 Alpha)
- SDL_MapSurfaceRGBA:将 RGBA 颜色转换为 Surface 格式的像素值
- SDL_PremultiplyAlpha:预乘 Alpha 通道(优化混合计算)
- SDL_PremultiplySurfaceAlpha:为 Surface 预乘 Alpha 通道
- SDL_ReadSurfacePixel:读取 Surface 中指定坐标的像素值(整型)
- SDL_ReadSurfacePixelFloat:读取 Surface 中指定坐标的像素值(浮点型)
- SDL_RemoveSurfaceAlternateImages:移除 Surface 的所有备用图像
- SDL_RotateSurface:旋转 Surface(指定角度,生成新 Surface)
- SDL_SaveBMP:将 Surface 保存为 BMP 文件
- SDL_SaveBMP_IO:将 Surface 保存到自定义 IO 流(BMP 格式)
- SDL_SavePNG:将 Surface 保存为 PNG 文件
- SDL_SavePNG_IO:将 Surface 保存到自定义 IO 流(PNG 格式)
- SDL_ScaleSurface:缩放 Surface(指定尺寸和缩放模式,生成新 Surface)
- SDL_SetSurfaceAlphaMod:设置 Surface 的透明度调制值
- SDL_SetSurfaceBlendMode:设置 Surface 的混合模式
- SDL_SetSurfaceClipRect:设置 Surface 的裁剪矩形
- SDL_SetSurfaceColorKey:设置 Surface 的颜色键(指定透明色)
- SDL_SetSurfaceColorMod:设置 Surface 的颜色调制值(调整整体色调)
- SDL_SetSurfaceColorspace:设置 Surface 的颜色空间
- SDL_SetSurfacePalette:设置 Surface 的调色板(索引色格式)
- SDL_SetSurfaceRLE:启用/禁用 Surface 的 RLE 压缩(优化透明色渲染)
- SDL_StretchSurface:拉伸 Surface(适配目标尺寸,旧接口,推荐用 SDL_ScaleSurface)
- SDL_SurfaceHasAlternateImages:判断 Surface 是否关联了备用图像
- SDL_SurfaceHasColorKey:判断 Surface 是否设置了颜色键(透明色)
- SDL_SurfaceHasRLE:判断 Surface 是否启用了 RLE 压缩
- SDL_UnlockSurface:解锁 Surface(完成像素修改后提交,与 Lock 成对使用)
- SDL_WriteSurfacePixel:向 Surface 指定坐标写入像素值(整型)
- SDL_WriteSurfacePixelFloat:向 Surface 指定坐标写入像素值(浮点型)
数据类型
- SDL_SurfaceFlags:Surface 标志位类型(存储 Surface 的属性,如是否有 Alpha、是否 RLE 压缩)
结构体
- SDL_Surface:Surface 核心结构体(包含像素缓冲区、尺寸、格式、调色板等信息)
枚举
- SDL_FlipMode:翻转模式枚举(SDL_FLIP_NONE/SDL_FLIP_HORIZONTAL/SDL_FLIP_VERTICAL/SDL_FLIP_BOTH)
- SDL_ScaleMode:缩放模式枚举(SDL_SCALEMODE_NEAREST/SDL_SCALEMODE_LINEAR 等,控制缩放插值方式)
宏
- SDL_MUSTLOCK:判断 Surface 是否必须锁定才能修改像素(返回布尔值)
FreeBASIC 示例代码
' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库)
#Include "SDL.bi"
' 错误处理辅助函数
Sub CheckError(byval msg as string)
dim as zstring ptr err = SDL_GetError()
if (*err <> 0) then
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "%s:%s", msg, err)
SDL_ClearError()
end if
End Sub
' 主程序示例
Dim As SDL_Surface Ptr bmpSurface = NULL, newSurface = NULL
Dim As SDL_Rect dstRect
Dim As UInteger pixelColor
Dim As UByte r, g, b, a
' 1. 初始化 SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) then
CheckError("SDL 初始化失败")
end 1
end if
' 2. 加载 BMP 图像到 Surface
bmpSurface = SDL_LoadBMP("test.bmp")
if (bmpSurface = NULL) then
CheckError("加载 BMP 失败")
SDL_Quit()
end 1
end if
SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "加载的 BMP 尺寸:%dx%d", bmpSurface->w, bmpSurface->h)
' 3. 创建新 Surface(与源图像同格式,尺寸加倍)
newSurface = SDL_CreateSurface(bmpSurface->w * 2, bmpSurface->h * 2, bmpSurface->format->format)
if (newSurface = NULL) then
CheckError("创建新 Surface 失败")
SDL_DestroySurface(bmpSurface)
SDL_Quit()
end 1
end if
' 4. 填充新 Surface 背景为白色
pixelColor = SDL_MapSurfaceRGB(newSurface, 255, 255, 255)
SDL_FillSurfaceRect(newSurface, NULL, pixelColor)
CheckError("填充 Surface 失败")
' 5. 拷贝源 Surface 到新 Surface 的指定位置
dstRect.x = 50 : dstRect.y = 50 : dstRect.w = bmpSurface->w : dstRect.h = bmpSurface->h
SDL_BlitSurface(bmpSurface, NULL, newSurface, @dstRect)
CheckError("Surface 拷贝失败")
' 6. 修改 Surface 像素(读取并改写左上角像素)
if (SDL_MUSTLOCK(newSurface)) then
if (SDL_LockSurface(newSurface) < 0) then
CheckError("锁定 Surface 失败")
goto cleanup
end if
end if
' 读取左上角像素
pixelColor = SDL_ReadSurfacePixel(newSurface, 0, 0)
SDL_GetRGBA(pixelColor, newSurface->format, @r, @g, @b, @a)
SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "左上角像素原始颜色:R=%d, G=%d, B=%d, A=%d", r, g, b, a)
' 改写为红色
pixelColor = SDL_MapSurfaceRGBA(newSurface, 255, 0, 0, 255)
SDL_WriteSurfacePixel(newSurface, 0, 0, pixelColor)
if (SDL_MUSTLOCK(newSurface)) then
SDL_UnlockSurface(newSurface)
end if
' 7. 保存修改后的 Surface 为新 BMP
if (SDL_SaveBMP(newSurface, "output.bmp") < 0) then
CheckError("保存 BMP 失败")
end if
' 8. 缩放 Surface(缩小为原尺寸的 50%)
Dim As SDL_Surface Ptr scaledSurface = SDL_ScaleSurface(newSurface, _
newSurface->w / 2, newSurface->h / 2, SDL_SCALEMODE_LINEAR)
if (scaledSurface <> NULL) then
SDL_SavePNG(scaledSurface, "scaled.png")
SDL_DestroySurface(scaledSurface)
end if
' 9. 清理资源
cleanup:
if (bmpSurface <> NULL) then SDL_DestroySurface(bmpSurface)
if (newSurface <> NULL) then SDL_DestroySurface(newSurface)
SDL_Quit()
SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "程序执行完成")
end 0
总结
- SDL Surface 是系统内存中的像素缓冲区,核心优势是无需 GPU 即可操作像素,
SDL_LoadBMP/SDL_SaveBMP是最基础的加载/保存函数; - FreeBASIC 中使用 Surface 需遵循「锁定-修改-解锁」流程(
SDL_LockSurface/SDL_UnlockSurface),SDL_MUSTLOCK宏可判断是否需要锁定; - 关键操作:
SDL_BlitSurface(拷贝)、SDL_FillSurfaceRect(填充)、SDL_ConvertSurface(格式转换),修改像素前务必确认 Surface 已锁定,避免内存错误。
评论一下?