更多内容请点击 我的博客 查看,欢迎来访。

用来做什么?

个人在写博客时,发现上传的图片如果很大,web访问第一次加载该图片就特别的慢。
可以考虑使用缩略图,浏览时显示缩略图,如果要看高清图,需点击图片放大查看。
但更希望找到一种能无损压缩图片的方法,由于博客使用的截图大部分是png,就开始在网上查找了。

使用 Pillow 压缩图片(效果不好)

测试支持png、jpg等

import os
import shutil
from PIL import Image  # 处理图片
from PIL import ImageDraw  # 图片水印使用
from PIL import ImageFont  # 图片文字水印# 图片压缩,添加水印功能
class CompressWatermarkImage(object):def __init__(self):self.suffix = ['.jpg', '.png', '.jpeg']self.size = 80 * 1024  # 设置小于80kb的图片不压缩def compress(self, src_image, dst_image):# 图片压缩:src_image、dst_image为绝对路径if os.path.isfile(src_image) and os.path.splitext(src_image)[1] in self.suffix and os.path.getsize(src_image) > self.size:  # 指定文件后缀try:# 打开原图片缩小后保存,可以用if src_file.endswith(".jpg")或者split,splitext等函数等针对特定文件压缩s_img = Image.open(src_image)w, h = s_img.size# 设置压缩尺寸和选项,注意尺寸要用括号d_img = s_img.resize((int(w / 2), int(h / 2)), Image.ANTIALIAS)# 可以用src_image原路径保存,即覆盖源文件。或者更改后缀保存,save()后面可以加压缩编码选项JPEG之类的d_img.save(dst_image, quality=95)print(f"压缩到{dst_image}成功")except Exception as e:print(f"压缩到{dst_image}失败", e)def watermark(self, src_image, dst_image):# 添加水印:src_image、dst_image为绝对路径# 打开图片img = Image.open(src_image)# 图片大小:宽,高width, height = img.size# 水印字体大小,可以根据图片高度的1/10之一当做水印文字的大小font_size = int(height / 10)# 设置所使用的字体font = ImageFont.truetype(r"C:\Windows\Fonts\STXINWEI.ttf", font_size)# 画图draw = ImageDraw.Draw(img)draw.text(xy=(0, height - font_size * 2), text="http://blog.starmeow.cn", fill=(18, 183, 222, 300), font=font)  # 设置文字位置/内容/颜色/字体draw = ImageDraw.Draw(img)  # 绘图# 另存图片img.save(dst_image)def upload_processing(self, src_image):# 上传图片是就进行压缩和添加水印操作path_file, suffix = os.path.splitext(src_image)  # 路径\文件名;.pngdst_image = path_file + '_cw_img_bak' + suffixshutil.copy(src_image, dst_image)# 添加水印后再压缩self.watermark(src_image, src_image)  # 添加水印直接覆盖自己# 压缩图片self.compress(src_image, src_image)  # 压缩时直接覆盖源文件保存# !!!批处理时才能使用def walk_path(self, src_root_path, dst_root_path):# 遍历指定目录,压缩和添加水印if not os.path.exists(dst_root_path):os.makedirs(dst_root_path)  # 创建备份目录for root, dirs, files in os.walk(src_root_path):rel_path = str(root).replace(src_root_path, '').lstrip('\\').lstrip('/')  # 获取基于src_root_path的相对路径,去除前面\\(Windows),取出/(Linux)# print(rel_path)for file in files:# 拼接基于dst_root_path新的路径dst_path = os.path.join(dst_root_path, rel_path)if not os.path.exists(dst_path):os.makedirs(dst_path)  # 如果不存在目标文件夹,则创建dst_file = os.path.join(dst_path, file)  # 目标文件if os.path.exists(dst_file):# 当第一次备份后,后面再运行时,以另一名称保存,即不影响初始文件命名方式dst_file = os.path.join(dst_path, 'last_' + file)src_file = os.path.join(root, file)  # 源文件# 即将src_file复制到dst_file# print(src_file, ' --> ', dst_file)shutil.copy(src_file, dst_file)# 添加水印self.watermark(src_file, src_file)  # 添加水印直接覆盖自己# 压缩图片self.compress(src_file, src_file)  # 压缩时直接覆盖源文件保存

