朋友问我能不能搞个九图切割的小软件,我就着手搞了
不过这次注释我会用英文写
我发现写框架是个很好的方式,看的时候不会纠结于具体的语言细节,而是先理清楚程序的功能逻辑
# import modules
from someModule import someMethod
# some functions
def get_pic():
# get the image from the path given
pass
def cut_pic():
# cut the picture into 9 picecs
# the main function of this program
pass
def save_pic():
# choose path and save the cutted picture
pass
# use class to build GUI
# I was mentioned in my last blog
class Main_Function():
def __init__(self,master):
# build the body of my GUI
master
a Entry() that show the path
a Button() used to choose path
a Button() used to begin cut and automatical save
pass
def Choose(self):
# bind to the first button
# choose pic's path
pass
def Cut(self):
# bind to the second button
# begin cut and save automatically
pass
# some basic program
def main():
root = Tk()
app = Main_Function(root)
root.mainloop()
if __name__ == "__main__":
main()
这是一句鼓励的话:实际学习的时候并不会想看代码一样流程非常轻松地就出来了,我也是从懵逼到查资料到写出代码。
我自己在记录这个流程的时候是尽量保证逻辑连贯性的,所以看上去非常得easy,不过如果自己写代码特备hard的话,不要灰心丧气哈~
GUI采用tkinter,图片处理用PIL
from tkinter import *
from tkinter import filedialog # this is used to choose path
from PIL import Image
实现很简单,其实可以直接写在其他函数里,但是写在外面对于整体结构的表达看起来更清楚
def get_pic(pic_path):
return Image.open(pic_path)
def cut_pic(img):
# use list r_image to save all the pictures cutted
r_image = []
# img.size stores the size of the picture
# [0] is x axis, [1] is y axis
x = img.size[0]
y = img.size[1]
# cut to 9 pieces
for i in range(3):
for j in range(3):
# use crop to cut
r_image.append(img.crop((j*x/3,i*y/3,(j+1)*x/3,(i+1)*y/3)))
# this sentence to confirm that my prgram works correctly
print("%d th pic cut success" %(i+j*3))
return r_image
def save_pic(img):
# store 9 pictures in order
for i in range(9):
img[i] = img[i].resize((128,128))
# name the picture
name = "cut_pic_"+str(i)+".png"
# use save to save
img[i].save(name)
# this sectence is used to confirm that my program works correctly
print("%d th pic save success" % i)
class Main_Function():
def __init__(self,master):
# build the master
self.master = master
# set the title
master.title("PNG Picture Cutter")
# set the GUI's position
# get the height and width of the screen
ws = master.winfo_screenwidth()
hs = master.winfo_screenheight()
# calculate the position of x & y
x = (ws/2)-300
y = (hs/2)-200
master.geometry('500x50+%d+%d' % (x,y))
# can't change the size of the tk()
master.resizable(False,False)
# the Entry shows the path of the picture
self.content = Entry(master,width=40)
# use pack to place the Entry
self.content.pack(side=LEFT)
# the Button to start cut
self.CutPic= Button(master,text="Cut",command=self.Cut)
self.CutPic.pack(side=RIGHT)
# the Button to choose picture's path
self.ChoosePic = Button(master,text="Choose pic",command=self.Choose)
self.ChoosePic.pack(side=RIGHT)
# pack CutPic and ChoosePic in this order to make sure the second button appears in the left.
def Choose(self):
# bind the function to button 1
# you can test 'askopenfilename()' in other programe, it's very useful, you will love it.
self.FilePath = filedialog.askopenfilename()
# clear the content of the Entry(), make it able for insert
self.content.delete(0,'end')
# write the path in the Entry()
self.content.insert(0,self.FilePath)
def Cut(self):
# use get() to get the content of the Entry()
path=self.content.get()
# get the picture
img = get_pic(path)
# cut the picture
r_img = cut_pic(img)
# save pictures
save_pic(r_img)
当时只是纯粹放下了三个控件,想让文本框在左边,choose在中间,cut在右边。简单写了.pack(side=LEFT)
这种形式的代码
呈现效果就这么丑……
然后思考了一下该怎么改
可以用一个Frame控件,让Frame控件置中,其他的三个控件在Frame中布局。
这样的pace(side=xxxx)
就不会让控件变到最边缘了
这是布局的修改代码:
# use frame to control the position
self.frame = Frame(master)
self.frame.pack()
# attention!! ↓↓↓
self.content = Entry(self.frame,width=40)
self.content.pack(side=LEFT)
# attention!! ↓↓↓
self.Translate = Button(self.frame,text="Cut",command=self.Cut)
self.Translate.pack(side=RIGHT)
# attention!! ↓↓↓
self.ChoosePDF = Button(self.frame,text="Choose pic",command=self.Choose)
self.ChoosePDF.pack(side=RIGHT)
实际上可以用grid和place直接来布局,但是我还没用到,pack在这里很迅速很简洁
直接切九图,图片如果原本不是正方形,切出的图片都会是长方形,在朋友圈发图的时候上下边缘会被隐藏。
后来查资料,用resize
拉伸图形到统一尺寸。详情见函数save_pic()
试验后发现这种拉伸非常暴力,原本的图片比例会被破坏。
于是想要一种在空白处填补白色的算法,查阅资料后发现了如下代码,构造了fill_image()
def fill_image(image):
# size[0] is the width, size[1] is the height
width,height = image.size
# new_length records the maxmiun between width and height
new_length = width if width > height else height
# The Magic Code :)
# create a white image
r_image = Image.new(image.mode,(new_length,new_length),color='white')
# paste the original image to the white background
if width>height:
r_image.paste(image,(0,int((new_length-height)/2)))
else:
r_image.paste(image,(int((new_length-width)/2),0))
return r_image
然后在整体代码中添加使用这个函数。
一个位置是可以在button调用cut
函数的时候先fill
还有一个位置是可以在外部的函数cut_pic()
里先fill
我选择前者,于是修改后的代码如下:
def Cut(self):
path=self.content.get()
# get the picture
img = get_pic(path)
# turn to square
img = fill_image(img)
# cut the picture
r_img = cut_pic(img)
# save pictures
save_pic(r_img)
学到了加白边框的方法https://blog.csdn.net/eereere/article/details/79604682
其余资料后期再补,因为搜索地有点杂