一个尺寸自适应的图片切割器,Python实现,PIL,Image

前言

520前夕,又接了个活。对方的需求就是把一张照片切割成九宫格,这样发微信朋友圈感觉更炫酷一点。比如说520当天发对象的照片吖,就可以发九张凑成一张完整的。层次感一下子就上去了嘻嘻。

预备工作

这里需要用到PIL库,所以要先安装好这个库,
pip install pillow

整体思路

先说一下整体的思路。其实这个工作的流程就是:读取图片,并且按照不同的区域进行切割,最后把切割下来的图片保存起来就好了。但是有几个问题,

问题1,方块问题;
读取到的图片不一定而且几乎总不是正方形,因此不能直接长宽三等分切割。

问题2,方块边长问题;
长宽不一定能被三整除,所以要做一定的调整。

问题3,块数兼容问题
切割成九块和四块,能否实现兼容?

问题4,起始坐标问题
切割的图片所包含的区域与原图的关系如何?万一我一张长方形的图片,关键图像信息在右侧,结果一切把左边的无效信息给切下来了怎么处理?因此需要设置起始切割坐标,规定从该坐标开始进行切割。

问题5,方块收缩问题。
假设我切九宫格,不妨把每个方块称为“小方块”,九张图凑在一起的称为“大方块”,那么,如果原图中关键信息的面积比较小,那么我就想要调整大方块的边长,也就是说大方块的边长必须是可调整的。

解决以上问题,一个图片切割器就基本完成了。

Step1 读取图片,获取尺寸

首先要用到open方法来读取图片,并且使用size方法获取图片的尺寸

from PIL import Imageim = Image.open('--filepath--\\filename.jpg')
pic_x, pic_y = im.size

也可以不写路径,不写路径的话那就默认为当前的文件夹。

Step2计算新图片的边长

所谓“新图片”就是指前文所说的“大方块”,我的思路是这样的:
获得了原图的长宽信息后,以短边作为大方块的边长,这里要考虑两种情况:
第一:切9块:如果短边不能被3整除,那就令其-1再作判断,一直到其可以被3整除为止。
第二:切4块,如果短边不能被2整除,则令其-1.

因此我写了一个函数来计算大方块的边长。需要以原图的长、宽,以及切割块数作参数

def get_cubic(size_x, size_y, num):if num == 9:if size_x < size_y:while size_x % 3 != 0:size_x = size_x - 1return size_xelse:while size_y % 3 != 0:size_y = size_y - 1return size_yelse:return (size_x - size_x % 2) if size_x < size_y else (size_y - size_y % 2)

这时,便有大方块边长

pic_sum = 9
cbc_len = get_cubic(pic_x, pic_y, pic_sum)

至此,前三个问题都被解决。

这时要考虑问题4,方块收缩问题。方块收缩问题本质上就是对大方块的边长做调整因此写一个函数,以一个变量(不妨称之为“收缩常量”)作参数,返回收缩后边长就好了

当然,如果收缩常量太大,那么切割下来的图片质量就会差,或者直接把边长收缩成负值,那都没有意义,因此规定收缩后边长不能低于50.收缩以后,再根据方块数重新计算大方块边长。

def cubic_shrink(shrink_constant):flag = 0 if shrink_constant >= cbc_len - 50 else 3 if pic_sum == 9 else 2if flag:op_len = cbc_len - shrink_constantwhile (op_len) % flag != 0:op_len = op_len - 1print(f'with shrinking constant of {shrink_constant}, now the length of the big cubic was adjusted to {op_len}')return op_lenelse:print('Constant of Shrinking is too big!Now use the initial length!')return cbc_len

此时有:

cbc_srk = 200
cbc_len = cubic_shrink(cbc_srk)

至此,方块收缩问题也解决了。

Step3设置初始坐标

我们先来了解一下crop方法,
假设要从图像im中切割某一区域,该区域位rt,则

