feat: tiered PNG compression for artifact saving
This commit is contained in:
1 parent
d0a3d48c17
commit
02dc22364a
2 files changed
+66
-3
No files matched your search
@@ -24,9 +24,16 @@ class TempArtSink(Sink):
|
||||
return Address(AddressDomain.Temporary, *self.__comps)
|
||||
|
||||
def push(self, env: Environment, art: Artifact) -> None:
|
||||
"""
|
||||
Save given artifact to temporary directory.
|
||||
|
||||
The artifact is explicitly saved with the intermediary (faster)
|
||||
encoder configuration, because temporary artifacts are transient
|
||||
and usually get re-loaded and re-encoded later.
|
||||
"""
|
||||
p = self.push_hint(env)
|
||||
LOGGER.info("Saving temporary artifact: %s", p)
|
||||
artio.save_artifact(art, p)
|
||||
artio.save_artifact(art, p, for_intermediary=True)
|
||||
|
||||
def repull(self, env: Environment) -> Artifact:
|
||||
"""
|
||||
|
||||
@@ -42,9 +42,65 @@ def load_artifact(p: Path) -> Artifact:
|
||||
return PIL.Image.open(p, "r", ["PNG"])
|
||||
|
||||
|
||||
def save_artifact(art: Artifact, p: Path) -> None:
|
||||
def save_artifact(art: Artifact, p: Path, for_intermediary: bool = False) -> None:
|
||||
"""
|
||||
Save given artifact as PNG file.
|
||||
|
||||
The PNG encoder settings are selected in tiers by artifact size:
|
||||
smaller artifacts are saved with lighter compression while larger
|
||||
ones are saved with stronger compression. This tiered configuration
|
||||
exists to strike a balance between final artifact file size and
|
||||
assembly speed, since strong compression is slow and only pays off
|
||||
on large images.
|
||||
|
||||
:param art: The artifact to be saved.
|
||||
:param p: The path to saved PNG file.
|
||||
:param for_intermediary: Whether this artifact is saved as an
|
||||
intermediary. Intermediaries are transient and will be loaded
|
||||
and re-encoded later, so they are always saved with the
|
||||
balanced, faster configuration regardless of their size.
|
||||
"""
|
||||
LOGGER.debug("Saving artifact: %s", p)
|
||||
art.save(p, format="PNG")
|
||||
|
||||
# compute optimize flag and compress level based on artifact size.
|
||||
optimize: bool
|
||||
compress_level: int
|
||||
|
||||
if for_intermediary:
|
||||
# If this image is saved for intermediary,
|
||||
# we use default balanced config.
|
||||
optimize = False
|
||||
compress_level = 6
|
||||
else:
|
||||
pixels = art.width * art.height
|
||||
if pixels >= 1024**2:
|
||||
# >= 1024x1024, super large icon,
|
||||
# use best compression config.
|
||||
optimize = True
|
||||
compress_level = 9
|
||||
elif pixels >= 256**2:
|
||||
# >= 256x256 and < 1024x1024, large icon,
|
||||
# use max compress level.
|
||||
optimize = False
|
||||
compress_level = 9
|
||||
elif pixels >= 64**2:
|
||||
# >= 64x64 and < 256x256, medium icon,
|
||||
# use higher compress level.
|
||||
optimize = False
|
||||
compress_level = 8
|
||||
elif pixels >= 16**2:
|
||||
# >= 16x16 and < 64x64, small icon,
|
||||
# use higher compress level.
|
||||
optimize = False
|
||||
compress_level = 7
|
||||
else:
|
||||
# < 16x16, very small icon,
|
||||
# use default balanced config.
|
||||
optimize = False
|
||||
compress_level = 6
|
||||
|
||||
# save as PNG with computed optimize flag and compress level
|
||||
art.save(p, format="PNG", optimize=optimize, compress_level=compress_level)
|
||||
|
||||
|
||||
def dup_artifact(src: Path, dst: Path) -> None:
|
||||
|
||||
Reference in new issue
Block a user