1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
import os
import sys
import pytest
import sdl2
from sdl2 import ext as sdl2ext
from sdl2.ext import color
from sdl2 import surface as surf
from sdl2 import pixels
try:
from sdl2 import sdlimage
_HASSDLIMAGE=True
except:
_HASSDLIMAGE=False
try:
import PIL
_HASPIL = True
except ImportError:
_HASPIL = False
parent_path = os.path.abspath(os.path.dirname(__file__))
resource_path = os.path.join(parent_path, "resources")
is32bit = sys.maxsize <= 2**32
ismacos = sys.platform == "darwin"
skip_formats = []
if _HASSDLIMAGE:
# SVG unsupported on SDL2_image < 2.0.2
if sdlimage.dll.version < 2002:
skip_formats.append("svg")
# As of SDL2_image 2.0.5, XCF support seems to be broken (fails to load
# on 32-bit, transparent surface on 64-bit)
# XCF support is also broken in official SDL2_image macOS .frameworks
if sdlimage.dll.version == 2005 or ismacos:
skip_formats.append("xcf")
# WEBP support is broken in the 32-bit Windows SDL2_image 2.0.2 binary
if is32bit and sdlimage.dll.version == 2002:
skip_formats.append("webp")
# QOI support requires SDL2_image 2.6.0 or newer
if sdlimage.dll.version < 2060:
skip_formats.append("qoi")
# List of lossy/non-color formats that shouldn't be compared against reference
# during tests
skip_color_check = ['gif', 'jpg', 'lbm', 'pbm', 'pgm', 'svg', 'webp']
# Skip ICO and CUR tests on big-endian, since they don't seem to work yet
if sys.byteorder == "big":
skip_color_check += ['ico', 'cur', 'xcf']
# SDL 2.0.10 has a bug that messes up converting surfaces with transparency
if sdl2.dll.version == 2010:
skip_color_check.append('xpm')
colors = {
'red': color.Color(255, 0, 0, 255),
'blue': color.Color(0, 0, 255, 255),
'black': color.Color(0, 0, 0, 255),
'white': color.Color(255, 255, 255, 255)
}
def check_image_contents(img):
# Test different coordinates on surface
pxview = sdl2ext.PixelView(img)
img_red = color.ARGB(pxview[0][0])
img_blue = color.ARGB(pxview[0][16])
img_white = color.ARGB(pxview[0][31])
img_black = color.ARGB(pxview[31][31])
assert img_red == colors['red']
assert img_blue == colors['blue']
assert img_white == colors['white']
assert img_black == colors['black']
def test_load_bmp(with_sdl):
# Test loading a basic BMP image
img_path = os.path.join(resource_path, "surfacetest.bmp")
sf = sdl2ext.load_bmp(img_path)
assert isinstance(sf, surf.SDL_Surface)
check_image_contents(sf)
surf.SDL_FreeSurface(sf)
# Test exception on missing file
bad_path = os.path.join(resource_path, "doesnt_exist.bmp")
with pytest.raises(IOError):
sdl2ext.load_bmp(bad_path)
# Test exception on bad file type
bad_type = os.path.join(resource_path, "surfacetest.png")
with pytest.raises(sdl2ext.SDLError):
sdl2ext.load_bmp(bad_type)
def test_save_bmp(with_sdl, tmpdir):
# Open a BMP that we can re-save
img_path = os.path.join(resource_path, "surfacetest.bmp")
sf = sdl2ext.load_bmp(img_path)
assert isinstance(sf, surf.SDL_Surface)
# Try saving the BMP to a new folder and re-loading it
outpath = os.path.join(str(tmpdir), "save_test.bmp")
sdl2ext.save_bmp(sf, outpath)
assert os.path.exists(outpath)
sf_saved = sdl2ext.load_bmp(outpath)
assert isinstance(sf_saved, surf.SDL_Surface)
check_image_contents(sf_saved)
# Try modifying/overwriting the existing BMP
sdl2ext.fill(sf, (0, 255, 0, 255))
sdl2ext.save_bmp(sf, outpath, overwrite=True)
sf_saved2 = sdl2ext.load_bmp(outpath)
assert isinstance(sf_saved2, surf.SDL_Surface)
with pytest.raises(AssertionError):
check_image_contents(sf_saved2)
surf.SDL_FreeSurface(sf)
surf.SDL_FreeSurface(sf_saved)
surf.SDL_FreeSurface(sf_saved2)
# Test existing file exception with overwrite=False
with pytest.raises(RuntimeError):
sdl2ext.save_bmp(sf_saved, outpath, overwrite=False)
# Test exception with non-existent save directory
bad_path = os.path.join(resource_path, "doesnt_exist", "tst.bmp")
with pytest.raises(IOError):
sdl2ext.save_bmp(sf_saved, bad_path)
@pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image")
def test_load_img(with_sdl):
# Test loading all test images, with and without ARGB conversion
resources = os.listdir(resource_path)
test_imgs = [f for f in resources if f[:11] == "surfacetest"]
for img in sorted(test_imgs):
img_path = os.path.join(resource_path, img)
fmt = img.split(".")[-1]
if fmt in skip_formats:
continue
sf = sdl2ext.load_img(img_path)
assert isinstance(sf, surf.SDL_Surface)
assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888
if fmt not in skip_color_check:
check_image_contents(sf)
surf.SDL_FreeSurface(sf)
sf2 = sdl2ext.load_img(img_path, as_argb=False)
assert isinstance(sf2, surf.SDL_Surface)
surf.SDL_FreeSurface(sf2)
# Test exception on missing file
bad_path = os.path.join(resource_path, "doesnt_exist.bmp")
with pytest.raises(IOError):
sdl2ext.load_img(bad_path)
# Test exception on bad file type
bad_type = os.path.join(resource_path, "tuffy.ttf")
with pytest.raises(sdl2ext.SDLError):
sdl2ext.load_img(bad_type)
@pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image")
def test_load_svg(with_sdl):
# Function requires SDL_image >= 2.6.0
if sdlimage.dll.version_tuple < (2, 6, 0):
pytest.skip("Requires SDL2_image >= 2.6.0")
# Test loading SVG without size
svg_path = os.path.join(resource_path, "surfacetest.svg")
sf = sdl2ext.load_svg(svg_path)
assert isinstance(sf, surf.SDL_Surface)
assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888
surf.SDL_FreeSurface(sf)
# Test loading SVG at a specific size
sf = sdl2ext.load_svg(svg_path, width = 100)
assert isinstance(sf, surf.SDL_Surface)
assert sf.w == 100
surf.SDL_FreeSurface(sf)
# Test exception on missing file
bad_path = os.path.join(resource_path, "doesnt_exist.svg")
with pytest.raises(IOError):
sdl2ext.load_svg(bad_path)
# Test exception on bad file type
bad_type = os.path.join(resource_path, "tuffy.ttf")
with pytest.raises(sdl2ext.SDLError):
sdl2ext.load_svg(bad_type)
@pytest.mark.skipif(not _HASPIL, reason="Pillow library is not installed")
def test_pillow_to_image(with_sdl):
# Import an image using Pillow
from PIL import Image
try:
from PIL.Image import Palette
WEB_PALETTE = Palette.WEB
except ImportError:
WEB_PALETTE = Image.WEB
img_path = os.path.join(resource_path, "surfacetest.bmp")
pil_img = Image.open(img_path)
# Convert the image to an SDL surface and verify it worked
sf = sdl2ext.pillow_to_surface(pil_img)
assert isinstance(sf, surf.SDL_Surface)
check_image_contents(sf)
surf.SDL_FreeSurface(sf)
# Pallete conversion not working reliably on 2.0.5 64-bit
if sdl2.dll.version_tuple < (2, 0, 6):
pytest.skip("Requires SDL2 >= 2.0.6")
# Try converting a palette image
palette_img = pil_img.convert("P", palette=WEB_PALETTE)
sfp = sdl2ext.pillow_to_surface(palette_img)
pxformat = sfp.format.contents
assert isinstance(sfp, surf.SDL_Surface)
check_image_contents(sfp)
assert pxformat.BytesPerPixel == 4
surf.SDL_FreeSurface(sfp)
# Try converting a palette image without ARGB conversion
sfp2 = sdl2ext.pillow_to_surface(palette_img, False)
pxformat = sfp2.format.contents
assert isinstance(sfp2, surf.SDL_Surface)
assert pxformat.BytesPerPixel == 1
sdl_palette = pxformat.palette.contents
pil_palette = palette_img.getpalette()
assert sdl_palette.colors[0].r == pil_palette[0]
assert sdl_palette.colors[0].g == pil_palette[1]
assert sdl_palette.colors[0].b == pil_palette[2]
surf.SDL_FreeSurface(sfp2)
# Test loading all supported test images and compare against reference
resources = os.listdir(resource_path)
test_imgs = [f for f in resources if f[:11] == "surfacetest"]
for img in test_imgs:
fmt = img.split(".")[-1]
if fmt in ("webp", "xcf", "lbm", "svg", "qoi"):
continue
pil_img = Image.open(os.path.join(resource_path, img))
sf = sdl2ext.pillow_to_surface(pil_img)
assert isinstance(sf, surf.SDL_Surface)
assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888
if fmt not in skip_color_check:
check_image_contents(sf)
surf.SDL_FreeSurface(sf)
@pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image")
def test_load_image(with_sdl):
resources = os.listdir(resource_path)
test_imgs = [f for f in resources if f[:11] == "surfacetest"]
for img in test_imgs:
img_path = os.path.join(resource_path, img)
fmt = img.split(".")[-1]
if fmt in skip_formats:
continue
# Try normal loading
sf = sdl2ext.load_image(img_path)
assert isinstance(sf, surf.SDL_Surface)
# Force only PIL
if _HASPIL and fmt not in ("webp", "xcf", "lbm", "svg", "qoi"):
sf = sdl2ext.load_image(img_path, enforce="PIL")
assert isinstance(sf, surf.SDL_Surface)
# Force only sdlimage
sf = sdl2ext.load_image(img_path, enforce="SDL")
assert isinstance(sf, surf.SDL_Surface)
# Clean up surface now that we're done with it
surf.SDL_FreeSurface(sf)
|