box = (x1, y1, x2, y2)
rt = im.crop(box)

当然也可以写作

rt = im.crop(x1, y1, x2, y2)

其中box()的参数含义如下:

显然,现在的情况是:x2-x1 = cubic_length, y2-y1 = cubic_length,
因此,只要手动输入起始坐标x1与y1即可,故有:

cstn_Rx = 500
cstn_Ry = 200

然而,这里又引发一个问题,如果起始坐标过大,就会把原图区域以外的地方切下来,效果就是一片黑色,,,(示意图如下)

因此,对于所输入的起始坐标也要有一个调整,必须自适应于原图的尺寸,这里也写了两个函数去实现这个自适应的过程(其实原理是一模一样的,但是我想让函数打印屏幕的内容不一样,所以写了两个,这个问题还在想办法优化)

def jud_Rx(ipR):if ipR + cbc_len >= pic_x:print('csnt_x is too big!')while ipR + cbc_len >= pic_x:ipR = ipR - 1print(f'csnt_x was adjusted to {ipR}')return ipRelse:print('csnt_x check!')return ipRdef jud_Ry(ipR):if ipR + cbc_len >= pic_y:print('csnt_y is too big!')while ipR + cbc_len >= pic_y:ipR = ipR - 1print(f'csnt_y was adjusted to {ipR}')return ipRelse:print('csnt_y check!')return ipR

这时有:

cstn_Rx = jud_Rx(cstn_Rx)
cstn_Ry = jud_Ry(cstn_Ry)

初始坐标问题也解决了

Step4切割图片并保存

刚才介绍过crop方法,而到了这个步骤,经过以上流程,我们得到了关键信息有如下:

大方块边长:cbc_len (原图尺寸以及收缩系数用于计算最终的大方块边长,此时可以不考察)
起始切割坐标(cstn_Rx, cstn_Ry)
方块数pic_sum

在对大、小方块的边长关系做分析:

因此可以用两个镶嵌的for语句来进行切割,固有:

def pic_crop(num):flag = (cbc_len / 3) if num == 9 else (cbc_len / 2)rb = 4 if num == 9 else 3pic_num = 1for tar_x in range(1, rb):for tar_y in range(1, rb):box = (cstn_Rx + flag * (tar_x - 1), cstn_Ry + flag * (tar_y - 1), cstn_Rx + flag * tar_x,cstn_Ry + flag * tar_y)rt = im.crop(box)rt.save(f'--filepath--\\{pic_num}.jpg')pic_num = pic_num + 1

在这个步骤中,还要考虑一个问题,即,切割方块数只能是4或者9,因此,如果方块数输入为其他数时,需要报错。因此写了一个函数来判断方块数是否有效:

def jud_N(num):if num == 9 or num == 4:print('number of the cubic check!')else:print('parameter error!')return 1

此时,在输入方块数后,利用这个函数来判断就可以了,如果有效则进行下一步操作,如果输入无效那就终止程序,并提示重新输入。

pic_sum = 9
if jud_N(pic_sum):print('please restart the program and input a correct parameter of pic_sum \n only 4&9 are available')
else:# ……下一步操作……

完整代码

由于图片路径、文件名、起始坐标等等的变量,是需要手动输入,在实际中利用input函数来给变量赋值。而在调制程序的过程中每次运行都要手动重新输入一次所有参数,很费时间,因此在完整代码中,把input函数相关的语句都注释掉。在利用pyinstaller 打包前,把给变量赋值的语句注释,并且把input函数相关语句编入其中就可以使用了。

哦对了,由于一开始的时候我的IDE编码出来点问题,不能有中文,所以一开始都是用英文写的,英文水平并不太好,中式英语多多见谅哈哈

