Skip to content

utils

crop_to_ratio(image, ratio=1)

Reshapes an image to the specified ratio by cropping along the larger dimension.

Parameters:

Name Type Description Default
image Image

PIL.Image to crop.

required
ratio float

width to height ratio to which to crop the image. Use 1 to obtain a square image.

1

Returns:

Type Description
Image

Cropped PIL.Image.

Source code in phomo/utils.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def crop_to_ratio(image: Image.Image, ratio: float = 1) -> Image.Image:
    """Reshapes an image to the specified ratio by cropping along the larger
    dimension.

    Args:
        image: PIL.Image to crop.
        ratio: width to height ratio to which to crop the image. Use 1 to obtain a
            square image.

    Returns:
        Cropped PIL.Image.
    """

    width, height = image.size

    def crop_height(image, rx):
        return image.crop(
            (
                0,
                (rx / 2),
                width,
                height - (rx / 2),
            )
        )

    def crop_width(image, rx):
        return image.crop(
            (
                (rx / 2),
                0,
                width - (rx / 2),
                height,
            )
        )

    # Find the delta change.
    rxheight = width / ratio - height
    rxwidth = height * ratio - width

    # Can only crop pixels, not add them.
    if rxheight < 0 and rxwidth < 0:
        # If both sides can be cropped to get what we want:
        # Select the largest (because both are negative)
        if rxheight > rxwidth:
            return crop_height(image, rxheight * -1)
        else:
            return crop_width(image, rxwidth * -1)

    elif rxheight < 0:
        # Trim height to fit aspect ratio
        return crop_height(image, rxheight * -1)

    elif rxwidth < 0:
        # Trim width to fit aspect ratio
        return crop_width(image, rxwidth * -1)

    else:
        # Can't do anything in this case
        return image

open_img_file(img_file, crop_ratio=None, size=None, mode=None)

Open an image file with some extra bells and whistles.

Parameters:

Name Type Description Default
img_file PathLike

path to the image.

required
crop_ratio Optional[float]

width to height to which to crop the image.

None
size Optional[Tuple[int, int]]

resize image.

None
mode Optional[str]

convert the image to the provided mode. See PIL image modes.

None

Returns:

Type Description
Image

Image instance.

Source code in phomo/utils.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def open_img_file(
    img_file: PathLike,
    crop_ratio: Optional[float] = None,
    size: Optional[Tuple[int, int]] = None,
    mode: Optional[str] = None,
) -> Image.Image:
    """Open an image file with some extra bells and whistles.

    Args:
        img_file: path to the image.
        crop_ratio: width to height to which to crop the image.
        size: resize image.
        mode: convert the image to the provided mode. See PIL image modes.

    Returns:
        Image instance.
    """
    with Image.open(img_file) as img:
        img_t = exif_transpose(img)
        img = img_t if img_t is not None else img
        if crop_ratio is not None:
            img = crop_to_ratio(img, crop_ratio)
        if size is not None:
            img = img.resize(size)
        if mode is not None:
            img = img.convert(mode)
        else:
            img = img.convert("RGB")
    return img

rainbow_of_squares(target_dir, size=(10, 10), r_range=range(0, 256, 15), g_range=range(0, 256, 15), b_range=range(0, 256, 15))

Generate a bunch of solid-color tiles for experimentation and testing.

Parameters:

Name Type Description Default
target_dir Path

direcotry in which to place the rainbow tiles.

required
size Tuple[int, int]

size of the images, width followed by height.

(10, 10)
r_range_params

Passed to range() to stride through the red channel.

required
g_range_params

Passed to range() to stride through the green channel.

required
b_range_params

Passed to range() to stride through the blue channel.

required
Source code in phomo/utils.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def rainbow_of_squares(
    target_dir: Path,
    size: Tuple[int, int] = (10, 10),
    r_range: range = range(0, 256, 15),
    g_range: range = range(0, 256, 15),
    b_range: range = range(0, 256, 15),
) -> None:
    """Generate a bunch of solid-color tiles for experimentation and testing.

    Args:
        target_dir: direcotry in which to place the rainbow tiles.
        size: size of the images, width followed by height.
        r_range_params: Passed to ``range()`` to stride through the red channel.
        g_range_params: Passed to ``range()`` to stride through the green channel.
        b_range_params: Passed to ``range()`` to stride through the blue channel.
    """
    target_dir.mkdir(exist_ok=True)
    with tqdm(
        total=len(r_range) + len(g_range) + len(b_range), desc="Generating color tiles"
    ) as pbar:
        canvas = np.ones((*size[::-1], 3))
        for r in r_range:
            for g in g_range:
                for b in b_range:
                    img = (canvas * [r, g, b]).astype(np.uint8)
                    filename = "{:03d}-{:03d}-{:03d}.png".format(r, g, b)
                    img = Image.fromarray(img, mode="RGB")
                    img.save(target_dir / filename)
                    pbar.update()

resize_array(array, size, *args, **kwargs)

Resize an array representing and image.

Parameters:

Name Type Description Default
array ndarray

array containing the images data.

required
size Tuple[int, int]

desired size, width followed by height.

required
*args, **kwargs

passed to PIL.Image.resize.

required

Returns:

Type Description
ndarray

Array containing the resized image data.

Source code in phomo/utils.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
def resize_array(
    array: np.ndarray, size: Tuple[int, int], *args, **kwargs
) -> np.ndarray:
    """Resize an array representing and image.

    Args:
        array: array containing the images data.
        size: desired size, width followed by height.
        *args, **kwargs: passed to `PIL.Image.resize`.

    Returns:
        Array containing the resized image data.
    """
    return np.asarray(Image.fromarray(array).resize(size, *args, **kwargs))