Files
OCRmyPDF/src/ocrmypdf/_exec/pngquant.py
T

65 lines
1.7 KiB
Python

# SPDX-FileCopyrightText: 2022 James R. Barlow
# SPDX-License-Identifier: MPL-2.0
"""Interface to pngquant executable."""
from __future__ import annotations
from contextlib import contextmanager
from io import BytesIO
from pathlib import Path
from subprocess import PIPE
from packaging.version import Version
from PIL import Image
from ocrmypdf.exceptions import MissingDependencyError
from ocrmypdf.subprocess import get_version, run
def version() -> Version:
return Version(get_version('pngquant', regex=r'(\d+(\.\d+)*).*'))
def available():
try:
version()
except MissingDependencyError:
return False
return True
@contextmanager
def input_as_png(input_file: Path):
if not input_file.name.endswith('.png'):
with Image.open(input_file) as im:
bio = BytesIO()
im.save(bio, format='png')
bio.seek(0)
yield bio
else:
with open(input_file, 'rb') as f:
yield f
def quantize(input_file: Path, output_file: Path, quality_min: int, quality_max: int):
with input_as_png(input_file) as input_stream:
args = [
'pngquant',
'--force',
'--skip-if-larger',
'--quality',
f'{quality_min}-{quality_max}',
'--', # pngquant: stop processing arguments
'-', # pngquant: stream input and output
]
result = run(args, stdin=input_stream, stdout=PIPE, stderr=PIPE, check=False)
if result.returncode == 0:
# input_file could be the same as output_file, so we defer the write
output_file.write_bytes(result.stdout)
def quantize_mp(args):
return quantize(*args)