from PIL import Imagedef get_cubic(size_x, size_y, num):if num == 9:if size_x < size_y:while size_x % 3 != 0:size_x = size_x - 1return size_xelse:while size_y % 3 != 0:size_y = size_y - 1return size_yelse:return (size_x - size_x % 2) if size_x < size_y else (size_y - size_y % 2)def jud_N(num):if num == 9 or num == 4:print('number of the cubic check!')else:print('parameter error!')return 1def cubic_shrink(shrink_constant):flag = 0 if shrink_constant >= cbc_len - 50 else 3 if pic_sum == 9 else 2if flag:op_len = cbc_len - shrink_constantwhile (op_len) % flag != 0:op_len = op_len - 1print(f'with shrinking constant of {shrink_constant}, now the length of the big cubic was adjusted to {op_len}')return op_lenelse:print('Constant of Shrinking is too big!Now use the initial length!')return cbc_lendef jud_Rx(ipR):if ipR + cbc_len >= pic_x:print('csnt_x is too big!')while ipR + cbc_len >= pic_x:ipR = ipR - 1print(f'csnt_x was adjusted to {ipR}')return ipRelse:print('csnt_x check!')return ipRdef jud_Ry(ipR):if ipR + cbc_len >= pic_y:print('csnt_y is too big!')while ipR + cbc_len >= pic_y:ipR = ipR - 1print(f'csnt_y was adjusted to {ipR}')return ipRelse:print('csnt_y check!')return ipRdef pic_crop(num):flag = (cbc_len / 3) if num == 9 else (cbc_len / 2)rb = 4 if num == 9 else 3pic_num = 1for tar_x in range(1, rb):for tar_y in range(1, rb):box = (cstn_Rx + flag * (tar_x - 1), cstn_Ry + flag * (tar_y - 1), cstn_Rx + flag * tar_x,cstn_Ry + flag * tar_y)rt = im.crop(box)rt.save(f'--filepath--\\{pic_num}.jpg')pic_num = pic_num + 1open_adress = '--filepath--\\filename.jpg'
# open_adress = input('第一步:输入图片的路径以及文件名(包括后缀名)\n')# save_adress = input('第二步:输入保存地址\n')
# save_adress = '--filepath--'pic_sum = 9
# pic_sum = int(input('第三步:输入你希望得到的方块数:(4/9)\n'))
if jud_N(pic_sum):print('please restart the program and input a correct parameter of pic_sum \n only 4&9 is available')
else:cstn_Rx = 500# cstn_Rx = int(input('第四步:输入起始横坐标:\n'))cstn_Ry = 200# cstn_Ry = int(input('第五步:输入起始纵坐标:\n'))cbc_srk = 200# cbc_srk = int(input('最后一步:输入收缩系数:\n'))im = Image.open(open_adress)pic_x, pic_y = im.sizecbc_len = get_cubic(pic_x, pic_y, pic_sum)cbc_len = cubic_shrink(cbc_srk)cstn_Rx = jud_Rx(cstn_Rx)cstn_Ry = jud_Ry(cstn_Ry)pic_crop(pic_sum)

结语

在写这个程序的过程中,参考过这位老师的博客,是PIL库Image的详细使用说明,对我帮助非常大!
作者:Leemboy
链接// https://blog.csdn.net/leemboy/article/details/83792729

