Python实现的图片压缩处理工具

前言

最近在博客中做了一个相册功能,但是问题是我的图片都很大,用图片压缩工具压缩了一遍感觉不是很方便,于是就搜了一下python相关工具,后来发现知乎上的一篇文章《如何用Python智能批量压缩图片》,这里感谢作者提供了思路,短短几行代码实现了图片压缩需求。

最后添加了图片水印功能,可以方便配置图片路径来实现压缩和水印添加,本来打算使用Tkinter来实现一个图片界面方便操作,后来想想还是把精力放在核心逻辑上面吧,其实使用图形界面不见的就很方便,这样修改配置其实更方便些,如果你想实现成图形界面可参考我的另一篇博文《Python两个案例练习》

知识点

内置模块和第三方模块

在python中,一个.py文件就可以理解为一个模块,模块之间可以互相引用。

模块分为三种:自己写的、内置的、第三方的。

内置模块一般存放在安装目录的lib目录下,第三方库一般存放在安装目录的lib\site-packages目录下。第三方库使用前需要提前安装,例如Python操作图像的模块PIL需要提前安装。

两种导入方式,例如下面导入module1并调用模块方法say():

#第一种导入方式
import module1
module1.say()
#第二种导入方式
from module1 import *
say()

from …import提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。

PIL模块

PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。

安装: 在Debian/Ubuntu Linux下直接通过apt安装:$ sudo apt-get install python-imaging Windows平台就去PIL官方网站下载exe安装包。

在本文中我安装的是Pillow,Pillow是一个对PIL友好的分支,作者是Alex Clark和贡献者。而PIL是一个Python图像处理库,作者是Fredrik Lundh和贡献者。

有关Pillow的中文文档请参考这里

glob模块

glob是python的内置模块,是一个文件操作相关模块,用它可以查找符合自己目的文件。

截止目前官方最新python版本是3.7.3,该版本的标准库文档链接——点这里查看

压缩实现

下面是用PIL实现的图片压缩函数,可直接粘贴修改目录使用(记得安装Pillow)。

#coding=utf-8
#!/usr/bin/python

from glob import glob
#pip install Pillow
from PIL import Image
import os
import math

SORUCE_DIR = 'D:\\blog\\gitlab\\source\\images\\photo'
TARGET_DIR= 'D:\\blog\\gitlab\\source\\images\\photo\\thumb'
THRESHOLD = 100000  #100kb
NEW_W_H = 800

def resize_images(source_dir, target_dir, threshold, new_w_or_h):
    filenames = glob('{}/*'.format(source_dir))
    if not os.path.exists(target_dir):
        os.makedirs(target_dir)
    for filename in filenames:
        filesize = os.path.getsize(filename)
        if filesize >= threshold:
            print(filename)
            with Image.open(filename) as im:
                width, height = im.size
                if width >= height:
                    new_width = new_w_or_h
                    new_height = int(new_width * height * 1.0 / width)
                else:
                    new_height = new_w_or_h
                    new_width = int(new_height * width * 1.0 / height)
                resized_im = im.resize((new_width, new_height))
                output_filename = filename.replace(source_dir, target_dir)
                resized_im.save(output_filename)
    

resize_images(SORUCE_DIR, TARGET_DIR, THRESHOLD, NEW_W_H)

添加水印

#预定义一个字体
FONT_FAMILY = 'C:\\Windows\\Fonts\\consola.ttf'

def add_text_to_image(image, text, font_size, font_family=FONT_FAMILY):
    width, height = image.size
    #相当于将图片转换为可以绘制的画布
    img_draw = ImageDraw.Draw(image)
    #创建字体画笔
    Font = ImageFont.truetype(font_family, font_size)  
    #获取文字尺寸
    textW,textH = Font.getsize(text)   
    #将文字写在屏幕右下角,文字白色透明度100/255
    pointX = width - textW - textH / 2
    pointY = height - textH - textH / 2
    img_draw.text([pointX, pointY], text, fill=(255, 255, 255, 100), font = Font)

add_text_to_image(resized_im, "dp2px.com", 30)

完整代码

#coding=utf-8
#!/usr/bin/python

from glob import glob
#pip install Pillow
from PIL import Image, ImageDraw, ImageFont
import os
import math

#原始图片目录
SORUCE_DIR = 'D:\\blog\\gitlab\\source\\images\\photo'
#处理后图片目录
TARGET_DIR= 'D:\\blog\\gitlab\\source\\images\\photo\\thumb'
#图片筛选条件
THRESHOLD = 100000  #100kb
#图片最大宽/高
NEW_W_H = 800
#是否开启水印 0不开启 1开启
WAHTER_MARK = 0  

FONT_FAMILY = 'C:\\Windows\\Fonts\\constan.ttf'

def add_text_to_image(image, text, font_size, font_family=FONT_FAMILY):
    width, height = image.size
    #相当于将图片转换为可以绘制的画布
    img_draw = ImageDraw.Draw(image)
    #创建字体画笔
    Font = ImageFont.truetype(font_family, font_size)  
    #获取文字尺寸
    textW,textH = Font.getsize(text)   
    #将文字写在空白图像正中间      
    pointX = width - textW - textH / 2
    pointY = height - textH - textH / 2
    img_draw.text([pointX, pointY], text, fill=(255, 255, 255, 100), font = Font)


def resize_images(source_dir, target_dir, threshold, new_w_or_h):
    #读取目录下所有文件
    filenames = glob('{}/*'.format(source_dir))
    #判断输出目录
    if not os.path.exists(target_dir):
        os.makedirs(target_dir)
    #遍历处理
    for filename in filenames:
        filesize = os.path.getsize(filename)
        #比较筛选
        if filesize >= threshold:
            with Image.open(filename) as im:
                width, height = im.size
                #判断图片方向(横/竖)
                if width >= height:
                    new_width = new_w_or_h
                    new_height = int(new_width * height * 1.0 / width)
                else:
                    new_height = new_w_or_h
                    new_width = int(new_height * width * 1.0 / height)
                resized_im = im.resize((new_width, new_height))
                #判断是否添加水印
                if WAHTER_MARK != 0:
                    add_text_to_image(resized_im, "dp2px.com", int(new_w_or_h / 30))
                #保存到输出目录
                output_filename = filename.replace(source_dir, target_dir)
                resized_im.save(output_filename)
    print('图片处理完成!')

#调用处理方法处理图片
resize_images(SORUCE_DIR, TARGET_DIR, THRESHOLD, NEW_W_H)

啰嗦一句

最后给他家推荐一个编辑器来编辑和运行python程序,准确的说应该是一个插件。

编辑器:Visual Studio Code 插件:Code Runner

这个插件目前几乎支持所有语言的编译和运行,非常好用方便,安装好后操作栏会多出一个运行的小三角按钮,点击运行即可。