pyglet 2.1.12__py3-none-any.whl → 3.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglet/__init__.py +67 -61
- pyglet/__init__.pyi +15 -8
- pyglet/app/__init__.py +22 -13
- pyglet/app/async_app.py +212 -0
- pyglet/app/base.py +2 -1
- pyglet/app/{xlib.py → linux.py} +3 -3
- pyglet/config/__init__.py +101 -0
- pyglet/config/gl/__init__.py +30 -0
- pyglet/config/gl/egl.py +120 -0
- pyglet/config/gl/macos.py +262 -0
- pyglet/config/gl/windows.py +267 -0
- pyglet/config/gl/x11.py +142 -0
- pyglet/customtypes.py +43 -2
- pyglet/display/__init__.py +8 -6
- pyglet/display/base.py +3 -63
- pyglet/display/cocoa.py +12 -17
- pyglet/display/emscripten.py +39 -0
- pyglet/display/headless.py +23 -30
- pyglet/display/wayland.py +157 -0
- pyglet/display/win32.py +4 -17
- pyglet/display/xlib.py +19 -27
- pyglet/display/xlib_vidmoderestore.py +2 -2
- pyglet/enums.py +183 -0
- pyglet/event.py +0 -1
- pyglet/experimental/geoshader_sprite.py +15 -13
- pyglet/experimental/hidraw.py +6 -15
- pyglet/experimental/multitexture_sprite.py +31 -19
- pyglet/experimental/particles.py +13 -35
- pyglet/font/__init__.py +251 -85
- pyglet/font/base.py +116 -61
- pyglet/font/dwrite/__init__.py +349 -204
- pyglet/font/dwrite/dwrite_lib.py +27 -5
- pyglet/font/fontconfig.py +14 -6
- pyglet/font/freetype.py +138 -87
- pyglet/font/freetype_lib.py +19 -0
- pyglet/font/group.py +179 -0
- pyglet/font/harfbuzz/__init__.py +3 -3
- pyglet/font/pyodide_js.py +310 -0
- pyglet/font/quartz.py +319 -126
- pyglet/font/ttf.py +45 -3
- pyglet/font/user.py +14 -19
- pyglet/font/win32.py +45 -21
- pyglet/graphics/__init__.py +8 -787
- pyglet/graphics/allocation.py +115 -1
- pyglet/graphics/api/__init__.py +77 -0
- pyglet/graphics/api/base.py +299 -0
- pyglet/graphics/api/gl/__init__.py +58 -0
- pyglet/graphics/api/gl/base.py +24 -0
- pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
- pyglet/graphics/api/gl/cocoa/context.py +76 -0
- pyglet/graphics/api/gl/context.py +391 -0
- pyglet/graphics/api/gl/default_shaders.py +0 -0
- pyglet/graphics/api/gl/draw.py +627 -0
- pyglet/graphics/api/gl/egl/__init__.py +0 -0
- pyglet/graphics/api/gl/egl/context.py +92 -0
- pyglet/graphics/api/gl/enums.py +76 -0
- pyglet/graphics/api/gl/framebuffer.py +315 -0
- pyglet/graphics/api/gl/gl.py +5463 -0
- pyglet/graphics/api/gl/gl_info.py +188 -0
- pyglet/graphics/api/gl/global_opengl.py +226 -0
- pyglet/{gl → graphics/api/gl}/lib.py +34 -18
- pyglet/graphics/api/gl/shader.py +1476 -0
- pyglet/graphics/api/gl/shapes.py +55 -0
- pyglet/graphics/api/gl/sprite.py +102 -0
- pyglet/graphics/api/gl/state.py +219 -0
- pyglet/graphics/api/gl/text.py +190 -0
- pyglet/graphics/api/gl/texture.py +1526 -0
- pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
- pyglet/graphics/api/gl/vertexdomain.py +751 -0
- pyglet/graphics/api/gl/win32/__init__.py +0 -0
- pyglet/graphics/api/gl/win32/context.py +108 -0
- pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
- pyglet/graphics/api/gl/xlib/__init__.py +0 -0
- pyglet/graphics/api/gl/xlib/context.py +174 -0
- pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
- pyglet/graphics/api/gl1/__init__.py +0 -0
- pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
- pyglet/graphics/api/gl2/__init__.py +0 -0
- pyglet/graphics/api/gl2/buffer.py +320 -0
- pyglet/graphics/api/gl2/draw.py +600 -0
- pyglet/graphics/api/gl2/global_opengl.py +122 -0
- pyglet/graphics/api/gl2/shader.py +200 -0
- pyglet/graphics/api/gl2/shapes.py +51 -0
- pyglet/graphics/api/gl2/sprite.py +79 -0
- pyglet/graphics/api/gl2/text.py +175 -0
- pyglet/graphics/api/gl2/vertexdomain.py +364 -0
- pyglet/graphics/api/webgl/__init__.py +233 -0
- pyglet/graphics/api/webgl/buffer.py +302 -0
- pyglet/graphics/api/webgl/context.py +234 -0
- pyglet/graphics/api/webgl/draw.py +590 -0
- pyglet/graphics/api/webgl/enums.py +76 -0
- pyglet/graphics/api/webgl/framebuffer.py +360 -0
- pyglet/graphics/api/webgl/gl.py +1537 -0
- pyglet/graphics/api/webgl/gl_info.py +130 -0
- pyglet/graphics/api/webgl/shader.py +1346 -0
- pyglet/graphics/api/webgl/shapes.py +92 -0
- pyglet/graphics/api/webgl/sprite.py +102 -0
- pyglet/graphics/api/webgl/state.py +227 -0
- pyglet/graphics/api/webgl/text.py +187 -0
- pyglet/graphics/api/webgl/texture.py +1227 -0
- pyglet/graphics/api/webgl/vertexarray.py +54 -0
- pyglet/graphics/api/webgl/vertexdomain.py +616 -0
- pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
- pyglet/{image → graphics}/atlas.py +33 -32
- pyglet/graphics/base.py +10 -0
- pyglet/graphics/buffer.py +245 -0
- pyglet/graphics/draw.py +578 -0
- pyglet/graphics/framebuffer.py +26 -0
- pyglet/graphics/instance.py +178 -69
- pyglet/graphics/shader.py +267 -1553
- pyglet/graphics/state.py +83 -0
- pyglet/graphics/texture.py +703 -0
- pyglet/graphics/vertexdomain.py +695 -538
- pyglet/gui/ninepatch.py +10 -10
- pyglet/gui/widgets.py +120 -10
- pyglet/image/__init__.py +20 -1973
- pyglet/image/animation.py +12 -12
- pyglet/image/base.py +730 -0
- pyglet/image/codecs/__init__.py +9 -0
- pyglet/image/codecs/bmp.py +53 -30
- pyglet/image/codecs/dds.py +53 -31
- pyglet/image/codecs/gdiplus.py +38 -14
- pyglet/image/codecs/gdkpixbuf2.py +0 -2
- pyglet/image/codecs/js_image.py +99 -0
- pyglet/image/codecs/ktx2.py +161 -0
- pyglet/image/codecs/pil.py +1 -1
- pyglet/image/codecs/png.py +1 -1
- pyglet/image/codecs/wic.py +11 -2
- pyglet/info.py +26 -24
- pyglet/input/__init__.py +8 -0
- pyglet/input/base.py +163 -105
- pyglet/input/controller.py +13 -19
- pyglet/input/controller_db.py +39 -24
- pyglet/input/emscripten/__init__.py +18 -0
- pyglet/input/emscripten/gamepad_js.py +397 -0
- pyglet/input/linux/__init__.py +11 -5
- pyglet/input/linux/evdev.py +10 -11
- pyglet/input/linux/x11_xinput.py +2 -2
- pyglet/input/linux/x11_xinput_tablet.py +1 -1
- pyglet/input/macos/__init__.py +7 -2
- pyglet/input/macos/darwin_gc.py +559 -0
- pyglet/input/win32/__init__.py +1 -1
- pyglet/input/win32/directinput.py +34 -29
- pyglet/input/win32/xinput.py +11 -61
- pyglet/lib.py +3 -3
- pyglet/libs/__init__.py +1 -1
- pyglet/{gl → libs/darwin}/agl.py +1 -1
- pyglet/libs/darwin/cocoapy/__init__.py +2 -2
- pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
- pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
- pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
- pyglet/libs/darwin/cocoapy/runtime.py +81 -45
- pyglet/libs/darwin/coreaudio.py +4 -4
- pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
- pyglet/libs/darwin/quartzkey.py +1 -3
- pyglet/libs/egl/__init__.py +2 -0
- pyglet/libs/egl/egl_lib.py +576 -0
- pyglet/libs/egl/eglext.py +51 -5
- pyglet/libs/linux/__init__.py +0 -0
- pyglet/libs/linux/egl/__init__.py +0 -0
- pyglet/libs/linux/egl/eglext.py +22 -0
- pyglet/libs/linux/glx/__init__.py +0 -0
- pyglet/{gl → libs/linux/glx}/glx.py +13 -14
- pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
- pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
- pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
- pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
- pyglet/libs/linux/wayland/__init__.py +0 -0
- pyglet/libs/linux/wayland/client.py +1068 -0
- pyglet/libs/linux/wayland/lib_wayland.py +207 -0
- pyglet/libs/linux/wayland/wayland_egl.py +38 -0
- pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
- pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
- pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
- pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
- pyglet/libs/linux/x11/xrandr.py +0 -0
- pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
- pyglet/libs/shared/__init__.py +0 -0
- pyglet/libs/shared/spirv/__init__.py +0 -0
- pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
- pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
- pyglet/libs/win32/__init__.py +27 -5
- pyglet/libs/win32/constants.py +59 -48
- pyglet/libs/win32/context_managers.py +20 -3
- pyglet/libs/win32/dinput.py +105 -88
- pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
- pyglet/libs/win32/types.py +58 -23
- pyglet/{gl → libs/win32}/wgl.py +32 -25
- pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
- pyglet/media/__init__.py +9 -10
- pyglet/media/codecs/__init__.py +12 -1
- pyglet/media/codecs/base.py +99 -96
- pyglet/media/codecs/ffmpeg.py +2 -2
- pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
- pyglet/media/codecs/webaudio_pyodide.py +111 -0
- pyglet/media/drivers/__init__.py +9 -4
- pyglet/media/drivers/base.py +4 -4
- pyglet/media/drivers/openal/__init__.py +1 -1
- pyglet/media/drivers/openal/adaptation.py +3 -3
- pyglet/media/drivers/pulse/__init__.py +1 -1
- pyglet/media/drivers/pulse/adaptation.py +3 -3
- pyglet/media/drivers/pyodide_js/__init__.py +8 -0
- pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
- pyglet/media/drivers/xaudio2/adaptation.py +3 -3
- pyglet/media/player.py +276 -193
- pyglet/media/player_worker_thread.py +1 -1
- pyglet/model/__init__.py +39 -29
- pyglet/model/codecs/base.py +4 -4
- pyglet/model/codecs/gltf.py +3 -3
- pyglet/model/codecs/obj.py +71 -43
- pyglet/resource.py +129 -78
- pyglet/shapes.py +147 -177
- pyglet/sprite.py +47 -164
- pyglet/text/__init__.py +44 -54
- pyglet/text/caret.py +12 -7
- pyglet/text/document.py +19 -17
- pyglet/text/formats/html.py +2 -2
- pyglet/text/formats/structured.py +10 -40
- pyglet/text/layout/__init__.py +20 -13
- pyglet/text/layout/base.py +176 -287
- pyglet/text/layout/incremental.py +9 -10
- pyglet/text/layout/scrolling.py +7 -95
- pyglet/window/__init__.py +183 -172
- pyglet/window/cocoa/__init__.py +62 -51
- pyglet/window/cocoa/pyglet_delegate.py +2 -25
- pyglet/window/cocoa/pyglet_view.py +9 -8
- pyglet/window/dialog/__init__.py +184 -0
- pyglet/window/dialog/base.py +99 -0
- pyglet/window/dialog/darwin.py +121 -0
- pyglet/window/dialog/linux.py +72 -0
- pyglet/window/dialog/windows.py +194 -0
- pyglet/window/emscripten/__init__.py +779 -0
- pyglet/window/headless/__init__.py +44 -28
- pyglet/window/key.py +2 -0
- pyglet/window/mouse.py +2 -2
- pyglet/window/wayland/__init__.py +377 -0
- pyglet/window/win32/__init__.py +101 -46
- pyglet/window/xlib/__init__.py +104 -66
- {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
- pyglet-3.0.dev1.dist-info/RECORD +322 -0
- {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
- pyglet/gl/__init__.py +0 -208
- pyglet/gl/base.py +0 -499
- pyglet/gl/cocoa.py +0 -309
- pyglet/gl/gl.py +0 -4625
- pyglet/gl/gl.pyi +0 -2320
- pyglet/gl/gl_compat.pyi +0 -3097
- pyglet/gl/gl_info.py +0 -190
- pyglet/gl/headless.py +0 -166
- pyglet/gl/wgl_info.py +0 -36
- pyglet/gl/wglext_nv.py +0 -1096
- pyglet/gl/win32.py +0 -268
- pyglet/gl/xlib.py +0 -295
- pyglet/image/buffer.py +0 -274
- pyglet/image/codecs/s3tc.py +0 -354
- pyglet/libs/x11/xrandr.py +0 -166
- pyglet-2.1.12.dist-info/RECORD +0 -234
- /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
- /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
- /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
- /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
- /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
- {pyglet-2.1.12.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
pyglet/image/codecs/__init__.py
CHANGED
|
@@ -141,6 +141,15 @@ def add_default_codecs():
|
|
|
141
141
|
except ImportError:
|
|
142
142
|
pass
|
|
143
143
|
|
|
144
|
+
# Compressed texture in KTX2 format
|
|
145
|
+
try:
|
|
146
|
+
from pyglet.image.codecs import ktx2
|
|
147
|
+
registry.add_encoders(ktx2)
|
|
148
|
+
registry.add_decoders(ktx2)
|
|
149
|
+
except ImportError:
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
|
|
144
153
|
# Mac OS X default: Quartz
|
|
145
154
|
if compat_platform == 'darwin':
|
|
146
155
|
try:
|
pyglet/image/codecs/bmp.py
CHANGED
|
@@ -9,6 +9,7 @@ encoding. Alpha channel is supported for 32-bit BI_RGB only.
|
|
|
9
9
|
#
|
|
10
10
|
# But some details including alignment and bit/byte order are omitted; see
|
|
11
11
|
# http://www.fileformat.info/format/bmp/egff.htm
|
|
12
|
+
from __future__ import annotations
|
|
12
13
|
|
|
13
14
|
import ctypes
|
|
14
15
|
from ctypes.wintypes import DWORD, LONG, WORD
|
|
@@ -31,7 +32,7 @@ class BITMAPFILEHEADER(ctypes.LittleEndianStructure):
|
|
|
31
32
|
('bfSize', DWORD),
|
|
32
33
|
('bfReserved1', WORD),
|
|
33
34
|
('bfReserved2', WORD),
|
|
34
|
-
('bfOffBits', DWORD)
|
|
35
|
+
('bfOffBits', DWORD),
|
|
35
36
|
]
|
|
36
37
|
|
|
37
38
|
class BITMAPINFOHEADER(ctypes.LittleEndianStructure):
|
|
@@ -47,7 +48,7 @@ class BITMAPINFOHEADER(ctypes.LittleEndianStructure):
|
|
|
47
48
|
('biXPelsPerMeter', LONG),
|
|
48
49
|
('biYPelsPerMeter', LONG),
|
|
49
50
|
('biClrUsed', DWORD),
|
|
50
|
-
('biClrImportant', DWORD)
|
|
51
|
+
('biClrImportant', DWORD),
|
|
51
52
|
]
|
|
52
53
|
|
|
53
54
|
CIEXYZTRIPLE = FXPT2DOT30 * 9
|
|
@@ -92,7 +93,7 @@ class RGBQUAD(ctypes.LittleEndianStructure):
|
|
|
92
93
|
('rgbBlue', BYTE),
|
|
93
94
|
('rgbGreen', BYTE),
|
|
94
95
|
('rgbRed', BYTE),
|
|
95
|
-
('rgbReserved', BYTE)
|
|
96
|
+
('rgbReserved', BYTE),
|
|
96
97
|
]
|
|
97
98
|
|
|
98
99
|
def __repr__(self):
|
|
@@ -137,7 +138,7 @@ class BMPImageDecoder(ImageDecoder):
|
|
|
137
138
|
if width <= 0 or info_header.biPlanes != 1:
|
|
138
139
|
raise ImageDecodeException(
|
|
139
140
|
'BMP file has corrupt parameters: %r' % (filename or file))
|
|
140
|
-
pitch_sign = height < 0 and -1 or 1
|
|
141
|
+
pitch_sign = (height < 0 and -1) or 1
|
|
141
142
|
height = abs(height)
|
|
142
143
|
|
|
143
144
|
compression = info_header.biCompression
|
|
@@ -146,7 +147,7 @@ class BMPImageDecoder(ImageDecoder):
|
|
|
146
147
|
'Unsupported compression: %r' % (filename or file))
|
|
147
148
|
|
|
148
149
|
clr_used = 0
|
|
149
|
-
bitcount = info_header.biBitCount
|
|
150
|
+
bitcount = info_header.biBitCount
|
|
150
151
|
if bitcount == 1:
|
|
151
152
|
pitch = (width + 7) // 8
|
|
152
153
|
bits_type = ctypes.c_ubyte
|
|
@@ -166,7 +167,7 @@ class BMPImageDecoder(ImageDecoder):
|
|
|
166
167
|
elif bitcount == 24:
|
|
167
168
|
pitch = width * 3
|
|
168
169
|
bits_type = ctypes.c_ubyte
|
|
169
|
-
decoder = decode_24bit
|
|
170
|
+
decoder = decode_24bit
|
|
170
171
|
elif bitcount == 32:
|
|
171
172
|
pitch = width * 4
|
|
172
173
|
if compression == BI_RGB:
|
|
@@ -185,17 +186,17 @@ class BMPImageDecoder(ImageDecoder):
|
|
|
185
186
|
pitch = (pitch + 3) & ~3
|
|
186
187
|
packed_width = pitch // ctypes.sizeof(bits_type)
|
|
187
188
|
|
|
188
|
-
if bitcount < 16 and compression == BI_RGB:
|
|
189
|
+
if bitcount < 16 and compression == BI_RGB:
|
|
189
190
|
clr_used = info_header.biClrUsed or (1 << bitcount)
|
|
190
191
|
palette = to_ctypes(buffer, palette_offset, RGBQUAD * clr_used)
|
|
191
|
-
bits = to_ctypes(buffer, bits_offset,
|
|
192
|
+
bits = to_ctypes(buffer, bits_offset,
|
|
192
193
|
bits_type * packed_width * height)
|
|
193
194
|
return decoder(bits, palette, width, height, pitch, pitch_sign)
|
|
194
|
-
|
|
195
|
-
bits = to_ctypes(buffer, bits_offset,
|
|
195
|
+
if bitcount >= 16 and compression == BI_RGB:
|
|
196
|
+
bits = to_ctypes(buffer, bits_offset,
|
|
196
197
|
bits_type * (packed_width * height))
|
|
197
198
|
return decoder(bits, None, width, height, pitch, pitch_sign)
|
|
198
|
-
|
|
199
|
+
if compression == BI_BITFIELDS:
|
|
199
200
|
if info_header.biSize >= ctypes.sizeof(BITMAPV4HEADER):
|
|
200
201
|
info_header = to_ctypes(buffer, info_header_offset,
|
|
201
202
|
BITMAPV4HEADER)
|
|
@@ -204,7 +205,7 @@ class BMPImageDecoder(ImageDecoder):
|
|
|
204
205
|
b_mask = info_header.bV4BlueMask
|
|
205
206
|
else:
|
|
206
207
|
fields_offset = info_header_offset + \
|
|
207
|
-
ctypes.sizeof(BITMAPINFOHEADER)
|
|
208
|
+
ctypes.sizeof(BITMAPINFOHEADER)
|
|
208
209
|
fields = to_ctypes(buffer, fields_offset, RGBFields)
|
|
209
210
|
r_mask = fields.red
|
|
210
211
|
g_mask = fields.green
|
|
@@ -215,46 +216,60 @@ class BMPImageDecoder(ImageDecoder):
|
|
|
215
216
|
('data', bits_type * packed_width * height),
|
|
216
217
|
]
|
|
217
218
|
bits = to_ctypes(buffer, bits_offset, _BitsArray).data
|
|
218
|
-
return decoder(bits, r_mask, g_mask, b_mask,
|
|
219
|
-
|
|
219
|
+
return decoder(bits, r_mask, g_mask, b_mask, width, height, pitch, pitch_sign)
|
|
220
|
+
return None
|
|
221
|
+
|
|
220
222
|
|
|
221
223
|
def decode_1bit(bits, palette, width, height, pitch, pitch_sign):
|
|
222
|
-
rgb_pitch =
|
|
224
|
+
rgb_pitch = width * 3
|
|
223
225
|
buffer = (ctypes.c_ubyte * (height * rgb_pitch))()
|
|
224
226
|
i = 0
|
|
225
227
|
for row in bits:
|
|
228
|
+
pixel_count = 0
|
|
226
229
|
for packed in row:
|
|
227
230
|
for _ in range(8):
|
|
231
|
+
if pixel_count >= width:
|
|
232
|
+
break
|
|
228
233
|
rgb = palette[(packed & 0x80) >> 7]
|
|
229
234
|
buffer[i] = rgb.rgbRed
|
|
230
235
|
buffer[i + 1] = rgb.rgbGreen
|
|
231
236
|
buffer[i + 2] = rgb.rgbBlue
|
|
232
237
|
i += 3
|
|
238
|
+
pixel_count += 1
|
|
233
239
|
packed <<= 1
|
|
234
240
|
|
|
235
241
|
return ImageData(width, height, 'RGB', buffer, pitch_sign * rgb_pitch)
|
|
236
242
|
|
|
237
243
|
def decode_4bit(bits, palette, width, height, pitch, pitch_sign):
|
|
238
|
-
|
|
244
|
+
packed_row_bytes = (width + 1) // 2
|
|
245
|
+
rgb_pitch = width * 3
|
|
239
246
|
buffer = (ctypes.c_ubyte * (height * rgb_pitch))()
|
|
240
|
-
i
|
|
247
|
+
i = 0
|
|
241
248
|
for row in bits:
|
|
242
|
-
|
|
243
|
-
|
|
249
|
+
pixel_count = 0
|
|
250
|
+
for byte_i in range(packed_row_bytes):
|
|
251
|
+
packed = row[byte_i]
|
|
252
|
+
for index in ((packed & 0xF0) >> 4, packed & 0x0F):
|
|
253
|
+
if pixel_count >= width:
|
|
254
|
+
break
|
|
244
255
|
rgb = palette[index]
|
|
245
256
|
buffer[i] = rgb.rgbRed
|
|
246
257
|
buffer[i + 1] = rgb.rgbGreen
|
|
247
258
|
buffer[i + 2] = rgb.rgbBlue
|
|
248
259
|
i += 3
|
|
260
|
+
pixel_count += 1
|
|
249
261
|
|
|
250
262
|
return ImageData(width, height, 'RGB', buffer, pitch_sign * rgb_pitch)
|
|
251
263
|
|
|
264
|
+
|
|
252
265
|
def decode_8bit(bits, palette, width, height, pitch, pitch_sign):
|
|
253
|
-
rgb_pitch =
|
|
266
|
+
rgb_pitch = width * 3
|
|
254
267
|
buffer = (ctypes.c_ubyte * (height * rgb_pitch))()
|
|
268
|
+
|
|
255
269
|
i = 0
|
|
256
270
|
for row in bits:
|
|
257
|
-
for
|
|
271
|
+
for x in range(width):
|
|
272
|
+
index = row[x]
|
|
258
273
|
rgb = palette[index]
|
|
259
274
|
buffer[i] = rgb.rgbRed
|
|
260
275
|
buffer[i + 1] = rgb.rgbGreen
|
|
@@ -265,9 +280,18 @@ def decode_8bit(bits, palette, width, height, pitch, pitch_sign):
|
|
|
265
280
|
|
|
266
281
|
|
|
267
282
|
def decode_24bit(bits, palette, width, height, pitch, pitch_sign):
|
|
268
|
-
|
|
269
|
-
ctypes.
|
|
270
|
-
|
|
283
|
+
row_bytes = width * 3
|
|
284
|
+
buffer = (ctypes.c_ubyte * (height * row_bytes))()
|
|
285
|
+
|
|
286
|
+
src_base = ctypes.addressof(bits)
|
|
287
|
+
dst_base = ctypes.addressof(buffer)
|
|
288
|
+
|
|
289
|
+
for y in range(height):
|
|
290
|
+
src_row = src_base + y * pitch
|
|
291
|
+
dst_row = dst_base + y * row_bytes
|
|
292
|
+
ctypes.memmove(dst_row, src_row, row_bytes)
|
|
293
|
+
|
|
294
|
+
return ImageData(width, height, 'BGR', buffer, pitch_sign * row_bytes)
|
|
271
295
|
|
|
272
296
|
def decode_32bit_rgb(bits, palette, width, height, pitch, pitch_sign):
|
|
273
297
|
buffer = (ctypes.c_ubyte * (height * pitch))()
|
|
@@ -291,21 +315,20 @@ def get_shift(mask):
|
|
|
291
315
|
s = shift - (8 - shift_up)
|
|
292
316
|
if s < 0:
|
|
293
317
|
return 0, -s
|
|
294
|
-
|
|
295
|
-
return s, 0
|
|
318
|
+
return s, 0
|
|
296
319
|
|
|
297
|
-
def decode_bitfields(bits, r_mask, g_mask, b_mask,
|
|
298
|
-
width, height, pitch, pitch_sign):
|
|
320
|
+
def decode_bitfields(bits, r_mask, g_mask, b_mask, width, height, pitch, pitch_sign):
|
|
299
321
|
r_shift1, r_shift2 = get_shift(r_mask)
|
|
300
322
|
g_shift1, g_shift2 = get_shift(g_mask)
|
|
301
323
|
b_shift1, b_shift2 = get_shift(b_mask)
|
|
302
324
|
|
|
303
|
-
rgb_pitch =
|
|
325
|
+
rgb_pitch = width * 3
|
|
304
326
|
buffer = (ctypes.c_ubyte * (height * rgb_pitch))()
|
|
305
327
|
|
|
306
328
|
i = 0
|
|
307
329
|
for row in bits:
|
|
308
|
-
for
|
|
330
|
+
for x in range(width):
|
|
331
|
+
packed = row[x]
|
|
309
332
|
buffer[i] = (packed & r_mask) >> r_shift1 << r_shift2
|
|
310
333
|
buffer[i+1] = (packed & g_mask) >> g_shift1 << g_shift2
|
|
311
334
|
buffer[i+2] = (packed & b_mask) >> b_shift1 << b_shift2
|
pyglet/image/codecs/dds.py
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Reference: http://msdn2.microsoft.com/en-us/library/bb172993.aspx
|
|
4
4
|
"""
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
import struct
|
|
7
8
|
import itertools
|
|
9
|
+
from typing import BinaryIO
|
|
8
10
|
|
|
9
|
-
from pyglet.
|
|
10
|
-
from pyglet.image import CompressedImageData
|
|
11
|
+
from pyglet.image.base import CompressedImageData, CompressionFormat
|
|
11
12
|
from pyglet.image import codecs
|
|
12
|
-
from pyglet.image.codecs import
|
|
13
|
-
|
|
13
|
+
from pyglet.image.codecs import ImageDecodeException
|
|
14
14
|
|
|
15
15
|
# dwFlags of DDSURFACEDESC2
|
|
16
16
|
DDSD_CAPS = 0x00000001
|
|
@@ -53,10 +53,10 @@ class _FileStruct:
|
|
|
53
53
|
for field, value in itertools.zip_longest(self._fields, items, fillvalue=None):
|
|
54
54
|
setattr(self, field[0], value)
|
|
55
55
|
|
|
56
|
-
def __repr__(self):
|
|
56
|
+
def __repr__(self) -> str:
|
|
57
57
|
name = self.__class__.__name__
|
|
58
|
-
return '
|
|
59
|
-
['
|
|
58
|
+
return '{}({})'.format(name, (', \n%s' % (' ' * (len(name) + 1))).join(
|
|
59
|
+
[f'{field[0]} = {getattr(self, field[0])!r}' for field in self._fields]))
|
|
60
60
|
|
|
61
61
|
@classmethod
|
|
62
62
|
def get_format(cls):
|
|
@@ -82,13 +82,21 @@ class DDSURFACEDESC2(_FileStruct):
|
|
|
82
82
|
('dwCaps1', 'I'),
|
|
83
83
|
('dwCaps2', 'I'),
|
|
84
84
|
('dwCapsReserved', '8s'),
|
|
85
|
-
('dwReserved2', 'I')
|
|
85
|
+
('dwReserved2', 'I'),
|
|
86
86
|
]
|
|
87
87
|
|
|
88
88
|
def __init__(self, data):
|
|
89
89
|
super().__init__(data)
|
|
90
90
|
self.ddpfPixelFormat = DDPIXELFORMAT(self.ddpfPixelFormat)
|
|
91
91
|
|
|
92
|
+
class DDS_HEADER_DXT10(_FileStruct):
|
|
93
|
+
_fields = [
|
|
94
|
+
('dxgiFormat', 'I'),
|
|
95
|
+
('resourceDimension', 'I'),
|
|
96
|
+
('miscFlag', 'I'),
|
|
97
|
+
('arraySize', 'I'),
|
|
98
|
+
('miscFlags2', 'I'),
|
|
99
|
+
]
|
|
92
100
|
|
|
93
101
|
class DDPIXELFORMAT(_FileStruct):
|
|
94
102
|
_fields = [
|
|
@@ -99,25 +107,39 @@ class DDPIXELFORMAT(_FileStruct):
|
|
|
99
107
|
('dwRBitMask', 'I'),
|
|
100
108
|
('dwGBitMask', 'I'),
|
|
101
109
|
('dwBBitMask', 'I'),
|
|
102
|
-
('dwRGBAlphaBitMask', 'I')
|
|
110
|
+
('dwRGBAlphaBitMask', 'I'),
|
|
103
111
|
]
|
|
104
112
|
|
|
113
|
+
def _get_dds_block_size_dxgi(dxgi_format: int) -> int:
|
|
114
|
+
if dxgi_format in (71, 72, 80, 81): # BC1 = 8 bytes per 4x4 block
|
|
115
|
+
return 8
|
|
116
|
+
if dxgi_format in (74, 75, # BC2 = 16 bytes per 4x4 block
|
|
117
|
+
77, 78, # BC3
|
|
118
|
+
83, 84, # BC5
|
|
119
|
+
95, 96, # B6
|
|
120
|
+
98, 99): # BC7
|
|
121
|
+
return 16
|
|
122
|
+
msg = f"Unsupported DXGI format {dxgi_format}"
|
|
123
|
+
raise ImageDecodeException(msg)
|
|
105
124
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
(b'
|
|
110
|
-
|
|
111
|
-
(b'DXT5',
|
|
112
|
-
|
|
113
|
-
|
|
125
|
+
|
|
126
|
+
def _get_dds_block_size(fourcc: bytes) -> int:
|
|
127
|
+
"""Return block size in bytes based on the below formats."""
|
|
128
|
+
if fourcc in (b'DXT1', b'BC1 '):
|
|
129
|
+
return 8
|
|
130
|
+
if fourcc in (b'DXT3', b'DXT5', b'BC2 ', b'BC3 ', b'BC5 ', b'ATI2'):
|
|
131
|
+
return 16
|
|
132
|
+
if fourcc in (b'BC4 ', b'ATI1'):
|
|
133
|
+
return 8
|
|
134
|
+
|
|
135
|
+
return 0 # Not block compressed
|
|
114
136
|
|
|
115
137
|
|
|
116
138
|
class DDSImageDecoder(codecs.ImageDecoder):
|
|
117
|
-
def get_file_extensions(self):
|
|
139
|
+
def get_file_extensions(self) -> list[str]:
|
|
118
140
|
return ['.dds']
|
|
119
141
|
|
|
120
|
-
def decode(self, filename, file):
|
|
142
|
+
def decode(self, filename: str, file: BinaryIO | None = None):
|
|
121
143
|
if not file:
|
|
122
144
|
file = open(filename, 'rb')
|
|
123
145
|
|
|
@@ -147,19 +169,19 @@ class DDSImageDecoder(codecs.ImageDecoder):
|
|
|
147
169
|
|
|
148
170
|
has_alpha = desc.ddpfPixelFormat.dwRGBAlphaBitMask != 0
|
|
149
171
|
|
|
150
|
-
|
|
151
|
-
if
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
block_size = 8
|
|
172
|
+
fourcc = desc.ddpfPixelFormat.dwFourCC
|
|
173
|
+
if fourcc == b'DX10':
|
|
174
|
+
dx10_header_data = file.read(DDS_HEADER_DXT10.get_size())
|
|
175
|
+
dx10_header = DDS_HEADER_DXT10(dx10_header_data)
|
|
176
|
+
fmt = CompressionFormat(fourcc, has_alpha, dx10_header.dxgiFormat)
|
|
177
|
+
block_size = _get_dds_block_size_dxgi(dx10_header.dxgiFormat)
|
|
157
178
|
else:
|
|
158
|
-
block_size =
|
|
179
|
+
block_size = _get_dds_block_size(fourcc)
|
|
180
|
+
fmt = CompressionFormat(fourcc, has_alpha)
|
|
159
181
|
|
|
160
182
|
datas = []
|
|
161
183
|
w, h = width, height
|
|
162
|
-
for
|
|
184
|
+
for _ in range(mipmaps):
|
|
163
185
|
if not w and not h:
|
|
164
186
|
break
|
|
165
187
|
if not w:
|
|
@@ -172,7 +194,7 @@ class DDSImageDecoder(codecs.ImageDecoder):
|
|
|
172
194
|
w >>= 1
|
|
173
195
|
h >>= 1
|
|
174
196
|
|
|
175
|
-
image = CompressedImageData(width, height,
|
|
197
|
+
image = CompressedImageData(width, height, fmt, datas[0])
|
|
176
198
|
level = 0
|
|
177
199
|
for data in datas[1:]:
|
|
178
200
|
level += 1
|
|
@@ -181,9 +203,9 @@ class DDSImageDecoder(codecs.ImageDecoder):
|
|
|
181
203
|
return image
|
|
182
204
|
|
|
183
205
|
|
|
184
|
-
def get_decoders():
|
|
206
|
+
def get_decoders() -> list[DDSImageDecoder]:
|
|
185
207
|
return [DDSImageDecoder()]
|
|
186
208
|
|
|
187
209
|
|
|
188
|
-
def get_encoders():
|
|
210
|
+
def get_encoders() -> list:
|
|
189
211
|
return []
|
pyglet/image/codecs/gdiplus.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from ctypes import (
|
|
4
|
+
addressof,
|
|
2
5
|
POINTER,
|
|
3
6
|
Structure,
|
|
4
7
|
c_buffer,
|
|
@@ -15,10 +18,14 @@ from ctypes import (
|
|
|
15
18
|
create_string_buffer,
|
|
16
19
|
memmove,
|
|
17
20
|
windll,
|
|
21
|
+
byref,
|
|
22
|
+
c_int,
|
|
23
|
+
c_uint,
|
|
24
|
+
sizeof,
|
|
18
25
|
)
|
|
19
26
|
from ctypes.wintypes import BOOL, BYTE, INT, UINT, ULONG
|
|
20
27
|
|
|
21
|
-
from pyglet.image import Animation, AnimationFrame, ImageData
|
|
28
|
+
from pyglet.image import Animation, AnimationFrame, ImageData
|
|
22
29
|
from pyglet.image.codecs import ImageDecodeException, ImageDecoder
|
|
23
30
|
from pyglet.libs.win32 import _kernel32 as kernel32
|
|
24
31
|
from pyglet.libs.win32 import _ole32 as ole32
|
|
@@ -58,14 +65,14 @@ class GdiplusStartupInput(Structure):
|
|
|
58
65
|
('GdiplusVersion', c_uint32),
|
|
59
66
|
('DebugEventCallback', c_void_p),
|
|
60
67
|
('SuppressBackgroundThread', BOOL),
|
|
61
|
-
('SuppressExternalCodecs', BOOL)
|
|
68
|
+
('SuppressExternalCodecs', BOOL),
|
|
62
69
|
]
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
class GdiplusStartupOutput(Structure):
|
|
66
73
|
_fields = [
|
|
67
74
|
('NotificationHookProc', c_void_p),
|
|
68
|
-
('NotificationUnhookProc', c_void_p)
|
|
75
|
+
('NotificationUnhookProc', c_void_p),
|
|
69
76
|
]
|
|
70
77
|
|
|
71
78
|
|
|
@@ -76,7 +83,7 @@ class BitmapData(Structure):
|
|
|
76
83
|
('Stride', c_int),
|
|
77
84
|
('PixelFormat', c_int),
|
|
78
85
|
('Scan0', POINTER(c_byte)),
|
|
79
|
-
('Reserved', POINTER(c_uint))
|
|
86
|
+
('Reserved', POINTER(c_uint)),
|
|
80
87
|
]
|
|
81
88
|
|
|
82
89
|
|
|
@@ -85,7 +92,7 @@ class Rect(Structure):
|
|
|
85
92
|
('X', c_int),
|
|
86
93
|
('Y', c_int),
|
|
87
94
|
('Width', c_int),
|
|
88
|
-
('Height', c_int)
|
|
95
|
+
('Height', c_int),
|
|
89
96
|
]
|
|
90
97
|
|
|
91
98
|
|
|
@@ -94,7 +101,7 @@ class PropertyItem(Structure):
|
|
|
94
101
|
('id', c_uint),
|
|
95
102
|
('length', c_ulong),
|
|
96
103
|
('type', c_short),
|
|
97
|
-
('value', c_void_p)
|
|
104
|
+
('value', c_void_p),
|
|
98
105
|
]
|
|
99
106
|
|
|
100
107
|
|
|
@@ -221,9 +228,7 @@ class GDIPlusDecoder(ImageDecoder):
|
|
|
221
228
|
fmt = 'BGRA'
|
|
222
229
|
if pf == PixelFormat24bppRGB:
|
|
223
230
|
fmt = 'BGR'
|
|
224
|
-
elif pf == PixelFormat32bppRGB:
|
|
225
|
-
pass
|
|
226
|
-
elif pf == PixelFormat32bppARGB:
|
|
231
|
+
elif pf == PixelFormat32bppRGB or pf == PixelFormat32bppARGB:
|
|
227
232
|
pass
|
|
228
233
|
elif pf in (PixelFormat16bppARGB1555, PixelFormat32bppPARGB,
|
|
229
234
|
PixelFormat64bppARGB, PixelFormat64bppPARGB):
|
|
@@ -240,15 +245,34 @@ class GDIPlusDecoder(ImageDecoder):
|
|
|
240
245
|
rect.Height = height
|
|
241
246
|
bitmap_data = BitmapData()
|
|
242
247
|
gdiplus.GdipBitmapLockBits(bitmap, byref(rect), ImageLockModeRead, pf, byref(bitmap_data))
|
|
243
|
-
|
|
248
|
+
|
|
244
249
|
# Create buffer for RawImage
|
|
245
250
|
buffer = create_string_buffer(bitmap_data.Stride * height)
|
|
246
|
-
|
|
247
|
-
|
|
251
|
+
if fmt == 'BGR':
|
|
252
|
+
stride = bitmap_data.Stride
|
|
253
|
+
components = len(fmt)
|
|
254
|
+
packed_row = width * components
|
|
255
|
+
src_stride = abs(stride)
|
|
256
|
+
|
|
257
|
+
src_addr = cast(bitmap_data.Scan0, c_void_p).value
|
|
258
|
+
src = (c_byte * (src_stride * height)).from_address(src_addr)
|
|
259
|
+
|
|
260
|
+
buf_address = addressof(buffer)
|
|
261
|
+
src_address = addressof(src)
|
|
262
|
+
|
|
263
|
+
for y in range(height):
|
|
264
|
+
src_y = y if stride < 0 else (height - 1 - y)
|
|
265
|
+
src_off = src_y * src_stride
|
|
266
|
+
dst_off = y * packed_row
|
|
267
|
+
memmove(buf_address + dst_off, src_address + src_off, packed_row)
|
|
268
|
+
else:
|
|
269
|
+
memmove(buffer, bitmap_data.Scan0, len(buffer))
|
|
270
|
+
packed_row = -bitmap_data.Stride
|
|
271
|
+
|
|
248
272
|
# Unlock data
|
|
249
273
|
gdiplus.GdipBitmapUnlockBits(bitmap, byref(bitmap_data))
|
|
250
274
|
|
|
251
|
-
return ImageData(width, height, fmt, buffer,
|
|
275
|
+
return ImageData(width, height, fmt, buffer, packed_row)
|
|
252
276
|
|
|
253
277
|
def _delete_bitmap(self, bitmap):
|
|
254
278
|
# Release image and stream
|
|
@@ -286,7 +310,7 @@ class GDIPlusDecoder(ImageDecoder):
|
|
|
286
310
|
gdiplus.GdipGetPropertyItemSize(bitmap, prop_id, byref(prop_size))
|
|
287
311
|
|
|
288
312
|
prop_buffer = c_buffer(prop_size.value)
|
|
289
|
-
prop_item = cast(prop_buffer, POINTER(PropertyItem)).contents
|
|
313
|
+
prop_item = cast(prop_buffer, POINTER(PropertyItem)).contents
|
|
290
314
|
gdiplus.GdipGetPropertyItem(bitmap, prop_id, prop_size.value, prop_buffer)
|
|
291
315
|
|
|
292
316
|
n_delays = prop_item.length // sizeof(c_long)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import base64
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from pyglet.image import ImageDecoder
|
|
6
|
+
from pyglet.image import ImageData
|
|
7
|
+
from pyglet.image.codecs import ImageDecodeException
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import js
|
|
11
|
+
import pyodide.ffi
|
|
12
|
+
except ImportError:
|
|
13
|
+
raise ImportError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_image_canvas = js.document.createElement("canvas")
|
|
17
|
+
_image_context = _image_canvas.getContext("2d", willReadFrequently=True)
|
|
18
|
+
|
|
19
|
+
async def check_image_exists(url):
|
|
20
|
+
"""Check if an image exists at the given URL."""
|
|
21
|
+
try:
|
|
22
|
+
response = await js.fetch(url, {"method": "HEAD"}) # HEAD request (faster than GET)
|
|
23
|
+
if response.ok:
|
|
24
|
+
print(f"Image exists: {url}")
|
|
25
|
+
return True
|
|
26
|
+
else:
|
|
27
|
+
print(f"Image does NOT exist: {url} (Status: {response.status})")
|
|
28
|
+
return False
|
|
29
|
+
except Exception as e:
|
|
30
|
+
print(f"Error checking image: {e}")
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
async def load_image_from_vfs(vfs_path):
|
|
34
|
+
# Read image from Pyodide's VFS
|
|
35
|
+
with open(vfs_path, "rb") as f:
|
|
36
|
+
img_data = f.read()
|
|
37
|
+
|
|
38
|
+
# Convert image to Base64
|
|
39
|
+
base64_data = base64.b64encode(img_data).decode("utf-8")
|
|
40
|
+
|
|
41
|
+
# Create a Data URL
|
|
42
|
+
mime_type = "image/png" # Change this based on file type (e.g., "image/jpeg")
|
|
43
|
+
data_url = f"data:{mime_type};base64,{base64_data}"
|
|
44
|
+
|
|
45
|
+
# Use the Data URL as the image source
|
|
46
|
+
img = js.Image.new()
|
|
47
|
+
img.src = data_url
|
|
48
|
+
|
|
49
|
+
# Wait for image to load before returning
|
|
50
|
+
await pyodide.ffi.to_js(img.decode())
|
|
51
|
+
|
|
52
|
+
return img
|
|
53
|
+
|
|
54
|
+
class JSImageDecoder(ImageDecoder):
|
|
55
|
+
def get_file_extensions(self):
|
|
56
|
+
return ['.png']
|
|
57
|
+
|
|
58
|
+
async def decode(self, filename, file) -> ImageData:
|
|
59
|
+
t = time.perf_counter()
|
|
60
|
+
#img = js.Image.new()
|
|
61
|
+
#img.src = filename
|
|
62
|
+
|
|
63
|
+
#await pyodide.ffi.to_js(img.decode()) # Wait for image to load
|
|
64
|
+
img = await load_image_from_vfs(filename)
|
|
65
|
+
|
|
66
|
+
_image_canvas.width = img.width
|
|
67
|
+
_image_canvas.height = img.height
|
|
68
|
+
|
|
69
|
+
# Clear previous image
|
|
70
|
+
_image_context.clearRect(0, 0, img.width, img.height)
|
|
71
|
+
|
|
72
|
+
# Draw to context
|
|
73
|
+
_image_context.translate(0, img.height) # Move down
|
|
74
|
+
_image_context.scale(1, -1) # Flip vertically
|
|
75
|
+
_image_context.drawImage(img, 0, 0)
|
|
76
|
+
|
|
77
|
+
image_data = _image_context.getImageData(0, 0, img.width, img.height)
|
|
78
|
+
pixel_data = image_data.data # Uint8Array
|
|
79
|
+
|
|
80
|
+
print("Took", time.perf_counter() - t, "seconds")
|
|
81
|
+
|
|
82
|
+
return ImageData(img.width, img.height, 'RGBA', pixel_data)
|
|
83
|
+
|
|
84
|
+
def decode_animation(self, filename, file):
|
|
85
|
+
"""Decode the given file object and return an instance of :py:class:`~pyglet.image.Animation`.
|
|
86
|
+
Throws ImageDecodeException if there is an error. filename
|
|
87
|
+
can be a file type hint.
|
|
88
|
+
"""
|
|
89
|
+
raise ImageDecodeException('This decoder cannot decode animations.')
|
|
90
|
+
|
|
91
|
+
def __repr__(self) -> str:
|
|
92
|
+
return "{}{}".format(self.__class__.__name__,
|
|
93
|
+
self.get_animation_file_extensions() +
|
|
94
|
+
self.get_file_extensions())
|
|
95
|
+
def get_decoders():
|
|
96
|
+
return [JSImageDecoder()]
|
|
97
|
+
|
|
98
|
+
def get_encoders():
|
|
99
|
+
return []
|