Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/python_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ pub fn resize_lanczos4_opencv<'py>(
#[pyfunction]
pub fn imdecode_py<'py>(
py: Python<'py>,
buf: &[u8],
buf: pyo3::pybacked::PyBackedBytes,
flags: i32,
) -> PyResult<Bound<'py, PyArray3<u8>>> {
use crate::cv_compat::{imdecode, ImreadFlags};
Expand All @@ -1220,7 +1220,6 @@ pub fn imdecode_py<'py>(
}
};

let buf = buf.to_vec();
let decoded = py.allow_threads(move || imdecode(&buf, imread_flags));

match decoded {
Expand Down
13 changes: 13 additions & 0 deletions tests/test_python_bindings.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Tests for Python bindings of training_sample_rust."""

import importlib.util
import io

import numpy as np
import pytest
from PIL import Image

try:
import trainingsample as tsr
Expand Down Expand Up @@ -34,6 +36,17 @@ def sample_video():
class TestImageOperations:
"""Test image processing operations."""

@pytest.mark.parametrize("buffer_type", [bytes, bytearray])
def test_imdecode_owned_buffer(self, buffer_type):
"""Decode buffers that remain valid while the GIL is released."""
image = np.arange(4 * 5 * 3, dtype=np.uint8).reshape((4, 5, 3))
encoded = io.BytesIO()
Image.fromarray(image).save(encoded, format="PNG")

decoded = tsr.imdecode_py(buffer_type(encoded.getvalue()), 1)

np.testing.assert_array_equal(decoded, image)

def test_batch_crop_images(self, sample_images):
"""Test batch cropping with custom coordinates."""
crop_boxes = [(10, 10, 50, 50), (20, 20, 40, 40), (5, 5, 60, 60)]
Expand Down
Loading