python实现一个图片查看器——可拖动、缩放和颜色画笔

2023-12-21 14:45:15

0 前言

在现如今的数字时代,我们对于图片的需求越来越大。无论是在工作中,还是在日常生活中,我们都经常需要查看、编辑和操作各种类型的图片。为了满足这个需求,开发一款图片查看器是非常有必要的。
在这里插入图片描述

Python作为一种简单而强大的编程语言,提供了丰富的图像处理库和工具。借助于Python的图像处理功能,我们可以轻松地创建一个功能强大的图片查看器,实现图片的拖动、缩放和颜色画笔等功能。

在本博客中,我们将使用Python的图形用户界面库pysimplegui来实现这个图片查看器。pysimplegui是一款易于使用、功能丰富的GUI库,它可以帮助我们快速创建各种类型的图形用户界面。

通过本博客,我们将一步步地介绍如何使用pysimplegui库来创建一个图片查看器。首先,我们将学习如何加载和显示图片,并实现拖动和缩放功能。然后,我们将介绍如何使用颜色画笔工具,在图片上进行绘制操作。
在这里插入图片描述

通过学习本博客,您将能够掌握使用Python和pysimplegui库来创建一个功能强大的图片查看器的技巧。无论您是初学者还是经验丰富的开发者,本博客都将为您提供有用的知识和实践经验。

让我们一起开始这个令人兴奋的学习之旅,探索如何使用Python实现一个图片查看器!

在这里插入图片描述

1 准备工作

所需要安装如下python库,PySimpleGUI,pillow,tkinter,其中,Python3标准安装包中自带tkinter,即不用安装,导入即可使用。其它版本如下:
在这里插入图片描述
在这里插入图片描述

import PySimpleGUI as sg
from PIL import Image, ImageTk

2 窗口布局

窗口主要包含了路径选择器,颜色选择器,画笔粗细选择、拖动切换及图片显示画布:
在这里插入图片描述

layout = [ 
        [sg.Text('选择图像(png,jpg):'), sg.In(key='file'), sg.FileBrowse(file_types=( (("Image Files", "*.jpg;*.png"),)))], 
        [sg.Text('画笔粗细:'), sg.Slider((1, 100),1,1,orientation='h', size=(50, 15), key='slider')],         
        [sg.ColorChooserButton('选择颜色',key='chose', target='-COLOR-'),sg.Button('',key='color'),sg.In('', key='-COLOR-')],
        [sg.Text('画图:'),sg.Radio('OFF',"222",default=True,k='-off-'),sg.Radio('ON', "222",key="-on-")],
        [sg.Stretch(),can,sg.Stretch()],         
         ]

这里有个小细节,就是,窗口面对多种电脑的显示器尺寸,做了自适应的调整,这样就不会因为电脑显示器的大小,影响窗口的显示效果:

	#获取屏幕的大小
    screen_width, screen_height = sg.Window.get_screen_size()
    canratio=0.6
    winratio=0.8
    canwinra=canratio/winratio
    # 根据屏幕设置窗口显示大小
    window_width = int(screen_width * winratio)  # Set the window width to 80% of the screen width
    window_height = int(screen_height * winratio)  # Set the window height to 80% of the screen height

3 图片显示功能

这个直接可以通过Pillow库读取图片所在路径打开图片,并转化到tk能显示的图片格式即可。

def set_image(self, image_path):
        self.canvas.delete('all')
        #读取选择路径的图片
        self._image = Image.open(image_path)
        #转化为tk能读的格式
        self._image_tk = ImageTk.PhotoImage(self._image)
        #在画布上显示
        self.canvas.create_image(0, 0, image=self._image_tk, anchor="nw", tags="image")
        self.canvas.tag_lower("image")

3 图片拖拽功能

图片拖拽功能,使用了tkcanvas中的.scan_dragto()函数,是利用鼠标按下时记住当前点的坐标,然后通过鼠标的移动move事件,将画布坐标系scan到指定偏移量:

	#将下面两个函数与事件绑定
    self.canvas.bind("<ButtonPress-1>", self.scroll_start)#左键按下
    self.canvas.bind("<B1-Motion>", self.scroll_move)#左键移动
	#鼠标按下时记录拖动起点
	def scroll_start(self, event):         
        self.canvas.scan_mark(event.x, event.y)
    #鼠标移动时移动画布
    def scroll_move(self, event):     
    	self.canvas.scan_dragto(event.x, event.y, gain=1)

4 图片缩放功能(难度大)

图片缩放功能有一定的难度,需要计算几个坐标系的变化关系,画布严格说涉及到三个坐标系,一个时全局坐标系O,一个时画布自身坐标系Os,还有一个是画图缩放坐标系Od。大概的位置如下:
在这里插入图片描述其中O系和Os系可以通过自带函数转化:

Osx=self.canvas.canvasx(Ox)
Osy=self.canvas.canvasy(Oy)

O系是一个全局坐标,任何时候都是不变的。
Os系对缩放无感,根据平移会改变原点。
Od系是一个比较头疼的坐标系,他是根据Os系任意一点鼠标的位置经过N次缩、放后的存在。
这里图片如果要完美的跟着鼠标某点缩放,就要计算出每次滑轮滚动后的Os原点在Od系得坐标,坐标公式如下:

#self.prevzx为Os得原点,x为在Os系下缩放中心坐标,scale_factor为滚轮单位缩放因子
self.prevzx=(self.prevzx-x)*scale_factor+x
self.prevzy=(self.prevzy-y)*scale_factor+y

以上需要在滚轮事件中反复计算,保持记录self.prevzx,self.prevzy得坐标,即为图像得左上角,核心代码如下:

def _on_mousewheel(self, event):
        x = self.canvas.canvasx(event.x)
        y = self.canvas.canvasy(event.y)       
        scale_factor = 1.1 if event.delta > 0 else 1/1.1        
        self._scale *= scale_factor
        #执行缩放
        self.canvas.scale("all", x, y, scale_factor, scale_factor)
        #记录Os原点坐标
        self.prevzx=(self.prevzx-x)*scale_factor+x
        self.prevzy=(self.prevzy-y)*scale_factor+y

5 画笔功能

画笔功能,直接利用自带得self.canvas.create_line()函数实现即可,注意这里坐标要转化到Os系得坐标,然后执行直线函数:

#此为鼠标移动事件回调函数
def scroll_move(self, event):        
        if painterable:#绘画模式
            x = self.canvas.canvasx(event.x)
            y = self.canvas.canvasy(event.y)           
            if self.prev_x and self.prev_y:
                   self.canvas.create_line(self.prev_x, self.prev_y, x, y, fill=color, width=width)
            self.prev_x = x
            self.prev_y = y 
        else: #拖拽模式           
            self.canvas.scan_dragto(event.x, event.y, gain=1)      

6 颜色选择功能

这个直接用gui得组件就可以:

if values['-COLOR-']!=color:
            selected_color=values['-COLOR-']
            window['color'].update(button_color=('white', selected_color))
            
            color=values['-COLOR-']

其它功能较为简单略过

后记

总的来说,这个项目不仅具有实用性,还提供了一种有趣的方式来探索Python的功能。希望我的博客可以帮助更多的人了解python。
python可以实现得东西非常多,以上只是一个简单实例,后面我们继续探索好玩得功能,更加AI得功能。
在这里插入图片描述

源码

全部源码已经上传:
资源链接

文章来源:https://blog.csdn.net/kanbide/article/details/135128014
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。