Skip to content

Reference

Here you can find the reference for the user facing API of Pylette. This consists of the extract_colors function, which is used to extract a color palette from an image, and the Palette and Color classes, which are used to work with the extracted color palette.

Key Features

  • JSON Export: Export palettes to structured JSON format with metadata
  • Hex Colors: Access hex color codes through the Color.hex property
  • Semantic Fields: Export uses semantic field names (rgb, hsv, hls) instead of generic values
  • Metadata: Rich metadata including extraction parameters, timing, and image info
  • Batch Processing: Process multiple images with parallel execution support

Pylette.extract_colors

Extracts a set of 'palette_size' colors from the given image.

Parameters:

Name Type Description Default
image ImageInput

The input image.

required
palette_size int

The number of colors to extract.

5
resize bool

Whether to resize the image before processing.

True
mode ExtractionMethod

The color quantization algorithm to use.

KM
sort_mode Literal['luminance', 'frequency'] | None

The mode to sort colors.

None
alpha_mask_threshold int | None

Optional integer between 0, 255. Any pixel with alpha less than this threshold will be discarded from calculations.

None

Returns: Palette: A palette of the extracted colors.

Examples:

Colors can be extracted from a variety of sources, including local files, byte streams, URLs, and numpy arrays.

>>> extract_colors("path/to/image.jpg", palette_size=5, resize=True, mode="KM", sort_mode="luminance")
>>> extract_colors(b"image_bytes", palette_size=5, resize=True, mode="KM", sort_mode="luminance")
Source code in Pylette/src/color_extraction.py
def extract_colors(
    image: ImageInput,
    palette_size: int = 5,
    resize: bool = True,
    mode: ExtractionMethod = ExtractionMethod.KM,
    sort_mode: Literal["luminance", "frequency"] | None = None,
    alpha_mask_threshold: int | None = None,
) -> Palette:
    """
    Extracts a set of 'palette_size' colors from the given image.

    Parameters:
        image: The input image.
        palette_size: The number of colors to extract.
        resize: Whether to resize the image before processing.
        mode: The color quantization algorithm to use.
        sort_mode: The mode to sort colors.
        alpha_mask_threshold: Optional integer between 0, 255.
            Any pixel with alpha less than this threshold will be discarded from calculations.
    Returns:
        Palette: A palette of the extracted colors.

    Examples:
        Colors can be extracted from a variety of sources, including local files, byte streams, URLs, and numpy arrays.

        >>> extract_colors("path/to/image.jpg", palette_size=5, resize=True, mode="KM", sort_mode="luminance")
        >>> extract_colors(b"image_bytes", palette_size=5, resize=True, mode="KM", sort_mode="luminance")
    """

    start_time = time.time()

    source_type = _get_source_type_from_image_input(image)
    # Normalize input to PIL Image and convert to RGBA
    img_obj = _normalize_image_input(image)
    original_size = img_obj.size
    img = img_obj.convert("RGBA")

    # Store original image info
    image_info = ImageInfo(
        original_size=original_size,
        processed_size=img.size if not resize else (256, 256),
        format=getattr(img_obj, "format", None),
        mode=img.mode,
        has_alpha=img.mode in ("RGBA", "LA") or "transparency" in img_obj.info,
    )

    if resize:
        img = img.resize((256, 256))
        image_info["processed_size"] = (256, 256)

    width, height = img.size
    arr = np.asarray(img)

    if alpha_mask_threshold is None:
        alpha_mask_threshold = 0

    alpha_mask = arr[:, :, 3] <= alpha_mask_threshold
    valid_pixels = arr[~alpha_mask]

    if len(valid_pixels) == 0:
        raise ValueError(
            f"No valid pixels remain after applying alpha mask with threshold {alpha_mask_threshold}. "
            f"Try using a lower alpha-mask-threshold value or check if your image has transparency."
        )

    # Color extraction
    match mode:
        case ExtractionMethod.KM:
            colors = k_means_extraction(valid_pixels, height, width, palette_size)
        case ExtractionMethod.MC:
            colors = median_cut_extraction(valid_pixels, height, width, palette_size)

    if colors:
        if sort_mode == "luminance":
            colors.sort(key=lambda c: c.luminance, reverse=False)
        else:
            colors.sort(reverse=True)

    end_time = time.time()

    # Build comprehensive metadata
    metadata = PaletteMetaData(
        image_source=_get_descriptive_image_source(image, img_obj),
        source_type=source_type,
        extraction_params=ExtractionParams(
            palette_size=palette_size,
            mode=mode,
            sort_mode=sort_mode,
            resize=resize,
            alpha_mask_threshold=alpha_mask_threshold,
        ),
        image_info=image_info,
        processing_stats=ProcessingStats(
            total_pixels=width * height,
            valid_pixels=len(valid_pixels),
            extraction_time=end_time - start_time,
            timestamp=datetime.now().isoformat(),
        ),
    )

    return Palette(colors, metadata=metadata)

