Initial commit

This commit is contained in:
2024-08-27 20:33:44 +02:00
commit 1f1832267d
14794 changed files with 1599592 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
from .cwebp import Cwebp # noqa: F401
from .gifsicle import Gifsicle # noqa: F401
from .jpegoptim import Jpegoptim # noqa: F401
from .optipng import Optipng # noqa: F401
from .pngquant import Pngquant # noqa: F401

View File

@@ -0,0 +1,53 @@
import logging
import subprocess
from typing import ClassVar, List
logger = logging.getLogger("willow")
class OptimizerBase:
library_name: ClassVar[str] = ""
image_format: ClassVar[str] = ""
class Meta:
abstract = True
@classmethod
def applies_to(cls, image_format: str) -> bool:
return image_format.lower() == cls.image_format.lower()
@classmethod
def get_check_library_arguments(cls) -> List[str]:
"""
Return a list of arguments to check if the library exists.
Note: using --help by default as that usually returns a zero exit code
"""
return ["--help"]
@classmethod
def check_library(cls) -> bool:
args = [cls.library_name] + cls.get_check_library_arguments()
try:
subprocess.check_output(args, stderr=subprocess.STDOUT)
return True
except (FileNotFoundError, subprocess.CalledProcessError):
return False
@classmethod
def get_command_arguments(cls, file_path: str) -> List[str]:
"""Return a list of arguments for the given optimizer library."""
return []
@classmethod
def process(cls, file_path: str):
args = [cls.library_name] + cls.get_command_arguments(file_path)
try:
subprocess.check_output(args, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exc:
logger.exception(
"Error optimizing %s with the '%s' library with error: %s",
file_path,
cls.library_name,
exc.output,
)

View File

@@ -0,0 +1,34 @@
from typing import ClassVar, List
from .base import OptimizerBase
__all__ = ["Cwebp"]
class Cwebp(OptimizerBase):
"""https://developers.google.com/speed/webp/docs/cwebp"""
library_name: ClassVar[str] = "cwebp"
image_format: ClassVar[str] = "webp"
@classmethod
def get_check_library_arguments(cls) -> List[str]:
# running just cwebp gives basic infor and returns a zero exit code
return []
@classmethod
def get_command_arguments(
cls, file_path: str, progressive: bool = False
) -> List[str]:
return [
"-m",
"6", # inspect all encoding possibilities for best file size
"-mt", # use multithreading if possible
"-pass",
"10", # max number of passes
"-q",
"75", # compression factor. 100 produces the highest quality.
file_path,
"-o",
file_path,
]

View File

@@ -0,0 +1,20 @@
from typing import ClassVar, List
from .base import OptimizerBase
__all__ = ["Gifsicle"]
class Gifsicle(OptimizerBase):
"""http://www.lcdf.org/gifsicle/"""
library_name: ClassVar[str] = "gifsicle"
image_format: ClassVar[str] = "gif"
@classmethod
def get_command_arguments(cls, file_path: str) -> List[str]:
return [
"-b", # required parameter for the package
"-O3", # slowest, but produces best results
file_path, # the file
]

View File

@@ -0,0 +1,21 @@
from typing import ClassVar, List
from .base import OptimizerBase
__all__ = ["Jpegoptim"]
class Jpegoptim(OptimizerBase):
"""https://github.com/tjko/jpegoptim"""
library_name: ClassVar[str] = "jpegoptim"
image_format: ClassVar[str] = "jpeg"
@classmethod
def get_command_arguments(cls, file_path: str) -> List[str]:
return [
"--strip-all", # strip out all text information like comments and EXIF data
"--max=85", # set maximum quality
"--all-progressive", # make the resulting image progressive
file_path,
]

View File

@@ -0,0 +1,21 @@
from typing import ClassVar, List
from .base import OptimizerBase
__all__ = ["Optipng"]
class Optipng(OptimizerBase):
"""https://optipng.sourceforge.net/"""
library_name: ClassVar[str] = "optipng"
image_format: ClassVar[str] = "png"
@classmethod
def get_command_arguments(cls, file_path: str) -> List[str]:
return [
"-quiet",
"-o2", # optimization level 2 (out of 7)
"-i0", # non-interlaced, progressive scanned image
file_path, # the file
]

View File

@@ -0,0 +1,25 @@
from typing import ClassVar, List
from .base import OptimizerBase
__all__ = ["Pngquant"]
class Pngquant(OptimizerBase):
"""https://pngquant.org/"""
library_name: ClassVar[str] = "pngquant"
image_format: ClassVar[str] = "png"
@classmethod
def get_command_arguments(
cls, file_path: str, progressive: bool = False
) -> List[str]:
return [
"--force", # allow overwriting existing files
"--strip", # remove optional metadata
"--skip-if-larger",
file_path, # the file as input
"--output",
file_path, # the file as output
]