使用方式

ci = CompressWatermarkImage()# 指定目录,遍历将图片压缩及添加水印
ci.walk_path(r'**media\blog\images', r'**media\blog\images压缩加水印前备份')# 指定图片添加水印
ci.watermark(r'**cover\04\BLOG_20200403_120041_66.png', r'**cover\04\newBLOG_20200402_220015_39.png')

TinyPNG实现图片高质量压缩(网络影响)

介绍

使用脚本批量压缩,每个月的免费额度为500张图片;
一张图片重复上传不会消耗额度;

pypi安装:https://pypi.org/project/tinify/
官网地址:https://tinypng.com/

API Key获取

在TinyPng网站的Developer API页面上注册一个账号,并获取API key

输入用户名、邮箱,收到的邮件内容如下:

进去之后就可以看到API Key了

如果没复制好Key的内容,访问 https://tinypng.com/dashboard/api 重新获取即可

安装Python库tinify

pip install tinify

Python代码实现

import tinify# 使用TinyPNG压缩图片
def tinify(src_image, dst_image):tinify.key = "tVyt6R7Z**************nqqFPwkb"old_size = round(os.path.getsize(src_image) / 1024, 2)# 上传压缩过程tinify.from_file(src_image).to_file(dst_image)new_size = round(os.path.getsize(dst_image) / 1024, 2)print('{}压缩后:{}kb -> {}kb'.format(dst_image, old_size, new_size))

使用pngquant压缩图片(推荐)

官网: https://pngquant.org/

只支持png图片

命令行

  • Binary for macOS (v2.12.5)
  • Binary for Windows
  • Package for Debian Important: don’t use version 1.0 from Debian oldstable! Only install 2.0+ from “stretch”.
  • Various Linux packages, RPM spec
  • Latest source code (to build on other platforms)

选项(以Win为例)

  • --force / -f:覆盖现有的输出文件,即多次执行名字相同进行覆盖
  • --skip-if-larger:只有当转换后的文件比原始文件小时才保存它们
  • --output file / -o file 要使用的目标文件路径,而不是--ext设置的,不设置则默认输出当源文件相同路径下
  • --ext new.png:设置输出图片的后缀名,默认使用 -fs8.png 做后缀(防止与源文件重名),假如设置 -ext=.png 则需要带上 --force 参数,否则会提示输出文件与输入文件重名无法覆盖
  • --quality min-max:min 和 max 是从 0-100 的数值,用于设置压缩后图片的品质,品质越高压缩率越低;如果转换后的图片比最低品质还低,就不保存,并返回错误码99
  • --speed N:转换速度与品质的比例。1(最佳品质),11(速度最快且粗糙),默认是3
  • --nofs:禁用 Floyd–Steinberg dithering (即基于错误扩散的抖动算法)效果
  • --posterize N:按位数减少调色板的精度。当图像在低深度屏幕上显示时使用(例如,16位显示或压缩的纹理在ARBB44格式);
  • --strip:不要复制可选的 PNG 块。在MAC(使用Cocoa reader)时,元数据总是被删除。
  • --verbose / -v:打印状态消息

Windows操作压缩

下载工具Binary for Windows解压后会出现 pngquant.exe 文件

# 压缩后覆盖原文件保存
\pngquant>pngquant.exe --force --skip-if-larger --output 1.png --quality 50-80 --verbose 1.png
# 压缩后不覆盖,而是生成1.new.png
\pngquant>pngquant.exe --force --skip-if-larger --output 1.new.png --quality 50-80 --verbose 1.png

Debian操作压缩

安装pngquant

# apt-get install pngquant -y
# pngquant --force --skip-if-larger --output 1.new.png --quality 50-80 --verbose 1.png

这个和Win下操作一样