Python+PIL 轻松制作九宫格图片相关推荐

  1. Python工具之一:九宫格图片极致裁剪

    博客迁移 个人博客站点,欢迎访问,www.jiingfengji.tech Python工具之一:九宫格图片极致裁剪 工具用途 在读到文章(https://blog.uwa4d.com/archive ...

  2. 如何利用PPT制作九宫格图片效果

    在朋友圈.微博经常可以看到有人发九宫格图片.这里所说的九宫格图片其实是一张图,分在九张图片中显示,能够产生一种留白和想象的空间. 在制作PPT的过程中也可以做一个九宫格图片,增强视觉效果.下面介绍1种 ...

  3. 用python制作九宫格图片原来如此简单

    from PIL import Image import os# 读取图片 img_path = input('输入图片路径:') im = Image.open(img_path)# 获取图片的尺寸 ...

  4. indesign选中不了图片删除_PPT怎么制作九宫格图片?让你的PPT与众不同

    图片在PowerPoint演示文稿有着举足轻重的作用,如果只是单纯的插入图片,那么你的PPT显得有些单调乏味,大众化的作品很难让人眼前一亮. 今天一起来制作一张九宫格图片,给你的PPT添砖加瓦. 第一 ...

  5. 在android studio中制作九宫格图片

    本文介绍如何在android studio中制作一张九宫格图片. 1.选中准备进行处理的图片*.png,直接修改名为*.9.png.放入android studio 工程的drawable目录下.(. ...

  6. 4、PPT图表的制作(制作九宫格图片、更好看的图表)

    1.顶级商业图表网站 (1)麦肯锡中国:https://www.mckinsey.com.cn/# (2)第一财经:https://www.cbnweek.com/ (3)网易数读:http://da ...

  7. python九宫格拼图_Python制作九宫格图片

    思路: 1.打开要处理的图片 2.判断打开的图片是否为正方形 3.如果是正方形,就进行九等分,如果不是正方形,先用白色填充为正方形,再进行九等分 4.保存处理完的图片 原图: from PIL imp ...

  8. 其实特简单,不足100行 Python 代码轻松制作动态鞭炮

    大家好,农历虎年要来了,放鞭炮贺新春,在我国有两千多年历史.关于鞭炮的起源,有个有趣的传说. 西方山中有焉,长尺余,一足,性不畏人.犯之令人寒热,名曰年惊惮,后人遂象其形,以火药为之.--<神异 ...

  9. python+PIL批量制作淘宝主图(头图)及满屏水印添加

    导读 项目中需要用到图片批量化处理,所以玩了下PIL做了个简单的小项目,解放双手批量制作淘宝主图的功能 任务目标 根据传入的图片数量,自动放大缩小寻找计算可对齐的中心点进行裁切 按照传入图片数量,定制 ...

最新文章

  1. 渗透测试---数据库安全: sql注入数据库原理详解
  2. 对话国际农民丰收节贸易会-万祥军:雀巢全球谋定农民合作
  3. 哪些名人在学python_盘点计算机界十位顶级人物,看看你认识几个?
  4. 取代cookie的网站追踪技术:”帆布指纹识别”初探
  5. php-resque的设计和使用
  6. 关于linux拨号上网的软件实现方案[原创]
  7. PHP Curl 多线程实现
  8. Python 大文件处理
  9. 突然发现Windows 7 Ultimate中有个BUG,分享一下哈!
  10. mouse是计算机软件吗,手机控制电脑软件(EasyMouse)手机端
  11. python毕业设计总结范文大全_毕业设计心得体会与收获
  12. python 爬取淘宝视频_识别假货有绝招,先用python抓淘宝评论(附视频教程)
  13. Java 七参数计算
  14. 815. 打印字符串
  15. c语言单片机程序设计例,51单片机C语言程序设计经典实例(第2版)
  16. | + logger
  17. JavaMail发送邮件手机客户端图片无法显示
  18. python计算机视觉--基于(BOW)的图像检索与识别
  19. MATLAB-Simulink基础知识
  20. 字符串,字符指针,字符串指针,字符数组

热门文章

  1. 计算机常用术语cae是指,《计算机文化基础》练习题
  2. stable_sort应用例子
  3. 中国古代经典励志名言100句,百读不厌,陪孩子一起读经典!
  4. Swiper 轮播插件
  5. apmserver导入MySQL_APMServ MySQL 错误
  6. 并发编程的艺术 读书笔记
  7. 计算机输入法切换用户,电脑的输入法切换不了怎么办,教您如何解决电脑系统输入法...
  8. Java实现简单的弹窗
  9. dr优先级默认_OSPF路由器不能成为DR/BDR唯一的方法:DR优先级=0
  10. 基于SPringBoot的玩具销售商城管理系统