使用Python编写批量添加图片水印程序:二、桌面客户端

栏目: Python · 发布时间: 5年前

内容简介:在上一篇文章文章目录首先,我们来为这个添加图片水印的桌面客户端程序编写一个基础的图形界面。其包含:

在上一篇文章 《使用 Python 编写批量添加图片水印程序:一、代码方案》 中,我们介绍了使用Python为图片批量添加图像水印的方法,今天,我们继续优化这个小工具,借助QT for Python模块(PyQt5、PySide2)将其制作为一个桌面客户端程序。

文章目录

一、编写基础界面

首先,我们来为这个添加图片水印的桌面客户端程序编写一个基础的图形界面。其包含:

  • 一个显示图片所在路径的文本输入框;
  • 一个用于选择图片所在目录的按钮;
  • 一个显示水印图片路径的文本输入框;
  • 一个用于选择水印图片的按钮;
  • 一个显示图片保存目录的文本输入框;
  • 一个用于选择图片保存目录的按钮;
  • 一个水印放置位置的下拉框;
  • 一个用于批量添加图片水印的按钮;

上述的模块我们通过QLineEdit()模块实现输入框、QPushButton()实现按钮、QComboBox()实现下拉框。同时,我们使用网格布局QGridLayout()对模块进行布局。

其最终的图形界面如下图所示:

使用Python编写批量添加图片水印程序:二、桌面客户端

这个图形界面的创建代码如下图所示:

