0
# Image Loading and Processing
1
2
Image loading, saving, and manipulation through SDL2_image integration and surface operations. PySDL2 provides comprehensive support for various image formats and pixel-level manipulation.
3
4
## Capabilities
5
6
### Image Format Support
7
8
SDL2_image initialization and format support detection.
9
10
```python { .api }
11
def IMG_Init(flags: int) -> int:
12
"""
13
Initialize IMG with specific format support.
14
15
Parameters:
16
- flags: combination of IMG_INIT_* flags for desired formats
17
18
Returns:
19
Flags indicating successfully initialized formats
20
"""
21
22
def IMG_Quit() -> None:
23
"""Shut down IMG and free resources."""
24
25
def IMG_GetError() -> bytes:
26
"""Get last IMG error message."""
27
28
def IMG_SetError(fmt: bytes) -> None:
29
"""Set IMG error message."""
30
31
# Image format initialization flags
32
IMG_INIT_JPG: int = 0x00000001 # JPEG support
33
IMG_INIT_PNG: int = 0x00000002 # PNG support
34
IMG_INIT_TIF: int = 0x00000004 # TIFF support
35
IMG_INIT_WEBP: int = 0x00000008 # WebP support
36
IMG_INIT_JXL: int = 0x00000010 # JPEG XL support
37
IMG_INIT_AVIF: int = 0x00000020 # AVIF support
38
```
39
40
### Generic Image Loading
41
42
Functions for loading images from various sources.
43
44
```python { .api }
45
def IMG_Load(file: bytes) -> SDL_Surface:
46
"""
47
Load image from file (format auto-detected).
48
49
Parameters:
50
- file: path to image file as bytes
51
52
Returns:
53
SDL_Surface containing image or None on failure
54
"""
55
56
def IMG_Load_RW(src: SDL_RWops, freesrc: int) -> SDL_Surface:
57
"""Load image from SDL_RWops source."""
58
59
def IMG_LoadTyped_RW(src: SDL_RWops, freesrc: int, type: bytes) -> SDL_Surface:
60
"""
61
Load image from SDL_RWops with specified format.
62
63
Parameters:
64
- src: SDL_RWops source
65
- freesrc: whether to free source after loading
66
- type: image format hint (b"PNG", b"JPG", etc.)
67
68
Returns:
69
SDL_Surface containing image or None on failure
70
"""
71
72
def IMG_LoadTexture(renderer: SDL_Renderer, file: bytes) -> SDL_Texture:
73
"""
74
Load image directly as texture.
75
76
Parameters:
77
- renderer: renderer to create texture for
78
- file: path to image file as bytes
79
80
Returns:
81
SDL_Texture containing image or None on failure
82
"""
83
84
def IMG_LoadTexture_RW(renderer: SDL_Renderer, src: SDL_RWops, freesrc: int) -> SDL_Texture:
85
"""Load image as texture from SDL_RWops source."""
86
87
def IMG_LoadTextureTyped_RW(renderer: SDL_Renderer, src: SDL_RWops, freesrc: int, type: bytes) -> SDL_Texture:
88
"""Load image as texture from SDL_RWops with format hint."""
89
```
90
91
### Format-Specific Loading
92
93
Functions for loading specific image formats.
94
95
```python { .api }
96
def IMG_LoadBMP_RW(src: SDL_RWops) -> SDL_Surface:
97
"""Load BMP image from SDL_RWops."""
98
99
def IMG_LoadGIF_RW(src: SDL_RWops) -> SDL_Surface:
100
"""Load GIF image from SDL_RWops."""
101
102
def IMG_LoadJPG_RW(src: SDL_RWops) -> SDL_Surface:
103
"""Load JPEG image from SDL_RWops."""
104
105
def IMG_LoadLBM_RW(src: SDL_RWops) -> SDL_Surface:
106
"""Load LBM image from SDL_RWops."""
107
108
def IMG_LoadPCX_RW(src: SDL_RWops) -> SDL_Surface:
109
"""Load PCX image from SDL_RWops."""
110
111
def IMG_LoadPNG_RW(src: SDL_RWops) -> SDL_Surface:
112
"""Load PNG image from SDL_RWops."""
113
114
def IMG_LoadPNM_RW(src: SDL_RWops) -> SDL_Surface:
115
"""Load PNM image from SDL_RWops."""
116
117
def IMG_LoadSVG_RW(src: SDL_RWops) -> SDL_Surface:
118
"""Load SVG image from SDL_RWops."""
119
120
def IMG_LoadTGA_RW(src: SDL_RWops) -> SDL_Surface:
121
"""Load TGA image from SDL_RWops."""
122
123
def IMG_LoadTIF_RW(src: SDL_RWops) -> SDL_Surface:
124
"""Load TIFF image from SDL_RWops."""
125
126
def IMG_LoadWEBP_RW(src: SDL_RWops) -> SDL_Surface:
127
"""Load WebP image from SDL_RWops."""
128
129
def IMG_LoadXCF_RW(src: SDL_RWops) -> SDL_Surface:
130
"""Load XCF image from SDL_RWops."""
131
132
def IMG_LoadXPM_RW(src: SDL_RWops) -> SDL_Surface:
133
"""Load XPM image from SDL_RWops."""
134
135
def IMG_LoadXV_RW(src: SDL_RWops) -> SDL_Surface:
136
"""Load XV image from SDL_RWops."""
137
```
138
139
### Format Detection
140
141
Functions for detecting image formats.
142
143
```python { .api }
144
def IMG_isBMP(src: SDL_RWops) -> int:
145
"""Check if source contains BMP image."""
146
147
def IMG_isGIF(src: SDL_RWops) -> int:
148
"""Check if source contains GIF image."""
149
150
def IMG_isJPG(src: SDL_RWops) -> int:
151
"""Check if source contains JPEG image."""
152
153
def IMG_isLBM(src: SDL_RWops) -> int:
154
"""Check if source contains LBM image."""
155
156
def IMG_isPCX(src: SDL_RWops) -> int:
157
"""Check if source contains PCX image."""
158
159
def IMG_isPNG(src: SDL_RWops) -> int:
160
"""Check if source contains PNG image."""
161
162
def IMG_isPNM(src: SDL_RWops) -> int:
163
"""Check if source contains PNM image."""
164
165
def IMG_isSVG(src: SDL_RWops) -> int:
166
"""Check if source contains SVG image."""
167
168
def IMG_isTIF(src: SDL_RWops) -> int:
169
"""Check if source contains TIFF image."""
170
171
def IMG_isWEBP(src: SDL_RWops) -> int:
172
"""Check if source contains WebP image."""
173
174
def IMG_isXCF(src: SDL_RWops) -> int:
175
"""Check if source contains XCF image."""
176
177
def IMG_isXPM(src: SDL_RWops) -> int:
178
"""Check if source contains XPM image."""
179
180
def IMG_isXV(src: SDL_RWops) -> int:
181
"""Check if source contains XV image."""
182
```
183
184
### Image Saving
185
186
Functions for saving images to files.
187
188
```python { .api }
189
def IMG_SavePNG(surface: SDL_Surface, file: bytes) -> int:
190
"""
191
Save surface as PNG file.
192
193
Parameters:
194
- surface: surface to save
195
- file: output file path as bytes
196
197
Returns:
198
0 on success, -1 on failure
199
"""
200
201
def IMG_SavePNG_RW(surface: SDL_Surface, dst: SDL_RWops, freedst: int) -> int:
202
"""Save surface as PNG to SDL_RWops destination."""
203
204
def IMG_SaveJPG(surface: SDL_Surface, file: bytes, quality: int) -> int:
205
"""
206
Save surface as JPEG file.
207
208
Parameters:
209
- surface: surface to save
210
- file: output file path as bytes
211
- quality: JPEG quality (0-100)
212
213
Returns:
214
0 on success, -1 on failure
215
"""
216
217
def IMG_SaveJPG_RW(surface: SDL_Surface, dst: SDL_RWops, freedst: int, quality: int) -> int:
218
"""Save surface as JPEG to SDL_RWops destination."""
219
```
220
221
### High-Level Image Utilities
222
223
Extension module functions for simplified image handling.
224
225
```python { .api }
226
def get_image_formats() -> list[str]:
227
"""
228
Get list of supported image formats.
229
230
Returns:
231
List of supported format strings (e.g., ["PNG", "JPEG", "BMP"])
232
"""
233
234
def load_img(file: str) -> SDL_Surface:
235
"""
236
Load image from file (high-level wrapper).
237
238
Parameters:
239
- file: path to image file as string
240
241
Returns:
242
SDL_Surface containing image or None on failure
243
"""
244
245
def load_bmp(file: str) -> SDL_Surface:
246
"""
247
Load BMP image from file.
248
249
Parameters:
250
- file: path to BMP file as string
251
252
Returns:
253
SDL_Surface containing image or None on failure
254
"""
255
256
def save_bmp(surface: SDL_Surface, file: str) -> None:
257
"""
258
Save surface as BMP file.
259
260
Parameters:
261
- surface: surface to save
262
- file: output file path as string
263
"""
264
265
def load_svg(file: str, width: int = None, height: int = None) -> SDL_Surface:
266
"""
267
Load SVG image from file with optional size.
268
269
Parameters:
270
- file: path to SVG file as string
271
- width: desired width (None for original)
272
- height: desired height (None for original)
273
274
Returns:
275
SDL_Surface containing rendered SVG or None on failure
276
"""
277
```
278
279
### Pixel Access and Manipulation
280
281
Functions for direct pixel manipulation on surfaces.
282
283
```python { .api }
284
def pixels2d(surface: SDL_Surface) -> PixelView:
285
"""
286
Get 2D array view of surface pixels.
287
288
Parameters:
289
- surface: surface to access
290
291
Returns:
292
PixelView object for 2D pixel access
293
"""
294
295
def pixels3d(surface: SDL_Surface) -> PixelView:
296
"""
297
Get 3D array view of surface pixels (with RGB components).
298
299
Parameters:
300
- surface: surface to access
301
302
Returns:
303
PixelView object for 3D pixel access
304
"""
305
306
def surface_to_ndarray(surface: SDL_Surface, dtype: type = None) -> object:
307
"""
308
Convert surface to NumPy-like array.
309
310
Parameters:
311
- surface: surface to convert
312
- dtype: desired array data type
313
314
Returns:
315
Array object compatible with NumPy operations
316
"""
317
318
class PixelView:
319
"""2D/3D view of surface pixels for direct manipulation."""
320
321
def __init__(self, surface: SDL_Surface, transpose: bool = True):
322
"""
323
Create pixel view for surface.
324
325
Parameters:
326
- surface: surface to create view for
327
- transpose: whether to transpose array dimensions
328
"""
329
330
def __getitem__(self, key) -> int:
331
"""Get pixel value at coordinates."""
332
333
def __setitem__(self, key, value: int) -> None:
334
"""Set pixel value at coordinates."""
335
336
@property
337
def ndim(self) -> int:
338
"""Get number of dimensions."""
339
340
@property
341
def shape(self) -> tuple[int, ...]:
342
"""Get array shape."""
343
344
@property
345
def strides(self) -> tuple[int, ...]:
346
"""Get array strides."""
347
348
class SurfaceArray:
349
"""Array interface for surface manipulation."""
350
351
def __init__(self, surface: SDL_Surface):
352
"""
353
Create surface array.
354
355
Parameters:
356
- surface: surface to wrap
357
"""
358
359
def __array__(self) -> object:
360
"""Convert to array object."""
361
```
362
363
### Color Key and Alpha
364
365
Functions for transparency and color key operations.
366
367
```python { .api }
368
def SDL_SetColorKey(surface: SDL_Surface, flag: int, key: int) -> int:
369
"""
370
Set color key (transparent color) for surface.
371
372
Parameters:
373
- surface: surface to modify
374
- flag: SDL_TRUE to enable, SDL_FALSE to disable
375
- key: color value to treat as transparent
376
377
Returns:
378
0 on success, -1 on failure
379
"""
380
381
def SDL_GetColorKey(surface: SDL_Surface, key: ctypes.POINTER(ctypes.c_uint32)) -> int:
382
"""Get color key for surface."""
383
384
def SDL_SetSurfaceAlphaMod(surface: SDL_Surface, alpha: int) -> int:
385
"""
386
Set surface alpha modulation (0-255).
387
388
Parameters:
389
- surface: surface to modify
390
- alpha: alpha value (0=transparent, 255=opaque)
391
392
Returns:
393
0 on success, -1 on failure
394
"""
395
396
def SDL_GetSurfaceAlphaMod(surface: SDL_Surface, alpha: ctypes.POINTER(ctypes.c_uint8)) -> int:
397
"""Get surface alpha modulation."""
398
399
def SDL_SetSurfaceColorMod(surface: SDL_Surface, r: int, g: int, b: int) -> int:
400
"""
401
Set surface color modulation.
402
403
Parameters:
404
- surface: surface to modify
405
- r, g, b: color modulation values (0-255 each)
406
407
Returns:
408
0 on success, -1 on failure
409
"""
410
411
def SDL_GetSurfaceColorMod(surface: SDL_Surface, r: ctypes.POINTER(ctypes.c_uint8),
412
g: ctypes.POINTER(ctypes.c_uint8), b: ctypes.POINTER(ctypes.c_uint8)) -> int:
413
"""Get surface color modulation."""
414
415
def SDL_SetSurfaceBlendMode(surface: SDL_Surface, blendMode: int) -> int:
416
"""Set surface blend mode."""
417
418
def SDL_GetSurfaceBlendMode(surface: SDL_Surface, blendMode: ctypes.POINTER(ctypes.c_int)) -> int:
419
"""Get surface blend mode."""
420
```
421
422
### Surface Format Conversion
423
424
Functions for converting between pixel formats.
425
426
```python { .api }
427
def SDL_ConvertSurface(src: SDL_Surface, fmt: SDL_PixelFormat, flags: int) -> SDL_Surface:
428
"""
429
Convert surface to specified pixel format.
430
431
Parameters:
432
- src: source surface
433
- fmt: target pixel format
434
- flags: conversion flags
435
436
Returns:
437
New surface with converted format or None on failure
438
"""
439
440
def SDL_ConvertSurfaceFormat(src: SDL_Surface, pixel_format: int, flags: int) -> SDL_Surface:
441
"""
442
Convert surface to specified pixel format constant.
443
444
Parameters:
445
- src: source surface
446
- pixel_format: target pixel format constant
447
- flags: conversion flags
448
449
Returns:
450
New surface with converted format or None on failure
451
"""
452
453
def SDL_CreateRGBSurfaceWithFormat(flags: int, width: int, height: int, depth: int, format: int) -> SDL_Surface:
454
"""Create surface with specific pixel format."""
455
456
def SDL_CreateRGBSurfaceWithFormatFrom(pixels: ctypes.c_void_p, width: int, height: int,
457
depth: int, pitch: int, format: int) -> SDL_Surface:
458
"""Create surface from existing pixel data."""
459
```
460
461
## Usage Examples
462
463
### Basic Image Loading and Display
464
465
```python
466
import sdl2
467
import sdl2.sdlimage
468
import sdl2.ext
469
470
# Initialize SDL2 and SDL2_image
471
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
472
sdl2.sdlimage.IMG_Init(sdl2.sdlimage.IMG_INIT_PNG | sdl2.sdlimage.IMG_INIT_JPG)
473
474
# Create window and renderer
475
window = sdl2.SDL_CreateWindow(b"Image Display",
476
sdl2.SDL_WINDOWPOS_CENTERED, sdl2.SDL_WINDOWPOS_CENTERED,
477
800, 600, sdl2.SDL_WINDOW_SHOWN)
478
renderer = sdl2.SDL_CreateRenderer(window, -1, sdl2.SDL_RENDERER_ACCELERATED)
479
480
# Load image directly as texture
481
texture = sdl2.sdlimage.IMG_LoadTexture(renderer, b"image.png")
482
if not texture:
483
print(f"Failed to load image: {sdl2.sdlimage.IMG_GetError()}")
484
exit(1)
485
486
# Get image dimensions
487
w = ctypes.c_int()
488
h = ctypes.c_int()
489
sdl2.SDL_QueryTexture(texture, None, None, w, h)
490
491
# Main loop
492
running = True
493
event = sdl2.SDL_Event()
494
495
while running:
496
while sdl2.SDL_PollEvent(event):
497
if event.type == sdl2.SDL_QUIT:
498
running = False
499
500
# Clear screen
501
sdl2.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255)
502
sdl2.SDL_RenderClear(renderer)
503
504
# Render image centered
505
dest_rect = sdl2.SDL_Rect(
506
(800 - w.value) // 2,
507
(600 - h.value) // 2,
508
w.value,
509
h.value
510
)
511
sdl2.SDL_RenderCopy(renderer, texture, None, dest_rect)
512
513
sdl2.SDL_RenderPresent(renderer)
514
515
# Cleanup
516
sdl2.SDL_DestroyTexture(texture)
517
sdl2.SDL_DestroyRenderer(renderer)
518
sdl2.SDL_DestroyWindow(window)
519
sdl2.sdlimage.IMG_Quit()
520
sdl2.SDL_Quit()
521
```
522
523
### High-Level Image Loading with Extensions
524
525
```python
526
import sdl2.ext
527
528
# Initialize SDL2 extensions (automatically initializes SDL2_image)
529
sdl2.ext.init()
530
531
# Create window and renderer
532
window = sdl2.ext.Window("Image Example", size=(800, 600))
533
window.show()
534
renderer = sdl2.ext.Renderer(window)
535
536
# Check supported formats
537
formats = sdl2.ext.get_image_formats()
538
print(f"Supported formats: {formats}")
539
540
# Load images using high-level functions
541
try:
542
# Load various formats
543
png_surface = sdl2.ext.load_img("image.png")
544
jpg_surface = sdl2.ext.load_img("photo.jpg")
545
bmp_surface = sdl2.ext.load_bmp("sprite.bmp")
546
547
# Convert surfaces to textures
548
png_texture = sdl2.ext.Texture(renderer, png_surface)
549
jpg_texture = sdl2.ext.Texture(renderer, jpg_surface)
550
bmp_texture = sdl2.ext.Texture(renderer, bmp_surface)
551
552
# Free surfaces (textures have copies)
553
sdl2.SDL_FreeSurface(png_surface)
554
sdl2.SDL_FreeSurface(jpg_surface)
555
sdl2.SDL_FreeSurface(bmp_surface)
556
557
# Main loop
558
running = True
559
while running:
560
events = sdl2.ext.get_events()
561
for event in events:
562
if event.type == sdl2.SDL_QUIT:
563
running = False
564
565
# Clear and render images
566
renderer.clear((50, 50, 50))
567
568
# Render images side by side
569
renderer.copy(png_texture, dstrect=sdl2.SDL_Rect(50, 50, 200, 200))
570
renderer.copy(jpg_texture, dstrect=sdl2.SDL_Rect(300, 50, 200, 200))
571
renderer.copy(bmp_texture, dstrect=sdl2.SDL_Rect(550, 50, 200, 200))
572
573
renderer.present()
574
575
except Exception as e:
576
print(f"Error loading images: {e}")
577
578
sdl2.ext.quit()
579
```
580
581
### Pixel Manipulation
582
583
```python
584
import sdl2
585
import sdl2.ext
586
587
# Initialize SDL2
588
sdl2.ext.init()
589
590
# Create surface for pixel manipulation
591
surface = sdl2.SDL_CreateRGBSurface(0, 256, 256, 32, 0, 0, 0, 0)
592
593
# Get pixel view for direct access
594
pixel_view = sdl2.ext.pixels2d(surface)
595
596
# Create gradient pattern
597
for x in range(256):
598
for y in range(256):
599
# Create RGB color from coordinates
600
r = x
601
g = y
602
b = (x + y) // 2
603
604
# Pack RGB into pixel format (assuming 32-bit RGB)
605
color = (r << 16) | (g << 8) | b
606
pixel_view[x, y] = color
607
608
# Create window and renderer
609
window = sdl2.ext.Window("Pixel Manipulation", size=(512, 512))
610
window.show()
611
renderer = sdl2.ext.Renderer(window)
612
613
# Convert surface to texture
614
texture = sdl2.ext.Texture(renderer, surface)
615
616
# Main loop
617
running = True
618
while running:
619
events = sdl2.ext.get_events()
620
for event in events:
621
if event.type == sdl2.SDL_QUIT:
622
running = False
623
624
# Render gradient
625
renderer.clear((0, 0, 0))
626
renderer.copy(texture, dstrect=sdl2.SDL_Rect(128, 128, 256, 256))
627
renderer.present()
628
629
# Cleanup
630
sdl2.SDL_FreeSurface(surface)
631
sdl2.ext.quit()
632
```
633
634
### Image Format Conversion and Saving
635
636
```python
637
import sdl2
638
import sdl2.sdlimage
639
640
# Initialize
641
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
642
sdl2.sdlimage.IMG_Init(sdl2.sdlimage.IMG_INIT_PNG | sdl2.sdlimage.IMG_INIT_JPG)
643
644
# Load image
645
surface = sdl2.sdlimage.IMG_Load(b"input.jpg")
646
if not surface:
647
print("Failed to load image")
648
exit(1)
649
650
print(f"Original format: {surface.contents.format.contents.BitsPerPixel} bpp")
651
652
# Convert to different pixel format (24-bit RGB)
653
rgb_surface = sdl2.SDL_ConvertSurfaceFormat(surface, sdl2.SDL_PIXELFORMAT_RGB24, 0)
654
655
# Save as PNG
656
result = sdl2.sdlimage.IMG_SavePNG(rgb_surface, b"output.png")
657
if result != 0:
658
print(f"Failed to save PNG: {sdl2.sdlimage.IMG_GetError()}")
659
660
# Save as JPEG with quality setting
661
result = sdl2.sdlimage.IMG_SaveJPG(rgb_surface, b"output_quality.jpg", 90)
662
if result != 0:
663
print(f"Failed to save JPEG: {sdl2.sdlimage.IMG_GetError()}")
664
665
# Save as BMP using SDL function
666
result = sdl2.SDL_SaveBMP(rgb_surface, b"output.bmp")
667
if result != 0:
668
print(f"Failed to save BMP: {sdl2.SDL_GetError()}")
669
670
# Cleanup
671
sdl2.SDL_FreeSurface(rgb_surface)
672
sdl2.SDL_FreeSurface(surface)
673
sdl2.sdlimage.IMG_Quit()
674
sdl2.SDL_Quit()
675
676
print("Image conversion and saving completed!")
677
```
678
679
### Color Key and Transparency
680
681
```python
682
import sdl2
683
import sdl2.sdlimage
684
import sdl2.ext
685
686
# Initialize
687
sdl2.ext.init()
688
window = sdl2.ext.Window("Transparency Example", size=(800, 600))
689
window.show()
690
renderer = sdl2.ext.Renderer(window)
691
692
# Load sprite with transparent background
693
sprite_surface = sdl2.sdlimage.IMG_Load(b"sprite_with_magenta_bg.png")
694
695
# Set magenta (255, 0, 255) as transparent color key
696
magenta = sdl2.SDL_MapRGB(sprite_surface.contents.format, 255, 0, 255)
697
sdl2.SDL_SetColorKey(sprite_surface, sdl2.SDL_TRUE, magenta)
698
699
# Create texture from surface
700
sprite_texture = sdl2.ext.Texture(renderer, sprite_surface)
701
sdl2.SDL_FreeSurface(sprite_surface)
702
703
# Load background image
704
bg_surface = sdl2.sdlimage.IMG_Load(b"background.jpg")
705
bg_texture = sdl2.ext.Texture(renderer, bg_surface)
706
sdl2.SDL_FreeSurface(bg_surface)
707
708
# Main loop
709
sprite_x = 0
710
running = True
711
712
while running:
713
events = sdl2.ext.get_events()
714
for event in events:
715
if event.type == sdl2.SDL_QUIT:
716
running = False
717
718
# Move sprite across screen
719
sprite_x += 2
720
if sprite_x > 800:
721
sprite_x = -64
722
723
# Render background
724
renderer.clear((0, 0, 0))
725
renderer.copy(bg_texture)
726
727
# Render sprite with transparency
728
renderer.copy(sprite_texture, dstrect=sdl2.SDL_Rect(sprite_x, 200, 64, 64))
729
730
renderer.present()
731
732
sdl2.ext.quit()
733
```