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

1import numpy as np 

2import imageio 

3import base64 

4from .metadata.image_shape import ImageShape 

5from typing import Optional, Union 

6 

7 

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. 

14 

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") 

28 

29 if shape is None: 

30 return image 

31 else: 

32 return _reorder_axes(image, shape) 

33 

34 

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. 

41 

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) 

52 

53 

54def _reorder_axes(image: np.ndarray, shape: ImageShape): 

55 """ 

56 Reorder the axes of the provided image to (c, y, x). 

57 

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 

75 

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