diff --git a/win2xcur/cursor.py b/win2xcur/cursor.py index f864459..47a2dd2 100644 --- a/win2xcur/cursor.py +++ b/win2xcur/cursor.py @@ -6,13 +6,15 @@ from wand.sequence import SingleImage class CursorImage: image: SingleImage hotspot: Tuple[int, int] + nominal: int - def __init__(self, image: SingleImage, hotspot: Tuple[int, int]) -> None: + def __init__(self, image: SingleImage, hotspot: Tuple[int, int], nominal: int) -> None: self.image = image self.hotspot = hotspot + self.nominal = nominal def __repr__(self) -> str: - return 'CursorImage(image=%r, hotspot=%r)' % (self.image, self.hotspot) + return 'CursorImage(image=%r, hotspot=%r, nominal=%r)' % (self.image, self.hotspot, self.nominal) class CursorFrame: diff --git a/win2xcur/parser/cur.py b/win2xcur/parser/cur.py index 5ae4ed9..d8cf524 100644 --- a/win2xcur/parser/cur.py +++ b/win2xcur/parser/cur.py @@ -22,7 +22,7 @@ class CURParser(BaseParser): self._image = Image(blob=blob, format='cur') self._hotspots = self._parse_header() self.frames = [CursorFrame([ - CursorImage(image, hotspot) for image, hotspot in zip(self._image.sequence, self._hotspots) + CursorImage(image, hotspot, image.width) for image, hotspot in zip(self._image.sequence, self._hotspots) ])] def _parse_header(self) -> List[Tuple[int, int]]: diff --git a/win2xcur/parser/xcursor.py b/win2xcur/parser/xcursor.py index 5838d62..369a51d 100644 --- a/win2xcur/parser/xcursor.py +++ b/win2xcur/parser/xcursor.py @@ -81,7 +81,7 @@ class XCursorParser(BaseParser): image = Image(width=width, height=height) image.import_pixels(channel_map='BGRA', data=blob) images_by_size[nominal_size].append( - (CursorImage(image.sequence[0], (x_offset, y_offset)), delay) + (CursorImage(image.sequence[0], (x_offset, y_offset), nominal_size), delay) ) if len(set(map(len, images_by_size.values()))) != 1: diff --git a/win2xcur/shadow.py b/win2xcur/shadow.py index 11b991b..d987535 100644 --- a/win2xcur/shadow.py +++ b/win2xcur/shadow.py @@ -1,5 +1,6 @@ from typing import List +from wand.color import Color from wand.image import BaseImage, Image from win2xcur.cursor import CursorFrame @@ -7,18 +8,27 @@ from win2xcur.cursor import CursorFrame def apply_to_image(image: BaseImage, *, color: str, radius: float, sigma: float, xoffset: float, yoffset: float) -> Image: - opacity = Image(width=image.width, height=image.height, pseudo='xc:white') - opacity.composite(image.channel_images['opacity'], left=round(xoffset * image.width), - top=round(yoffset * image.height)) + xoffset = round(xoffset * image.width) + yoffset = round(yoffset * image.height) + new_width = image.width + 3 * xoffset + new_height = image.height + 3 * yoffset + + opacity = Image(width=new_width, height=new_height, pseudo='xc:white') + opacity.composite(image.channel_images['opacity'], left=xoffset, top=yoffset) opacity.gaussian_blur(radius * image.width, sigma * image.width) opacity.negate() opacity.modulate(50) - shadow = Image(width=image.width, height=image.height, pseudo='xc:' + color) + shadow = Image(width=new_width, height=new_height, pseudo='xc:' + color) shadow.composite(opacity, operator='copy_opacity') - result = image.clone() + result = Image(width=new_width, height=new_height, pseudo='xc:transparent') + result.composite(image) result.composite(shadow, operator='difference') + + trimmed = result.clone() + trimmed.trim(color=Color('transparent')) + result.crop(width=max(image.width, trimmed.width), height=max(image.height, trimmed.height)) return result