class MainApp(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("一键图片水印") # 窗口标题
        self.setFixedSize(350,160) # 设置窗口高和宽

        self.main_widget = QtWidgets.QWidget() # 窗口主控件
        self.main_layout = QtWidgets.QGridLayout() # 窗口主控件布局
        self.main_widget.setLayout(self.main_layout)

        self.folder_input = QtWidgets.QLineEdit()
        self.folder_input.setReadOnly(True)
        self.folder_btn = QtWidgets.QPushButton("选择文件夹")

        self.wm_input = QtWidgets.QLineEdit()
        self.wm_input.setReadOnly(True)
        self.wm_btn = QtWidgets.QPushButton("选择水印图片")

        self.save_input = QtWidgets.QLineEdit()
        self.save_input.setReadOnly(True)
        self.save_btn = QtWidgets.QPushButton("保存目录")

        self.position_label = QtWidgets.QLabel('水印位置(州的先生zmister.com):')
        self.position_box = QtWidgets.QComboBox()
        self.position_box.addItem("左上")
        self.position_box.addItem("左下")
        self.position_box.addItem("右上")
        self.position_box.addItem("右下")
        self.position_box.addItem("居中")

        self.submit_btn = QtWidgets.QPushButton("生成图片")

        self.main_layout.addWidget(self.folder_input,0,0,1,1)
        self.main_layout.addWidget(self.folder_btn, 0, 1, 1, 1)
        self.main_layout.addWidget(self.wm_input, 1, 0, 1, 1)
        self.main_layout.addWidget(self.wm_btn, 1, 1, 1, 1)
        self.main_layout.addWidget(self.save_input,2,0,1,1)
        self.main_layout.addWidget(self.save_btn,2,1,1,1)
        self.main_layout.addWidget(self.position_label, 3, 0, 1, 1)
        self.main_layout.addWidget(self.position_box, 3, 1, 1, 1)
        self.main_layout.addWidget(self.submit_btn, 4, 0, 1, 2)
        self.setCentralWidget(self.main_widget) # 设置窗口初始化控件

这样,我们的基础界面已经创建好了,下面我们来对几个按钮的事件进行响应。

二、实现图片选取

在图形界面中,我们设置了4个按钮,其中3个用于目录和文件的选择,一个用于最终批量处理图片。在3个用于目录和文件选择的按钮中,其中:

  • 第一个按钮用于选择图片所在的文件夹;
  • 第二个按钮用于选择图片水印;
  • 第三个按钮用于选择新图片保存的目录;

我们通过QFileDialog.getExistingDirectory()来选择文件夹、通过QFileDialog.getOpenFileName()来选择文件。最终,我们在MainApp()中新建3个方法:

# 选择图片文件夹
def select_folder(self):
    file = str(QtWidgets.QFileDialog.getExistingDirectory(self, "选择文件夹"))
    print('文件夹为:',file)
    if file != '':
        self.folder_input.setText(file)

# 选择水印图片
def select_wm_img(self):
    file,_ = QtWidgets.QFileDialog.getOpenFileName(
        self,'选择水印图片','','Images (*.png *.xpm *.jpg)'
    )
    print("水印图片为:",file)
    if file != '':
        self.wm_input.setText(file)

# 选择保存目录
def select_save_folder(self):
    file = str(QtWidgets.QFileDialog.getExistingDirectory(self, "选择文件夹"))
    print('文件夹为:', file)
    if file != '':
        self.save_input.setText(file)

然后将3个按钮的点击信号连接到这3个方法上:

self.save_btn.clicked.connect(self.select_save_folder)
self.wm_btn.clicked.connect(self.select_wm_img)
self.folder_btn.clicked.connect(self.select_folder)

这样,我们我们图形界面中的按钮就有实际的功能了,其效果如下动图所示:

使用Python编写批量添加图片水印程序:二、桌面客户端

这样,我们就可以开始利用选择的东西对图片进行水印操作了。

三、绑定水印添加线程

因为批量对图片添加水印在原图片数量多的情况下,可能会非常耗时。如果我们将其放置在主类里面可能会导致主界面进行的堵塞,所以在此我们通过QThread在子线程中进行批量添加图片水印的任务。其定义如下所示:

class WmThread(QtCore.QThread):
    finished_signal = QtCore.pyqtSignal(int) # 使用PySide2模块需要将pyqtSignal改成Signal

    def __init__(self,parent=None,wm_file=None,fpath=None,save_path=None,position=None):
        super().__init__(parent)
        self.wm_file = wm_file
        self.fpath = fpath
        self.save_path = save_path
        self.position = position
        print(self.wm_file,self.fpath)

    # 获取文件夹图片
    def get_folder(self,fpath):
        try:
            img_suffix_list = ['png', 'jpg', 'bmp']
            for i in os.listdir(fpath):
                if i.split('.')[-1] in img_suffix_list:
                    img_path = fpath + '/' + i
                    self.img_water_mark(img_file=img_path,wm_file=self.wm_file)
        except Exception as e:
            print(traceback.print_exc())

    # 图片添加水印
    def img_water_mark(self,img_file, wm_file):
        try:
            img = Image.open(img_file)  # 打开图片
            watermark = Image.open(wm_file)  # 打开水印
            img_size = img.size
            wm_size = watermark.size
            # 如果图片大小小于水印大小
            if img_size[0] < wm_size[0]:
                watermark.resize(tuple(map(lambda x: int(x * 0.5), watermark.size)))
            print('图片大小:', img_size,"水印位置:",self.position)
            if self.position == '左上':
                wm_position = (0,0)
            elif self.position == '左下':
                wm_position = (0,img_size[1]-wm_size[1])
            elif self.position == '右上':
                wm_position = (img_size[0]-wm_size[0],0)
            elif self.position == '右下':
                wm_position = (img_size[0]-wm_size[0],img_size[1]-wm_size[1])
            elif self.position == '居中':
                wm_position = (img_size[0]//2-wm_size[0]//2,img_size[1]//2-wm_size[1]//2)
            layer = Image.new('RGBA', img.size)  # 新建一个图层
            layer.paste(watermark, wm_position)  # 将水印图片添加到图层上
            mark_img = Image.composite(layer, img, layer)
            new_file_name = '/new_'+img_file.split('/')[-1]
            if self.save_path == '':
                mark_img.save(self.fpath+new_file_name)
            else:
                mark_img.save(self.save_path + new_file_name)
        except Exception as e:
            print(traceback.print_exc())

    def run(self):
        try:
            print("开始处理……")
            self.get_folder(fpath=self.fpath)
            self.finished_signal.emit(1)
        except Exception as e:
            print(traceback.print_exc())
            self.finished_signal.emit(0)

这样,我们就定义了一个子线程类,批量添加图片水印的实际工作都有这个子线程类来处理。然后我们需要在主类MainApp()中对这个子线程类进行调用:

# 生成水印图片
def generate_img(self):
    try:
        print("获取图片目录及水印文件名")
        folder_text = self.folder_input.text()
        wm_text = self.wm_input.text()
        save_text = self.save_input.text()
        position_text = self.position_box.currentText()
        print('判断是否为空')
        if folder_text != '' and wm_text != '':
            self.submit_btn.setEnabled(False)
            self.genare_thread = WmThread(
                wm_file= wm_text,
                fpath=folder_text,
                save_path = save_text,
                position = position_text
            )
            print('启动线程')
            self.genare_thread.finished_signal.connect(self.thread_resp)
            self.genare_thread.start()

    except Exception as e:
        print(traceback.print_exc())

def thread_resp(self,value):
    if value == 1:
        QtWidgets.QMessageBox.information(self,'提示','处理完成!',QtWidgets.QMessageBox.Yes)
    if value == 0:
        QtWidgets.QMessageBox.information(self,'提示', '处理出错!',QtWidgets.QMessageBox.Yes)
    self.submit_btn.setEnabled(True)

最后将generate_img()方法绑定到生成按钮的点击信号上:

self.submit_btn.clicked.connect(self.generate_img)

这样,我们的批量添加图片水印客户端程序就编写完成了。

四、将代码打包为EXE程序

最后,我们借助PyInstaller模块将编写好的代码打包为EXE格式的可执行文件。使用如下命令将其打包为一个文件夹:

pyinstaller -w main.py

最后打包生成了一个最终的文件夹,如下图所示:

使用Python编写批量添加图片水印程序:二、桌面客户端

最后,我们运行main.exe文件,就会出现之前编写的图形界面,功能亦是相同的。

使用Python编写批量添加图片水印程序:二、桌面客户端

这样,我们就完成了图片水印批量添加程序的开发和打包。有问题欢迎留言讨论,本程序将会逐步迭代更新并开放免费使用,争取早日实现同类型商业化软件的功能,敬请关注。


以上所述就是小编给大家介绍的《使用Python编写批量添加图片水印程序:二、桌面客户端》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

引爆流行

引爆流行

[美] 马尔科姆·格拉德威尔 / 钱清、覃爱冬 / 中信出版社 / 2002-7 / 18.00元

马尔科姆·格拉德威尔以社会上突如其来的流行风潮研究为切入点,从一个全新的角度探索了控制科学和营销模式。他认为,思想、行为、信息以及产品常常会像传染病爆发一样,迅速传播蔓延。正如一个病人就能引起一场全城流感;如果个别工作人员对顾客大打出手,或几位涂鸦爱好者管不住自己,也能在地铁里掀起一场犯罪浪潮;一位满意而归的顾客还能让新开张的餐馆座无虚席。这些现象均属“社会流行潮”,它爆发的那一刻,即达到临界水平......一起来看看 《引爆流行》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具