Implement support for adding a background image on top of the background color but below the animation.
This commit is contained in:
parent
cc5cdde995
commit
7eb41a45e7
@ -291,6 +291,7 @@ class AFPRenderer(VerboseOutput):
|
||||
self,
|
||||
path: str,
|
||||
background_color: Optional[Color] = None,
|
||||
background_image: Optional[Image.Image] = None,
|
||||
only_depths: Optional[List[int]] = None,
|
||||
movie_transform: Matrix = Matrix.identity(),
|
||||
verbose: bool = False,
|
||||
@ -301,7 +302,7 @@ class AFPRenderer(VerboseOutput):
|
||||
# This is the SWF we care about.
|
||||
with self.debugging(verbose):
|
||||
swf.color = background_color or swf.color
|
||||
return self.__render(swf, only_depths, movie_transform)
|
||||
return self.__render(swf, only_depths, movie_transform, background_image)
|
||||
|
||||
raise Exception(f'{path} not found in registered SWFs!')
|
||||
|
||||
@ -1009,7 +1010,13 @@ class AFPRenderer(VerboseOutput):
|
||||
# We didn't find the tag we were after.
|
||||
return None
|
||||
|
||||
def __render(self, swf: SWF, only_depths: Optional[List[int]], movie_transform: Matrix) -> Tuple[int, List[Image.Image]]:
|
||||
def __render(
|
||||
self,
|
||||
swf: SWF,
|
||||
only_depths: Optional[List[int]],
|
||||
movie_transform: Matrix,
|
||||
background_image: Optional[Image.Image],
|
||||
) -> Tuple[int, List[Image.Image]]:
|
||||
# First, let's attempt to resolve imports.
|
||||
self.__registered_objects = self.__handle_imports(swf)
|
||||
|
||||
@ -1039,6 +1046,69 @@ class AFPRenderer(VerboseOutput):
|
||||
)
|
||||
self.__movie = Movie(root_clip)
|
||||
|
||||
# If we have a background image, add it to the root clip.
|
||||
if background_image:
|
||||
# Stretch the image to make sure it fits the entire frame.
|
||||
imgwidth = float(background_image.width)
|
||||
imgheight = float(background_image.height)
|
||||
background_matrix = Matrix(
|
||||
a=swf.location.width / imgwidth,
|
||||
b=0,
|
||||
c=0,
|
||||
d=swf.location.height / imgheight,
|
||||
tx=0,
|
||||
ty=0,
|
||||
)
|
||||
|
||||
# Register the background image with the texture library.
|
||||
name = f"{swf.exported_name}_inserted_background"
|
||||
self.textures[name] = background_image.convert("RGBA")
|
||||
|
||||
# Place an instance of this background on the root clip.
|
||||
root_clip.placed_objects.append(
|
||||
PlacedShape(
|
||||
-1,
|
||||
-1,
|
||||
Point.identity(),
|
||||
background_matrix,
|
||||
Color(1.0, 1.0, 1.0, 1.0),
|
||||
Color(0.0, 0.0, 0.0, 0.0),
|
||||
0,
|
||||
None,
|
||||
RegisteredShape(
|
||||
-1,
|
||||
# The coordinates of the rectangle of the shape in screen space.
|
||||
[
|
||||
Point(0.0, 0.0),
|
||||
Point(imgwidth, 0.0),
|
||||
Point(imgwidth, imgheight),
|
||||
Point(0.0, imgheight),
|
||||
],
|
||||
# The coordinates of the original texture in UV space (we don't use this).
|
||||
[
|
||||
Point(0.0, 0.0),
|
||||
Point(1.0, 0.0),
|
||||
Point(1.0, 1.0),
|
||||
Point(0.0, 1.0),
|
||||
],
|
||||
# No texture colors.
|
||||
[],
|
||||
[
|
||||
DrawParams(
|
||||
# Instantiable, includes texture.
|
||||
0x3,
|
||||
# The texture this should use for drawing.
|
||||
name,
|
||||
# The coordinates of the triangles that get drawn (we don't use this).
|
||||
[0, 1, 2, 2, 1, 3],
|
||||
# The blend color.
|
||||
None,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# Create the root mask for where to draw the root clip.
|
||||
movie_mask = Image.new("RGBA", actual_size, color=(255, 0, 0, 255))
|
||||
|
||||
|
@ -262,6 +262,12 @@ def main() -> int:
|
||||
default=None,
|
||||
help="Set the background color of the animation as a comma-separated RGB or RGBA color, overriding a default if present in the SWF.",
|
||||
)
|
||||
render_parser.add_argument(
|
||||
"--background-image",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Set a background image to be placed behind the animation. Note that it will be stretched to fit the animation.",
|
||||
)
|
||||
render_parser.add_argument(
|
||||
"--only-depths",
|
||||
type=str,
|
||||
@ -731,6 +737,12 @@ def main() -> int:
|
||||
else:
|
||||
color = None
|
||||
|
||||
# Allow inserting a background image.
|
||||
if args.background_image:
|
||||
background = Image.open(args.background_image)
|
||||
else:
|
||||
background = None
|
||||
|
||||
# Calculate the size of the SWF so we can apply scaling options.
|
||||
swf_location = renderer.compute_path_location(args.path)
|
||||
requested_width = swf_location.width
|
||||
@ -783,7 +795,7 @@ def main() -> int:
|
||||
depths = [int(d.strip()) for d in args.only_depths.split(",")]
|
||||
else:
|
||||
depths = None
|
||||
duration, images = renderer.render_path(args.path, verbose=args.verbose, background_color=color, only_depths=depths, movie_transform=transform)
|
||||
duration, images = renderer.render_path(args.path, verbose=args.verbose, background_color=color, background_image=background, only_depths=depths, movie_transform=transform)
|
||||
|
||||
if len(images) == 0:
|
||||
raise Exception("Did not render any frames!")
|
||||
|
Loading…
x
Reference in New Issue
Block a user