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)
|
return Address(AddressDomain.Temporary, *self.__comps)
|
||||||
|
|
||||||
def push(self, env: Environment, art: Artifact) -> None:
|
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)
|
p = self.push_hint(env)
|
||||||
LOGGER.info("Saving temporary artifact: %s", p)
|
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:
|
def repull(self, env: Environment) -> Artifact:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -42,9 +42,65 @@ def load_artifact(p: Path) -> Artifact:
|
|||||||
return PIL.Image.open(p, "r", ["PNG"])
|
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)
|
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:
|
def dup_artifact(src: Path, dst: Path) -> None:
|
||||||
|
|||||||
Reference in new issue
Block a user