Pylette.batch_extract_colors

Extract colors from multiple images in parallel.

Parameters:

Name Type Description Default
progress_callback Callable[[int, BatchResult], None] | None

Optional callback function called when each task completes. Receives (task_number, result) as arguments.

None
Source code in Pylette/src/color_extraction.py
def batch_extract_colors(
    images: Sequence[ImageInput],
    palette_size: int = 5,
    resize: bool = True,
    mode: ExtractionMethod = ExtractionMethod.KM,
    sort_mode: Literal["luminance", "frequency"] | None = None,
    alpha_mask_threshold: int | None = None,
    max_workers: int | None = None,
    progress_callback: Callable[[int, BatchResult], None] | None = None,
) -> list[BatchResult]:
    """Extract colors from multiple images in parallel.

    Args:
        progress_callback: Optional callback function called when each task completes.
                         Receives (task_number, result) as arguments.
    """

    def thread_fn(image: ImageInput):
        return extract_colors(
            image=image,
            palette_size=palette_size,
            resize=resize,
            mode=mode,
            sort_mode=sort_mode,
            alpha_mask_threshold=alpha_mask_threshold,
        )

    results: list[BatchResult] = []
    task_number = 1

    with ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="pylette") as executor:
        futures_to_image_map = {executor.submit(thread_fn, image): image for image in images}

        for future in as_completed(futures_to_image_map):
            source_image = futures_to_image_map[future]
            try:
                r = future.result()
                batch_result = BatchResult(source=source_image, result=r)
                results.append(batch_result)
                if progress_callback:
                    progress_callback(task_number, batch_result)
            except Exception as e:
                batch_result = BatchResult(source=source_image, exception=e)
                results.append(batch_result)
                if progress_callback:
                    progress_callback(task_number, batch_result)
            task_number += 1

    # Return results in original order
    source_to_result = {r.source: r for r in results}
    return [source_to_result[source] for source in images]

Pylette.Palette

