Source code for manim_beanim.other_objects.photo

from ..my_imports import *
__all__ = ['Photo']


def clip_image_to_mobject(image, mobj):
    """
    Crop an ImageMobject into the shape of another mobject.

    This utility captures a snapshot of `image`, then masks it with `mobj` to produce
    a clipped image in the shape of the given mobject.

    :param image: The ImageMobject to crop.
    :type image: ImageMobject

    :param mobj: The shape mobject used as a cropping mask.
    :type mobj: Mobject

    :return: A new ImageMobject cropped to the shape of `mobj`.
    :rtype: ImageMobject
    """
    scene = Scene()
    render = scene.renderer

    aux = Image.fromarray(render.camera.pixel_array)
    bg = Image.new("RGBA", aux.size, (0, 0, 0, 0))

    render.camera.set_pixel_array(np.zeros_like(render.camera.pixel_array))
    render.camera.capture_mobjects([image])
    img = Image.fromarray(render.camera.pixel_array.copy())

    render.camera.set_pixel_array(np.zeros_like(render.camera.pixel_array))
    render.camera.capture_mobjects([mobj])
    mask = Image.fromarray(render.camera.pixel_array.copy())

    result = Image.composite(img, bg, mask)
    cropped = result.crop(result.getbbox())
    return ImageMobject(cropped)


[docs] class Photo(Group): """ Represent and decorate a photograph with optional polaroid or frame styling. :param photo: Path to the image file. :type photo: str :param decorator_style: Style of decoration. Options: - ``"polaroid"``: Photo with a pin and caption. - ``"techno"``: Photo with a simple colored frame. :type decorator_style: str, optional :param caption: Text caption under the polaroid photo (only for ``polaroid`` style). :type caption: str, optional :param text_size: Font size for caption text. Default is ``35``. :type text_size: float :param text_color: Color of caption text. Default is ``WHITE``. :type text_color: ParsableManimColor :param decorator_color: Color for the frame or pin. Default is ``WHITE``. :type decorator_color: ParsableManimColor :param pin_color: Color for the pin on the polaroid. Default is ``WHITE``. :type pin_color: ParsableManimColor :param corner_rad: Corner radius for frames. Default is ``0``. :type corner_rad: float :param decorator_stroke_w: Stroke width for frames. Default is ``1``. :type decorator_stroke_w: float :param kwargs: Additional arguments passed to :class:`Group`. .. note:: Captions apply only when ``decorator_style == "polaroid"``. **Example usage:** .. code-block:: python from manim import * from manim_beanim import Photo class Example_Photo(Scene): def construct(self): photo1 = Photo("figures/pic.png", decorator_style="polaroid", caption="My Photo") photo2 = Photo("figures/pic.png", decorator_style="techno") self.add(photo1, photo2) """ def __init__( self, photo, decorator_style: str = "techno", caption: str = "", text_size: float = 35, text_color: ParsableManimColor = WHITE, decorator_color: ParsableManimColor = WHITE, pin_color: ParsableManimColor = WHITE, corner_rad: float = 0, decorator_stroke_w: float = 1, **kwargs ): super().__init__(**kwargs) # This gets the svg path in the package, wherever the package is and then add the desired svg. Observe that path.dirname gets the path where this file is located. I then go back to the parent directory, where the figure folder is. get_svg_path = path.join(path.dirname(__file__), '../figures/pin.svg') # Polaroid if decorator_style == "polaroid": r1 = RoundedRectangle(width=2, height=2.9, corner_radius=corner_rad/2) r2 = RoundedRectangle(width=1.8, height=2.1, corner_radius=corner_rad / 2).move_to(r1.get_center()).shift(0.3*UP) polaroid = Cutout(r1, r2, fill_opacity=1, color=WHITE, stroke_color=decorator_color, stroke_width=3*decorator_stroke_w) image = ImageMobject(photo).set(z_index=-1) frame = SurroundingRectangle(r2, color=decorator_color, stroke_width=decorator_stroke_w, buff=0.0) mask = frame.copy().set_fill(BLACK, 1).set_stroke(width=5) clip = clip_image_to_mobject(image, mask) clip.move_to(mask).scale_to_fit_width(mask.width).set_z_index(-10) pin = SVGMobject(get_svg_path).scale(0.2).next_to(polaroid, UP, buff=-0.05).shift(0.2*RIGHT) pin.set_color(pin_color) # Text under polaroid texto = Tex(caption, font_size=text_size, color=text_color).next_to(clip, DOWN, buff=0.2).set(z_index=4) self.chosen_photo = Group(polaroid, clip, texto, pin) self.add(self.chosen_photo) # Technophoto if decorator_style == "techno": image = ImageMobject(photo).scale_to_fit_height(config['frame_height']) frame = SurroundingRectangle(image, corner_radius=corner_rad, color=decorator_color, stroke_width=3*decorator_stroke_w, buff=-0.2) mask = frame.copy().set_fill(WHITE, 1).set_stroke(width=0) clip = clip_image_to_mobject(image, mask) clip.move_to(mask).scale_to_fit_width(mask.width) self.chosen_photo = Group(clip, frame) self.add(self.chosen_photo)