Coverage for qubalab/images/utils.py: 93%
28 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-10-07 15:29 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-10-07 15:29 +0000
1import numpy as np
2import imageio
3import base64
4from .metadata.image_shape import ImageShape
5from typing import Optional, Union
8def bytes_to_image(
9 uri: Union[str, bytes], is_rgb: bool, shape: Optional[ImageShape] = None
10) -> np.ndarray:
11 """
12 Read the provided bytes (or URI pointing to a binary file) and convert them to a numpy array
13 representing an image.
15 :param uri: an URI pointing to a binary file, or an array of bytes. This must
16 represent a 2-dimensionnal or 3-dimensionnal (with a channel axis) image
17 :param is_rgb: whether the expected image should have the RGB format
18 :param shape: the shape of the image to open. This will be used to reorder axes.
19 Can be None to not reorder axes
20 :returns: a numpy array representing the input image. If shape is defined, this function
21 will try to set its dimensions to (c, y, x), but this may not always be the case if two
22 dimensions have the same number of elements
23 """
24 if is_rgb:
25 image = imageio.v3.imread(uri)
26 else:
27 image = imageio.volread(uri, format="tiff")
29 if shape is None:
30 return image
31 else:
32 return _reorder_axes(image, shape)
35def base64_to_image(
36 data: str, is_rgb: bool, shape: Optional[ImageShape] = None
37) -> np.ndarray:
38 """
39 Read the provided string with the Base64 format and convert it to a numpy array
40 representing an image.
42 :param uri: a text with the Base64 format. This must represent a 2-dimensionnal
43 or 3-dimensionnal (with a channel axis) image
44 :param is_rgb: whether the expected image should have the RGB format
45 :param shape: the shape of the image to open. This will be used to reorder axes.
46 Can be None to not reorder axes
47 :returns: a numpy array representing the input image. If shape is defined, this function
48 will try to set its dimensions to (c, y, x), but this may not always be the case if two
49 dimensions have the same number of elements
50 """
51 return bytes_to_image(base64.b64decode(data), is_rgb, shape)
54def _reorder_axes(image: np.ndarray, shape: ImageShape):
55 """
56 Reorder the axes of the provided image to (c, y, x).
58 :param image: the image to reorder
59 :param shape: the desired shape of the image
60 :param shape: the shape of the image to open. This will be used to reorder axes
61 :returns: a numpy array representing the input image. This function will try to set
62 its dimensions to (c, y, x), but this may not be the case if two
63 dimensions have the same number of elements
64 """
65 x_axis = -1
66 y_axis = -1
67 c_axis = -1
68 for axis, number_of_elements_on_axis in enumerate(image.shape):
69 if c_axis == -1 and number_of_elements_on_axis == shape.c:
70 c_axis = axis
71 elif y_axis == -1 and number_of_elements_on_axis == shape.y:
72 y_axis = axis
73 elif x_axis == -1 and number_of_elements_on_axis == shape.x:
74 x_axis = axis
76 if x_axis != -1 and y_axis != -1 and c_axis != -1:
77 return np.moveaxis(image, [c_axis, y_axis, x_axis], [0, 1, 2]).copy()
78 else:
79 return image