Source code in Pylette/src/palette.py
class Palette:
    def __init__(self, colors: list[Color], metadata: PaletteMetaData | None = None):
        """
        Initializes a color palette with a list of Color objects.

        Parameters:
            colors (list[Color]): A list of Color objects.
        """

        self.colors = colors
        self.frequencies = [c.freq for c in colors]
        self.number_of_colors = len(colors)
        self.metadata = metadata

    def _generate_palette_image(self, w: int = 50, h: int = 50) -> Image.Image:
        """
        Helper method to generate a palette image.

        Parameters:
            w (int): Width of each color component.
            h (int): Height of each color component.

        Returns:
            PIL.Image.Image: The generated palette image.
        """
        img = Image.new("RGB", size=(w * self.number_of_colors, h))
        arr = np.asarray(img).copy()
        for i in range(self.number_of_colors):
            c = self.colors[i]
            arr[:, i * h : (i + 1) * h, :] = c.rgb
        return Image.fromarray(arr, "RGB")

    def save(
        self,
        w: int = 50,
        h: int = 50,
        filename: str = "color_palette",
        extension: str = "jpg",
    ) -> None:
        """
        Saves the color palette as an image.

        Parameters:
            w (int): Width of each color component.
            h (int): Height of each color component.
            filename (str): Filename.
            extension (str): File extension.
        """
        img = self._generate_palette_image(w, h)
        img.save(f"{filename}.{extension}")

    def display(
        self,
        w: int = 50,
        h: int = 50,
        save_to_file: bool = False,
        filename: str = "color_palette",
        extension: str = "jpg",
    ) -> None:
        """
        Displays the color palette as an image, with an option for saving the image.

        Parameters:
            w (int): Width of each color component.
            h (int): Height of each color component.
            save_to_file (bool): Whether to save the file or not.
            filename (str): Filename.
            extension (str): File extension.
        """
        img = self._generate_palette_image(w, h)
        img.show()

        if save_to_file:
            self.save(w, h, filename, extension)

    def __getitem__(self, item: int) -> Color:
        return self.colors[item]

    def __len__(self) -> int:
        return self.number_of_colors

    def random_color(self, N: int, mode: str = "frequency") -> list[Color]:
        """
        Returns N random colors from the palette, either using the frequency of each color, or choosing uniformly.

        Parameters:
            N (int): Number of random colors to return.
            mode (str): Mode to use for selection. Can be "frequency" or "uniform".

        Returns:
            list[Color]: List of N random colors from the palette.
        """

        if mode == "frequency":
            # Convert to numpy-compatible format for weighted selection
            colors_array = np.array(range(len(self.colors)))
            indices = np.random.choice(colors_array, size=N, p=self.frequencies)
            return [self.colors[i] for i in indices]
        elif mode == "uniform":
            # Uniform selection without weights
            colors_array = np.array(range(len(self.colors)))
            indices = np.random.choice(colors_array, size=N)
            return [self.colors[i] for i in indices]
        else:
            raise ValueError(f"Invalid mode: {mode}. Must be 'frequency' or 'uniform'.")

    def to_json(
        self,
        filename: str | None = None,
        colorspace: ColorSpace = ColorSpace.RGB,
        include_metadata: bool = True,
    ) -> dict[str, object] | None:
        """
        Exports the palette to JSON format.

        Parameters:
            filename (str | None): File to save to. If None, returns the dictionary.
            colorspace (Literal["rgb", "hsv", "hls"]): Color space to use.
            include_metadata (bool): Whether to include palette metadata.

        Returns:
            dict | None: The palette data as a dictionary if filename is None.
        """

        # Build the palette data
        palette_data: dict[str, object] = {
            "colors": [],
            "palette_size": self.number_of_colors,
            "colorspace": colorspace,
        }

        colors_list = []
        # Add color data
        for color in self.colors:
            color_values = color.get_colors(colorspace)
            color_data: dict[str, object] = {
                "frequency": float(color.freq),
            }

            # Add colorspace-specific field
            colorspace_field = colorspace.value.lower()  # "rgb", "hsv", "hls"
            if colorspace == ColorSpace.RGB:
                # RGB values should be integers
                color_data[colorspace_field] = [int(v) if isinstance(v, np.integer) else v for v in color_values]
            else:
                # HSV/HLS values should be floats
                color_data[colorspace_field] = [
                    float(v) if isinstance(v, (np.integer, np.floating)) else v for v in color_values
                ]

            # Add hex (always present, derived from RGB)
            color_data["hex"] = color.hex

            # Add RGB reference if colorspace is not RGB
            if colorspace != ColorSpace.RGB:
                color_data["rgb"] = [int(v) if isinstance(v, np.integer) else v for v in color.rgb]

            colors_list.append(color_data)

        palette_data["colors"] = colors_list

        # Add metadata if requested and available
        if include_metadata and self.metadata:
            metadata_dict: dict[str, object] = {}

            if "image_source" in self.metadata:
                metadata_dict["image_source"] = self.metadata["image_source"]
            if "source_type" in self.metadata:
                metadata_dict["source_type"] = self.metadata["source_type"]
            if "extraction_params" in self.metadata:
                metadata_dict["extraction_params"] = self.metadata["extraction_params"]
            if "image_info" in self.metadata:
                metadata_dict["image_info"] = self.metadata["image_info"]
            if "processing_stats" in self.metadata:
                metadata_dict["processing_stats"] = self.metadata["processing_stats"]

            palette_data["metadata"] = metadata_dict

        # Save to file if filename provided
        if filename is not None:
            with open(filename, "w") as f:
                json.dump(palette_data, f, indent=2)
            return None

        # Return data if no filename provided
        return palette_data

    def export(
        self,
        filename: str,
        colorspace: ColorSpace = ColorSpace.RGB,
        include_metadata: bool = True,
    ) -> None:
        """
        Export palette to JSON format.

        Parameters:
            filename (str): File to save to (extension will be added automatically if not present).
            colorspace (ColorSpace): Color space to use.
            include_metadata (bool): Whether to include metadata.
        """

        # Add .json extension if not present
        if not filename.endswith(".json"):
            filename = f"{filename}.json"

        self.to_json(filename=filename, colorspace=colorspace, include_metadata=include_metadata)

    def __str__(self):
        return "".join(["({}, {}, {}, {}) \n".format(c.rgb[0], c.rgb[1], c.rgb[2], c.freq) for c in self.colors])

    # Convenient metadata accessors
    @property
    def image_source(self) -> str | None:
        """Get the image source from metadata."""
        return self.metadata.get("image_source") if self.metadata else None

    @property
    def source_type(self) -> SourceType | None:
        """Get the source type from metadata."""
        return self.metadata.get("source_type") if self.metadata else None

    @property
    def extraction_params(self) -> ExtractionParams | None:
        """Get the extraction parameters from metadata."""
        return self.metadata.get("extraction_params") if self.metadata else None

    @property
    def image_info(self) -> ImageInfo | None:
        """Get the image information from metadata."""
        return self.metadata.get("image_info") if self.metadata else None

    @property
    def processing_stats(self) -> ProcessingStats | None:
        """Get the processing statistics from metadata."""
        return self.metadata.get("processing_stats") if self.metadata else None