Python代码实现

import os
import platformdef pngquant(src_image, dst_image):if os.path.isfile(src_image) and os.path.splitext(src_image)[1] == '.png':  # 指定文件后缀  cmd = 'pngquant --force --skip-if-larger --output {} --quality 50-80 --verbose {}'.format(dst_image, src_image)# Linux和Windows通用rt = os.system(cmd)# print(rt)if rt == 0:print(f"压缩到{dst_image}成功")elif rt == 1:print(f"压缩到{dst_image}失败,命令错误")elif rr == 2:print(f"压缩到{dst_image}失败,参数错误")else:print('其它错误')return rt# Windows上使用方法
pngquant(r'C:\Users\LR\Desktop\pngquant\1.png', dst_image=r'C:\Users\LR\Desktop\pngquant\2.png')

压缩对比


可以节省约70%的空间。

综合应用指定图片打水印且压缩

  • 实现了3种压缩图片的方法,如果是png图片,推荐使用pngquant工具
  • 实现了1中加水印的方法
  • 指定图片的绝对路径,先对该图片进行备份,然后加水印,最后压缩,pngquant压缩比还是比较可观的。
# 图片压缩,添加水印功能
class CompressWatermarkImage(object):def __init__(self):self.suffix = ['.jpg', '.png', '.jpeg']self.size = 80 * 1024  # 设置小于80kb的图片不压缩# 使用 Pillow 压缩图片(效果不好)def pillow_compress(self, src_image, dst_image):# 图片压缩:src_image、dst_image为绝对路径if os.path.splitext(src_image)[1] in self.suffix and os.path.getsize(src_image) > self.size:  # 指定文件后缀try:# 打开原图片缩小后保存,可以用if src_file.endswith(".jpg")或者split,splitext等函数等针对特定文件压缩s_img = Image.open(src_image)w, h = s_img.size# 设置压缩尺寸和选项,注意尺寸要用括号d_img = s_img.resize((int(w / 2), int(h / 2)), Image.ANTIALIAS)# 可以用src_image原路径保存,即覆盖源文件。或者更改后缀保存,save()后面可以加压缩编码选项JPEG之类的d_img.save(dst_image, quality=95)print(f"运行pillow_compress压缩到{dst_image}成功")except Exception as e:print(f"运行pillow_compress压缩到{dst_image}失败", e)# 使用TinyPNG压缩图片def tinify_compress(self, src_image, dst_image):tinify.key = "tVyt6R7*******************qqFPwkb"tinify.from_file(src_image).to_file(dst_image)print(f'运行tinify_compress压缩到{dst_image}完成')#  使用pngquant压缩图片,只能压缩png图片def pngquant_compress(self, src_image, dst_image):if os.path.splitext(src_image)[1] == '.png':  # 指定文件后缀if platform.system() == 'Linux':# 如果是Debianif os.system('which pngquant') != 0:os.system('apt-get install pngquant -y')  # 如果是Debian以root用户登录执行命令# 其他系统没做判断了pngquant = '/usr/bin/pngquant'elif platform.system() == 'Windows':pngquant = r'C:\Apps\pngquant\pngquant.exe'else:# 获取不管在Windows还是Linux上都添加环境变量,直接运行 pngquant 命令即可。pngquant = 'pngquant'cmd = '{} --force --skip-if-larger --output {} --quality 20-50 --verbose {}'.format(pngquant, dst_image, src_image)rt = os.system(cmd)# print(rt)if rt == 0:print(f"运行pngquant_compress压缩到{dst_image}成功")elif rt == 1:print(f"运行pngquant_compress压缩到{dst_image}失败,命令错误")elif rt == 2:print(f"运行pngquant_compress压缩到{dst_image}失败,参数错误")else:print('运行pngquant_compress其它错误')return rt# 调用压缩图片的方法def compress(self, src_image, dst_image):if os.path.isfile(src_image):old_size = round(os.path.getsize(src_image) / 1024, 2)if os.path.splitext(src_image)[1] == '.png':self.pngquant_compress(src_image, dst_image)else:try:self.tinify_compress(src_image, dst_image)except Exception:self.pillow_compress(src_image, dst_image)new_size = round(os.path.getsize(dst_image) / 1024, 2)print('压缩:{}kb -> {}kb,节省空间:{}%'.format(old_size, new_size, round((old_size - new_size) / old_size * 100, 2)))else:print('不是文件,不执行压缩')# 添加图片水印def watermark(self, src_image, dst_image):# 添加水印:src_image、dst_image为绝对路径# 打开图片img = Image.open(src_image)# 图片大小:宽,高width, height = img.size# 水印字体大小,可以根据图片高度的1/15之一当做水印文字的大小font_size = int(height / 15)# 设置所使用的字体# font = ImageFont.truetype(r"C:\Windows\Fonts\STXINWEI.ttf", font_size)# 使用自定义的ttf文件font = ImageFont.truetype(os.path.join(settings.MEDIA_ROOT, 'blog/fonts/Ubuntu-Medium.ttf'), font_size)# 画图draw = ImageDraw.Draw(img)draw.text(xy=(0, height - font_size * 2), text="http://blog.starmeow.cn", fill=(18, 183, 222, 300), font=font)  # 设置文字位置/内容/颜色/字体draw = ImageDraw.Draw(img)  # 绘图# 另存图片img.save(dst_image)def upload_processing(self, src_image):"""上传图片是就进行压缩和添加水印操作;备份文件->加水印->压缩:param src_image: 操作图片的绝对路径:return:"""path_file, suffix = os.path.splitext(src_image)  # 路径\文件名;.pngdst_image = path_file + '_cw_img_bak' + suffixshutil.copy(src_image, dst_image)print('添加水印中···')self.watermark(src_image, src_image)  # 添加水印直接覆盖自己print('压缩图片中···')self.compress(src_image, src_image)  # 压缩时直接覆盖源文件保存# !!!批处理时才能使用def walk_path(self, src_root_path, dst_root_path):# 遍历指定目录,压缩和添加水印if not os.path.exists(dst_root_path):os.makedirs(dst_root_path)  # 创建备份目录for root, dirs, files in os.walk(src_root_path):rel_path = str(root).replace(src_root_path, '').lstrip('\\').lstrip('/')  # 获取基于src_root_path的相对路径,去除前面\\(Windows),取出/(Linux)# print(rel_path)for file in files:# 拼接基于dst_root_path新的路径dst_path = os.path.join(dst_root_path, rel_path)if not os.path.exists(dst_path):os.makedirs(dst_path)  # 如果不存在目标文件夹,则创建dst_file = os.path.join(dst_path, file)  # 目标文件if os.path.exists(dst_file):# 当第一次备份后,后面再运行时,以另一名称保存,即不影响初始文件命名方式dst_file = os.path.join(dst_path, 'last_' + file)src_file = os.path.join(root, file)  # 源文件# 即将src_file复制到dst_file# print(src_file, ' --> ', dst_file)shutil.copy(src_file, dst_file)# 添加水印self.watermark(src_file, src_file)  # 添加水印直接覆盖自己# 压缩图片self.compress(src_file, src_file)  # 压缩时直接覆盖源文件保存

