86 lines
3.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import pathlib
import subprocess
from typing import Union
import matplotlib
import matplotlib.pyplot as plt
class Week1:
def __init__(self):
# 避免覆盖内置名 list
self.qualities = [2, 7, 12, 17, 22, 27, 31]
def _ffmpeg_path(self) -> pathlib.Path:
"""
返回项目 bin 目录下 ffmpeg 的可执行路径。
Week1/Week1.py 位于项目的 Week1 目录内bin 与 Week1 处于同级。
"""
here = pathlib.Path(__file__).resolve()
project_root = here.parent.parent # <project_root>/Week1/Week1.py -> <project_root>
bin_dir = project_root / "bin"
exe_name = "ffmpeg.exe" if os.name == "nt" else "ffmpeg"
ffmpeg = bin_dir / exe_name
if not ffmpeg.exists():
raise FileNotFoundError(f"未找到 ffmpeg 可执行文件: {ffmpeg}")
return ffmpeg
def compress(self, image_src: Union[str, pathlib.Path]):
"""
使用不同 q:v 质量参数将 PNG 转为 JPEG。
输出文件与输入文件位于同目录,命名为 <原名>_<q>.jpg
"""
image_path = pathlib.Path(image_src).resolve()
if not image_path.exists():
raise FileNotFoundError(f"输入图像不存在: {image_path}")
ffmpeg = self._ffmpeg_path()
stem = image_path.stem
parent = image_path.parent
for q in self.qualities:
out_path = parent / f"{stem}_{q}.jpg"
# -y 覆盖已存在文件;参数以列表方式传入
cmd = [
str(ffmpeg),
"-y",
"-i", str(image_path),
"-q:v", str(q),
str(out_path),
]
# 失败时抛异常,便于定位问题
subprocess.run(cmd, check=True)
def render(self, image_src: Union[str, pathlib.Path]):
"""
读取生成的 JPEG 文件大小,并绘制质量(q) vs 文件大小(bytes) 的折线图。
"""
image_path = pathlib.Path(image_src).resolve()
stem = image_path.stem
parent = image_path.parent
sizes = []
qualities = []
for q in self.qualities:
jpg_path = parent / f"{stem}_{q}.jpg"
if not jpg_path.exists():
# 若缺失,给出清晰异常,提示先运行 compress
raise FileNotFoundError(f"缺少压缩输出文件,请先运行 compress: {jpg_path}")
qualities.append(q)
sizes.append(os.path.getsize(jpg_path)/8)
# 使用 pyplot 正确保存图像
plt.figure(figsize=(6, 4))
plt.plot(qualities, sizes, marker="o")
plt.xlabel("JPEG quality (q:v)")
plt.ylabel("File size (Kbytes)")
plt.title("Quality vs File Size")
plt.grid(True)
project_root = pathlib.Path(__file__).resolve().parent.parent
out_png = project_root / "data" / "render.png"
out_png.parent.mkdir(parents=True, exist_ok=True)
plt.tight_layout()
plt.savefig(str(out_png))
plt.close()