extraction_params: ExtractionParams | None property

Get the extraction parameters from metadata.

image_info: ImageInfo | None property

Get the image information from metadata.

image_source: str | None property

Get the image source from metadata.

processing_stats: ProcessingStats | None property

Get the processing statistics from metadata.

source_type: SourceType | None property

Get the source type from metadata.

__init__

Initializes a color palette with a list of Color objects.

Parameters:

Name Type Description Default
colors list[Color]

A list of Color objects.

required
Source code in Pylette/src/palette.py
def __init__(self, colors: list[Color], metadata: PaletteMetaData | None = None):
    """
    Initializes a color palette with a list of Color objects.

    Parameters:
        colors (list[Color]): A list of Color objects.
    """

    self.colors = colors
    self.frequencies = [c.freq for c in colors]
    self.number_of_colors = len(colors)
    self.metadata = metadata

display

Displays the color palette as an image, with an option for saving the image.

Parameters:

Name Type Description Default
w int

Width of each color component.

50
h int

Height of each color component.

50
save_to_file bool

Whether to save the file or not.

False
filename str

Filename.

'color_palette'
extension str

File extension.

'jpg'
Source code in Pylette/src/palette.py
def display(
    self,
    w: int = 50,
    h: int = 50,
    save_to_file: bool = False,
    filename: str = "color_palette",
    extension: str = "jpg",
) -> None:
    """
    Displays the color palette as an image, with an option for saving the image.

    Parameters:
        w (int): Width of each color component.
        h (int): Height of each color component.
        save_to_file (bool): Whether to save the file or not.
        filename (str): Filename.
        extension (str): File extension.
    """
    img = self._generate_palette_image(w, h)
    img.show()

    if save_to_file:
        self.save(w, h, filename, extension)

export

Export palette to JSON format.

