def _check_options(border_size: int=0, border_color: str=None, padding_size: int=0, padding_color: str=None, background_color=None, supersample: int=DEFAULT_SUPERSAMPLE) -> tuple: """Check supplied options.""" if padding_size < 0: raise exceptions.InvalidOption(f"Padding size has to be non-zero, padding size provided: {padding_size}") if border_size < 0: raise exceptions.InvalidOption(f"Border size has to be non-zero, border size provided: {border_size}") if padding_color: try: padding_color = ImageColor.getrgb(padding_color) except ValueError as exc: raise exceptions.InvalidOption(f"Invalid padding color provided: {padding_color!r}") from exc if border_color: try: border_color = ImageColor.getrgb(border_color) except ValueError as exc: raise exceptions.InvalidOption(f"Invalid border color provided: {border_color!r}") from exc if background_color: try: background_color = ImageColor.getrgb(background_color) except ValueError as exc: raise exceptions.InvalidOption(f"Invalid background color provided: {background_color!r}") from exc if supersample < 1: raise exceptions.InvalidOption(f"Supersample must not be less than one, supersample provided: {supersample}") return border_color, padding_color, background_color
def create_hexsticker(image: str, output: str, *, border_size: int=0, border_color: str=None, padding_size: int=0, padding_color: str=None, background_color=None, supersample: int=DEFAULT_SUPERSAMPLE) -> str: """Create a hexagon sticker. :param image: A source image to use as a hexsticker source. :param output: A path to output file. :param border_size: Size of sticker hexagonal border. :param border_color: Color of hexagonal border (defaults to white). :param padding_size: Optional padding for the image. :param padding_color: Color of padded area (defaults to white). :param background_color: Color of background around hexagon :param supersample: Scale factor to use for supersampling. :return: a path to resulting image """ _LOGGER.debug("Checking supplied options") border_color, padding_color, background_color = _check_options( border_size=border_size, border_color=border_color, padding_size=padding_size, padding_color=padding_color, background_color=background_color, supersample=supersample, ) _LOGGER.debug("Loading input image") try: source_img = Image.open(image).convert("RGBA") except Exception as exc: raise exceptions.LoadError(f"Failed to load input image {image}: {str(exc)}") from exc # Cut image to fit aspect ratio, crop to center. _LOGGER.debug("Cropping source image") img = _crop_image(source_img) source_size = img.size supersample_size = (source_size[0] * supersample, source_size[1] * supersample) if supersample > 1: _LOGGER.debug(f"Upscaling source image {supersample}x to {supersample_size}") img = img.resize(supersample_size) if padding_size: _LOGGER.debug("Padding image to center") img = ImageOps.expand(img, border=padding_size, fill=padding_color or DEFAULT_PADDING_COLOR) elif padding_color: raise exceptions.InvalidOption(f"Padding size is set to zero, but padding color set to {padding_color!r}") if border_size: _LOGGER.debug("Creating hexagon border") _draw_hexagon(img, color=border_color or DEFAULT_BORDER_COLOR) border = Image.new( 'RGBA', (int(img.size[0] + border_size / HEIGHT_TO_WIDTH_RATIO), img.size[1] + border_size), color=border_color or DEFAULT_BORDER_COLOR ) border.paste(img, (int((border_size / HEIGHT_TO_WIDTH_RATIO) / 2), border_size // 2)) img = border elif border_color: raise exceptions.InvalidOption(f"Border size is set to zero, but border color set to {border_color!r}") _LOGGER.debug("Creating surrounding hexagon") _draw_hexagon(img, color=background_color or DEFAULT_BACKGROUND_COLOR) if supersample > 1: _LOGGER.debug(f"Downscaling output image {supersample}x back to {source_size}") img = img.resize(source_size, Image.ANTIALIAS) output = output or _get_output_file_name(image) output_file_type = _get_file_type(output) if output else _get_file_type(image) _LOGGER.debug("Resulting file type: %r", output_file_type) _LOGGER.info("Writing output to %r", output) with open(output, 'wb') as output_file: try: img.save(output_file, output_file_type.upper()) except Exception as exc: raise exceptions.SaveError(f"Failed to save resulting image: {str(exc)}") from exc return output