docs: 更新 README 并新增 pngquant 自动安装脚本

This commit is contained in:
2026-03-26 14:10:54 +08:00
10 changed files with 992 additions and 140 deletions

View File

@@ -22,17 +22,17 @@ class convertPPT:
"""
TTYPES = {"JPG": 17, "PNG": 18, "PDF": 32, "XPS": 33}
__all__ = ["savetype", "trans", "close", "open"]
def __init__(self, file: str | Path, trans: str = "JPG") -> None:
if sys.platform != "win32":
raise SystemError("Only support Windows system.")
if not Path(file).exists():
raise FileNotFoundError("File not found! Please check the file path.")
if trans.upper() not in convertPPT.TTYPES.keys():
raise ValueError("Save type is not supported.")
self.__file = Path(file)
self.__saveType = (convertPPT.TTYPES[trans.upper()], trans.upper())
if not self.__file.exists():
raise FileNotFoundError("File not found! Please check the file path.")
trans_upper = trans.upper()
if trans_upper not in convertPPT.TTYPES:
raise ValueError("Save type is not supported.")
self.__saveType = (convertPPT.TTYPES[trans_upper], trans_upper)
self.__inUsing = wcc.Dispatch("PowerPoint.Application")
def __enter__(self) -> Self:
@@ -50,22 +50,20 @@ class convertPPT:
return cls(file, trans=trans.upper())
def saveAs(self, saveType: str | None = None) -> None:
if saveType not in convertPPT.TTYPES.keys():
raise ValueError("Save type is not supported.")
if saveType is not None:
self.__saveType = (convertPPT.TTYPES[saveType.upper()], saveType.upper())
else:
if saveType is None:
self.__saveType = (convertPPT.TTYPES["JPG"], "JPG")
else:
saveType_upper = saveType.upper()
if saveType_upper not in convertPPT.TTYPES:
raise ValueError("Save type is not supported.")
self.__saveType = (convertPPT.TTYPES[saveType_upper], saveType_upper)
def trans(self, saveto: str | Path = ".", width: int | None = None) -> None:
"""
saveto : 保存路径,默认为当前路径。
"""
ppt = self.__inUsing.Presentations.Open(self.__file.absolute())
if Path(saveto) == Path("."):
output = self.__file.absolute()
else:
output = Path(saveto).absolute()
output = Path(saveto).absolute()
if width is not None:
ppt.Export(output, self.__saveType[1], width)
else:
@@ -85,40 +83,44 @@ def PPT_longPic(
700 "22.1%"
指定为None的时候不进行图像缩放。
"""
pptFile = Path(pptFile)
if saveName:
sType = saveName.split(".")[-1] if "." in saveName else "JPG"
if sType.upper() not in ["JPG", "PNG"]:
sType = Path(saveName).suffix[1:].upper() if Path(saveName).suffix else "JPG"
if sType not in ["JPG", "PNG"]:
raise ValueError(f"Unable to save this type `{sType}` of image.")
else:
sType = "JPG"
with TemporaryDirectory() as tmpdirname:
with convertPPT(pptFile, trans=sType) as ppt:
ppt.trans(saveto=tmpdirname)
picList = list(Path(tmpdirname).glob(f"*.{sType}"))
picList = sorted(Path(tmpdirname).glob(f"*.{sType}"))
if not picList:
raise ValueError("No images generated from PPT conversion.")
with Image.open(picList[0]) as img:
if isinstance(width, str):
qw = float(width[:-1]) / 100.0
qw = float(width.rstrip("%")) / 100.0
nwidth, nheight = (int(img.width * qw), int(img.height * qw))
elif width is None:
nwidth, nheight = img.size
else:
nwidth, nheight = (width, int(img.height * width / img.width))
canvas = Image.new(img.mode, (nwidth, nheight * len(picList)))
for i in range(1, len(picList) + 1):
with Image.open(Path(tmpdirname).joinpath(f"幻灯片{i}.{sType}")) as img:
for i, picPath in enumerate(picList, 1):
with Image.open(picPath) as img:
new_img = img.resize((nwidth, nheight), resample=Image.Resampling.LANCZOS)
canvas.paste(new_img, box=(0, (i - 1) * nheight))
if Path(saveto) == Path("."):
filepath = Path(pptFile).parent
else:
filepath = Path(saveto)
filepath = pptFile.parent if Path(saveto) == Path(".") else Path(saveto)
if saveName:
if "." in saveName:
canvas.save(filepath.joinpath(saveName))
if Path(saveName).suffix:
canvas.save(filepath / saveName)
else:
canvas.save(filepath.joinpath(saveName), format=sType)
canvas.save(filepath / saveName, format=sType)
else:
canvas.save(filepath.joinpath(Path(pptFile).stem), format=sType)
canvas.save(filepath / pptFile.name, format=sType)
def imageOptimization(
@@ -136,40 +138,48 @@ def imageOptimization(
if isinstance(imageFile, str | Path):
imageFile = Image.open(imageFile)
img = cv2.cvtColor(np.array(imageFile), cv2.COLOR_RGB2BGR)
if max_width or max_height:
height, width, _ = img.shape
oShape = (width, height)
new_width, new_height = width, height
if max_width:
if width > max_width:
height = int(height * max_width / width)
width = max_width
if max_width < 1:
width = int(width * max_width)
height = int(height * max_width)
new_width = int(width * max_width)
new_height = int(height * max_width)
elif width > max_width:
new_width = max_width
new_height = int(height * max_width / width)
if max_height:
if height > max_height:
width = int(width * max_height / height)
height = max_height
if max_height < 1:
if width < oShape[0]:
if height / oShape[1] > max_height:
height = int(oShape[1] * max_height)
width = int(oShape[0] * max_height)
if new_width < width:
if new_height / height > max_height:
new_height = int(height * max_height)
new_width = int(width * max_height)
else:
height = int(height * max_height)
width = int(width * max_height)
img = cv2.resize(img, (width, height))
new_height = int(new_height * max_height)
new_width = int(new_width * max_height)
elif new_height > max_height:
new_width = int(new_width * max_height / new_height)
new_height = max_height
img = cv2.resize(img, (new_width, new_height))
res = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
with TemporaryDirectory(prefix="pytoolsz") as tmpFolder:
res.save(Path(tmpFolder) / "tmp.png", compress_level=2, quality=100)
tmpPath = Path(tmpFolder) / "tmp.png"
res.save(tmpPath, compress_level=2, quality=100)
if engine:
try:
subprocess.run([engine, engine_conf, Path(tmpFolder) / "tmp.png"], shell=True, check=True)
subprocess.run([engine, engine_conf, tmpPath], shell=True, check=True)
except Exception as e:
print("未安装pngquant不能进行图片优化压缩。\n可使用`scoop install pngquant`进行安装。")
raise e
else:
res.save(Path(tmpFolder) / "tmp.png", compress_level=7, quality=95)
res.save(tmpPath, compress_level=7, quality=95)
if saveFile is None:
res = Image.open(lastFile(Path(tmpFolder), "*.*"))
return res