Parameters:

Name Type Description Default
filename str

File to save to (extension will be added automatically if not present).

required
colorspace ColorSpace

Color space to use.

RGB
include_metadata bool

Whether to include metadata.

True
Source code in Pylette/src/palette.py
def export(
    self,
    filename: str,
    colorspace: ColorSpace = ColorSpace.RGB,
    include_metadata: bool = True,
) -> None:
    """
    Export palette to JSON format.

    Parameters:
        filename (str): File to save to (extension will be added automatically if not present).
        colorspace (ColorSpace): Color space to use.
        include_metadata (bool): Whether to include metadata.
    """

    # Add .json extension if not present
    if not filename.endswith(".json"):
        filename = f"{filename}.json"

    self.to_json(filename=filename, colorspace=colorspace, include_metadata=include_metadata)

random_color

Returns N random colors from the palette, either using the frequency of each color, or choosing uniformly.

Parameters:

Name Type Description Default
N int

Number of random colors to return.

required
mode str

Mode to use for selection. Can be "frequency" or "uniform".

'frequency'

Returns:

Type Description
list[Color]

list[Color]: List of N random colors from the palette.

Source code in Pylette/src/palette.py
def random_color(self, N: int, mode: str = "frequency") -> list[Color]:
    """
    Returns N random colors from the palette, either using the frequency of each color, or choosing uniformly.

    Parameters:
        N (int): Number of random colors to return.
        mode (str): Mode to use for selection. Can be "frequency" or "uniform".

    Returns:
        list[Color]: List of N random colors from the palette.
    """

    if mode == "frequency":
        # Convert to numpy-compatible format for weighted selection
        colors_array = np.array(range(len(self.colors)))
        indices = np.random.choice(colors_array, size=N, p=self.frequencies)
        return [self.colors[i] for i in indices]
    elif mode == "uniform":
        # Uniform selection without weights
        colors_array = np.array(range(len(self.colors)))
        indices = np.random.choice(colors_array, size=N)
        return [self.colors[i] for i in indices]
    else:
        raise ValueError(f"Invalid mode: {mode}. Must be 'frequency' or 'uniform'.")

save

Saves the color palette as an image.

Parameters:

Name Type Description Default
w int

Width of each color component.

50
h int

Height of each color component.

50
filename str

Filename.

'color_palette'
extension str

File extension.

'jpg'
Source code in Pylette/src/palette.py
def save(
    self,
    w: int = 50,
    h: int = 50,
    filename: str = "color_palette",
    extension: str = "jpg",
) -> None:
    """
    Saves the color palette as an image.

    Parameters:
        w (int): Width of each color component.
        h (int): Height of each color component.
        filename (str): Filename.
        extension (str): File extension.
    """
    img = self._generate_palette_image(w, h)
    img.save(f"{filename}.{extension}")

to_json

Exports the palette to JSON format.

Parameters:

Name Type Description Default
filename str | None

File to save to. If None, returns the dictionary.

None
colorspace Literal[rgb, hsv, hls]

Color space to use.

RGB
include_metadata bool

Whether to include palette metadata.

True

Returns:

Type Description
dict[str, object] | None

dict | None: The palette data as a dictionary if filename is None.