【pngquant】使用Python压缩图片,降低网页加载时间相关推荐

  1. 打开服务器网页要5秒,网页优化技巧 如何把网页加载时间控制在1.5秒以内

    今天为大家分享"如何把网页加载时间控制在1.5秒以内(必看)"当然了,控制在2秒以内其实是完全可以的,我们为什么要控制页面打开速度那?首先百度会对加载慢的页面进行打击,对SEO排名 ...

  2. android测量网页加载时间

    如果被测浏览器用的是webkit内核,或者是自己写的程序,总之就是如果可以获取对应的webview对象:可以通过重写webviewclient来获取加载时间.webviewclient中的onPage ...

  3. firefox 显示网页加载时间的插件

    Firebug/YSlow就可以. YSlow不仅可以显示网页加载时间,还可以显示各个组件的加载时间以及对网页评分,提供性能优化建议等. 但YSlow是基于Firebug的,所以必须先装Firebug ...

  4. 浅析用Base64编码的图片优化网页加载速度

    想必大家都知道网页加载的过程,从开始请求,到加载页面,开始解析和显示网页,遇到图片就再次向服务器发送请求,加载图片.如果图片很多的话,就会产生大量的http请求,从而影响页面的加载速度.所以现在有一种 ...

  5. 测试网页加载时间(转)

    网站的加载速度是决定网站等级的重要因素,值得站长特别关注.原因很简单,没有人愿意为了打开一个网页而等老半天,换句话说,如果你的网站打开速度 很慢,将流失大量的访客,甚至出现多米诺效应的不良影响.在埋头 ...

  6. 内容分发网络 CDN 是如何提高网页加载时间的?

    几乎 Internet 上的每个人都体验过内容分发网络 (CDN) 的好处.大多数科技公司,包括谷歌.苹果和微软等公司,都使用 CDN 来减少加载网页内容的延迟. CDN 通常会将服务器放置在不同网络 ...

  7. 网站显示网页加载时间代码-Typecho

    介绍: 给你的网站加一个显示加载时间 网盘下载地址: http://kekewangLuo.net/6nXDXB9ciMB0 图片:

  8. 页面上有大量的图片,网页加载很慢,可以用哪些方法优化这些图片

    对于图片懒加载,可以为页面添加一个滚动条事件,判断图片是否在可视区域内或者即将进入可视区域,优先加载. 如果为幻灯片.相册文件等,可以使用图片预加载技术,对于当前展示图片的前一张图片和后一张图片优先下 ...

  9. 网站性能测试:使用Selenium测试网页加载时间

    WebLOAD与用于Web浏览器应用程序的开源测试工具Selenium的集成,使您可以将执行实际活动的真实Web浏览器集成到您的性能测试场景中,并准确识别问题. 使用集成,您可以使用WebLOAD的虚 ...

