0
# Preview and Display
1
2
Preview system supporting multiple display methods including Qt widgets, DRM/KMS direct rendering, and headless operation. The preview system provides real-time camera feed display with overlay support and platform-specific optimizations.
3
4
## Capabilities
5
6
### Preview Control
7
8
Start, stop, and manage camera preview display.
9
10
```python { .api }
11
def start_preview(
12
self,
13
preview: Preview = None,
14
**kwargs
15
):
16
"""
17
Start camera preview display.
18
19
Parameters:
20
- preview: Preview type ("null", "drm", "qt", "qtgl") or Preview object
21
- **kwargs: Preview-specific parameters
22
23
Common kwargs:
24
- width: int, preview window width
25
- height: int, preview window height
26
- x: int, window x position
27
- y: int, window y position
28
- fullscreen: bool, fullscreen display
29
- title: str, window title
30
31
Raises:
32
- RuntimeError: If preview system fails to initialize
33
"""
34
35
def stop_preview(self):
36
"""
37
Stop camera preview display.
38
39
Closes preview window and releases display resources.
40
"""
41
42
def attach_preview(self, preview):
43
"""
44
Attach custom preview object.
45
46
Parameters:
47
- preview: Preview instance (NullPreview, DrmPreview, etc.)
48
"""
49
50
def detach_preview(self):
51
"""
52
Detach current preview object.
53
54
Preview remains running but is no longer managed by camera.
55
"""
56
57
def set_overlay(self, overlay):
58
"""
59
Set preview overlay content.
60
61
Parameters:
62
- overlay: PIL Image or numpy array for overlay graphics
63
"""
64
```
65
66
### Preview Types
67
68
Enumeration of available preview display methods.
69
70
```python { .api }
71
class Preview(Enum):
72
"""Preview display types."""
73
74
NULL = "null" # No display (headless)
75
DRM = "drm" # Direct DRM/KMS rendering
76
QT = "qt" # Qt widget display
77
QTGL = "qtgl" # Qt OpenGL display
78
```
79
80
### Preview Classes
81
82
Base preview interface and concrete implementations.
83
84
```python { .api }
85
class PreviewBase:
86
"""Base class for preview implementations."""
87
88
def __init__(self, **kwargs):
89
"""
90
Initialize preview with parameters.
91
92
Common parameters:
93
- width: int, display width
94
- height: int, display height
95
- x: int, window x position
96
- y: int, window y position
97
"""
98
99
def start(self, picam2: Picamera2):
100
"""
101
Start preview with camera instance.
102
103
Parameters:
104
- picam2: Picamera2 instance providing frames
105
"""
106
107
def stop(self):
108
"""Stop preview and clean up resources."""
109
110
def set_overlay(self, overlay):
111
"""
112
Set overlay graphics.
113
114
Parameters:
115
- overlay: PIL Image or numpy array
116
"""
117
118
def render_request(self, completed_request: CompletedRequest):
119
"""
120
Render frame from completed request.
121
122
Parameters:
123
- completed_request: CompletedRequest with frame data
124
"""
125
126
class NullPreview(PreviewBase):
127
"""
128
Null preview for headless operation.
129
130
Provides preview interface without actual display.
131
Useful for server applications and automated capture.
132
"""
133
134
class DrmPreview(PreviewBase):
135
"""
136
Direct rendering via DRM/KMS.
137
138
High-performance preview using direct hardware access.
139
Requires DRM/KMS support and appropriate permissions.
140
141
Parameters:
142
- x: int, display x offset
143
- y: int, display y offset
144
- width: int, display width (0 = full screen width)
145
- height: int, display height (0 = full screen height)
146
- plane_alpha: float, alpha blending (0.0-1.0)
147
"""
148
149
class QtPreview(PreviewBase):
150
"""
151
Qt widget-based preview display.
152
153
Cross-platform preview using Qt framework.
154
Provides window management and user interaction.
155
156
Parameters:
157
- parent: QWidget, parent widget
158
- width: int, window width
159
- height: int, window height
160
- keep_ar: bool, maintain aspect ratio
161
- title: str, window title
162
"""
163
164
class QtGlPreview(PreviewBase):
165
"""
166
Qt OpenGL-based preview display.
167
168
Hardware-accelerated preview using OpenGL rendering.
169
Provides better performance than QtPreview for high-resolution streams.
170
171
Parameters: Same as QtPreview plus:
172
- shader: str, custom fragment shader
173
- vertex_shader: str, custom vertex shader
174
"""
175
```
176
177
## Usage Examples
178
179
### Basic Preview
180
181
```python
182
from picamera2 import Picamera2, Preview
183
184
picam2 = Picamera2()
185
preview_config = picam2.create_preview_configuration()
186
picam2.configure(preview_config)
187
188
# Start with automatic preview detection
189
picam2.start(show_preview=True)
190
191
# Or explicitly start preview
192
picam2.start()
193
picam2.start_preview()
194
195
# Keep preview running
196
input("Press Enter to stop preview...")
197
198
picam2.stop_preview()
199
picam2.close()
200
```
201
202
### Specific Preview Types
203
204
```python
205
from picamera2 import Picamera2, Preview
206
207
picam2 = Picamera2()
208
picam2.configure(picam2.create_preview_configuration())
209
picam2.start()
210
211
# Qt widget preview with custom window
212
picam2.start_preview(Preview.QT, width=800, height=600, title="Camera Feed")
213
214
time.sleep(5)
215
216
# Switch to OpenGL preview for better performance
217
picam2.stop_preview()
218
picam2.start_preview(Preview.QTGL, width=1024, height=768)
219
220
time.sleep(5)
221
picam2.stop_preview()
222
picam2.close()
223
```
224
225
### DRM Preview (Raspberry Pi)
226
227
```python
228
from picamera2 import Picamera2, Preview
229
230
picam2 = Picamera2()
231
picam2.configure(picam2.create_preview_configuration())
232
picam2.start()
233
234
# Full-screen DRM preview (requires root or appropriate permissions)
235
picam2.start_preview(Preview.DRM,
236
x=0, y=0,
237
width=0, height=0, # 0 = full screen
238
plane_alpha=1.0)
239
240
input("Press Enter to stop full-screen preview...")
241
picam2.stop_preview()
242
picam2.close()
243
```
244
245
### Custom Preview Object
246
247
```python
248
from picamera2 import Picamera2
249
from picamera2.previews import QtPreview
250
251
picam2 = Picamera2()
252
picam2.configure(picam2.create_preview_configuration())
253
254
# Create custom preview with specific settings
255
preview = QtPreview(width=640, height=480, keep_ar=True, title="My Camera")
256
257
# Attach and start
258
picam2.attach_preview(preview)
259
picam2.start()
260
261
# Preview is now active
262
time.sleep(10)
263
264
# Can detach for independent control
265
picam2.detach_preview()
266
# Preview continues running independently
267
268
# Stop preview manually
269
preview.stop()
270
picam2.close()
271
```
272
273
### Preview with Overlay
274
275
```python
276
from picamera2 import Picamera2, Preview
277
from PIL import Image, ImageDraw, ImageFont
278
import numpy as np
279
280
picam2 = Picamera2()
281
picam2.configure(picam2.create_preview_configuration())
282
picam2.start()
283
picam2.start_preview(Preview.QT)
284
285
# Create overlay graphics
286
overlay = Image.new("RGBA", (640, 480), (0, 0, 0, 0)) # Transparent
287
draw = ImageDraw.Draw(overlay)
288
289
# Draw overlay elements
290
draw.rectangle([10, 10, 200, 50], fill=(255, 0, 0, 128)) # Semi-transparent red
291
draw.text((20, 20), "RECORDING", fill=(255, 255, 255, 255))
292
293
# Apply overlay to preview
294
picam2.set_overlay(overlay)
295
296
time.sleep(10)
297
298
# Update overlay
299
draw.rectangle([10, 60, 200, 100], fill=(0, 255, 0, 128)) # Green bar
300
draw.text((20, 70), "LIVE", fill=(255, 255, 255, 255))
301
picam2.set_overlay(overlay)
302
303
time.sleep(5)
304
305
# Remove overlay
306
picam2.set_overlay(None)
307
308
picam2.stop_preview()
309
picam2.close()
310
```
311
312
### Dynamic Overlay Updates
313
314
```python
315
from picamera2 import Picamera2, Preview
316
from PIL import Image, ImageDraw
317
import threading
318
import time
319
import datetime
320
321
picam2 = Picamera2()
322
picam2.configure(picam2.create_preview_configuration())
323
picam2.start()
324
picam2.start_preview(Preview.QT)
325
326
def update_overlay():
327
"""Update overlay with current timestamp."""
328
while running:
329
# Create overlay with timestamp
330
overlay = Image.new("RGBA", (640, 480), (0, 0, 0, 0))
331
draw = ImageDraw.Draw(overlay)
332
333
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
334
draw.rectangle([10, 10, 300, 40], fill=(0, 0, 0, 128))
335
draw.text((15, 18), timestamp, fill=(255, 255, 255, 255))
336
337
picam2.set_overlay(overlay)
338
time.sleep(1)
339
340
# Start overlay update thread
341
running = True
342
overlay_thread = threading.Thread(target=update_overlay)
343
overlay_thread.start()
344
345
input("Press Enter to stop...")
346
347
# Stop overlay updates
348
running = False
349
overlay_thread.join()
350
351
picam2.stop_preview()
352
picam2.close()
353
```
354
355
### Headless Operation
356
357
```python
358
from picamera2 import Picamera2, Preview
359
360
# For server/headless applications
361
picam2 = Picamera2()
362
picam2.configure(picam2.create_preview_configuration())
363
picam2.start()
364
365
# Use null preview (no display)
366
picam2.start_preview(Preview.NULL)
367
368
# Camera runs without display - good for capture-only applications
369
for i in range(10):
370
picam2.capture_file(f"headless_{i:03d}.jpg")
371
time.sleep(1)
372
373
picam2.stop_preview()
374
picam2.close()
375
```
376
377
### Preview Stream Selection
378
379
```python
380
from picamera2 import Picamera2, Preview
381
382
picam2 = Picamera2()
383
384
# Configure with multiple streams
385
config = picam2.create_video_configuration(
386
main={"size": (1920, 1080), "format": "YUV420"},
387
lores={"size": (640, 480), "format": "YUV420"}
388
)
389
390
# Specify which stream to display
391
config.display = "lores" # Use low-res stream for preview
392
393
picam2.configure(config)
394
picam2.start()
395
picam2.start_preview(Preview.QT)
396
397
# Preview shows low-res stream while main stream can be used for recording
398
# This reduces preview overhead while maintaining recording quality
399
400
time.sleep(10)
401
picam2.stop_preview()
402
picam2.close()
403
```
404
405
### Platform-Specific Preview
406
407
```python
408
from picamera2 import Picamera2, Preview
409
from picamera2.platform import Platform, get_platform
410
411
picam2 = Picamera2()
412
picam2.configure(picam2.create_preview_configuration())
413
picam2.start()
414
415
# Choose preview based on platform capabilities
416
platform = get_platform()
417
418
if platform == Platform.VC4:
419
# Raspberry Pi 4 and earlier - use DRM for best performance
420
picam2.start_preview(Preview.DRM)
421
elif platform == Platform.PISP:
422
# Raspberry Pi 5 - can use Qt or DRM
423
picam2.start_preview(Preview.QTGL) # Hardware accelerated
424
else:
425
# Generic platform
426
picam2.start_preview(Preview.QT)
427
428
time.sleep(10)
429
picam2.stop_preview()
430
picam2.close()
431
```