Source code in Pylette/src/palette.py
def to_json(
    self,
    filename: str | None = None,
    colorspace: ColorSpace = ColorSpace.RGB,
    include_metadata: bool = True,
) -> dict[str, object] | None:
    """
    Exports the palette to JSON format.

    Parameters:
        filename (str | None): File to save to. If None, returns the dictionary.
        colorspace (Literal["rgb", "hsv", "hls"]): Color space to use.
        include_metadata (bool): Whether to include palette metadata.

    Returns:
        dict | None: The palette data as a dictionary if filename is None.
    """

    # Build the palette data
    palette_data: dict[str, object] = {
        "colors": [],
        "palette_size": self.number_of_colors,
        "colorspace": colorspace,
    }

    colors_list = []
    # Add color data
    for color in self.colors:
        color_values = color.get_colors(colorspace)
        color_data: dict[str, object] = {
            "frequency": float(color.freq),
        }

        # Add colorspace-specific field
        colorspace_field = colorspace.value.lower()  # "rgb", "hsv", "hls"
        if colorspace == ColorSpace.RGB:
            # RGB values should be integers
            color_data[colorspace_field] = [int(v) if isinstance(v, np.integer) else v for v in color_values]
        else:
            # HSV/HLS values should be floats
            color_data[colorspace_field] = [
                float(v) if isinstance(v, (np.integer, np.floating)) else v for v in color_values
            ]

        # Add hex (always present, derived from RGB)
        color_data["hex"] = color.hex

        # Add RGB reference if colorspace is not RGB
        if colorspace != ColorSpace.RGB:
            color_data["rgb"] = [int(v) if isinstance(v, np.integer) else v for v in color.rgb]

        colors_list.append(color_data)

    palette_data["colors"] = colors_list

    # Add metadata if requested and available
    if include_metadata and self.metadata:
        metadata_dict: dict[str, object] = {}

        if "image_source" in self.metadata:
            metadata_dict["image_source"] = self.metadata["image_source"]
        if "source_type" in self.metadata:
            metadata_dict["source_type"] = self.metadata["source_type"]
        if "extraction_params" in self.metadata:
            metadata_dict["extraction_params"] = self.metadata["extraction_params"]
        if "image_info" in self.metadata:
            metadata_dict["image_info"] = self.metadata["image_info"]
        if "processing_stats" in self.metadata:
            metadata_dict["processing_stats"] = self.metadata["processing_stats"]

        palette_data["metadata"] = metadata_dict

    # Save to file if filename provided
    if filename is not None:
        with open(filename, "w") as f:
            json.dump(palette_data, f, indent=2)
        return None

    # Return data if no filename provided
    return palette_data

Pylette.Color

Source code in Pylette/src/color.py
class Color(object):
    def __init__(self, rgba: tuple[int, ...], frequency: float):
        """
        Initializes a Color object with RGBA values and frequency.

        Parameters:
            rgba (tuple[int, ...]): A tuple of RGBA values.
            frequency (float): The frequency of the color.
        """
        assert len(rgba) == 4, "RGBA values must be a tuple of length 4"
        *rgb, alpha = rgba
        self.rgb = cast(tuple[int, int, int], rgb)
        self.rgba = rgba
        self.a = alpha
        self.freq: float = frequency
        self.weight = alpha / 255.0

    def display(self, w: int = 50, h: int = 50) -> None:
        """
        Displays the color in a window of specified width and height.

        Parameters:
        w (int): Width of the window in pixels.
        h (int): Height of the window in pixels.
        """

        from PIL import Image

        img = Image.new("RGBA", size=(w, h), color=self.rgba)
        img.show()

    def __lt__(self, other: "Color") -> bool:
        """
        Compares the frequency of this color with another color.

        Parameters:
            other (Color): The other Color object to compare with.

        Returns:
            bool: True if the frequency of this color is less than the frequency of the other color, False otherwise.
        """
        return self.freq < other.freq

    def get_colors(self, colorspace: ColorSpace = ColorSpace.RGB) -> tuple[int, ...] | tuple[float, ...]:
        """
        Returns the color values in the specified color space.

        Parameters:
            colorspace (ColorSpace): The color space to use.

        Returns:
            tuple[int, ...] | tuple[float, ...]: The color values in the specified color space.
        """
        colors = {ColorSpace.RGB: self.rgb, ColorSpace.HSV: self.hsv, ColorSpace.HLS: self.hls}
        return colors[colorspace]

    @property
    def hsv(self) -> tuple[float, float, float]:
        """
        Converts the RGB color to HSV color space.

        Returns:
            tuple[float, float, float]: The color values in HSV color space.
        """
        return colorsys.rgb_to_hsv(r=self.rgb[0] / 255, g=self.rgb[1] / 255, b=self.rgb[2] / 255)

    @property
    def hls(self) -> tuple[float, float, float]:
        """
        Converts the RGB color to HLS color space.

        Returns:
            tuple[float, float, float]: The color values in HLS color space.
        """
        return colorsys.rgb_to_hls(r=self.rgb[0] / 255, g=self.rgb[1] / 255, b=self.rgb[2] / 255)

    @property
    def hex(self) -> str:
        """
        Returns the color as a hexadecimal string.

        Returns:
            str: The color in hexadecimal format (e.g., "#FF5733").
        """
        return f"#{self.rgb[0]:02X}{self.rgb[1]:02X}{self.rgb[2]:02X}"

    @property
    def luminance(self) -> float:
        """
        Calculates the luminance of the color.

        Returns:
        float: The luminance of the color.
        """
        return np.dot(luminance_weights, self.rgb)

