Skip to content

Image Processing

Unified image I/O and manipulation regardless of source (file, URL, base64).


xpytools.xtool.img.load.load

Python
load(src: Union[str, Path, bytes], rtype: Literal['bytes', 'base64', 'pil.img'] = 'bytes', timeout: int = 20) -> Union[bytes, str, 'Image.Image']

Load an img from any source (file path, URL, base64, bytes) and return the requested representation.

Parameters:

Name Type Description Default

src

str | Path | bytes

Image source (local path, URL, base64 string, or raw bytes).

required

rtype

('bytes', 'base64', 'pil.img')

Return type.

'bytes'

timeout

int

Timeout for URL downloads.

20

Returns:

Type Description
bytes | str | Image

Image data in desired representation.

Source code in xpytools/xtool/img/load.py
Python
@requireModules(["PIL"], exc_raise=False)
def load(
        src: Union[str, Path, bytes],
        rtype: Literal["bytes", "base64", "pil.img"] = "bytes",
        timeout: int = 20,
        ) -> Union[bytes, str, "Image.Image"]:
    """
    Load an img from any source (file path, URL, base64, bytes)
    and return the requested representation.

    Parameters
    ----------
    src : str | Path | bytes
        Image source (local path, URL, base64 string, or raw bytes).
    rtype : {'bytes', 'base64', 'pil.img'}, default='bytes'
        Return type.
    timeout : int, default=20
        Timeout for URL downloads.

    Returns
    -------
    bytes | str | Image.Image
        Image data in desired representation.
    """
    # --- Normalize to bytes --------------------------------------------------
    if isinstance(src, (bytes, bytearray)):
        img_bytes = bytes(src)
    elif isinstance(src, str) and src.startswith(("http://", "https://")):
        img_bytes = _load_from_url(src, timeout)
    elif isinstance(src, str) and is_base64(src):
        from .conversions import base64_to_bytes
        img_bytes = base64_to_bytes(src)
    elif isinstance(src, Path):
        img_bytes = _load_from_path(src)
    elif isinstance(src, str) and '/' in src or '.' in src:
        img_bytes = _load_from_path(src)
    else:
        raise ValueError(f"Unsupported img source type: {type(src)}")

    # --- Delegate to converters ---------------------------------------------
    if rtype == "bytes":
        return img_bytes
    if rtype == "base64":
        return base64.b64encode(img_bytes).decode("utf-8")
    if rtype == "pil.img":
        if not Image:
            raise ImportError("Pillow not installed; cannot return PIL Image.")
        from .conversions import from_bytes
        return from_bytes(img_bytes)

    raise ValueError(f"Invalid rtype: {rtype!r} (expected 'bytes', 'base64', or 'pil.img').")

xpytools.xtool.img.conversions.to_bytes

Python
to_bytes(img: 'Image.Image', format: str = 'PNG') -> bytes
Source code in xpytools/xtool/img/conversions.py
Python
@requireModules(["PIL"], exc_raise=True)
def to_bytes(img: "Image.Image", format: str = "PNG") -> bytes:
    buf = BytesIO()
    img.save(buf, format=format)
    return buf.getvalue()

xpytools.xtool.img.conversions.to_base64

Python
to_base64(img: 'Image.Image', format: str = 'PNG') -> str
Source code in xpytools/xtool/img/conversions.py
Python
@requireModules(["PIL"], exc_raise=True)
def to_base64(img: "Image.Image", format: str = "PNG") -> str:
    return base64.b64encode(to_bytes(img, format)).decode("utf-8")

xpytools.xtool.img.conversions.from_bytes

Python
from_bytes(data: bytes) -> 'Image.Image'
Source code in xpytools/xtool/img/conversions.py
Python
@requireModules(["PIL"], exc_raise=True)
def from_bytes(data: bytes) -> "Image.Image":
    return Image.open(BytesIO(data))

xpytools.xtool.img.conversions.from_base64

Python
from_base64(b64_str: str) -> 'Image.Image'
Source code in xpytools/xtool/img/conversions.py
Python
@requireModules(["PIL"], exc_raise=True)
def from_base64(b64_str: str) -> "Image.Image":
    return from_bytes(_load_from_base64(b64_str))

xpytools.xtool.img.transform.create_thumbnail

Python
create_thumbnail(image_data: bytes, size: tuple[int, int] = (300, 300), format: str = 'PNG') -> bytes

Create a thumbnail from img bytes and return as bytes. Keeps aspect ratio, converts to RGB, and uses high-quality downsampling.

Source code in xpytools/xtool/img/transform.py
Python
@requireModules(['PIL'], exc_raise=True)
def create_thumbnail(
        image_data: bytes,
        size: tuple[int, int] = (300, 300),
        format: str = "PNG",
        ) -> bytes:
    """
    Create a thumbnail from img bytes and return as bytes.
    Keeps aspect ratio, converts to RGB, and uses high-quality downsampling.
    """
    if not Image:
        raise ImportError("Pillow (PIL) is required for img operations.")

    image = Image.open(BytesIO(image_data))
    if image.mode != "RGB":
        image = image.convert("RGB")

    image.thumbnail(size, Resampling.LANCZOS)
    buffer = BytesIO()
    image.save(buffer, format=format)
    return buffer.getvalue()

xpytools.xtool.img.transform.resize

Python
resize(image_data: bytes, size: tuple[int, int], format: Optional[str] = None, keep_aspect: bool = True) -> bytes

Resize img to a specific size. Optionally keeps aspect ratio.

Source code in xpytools/xtool/img/transform.py
Python
@requireModules(['PIL'], exc_raise=True)
def resize(
        image_data: bytes,
        size: tuple[int, int],
        format: Optional[str] = None,
        keep_aspect: bool = True,
        ) -> bytes:
    """
    Resize img to a specific size. Optionally keeps aspect ratio.
    """
    if not Image:
        raise ImportError("Pillow (PIL) is required for resize_image().")

    img = Image.open(BytesIO(image_data))
    if img.mode != "RGB":
        img = img.convert("RGB")

    if keep_aspect:
        img.thumbnail(size, Resampling.LANCZOS)
    else:
        img = img.resize(size, Resampling.LANCZOS)

    buf = BytesIO()
    fmt = format or img.format or "PNG"
    img.save(buf, format=fmt)
    return buf.getvalue()