pyimagecuda 0.0.8__cp313-cp313-win_amd64.whl → 0.0.9__cp313-cp313-win_amd64.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.
pyimagecuda/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import ctypes
2
2
  import sys
3
3
 
4
- __version__ = "0.0.7"
4
+ __version__ = "0.0.9"
5
5
 
6
6
  def _check_nvidia_driver():
7
7
  try:
@@ -37,7 +37,7 @@ except ImportError as e:
37
37
  if _INTERNAL_LOADED:
38
38
  try:
39
39
  from .image import Image, ImageU8
40
- from .io import upload, download, copy, save, load, convert_float_to_u8, convert_u8_to_float, from_numpy, to_numpy
40
+ from .io import upload, download, copy, save, load, convert_float_to_u8, convert_u8_to_float, from_numpy, to_numpy, save_u8
41
41
  from .fill import Fill
42
42
  from .resize import Resize
43
43
  from .blend import Blend
@@ -46,6 +46,7 @@ if _INTERNAL_LOADED:
46
46
  from .adjust import Adjust
47
47
  from .transform import Transform
48
48
  from .text import Text
49
+ from .gl_interop import GLResource
49
50
  from .pyimagecuda_internal import cuda_sync # type: ignore
50
51
  except ImportError as e:
51
52
  print(f"Warning: Error importing Python wrappers: {e}")