hex: str property

Returns the color as a hexadecimal string.

Returns:

Name Type Description
str str

The color in hexadecimal format (e.g., "#FF5733").

hls: tuple[float, float, float] property

Converts the RGB color to HLS color space.

Returns:

Type Description
tuple[float, float, float]

tuple[float, float, float]: The color values in HLS color space.

hsv: tuple[float, float, float] property

Converts the RGB color to HSV color space.

Returns:

Type Description
tuple[float, float, float]

tuple[float, float, float]: The color values in HSV color space.

luminance: float property

Calculates the luminance of the color.

Returns: float: The luminance of the color.

__init__

Initializes a Color object with RGBA values and frequency.

Parameters:

Name Type Description Default
rgba tuple[int, ...]

A tuple of RGBA values.

required
frequency float

The frequency of the color.

required
Source code in Pylette/src/color.py
def __init__(self, rgba: tuple[int, ...], frequency: float):
    """
    Initializes a Color object with RGBA values and frequency.

    Parameters:
        rgba (tuple[int, ...]): A tuple of RGBA values.
        frequency (float): The frequency of the color.
    """
    assert len(rgba) == 4, "RGBA values must be a tuple of length 4"
    *rgb, alpha = rgba
    self.rgb = cast(tuple[int, int, int], rgb)
    self.rgba = rgba
    self.a = alpha
    self.freq: float = frequency
    self.weight = alpha / 255.0

__lt__

Compares the frequency of this color with another color.

Parameters:

Name Type Description Default
other Color

The other Color object to compare with.

required

Returns:

Name Type Description
bool bool

True if the frequency of this color is less than the frequency of the other color, False otherwise.

Source code in Pylette/src/color.py
def __lt__(self, other: "Color") -> bool:
    """
    Compares the frequency of this color with another color.

    Parameters:
        other (Color): The other Color object to compare with.

    Returns:
        bool: True if the frequency of this color is less than the frequency of the other color, False otherwise.
    """
    return self.freq < other.freq

display

Displays the color in a window of specified width and height.

Parameters: w (int): Width of the window in pixels. h (int): Height of the window in pixels.

Source code in Pylette/src/color.py
def display(self, w: int = 50, h: int = 50) -> None:
    """
    Displays the color in a window of specified width and height.

    Parameters:
    w (int): Width of the window in pixels.
    h (int): Height of the window in pixels.
    """

    from PIL import Image

    img = Image.new("RGBA", size=(w, h), color=self.rgba)
    img.show()

get_colors

Returns the color values in the specified color space.

Parameters:

Name Type Description Default
colorspace ColorSpace

The color space to use.

RGB

Returns:

Type Description
tuple[int, ...] | tuple[float, ...]

tuple[int, ...] | tuple[float, ...]: The color values in the specified color space.

Source code in Pylette/src/color.py
def get_colors(self, colorspace: ColorSpace = ColorSpace.RGB) -> tuple[int, ...] | tuple[float, ...]:
    """
    Returns the color values in the specified color space.

    Parameters:
        colorspace (ColorSpace): The color space to use.

    Returns:
        tuple[int, ...] | tuple[float, ...]: The color values in the specified color space.
    """
    colors = {ColorSpace.RGB: self.rgb, ColorSpace.HSV: self.hsv, ColorSpace.HLS: self.hls}
    return colors[colorspace]

