使用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编写批量添加图片水印程序:二、桌面客户端》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Windows黑客编程技术详解

Windows黑客编程技术详解

甘迪文 / 人民邮电出版社 / 2018-12 / 108

《Windows黑客编程技术详解》介绍的是黑客编程的基础技术,涉及用户层下的Windows编程和内核层下的Rootkit编程。本书分为用户篇和内核篇两部分,用户篇包括11章,配套49个示例程序源码;内核篇包括7章,配套28个示例程序源码。本书介绍的每个技术都有详细的实现原理,以及对应的示例代码(配套代码均支持32位和64位Windows 7、Windows 8.1及Windows 10系统),旨在......一起来看看 《Windows黑客编程技术详解》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具