最新文章

  1. 梯度下降原理及线性回归代码实现(python/java/c++)
  2. 放大器和比较器的区别
  3. linux系统运行状态检查
  4. java user directory,Java ProcessBuilder directory()方法与示例
  5. 无边框窗体移动的方法
  6. 视频 + PPT | 数字化运营,从理论到实践
  7. SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战
  8. (二)nodejs循序渐进-nodejs基本类型和循环条件语法篇(基础篇)
  9. mysql 数据修改记录日志_mysql对数据的更新操作记录在哪个日志中?
  10. 吴恩达深度学习 —— 2.15 python中的广播
  11. Visual Studio配置(4):项目属性页-VC++目录
  12. 梦回2008样式原子化:Tailwind是如何让Facebook拜倒在她的石榴裙下?
  13. Qt 学习之路 2(15):标准对话框 QMessageBox
  14. SAP ABAP alv中设置回车事件
  15. html5微信视频无法播放视频教程,解决微信h5页面视频播放问题实例
  16. 怎么取名都不队-DevOps
  17. IP地址定位功能在网站上的应用
  18. 医院无线认证平台怎么样
  19. cf1月24日服务器维护更新公告,VIRUS网游公会[1月24日更新资料]
  20. 对于lpad与level的理解

热门文章

  1. 计算机信息处理技师选拔考试试题,江苏省机关事业单位工人技师部分工种选拔考试试卷...
  2. 2021-08-18 2021年安徽省安全员C证考试试卷及安徽省安全员C证模拟试题
  3. 中国各城市GDP水分多大?这对买房很有影响
  4. python之对比两张图像的相似度
  5. 安装python的步骤
  6. Qt:36---QSettings
  7. Unity AR应用(人脸识别)手把手教程
  8. mybatis和mybatisPlus中解决实体类字段与数据库关键字冲突问题
  9. Qt中视图 场景 图元坐标的转换
  10. 全连接神经网络的表达能力与泛化能力