Core Types:

Pylette.types.ArrayImage: TypeAlias = NDArray[np.uint8] module-attribute

Pylette.types.ArrayLike

Protocol for array-like objects.

Source code in Pylette/src/types.py
class ArrayLike(Protocol):
    """Protocol for array-like objects."""

    def __array__(self) -> NDArray[np.uint8]: ...

Pylette.types.BatchResult dataclass

Source code in Pylette/src/types.py
@dataclass
class BatchResult:
    source: ImageInput
    result: "Palette | None" = None
    exception: Exception | None = None

    @property
    def success(self) -> bool:
        return self.result is not None

    @property
    def palette(self) -> "Palette | None":
        return self.result

    @property
    def error(self) -> "Exception | None":
        return self.exception

Pylette.types.BytesImage: TypeAlias = bytes module-attribute

Pylette.types.ColorArray: TypeAlias = NDArray[np.uint8] module-attribute

Pylette.types.ColorSpace

Source code in Pylette/src/types.py
class ColorSpace(str, Enum):
    RGB = "rgb"
    HSV = "hsv"
    HLS = "hls"

Pylette.types.ColorTuple: TypeAlias = RGBTuple | RGBATuple module-attribute

Pylette.types.CV2Image: TypeAlias = MatLike module-attribute

Pylette.types.ExtractionMethod

Source code in Pylette/src/types.py
class ExtractionMethod(str, Enum):
    MC = "MedianCut"
    KM = "KMeans"

Pylette.types.ExtractionParams

Source code in Pylette/src/types.py
class ExtractionParams(TypedDict):
    palette_size: int
    mode: ExtractionMethod
    sort_mode: str | None
    resize: bool
    alpha_mask_threshold: int | None

Pylette.types.FloatArray: TypeAlias = NDArray[np.floating[Any]] module-attribute

Pylette.types.ImageInfo

Source code in Pylette/src/types.py
class ImageInfo(TypedDict):
    original_size: tuple[int, int]
    processed_size: tuple[int, int]
    format: str | None
    mode: str
    has_alpha: bool

Pylette.types.ImageInput: TypeAlias = PathLikeImage | URLImage | BytesImage | ArrayImage | PILImage | CV2Image module-attribute

Pylette.types.ImageLike

Protocol for image-like objects that can be converted to PIL Image.

Source code in Pylette/src/types.py
class ImageLike(Protocol):
    """Protocol for image-like objects that can be converted to PIL Image."""

    pass

Pylette.types.IntArray: TypeAlias = NDArray[np.integer[Any]] module-attribute

Pylette.types.PaletteMetaData

Source code in Pylette/src/types.py
class PaletteMetaData(TypedDict):
    image_source: str
    source_type: SourceType
    extraction_params: ExtractionParams
    image_info: ImageInfo
    processing_stats: ProcessingStats

Pylette.types.PathLikeImage: TypeAlias = str | Path module-attribute

Pylette.types.PILImage: TypeAlias = Image.Image module-attribute

Pylette.types.ProcessingStats

Source code in Pylette/src/types.py
class ProcessingStats(TypedDict):
    total_pixels: int
    valid_pixels: int
    extraction_time: float | None
    timestamp: str

Pylette.types.RGBATuple: TypeAlias = tuple[int, int, int, int] module-attribute

Pylette.types.RGBTuple: TypeAlias = tuple[int, int, int] module-attribute

Pylette.types.SourceType

Source code in Pylette/src/types.py
class SourceType(str, Enum):
    FILE_PATH = "file_path"
    URL = "url"
    BYTES = "bytes"
    PIL_IMAGE = "pil_image"
    NUMPY_ARRAY = "numpy_array"
    CV2_IMAGE = "cv2_image"
    UNKNOWN = "unknown"

Pylette.types.URLImage: TypeAlias = str module-attribute