概要
在开发电商平台时,经常需要展示大量的商品图片,一般设计给出来的图片都比较大,如果原图上传,会导致客户端卡顿,加载速度特别慢,特别是在低端手机中尤为明显,这时我们需要对商品列表图做压缩处理,以达到一个加载性能和客户体验平衡的效果。但是如何才能批量快速压缩图片呢?网上的工具很多都收费,不如自己手写一个。
效果展示
页面效果展示
图片压缩工具实现效果如下图所示,选择原图片文件夹和压缩后存放的目标文件夹,调整图片质量和最终压缩大小点击一键压缩即可实现批量压缩。
一键压缩效果展示
实现源码
这里我们使用PIL库做图片处理,PyQt5实现简单的ui页面。
from PIL import Image
import sys
import os
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton,QFileDialog,QSlider,QRadioButton,QHBoxLayout,QMessageBox
from PyQt5.Qt import QTextEdit,Qt
from PyQt5.Qt import QLabel
class App(QWidget):
def __init__(self):
super().__init__()
self.outfile = 'C:\out' # 输出
self.path = r"C:\in" # 输入
self.title = 'img tool'
self.left = 100
self.top = 100
self.width = 900
self.height = 800
self.quality = 90
self.kb = 90
self.initUI()
def get_size(self,file):
# 获取文件大小:KB
size = os.path.getsize(file)
return size / 1024
def get_outfile(self,infile, outfile):
if outfile:
return outfile
dir, suffix = os.path.splitext(infile)
outfile = '{}-out{}'.format(dir, suffix)
return outfile
def compress_image(self,infile,outfile, mb=500, step=5, quality=100):
o_size = self.get_size(infile)
if o_size <= mb:
return infile
outfile = self.get_outfile(infile, outfile)
while o_size > mb:
im = Image.open(infile)
try:
im.save(outfile, quality=quality)
except Exception as e:
txt = self.textboxLog.toPlainText() +"\n"+infile + "压缩失败"
self.textboxLog.setText(txt)
return 0,0
if quality - step < 0:
break
quality -= step
o_size = self.get_size(outfile)
return outfile, self.get_size(outfile)
def resize_image(self,infile,outfile, x_s=350):
im = Image.open(infile)
x, y = im.size
y_s = int(y * x_s / x)
out = im.resize((int(x_s), y_s), Image.ANTIALIAS)
outfile = self.get_outfile(infile, outfile)
out.save(outfile)
def on_click(self):
dir = self.textbox21.toPlainText()
if dir == '':
self.msg1("请选择图片文件夹")
return
dirOut = self.textbox22.toPlainText()
if dirOut == '':
self.msg1("请选择图片目标文件夹")
return
dirs = os.listdir(dir)
for i in dirs:
if i[-4:] == '.jpg' or i[-4:] == '.JPG' or i[-4:] == '.png' or i[-4:] == '.PNG':
file = dir + '\\' + i
ofile = dirOut + '\\' + i
txt = self.textboxLog.toPlainText() +"\n" + "正在压缩" + i
self.textboxLog.setText(txt)
self.compress_image(file, ofile, mb=self.kb,quality=self.quality) # 120k
self.resize_image(file,ofile,350)
txt = self.textboxLog.toPlainText() + "\n#############压缩完毕###################"
self.textboxLog.setText(txt)
def Output_File(self):
directory = QFileDialog.getExistingDirectory(None, "请选择文件夹路径", "D:/")
self.textbox22.setText(directory)
def input_File(self):
directory = QFileDialog.getExistingDirectory(None, "请选择文件夹路径", "D:/")
self.textbox21.setText(directory)
def changeZl(self):
self.quality = self.slider.value()
self.labelKd.setText("图片质量:" + str(self.quality))
def changeWidth(self):
self.width = self.slider.value()
self.labelKd.setText("宽度(像素):" + str(self.width) + "px")
def changekb(self):
self.kb = self.slider2.value()
self.labelKd2.setText("目标图片大小:" + str(self.kb) + "kb")
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.lable0 = QLabel("*图片文件夹", self)
self.lable0.move(10, 8)
self.textbox21 = QTextEdit(self)
self.textbox21.move(80, 0)
self.textbox21.resize(200, 30)
self.button = QPushButton('选择', self)
self.button.move(300, 2)
self.button.clicked.connect(self.input_File)
self.lable1 = QLabel("*目标文件夹", self)
self.lable1.move(420, 8)
self.textbox22 = QTextEdit(self)
self.textbox22.move(500, 0)
self.textbox22.resize(200, 30)
self.button1 = QPushButton('选择', self)
self.button1.move(700, 2)
self.button1.clicked.connect(self.Output_File)
# Create a button in the window
self.button = QPushButton('一键压缩', self)
self.button.setStyleSheet("QPushButton {"
"background-color: #FF8080;" # 设置按钮背景颜色为红色
"color: rgb(255, 255, 255);" # 设置按钮文本颜色为白色
"}")
self.button.move(800, 2)
self.slider = QSlider(Qt.Horizontal,self)
# 设置滑块的最小值
self.slider.setMinimum(60)
# 设置滑块的最大值
self.slider.setMaximum(100)
self.slider.setValue(90)
self.slider.move(20, 50)
self.slider.resize(300, 30)
self.slider.setTickInterval(1)
self.slider.valueChanged.connect(self.changeZl)
self.labelKd = QLabel("图片质量:90", self)
self.labelKd.move(330, 50)
self.labelKd.setStyleSheet("QLabel {"
"color: #ff3030;" # 设置按钮文本颜色为白色
"}")
self.slider = QSlider(Qt.Horizontal,self)
# 设置滑块的最小值
self.slider.setMinimum(200)
# 设置滑块的最大值
self.slider.setMaximum(1000)
self.slider.setValue(350)
self.slider.move(20, 100)
self.slider.resize(300, 30)
self.slider.setTickInterval(1)
self.slider.valueChanged.connect(self.changeZl)
self.labelKd = QLabel("图片质量:90", self)
self.labelKd.move(330, 50)
self.labelKd.setStyleSheet("QLabel {"
"color: #ff3030;" # 设置按钮文本颜色为白色
"}")
self.slider2 = QSlider(Qt.Horizontal,self)
# 设置滑块的最小值
self.slider2.setMinimum(20)
# 设置滑块的最大值
self.slider2.setMaximum(500)
self.slider2.setValue(80)
self.slider2.move(450, 50)
self.slider2.resize(300, 30)
self.slider2.setTickInterval(10)
self.labelKd2 = QLabel("目标图片大小:90kb", self)
self.labelKd2.move(750, 50)
self.labelKd2.setStyleSheet("QLabel {"
"color: #ff3030;" # 设置按钮文本颜色为白色
"}")
self.slider2.valueChanged.connect(self.changekb)
# 信号和槽函数的连接
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.textboxLog = QTextEdit(self)
self.textboxLog.move(10, 100)
self.textboxLog.resize(700, 700)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
app.exit(app.exec_())
小结
上述代码基于python3.8实现,理论上python3以上版本都可运行,直接复制到文件中,保存为py文件即可运行,代码中相关参数可以根据实际情况修改。