@@ -0,0 +1,83 @@
1
+ from .pyimagecuda_internal import ( # type: ignore
2
+ register_gl_pbo,
3
+ unregister_gl_resource,
4
+ copy_to_gl_pbo
5
+ )
6
+ from .image import ImageU8
7
+
8
+
9
+ class GLResource:
10
+ """
11
+ CUDA-OpenGL interop resource for direct GPU-to-GPU transfers.
12
+
13
+ Represents a registered OpenGL PBO that can receive ImageU8 data
14
+ directly without CPU roundtrips.
15
+
16
+ Docs & Examples: https://offerrall.github.io/pyimagecuda/opengl/
17
+ """
18
+
19
+ def __init__(self, pbo_id: int):
20
+ """
21
+ Parameters:
22
+ pbo_id: Valid OpenGL PBO ID. The PBO must exist and remain
23
+ valid for the lifetime of this GLResource.
24
+
25
+ Raises:
26
+ ValueError: If pbo_id is invalid
27
+ RuntimeError: If CUDA registration fails
28
+
29
+ Docs & Examples: https://offerrall.github.io/pyimagecuda/opengl/
30
+ """
31
+ if not isinstance(pbo_id, int) or pbo_id <= 0:
32
+ raise ValueError(f"Invalid PBO ID: {pbo_id}")
33
+
34
+ self._handle = None
35
+ self.pbo_id = pbo_id
36
+ self._handle = register_gl_pbo(pbo_id)
37
+
38
+ def copy_from(self, image: ImageU8) -> None:
39
+ """
40
+ Copies ImageU8 data directly to the registered PBO (GPU→GPU).
41
+
42
+ Docs & Examples: https://offerrall.github.io/pyimagecuda/opengl/
43
+ """
44
+ if not isinstance(image, ImageU8):
45
+ raise TypeError(f"Expected ImageU8, got {type(image).__name__}")
46
+
47
+ if self._handle is None:
48
+ raise RuntimeError("GLResource has been freed")
49
+
50
+ copy_to_gl_pbo(
51
+ image._buffer._handle,
52
+ self._handle,
53
+ image.width,
54
+ image.height
55
+ )
56
+
57
+ def free(self) -> None:
58
+ """
59
+ Unregisters the OpenGL resource from CUDA.
60
+
61
+ Docs & Examples: https://offerrall.github.io/pyimagecuda/opengl/
62
+ """
63
+ if self._handle is not None:
64
+ unregister_gl_resource(self._handle)
65
+ self._handle = None
66
+
67
+ def __enter__(self):
68
+ return self
69
+
70
+ def __exit__(self, exc_type, exc_value, traceback):
71
+ self.free()
72
+ return False
73
+
74
+ def __del__(self):
75
+ if hasattr(self, '_handle') and self._handle is not None:
76
+ try:
77
+ self.free()
78
+ except Exception:
79
+ pass
80
+
81
+ def __repr__(self) -> str:
82
+ status = "active" if getattr(self, '_handle', None) is not None else "freed"
83
+ return f"GLResource(pbo_id={self.pbo_id}, status={status})"
pyimagecuda/io.py CHANGED
@@ -121,26 +121,13 @@ def load(
121
121
  return f32_buffer if should_return else None
122
122
 
123
123
 
124
- def save(image: Image, filepath: str, u8_buffer: ImageU8 | None = None, quality: int | None = None) -> None:
125
- """
126
- Saves the floating-point image to a file (using an 8-bit buffer for conversion).
127
-
128
- Docs & Examples: https://offerrall.github.io/pyimagecuda/io/#saving-images
129
- """
130
- if u8_buffer is None:
131
- u8_buffer = ImageU8(image.width, image.height)
132
- owns_buffer = True
133
- else:
134
- ensure_capacity(u8_buffer, image.width, image.height)
135
- owns_buffer = False
136
-
137
- convert_float_to_u8(u8_buffer, image)
138
- pixel_data = download(u8_buffer)
124
+ def _save_internal(u8_image: ImageU8, filepath: str, quality: int | None = None) -> None:
125
+ pixel_data = download(u8_image)
139
126
 
140
127
  vips_img = pyvips.Image.new_from_memory(
141
128
  pixel_data,
142
- image.width,
143
- image.height,
129
+ u8_image.width,
130
+ u8_image.height,
144
131
  bands=4,
145
132
  format='uchar'
146
133
  )
@@ -157,10 +144,37 @@ def save(image: Image, filepath: str, u8_buffer: ImageU8 | None = None, quality:
157
144
  save_kwargs['Q'] = quality
158
145
 
159
146
  vips_img.write_to_file(filepath, **save_kwargs)
147
+
148
+
149
+ def save(image: Image, filepath: str, u8_buffer: ImageU8 | None = None, quality: int | None = None) -> None:
150
+ """
151
+ Saves the floating-point image to a file (using an 8-bit buffer for conversion).
152
+
153
+ Docs & Examples: https://offerrall.github.io/pyimagecuda/io/#saving-images
154
+ """
155
+ if u8_buffer is None:
156
+ u8_buffer = ImageU8(image.width, image.height)
157
+ owns_buffer = True
158
+ else:
159
+ ensure_capacity(u8_buffer, image.width, image.height)
160
+ owns_buffer = False
161
+
162
+ convert_float_to_u8(u8_buffer, image)
163
+ _save_internal(u8_buffer, filepath, quality)
160
164
 
161
165
  if owns_buffer:
162
166
  u8_buffer.free()
163
167
 
168
+
169
+ def save_u8(image: ImageU8, filepath: str, quality: int | None = None) -> None:
170
+ """
171
+ Saves an 8-bit unsigned integer image directly to a file.
172
+
173
+ Docs & Examples: https://offerrall.github.io/pyimagecuda/io/#saving-images
174
+ """
175
+ _save_internal(image, filepath, quality)
176
+
177
+
164
178
  def from_numpy(array, f32_buffer: Image | None = None, u8_buffer: ImageU8 | None = None) -> Image:
165
179
  """
166
180
  Creates a PyImageCUDA Image from a NumPy array (e.g. from OpenCV, Pillow, Matplotlib).
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pyimagecuda
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: GPU-accelerated image processing library for Python
5
5
  Author: Beltrán Offerrall
6
6
  Requires-Python: >=3.10
7
7
  Requires-Dist: pyvips[binary]
8
8
  Description-Content-Type: text/markdown
9
9
 
10
- # PyImageCUDA 0.0.8
10
+ # PyImageCUDA 0.0.9
11
11
 
12
12
  [![PyPI version](https://img.shields.io/pypi/v/pyimagecuda.svg)](https://pypi.org/project/pyimagecuda/)
13
13
  [![Build Status](https://github.com/offerrall/pyimagecuda/actions/workflows/build.yml/badge.svg)](https://github.com/offerrall/pyimagecuda/actions)
@@ -47,6 +47,7 @@ with Image(1024, 1024) as bg:
47
47
  * ✅ **Ultra-lightweight:** library weighs **~1 MB**.
48
48
  * ✅ **Studio Quality:** 32-bit floating-point precision (float32) to prevent color banding.
49
49
  * ✅ **Advanced Memory Control:** Reuse GPU buffers across operations and resize without reallocation—critical for video processing and batch workflows.
50
+ * ✅ **OpenGL Integration:** Direct GPU-to-GPU display for real-time preview widgets.
50
51
  * ✅ **API Simplicity:** Intuitive, Pythonic API designed for ease of use.
51
52
 
52
53
  ## Use Cases
@@ -54,6 +55,7 @@ with Image(1024, 1024) as bg:
54
55
  * **Generative Art:** Create thousands of unique variations in seconds.
55
56
  * **Motion Graphics:** Process video frames or generate effects in real-time.
56
57
  * **Image Compositing:** Complex multi-layer designs with GPU-accelerated effects.
58
+ * **Node Editors & Real-time Tools:** Build responsive image editors with instant preview.
57
59
  * **Game Development:** Procedural UI assets, icons, and sprite generation.
58
60
  * **Marketing Automation:** Mass-produce personalized graphics from templates.
59
61
  * **Data Augmentation:** High-speed batch transformations for ML datasets.
@@ -73,6 +75,7 @@ pip install pyimagecuda
73
75
  * [Getting Started Guide](https://offerrall.github.io/pyimagecuda/)
74
76
  * [Image & Memory](https://offerrall.github.io/pyimagecuda/image/) (Buffer management)
75
77
  * [IO](https://offerrall.github.io/pyimagecuda/io/) (Loading and Saving)
78
+ * [OpenGL Integration](https://offerrall.github.io/pyimagecuda/opengl/) (Real-time preview, zero-copy display)
76
79
 
77
80
  ### Operations
78
81
  * [Fill](https://offerrall.github.io/pyimagecuda/fill/) (Solid colors, Gradients, Checkerboard, Grid, Stripes, Dots, Circle, Ngon, Noise, Perlin)
@@ -129,4 +132,4 @@ pytest tests/tests.py
129
132
  Contributions welcome! Open issues or submit PRs
130
133
 
131
134
  ## License
132
- MIT License. See [LICENSE](LICENSE) for details.
135
+ MIT License. See [LICENSE](LICENSE) for details.
@@ -1,17 +1,18 @@
1
- pyimagecuda/__init__.py,sha256=4duktD0TUqTayWWg39PuCQgr6xPbwxSJ6cQyFx65QJg,2166
1
+ pyimagecuda/__init__.py,sha256=uTnh4hmahYz_-W1587VmdEUe8PnEMmAGaXnAYJs1NSg,2219
2
2
  pyimagecuda/adjust.py,sha256=xGSgifVWaFkaXyL718PUcYqwtZJAlnvMHNLQHiUS40M,3231
3
3
  pyimagecuda/blend.py,sha256=sPupoAh9Mnz16dAsv6C3ynZvDHmV-0MR-A32KpEcE6Q,9132
4
4
  pyimagecuda/effect.py,sha256=KBmDNitsl3qxfuRPT075UAsRF5mSXI25aFTb06JZ1WQ,6231
5
5
  pyimagecuda/fill.py,sha256=7ybr-wkyr5_ziLL_6bvrLAW_Ixe1nMz36Lrj6jJAiOI,8934
6
6
  pyimagecuda/filter.py,sha256=MK6iDQ-tajbx1bgC8hvhrSFusAFfoymaQRDQEkwNWsU,6601
7
+ pyimagecuda/gl_interop.py,sha256=UtKr1a7fTtAhLt6EoLh7LwGRKu9RzKjG9RHYLUs9e3w,2616
7
8
  pyimagecuda/image.py,sha256=VRDHUOF2VClwdj3Q5YSQsmy9lpirwQvbC1P8avE3PdI,2864
8
- pyimagecuda/io.py,sha256=zNUaljHJe7zGEd01qODXWQiydJ84xA9nlIRKrAoa1ys,8287
9
- pyimagecuda/pyimagecuda_internal.cp313-win_amd64.pyd,sha256=C9ZX9TYPWJlcFGESBCjaB9IHZgM-O_pNS5pl2P4iNoc,582656
9
+ pyimagecuda/io.py,sha256=na_1pyg_SQ3D_-g4kThJginxVmcuBNw8ew5A7w0SoAg,8733
10
+ pyimagecuda/pyimagecuda_internal.cp313-win_amd64.pyd,sha256=tCI74Mrcd3QOZH0LHjWEFNY0RKjjRJ1LgmdFwZPlXJQ,588800
10
11
  pyimagecuda/resize.py,sha256=txGYZr3KFmw9pYAbZ7vTnI6NDO-OycoZP6IeMirObcE,3291
11
12
  pyimagecuda/text.py,sha256=f3j1mi8ydk6kWiZt4gG7w85YFW--MwrezggpfuQW_tY,3558
12
13
  pyimagecuda/transform.py,sha256=cUrvPrNAkOoRDjuuOPdf-QnhZbk8VPMd01WR8IRgh_s,6450
13
14
  pyimagecuda/utils.py,sha256=8IZ35y783AVJVuoQmcStPVAyx5WK_PDhkWqLo51PbTo,633
14
- pyimagecuda-0.0.8.dist-info/METADATA,sha256=ILUUDcKbrj0jMtu1uF87jtRRpAyasv6TNG73p-8JeO4,6189
15
- pyimagecuda-0.0.8.dist-info/WHEEL,sha256=vkL3wTIkhjZa3RmEXX20hldNp6Q8qtwRjrXW6K5sw_Q,106
16
- pyimagecuda-0.0.8.dist-info/licenses/LICENSE,sha256=xfNh_pr4FPV8klv9rbs9GFflEfqf7vSFzcXK6BetRN0,1114
17
- pyimagecuda-0.0.8.dist-info/RECORD,,
15
+ pyimagecuda-0.0.9.dist-info/METADATA,sha256=FuVdOs5g4OIaVmmtUuLKwV0hxRPliklePU3n22EL5QU,6477
16
+ pyimagecuda-0.0.9.dist-info/WHEEL,sha256=vkL3wTIkhjZa3RmEXX20hldNp6Q8qtwRjrXW6K5sw_Q,106
17
+ pyimagecuda-0.0.9.dist-info/licenses/LICENSE,sha256=xfNh_pr4FPV8klv9rbs9GFflEfqf7vSFzcXK6BetRN0,1114
18
+ pyimagecuda-0.0.9.dist-info/RECORD,,