用Python图像处理

前几天弄了下django的图片上传,上传之后还需要做些简单的处理,python中PIL模块就是专门用来做这个事情的。

于是照葫芦画瓢做了几个常用图片操作,在这里记录下,以便备用。 

这里有个字体文件,大家可以在自己的系统中选取一个,我这打包放在网盘中  下载

 

一 图样

原始图片

 

 

操作一: 缩略图(通常不用这个方式,因为图片质量损坏太大)

 

操作二 : 旋转图片中的某一部分

 

操作三: 给图片添加一个图片水印, 2张图层合并

     

操作四: 给图片添加文字水印,这个用的比较多, 我这里弄了个白色通明低,可以弄成完全透明的

 

操作 五 等比压缩(比较适合做缩略图)

 

操作六 按照比例剪裁之后,等比压缩,有时候需要定比例的图片可以这么做

 

二 代码

 

[python] view plain copy
 
  1. # -*- encoding=utf-8 -*-  
  2. ''''' 
  3. author: orangleliu 
  4. pil处理图片,验证,处理 
  5. 大小,格式 过滤 
  6. 压缩,截图,转换 
  7.  
  8. 图片库最好用Pillow 
  9. 还有一个测试图片test.jpg, 一个log图片,一个字体文件 
  10. '''  
  11.   
  12. #图片的基本参数获取  
  13. try:  
  14.     from PIL import Image, ImageDraw, ImageFont, ImageEnhance  
  15. except ImportError:  
  16.     import Image, ImageDraw, ImageFont, ImageEnhance  
  17.   
  18. def compress_image(img, w=128, h=128):  
  19.     ''''' 
  20.     缩略图 
  21.     '''  
  22.     img.thumbnail((w,h))  
  23.     im.save('test1.png', 'PNG')  
  24.     print u'成功保存为png格式, 压缩为128*128格式图片'  
  25.   
  26. def cut_image(img):  
  27.     ''''' 
  28.     截图, 旋转,再粘贴 
  29.     '''  
  30.     #eft, upper, right, lower  
  31.     #x y z w  x,y 是起点, z,w是偏移值  
  32.     width, height = img.size  
  33.     box = (width-200, height-100, width, height)  
  34.     region = img.crop(box)  
  35.     #旋转角度  
  36.     region = region.transpose(Image.ROTATE_180)  
  37.     img.paste(region, box)  
  38.     img.save('test2.jpg', 'JPEG')  
  39.     print u'重新拼图成功'  
  40.   
  41. def logo_watermark(img, logo_path):  
  42.     ''''' 
  43.     添加一个图片水印,原理就是合并图层,用png比较好 
  44.     '''  
  45.     baseim = img  
  46.     logoim = Image.open(logo_path)  
  47.     bw, bh = baseim.size  
  48.     lw, lh = logoim.size  
  49.     baseim.paste(logoim, (bw-lw, bh-lh))  
  50.     baseim.save('test3.jpg', 'JPEG')  
  51.     print u'logo水印组合成功'  
  52.   
  53. def text_watermark(img, text, out_file="test4.jpg", angle=23, opacity=0.50):  
  54.     ''''' 
  55.     添加一个文字水印,做成透明水印的模样,应该是png图层合并 
  56.     http://www.pythoncentral.io/watermark-images-python-2x/ 
  57.     这里会产生著名的 ImportError("The _imagingft C module is not installed") 错误 
  58.     Pillow通过安装来解决 pip install Pillow 
  59.     '''  
  60.     watermark = Image.new('RGBA', img.size, (255,255,255)) #我这里有一层白色的膜,去掉(255,255,255) 这个参数就好了  
  61.   
  62.     FONT = "msyh.ttf"  
  63.     size = 2  
  64.   
  65.     n_font = ImageFont.truetype(FONT, size)                                       #得到字体  
  66.     n_width, n_height = n_font.getsize(text)  
  67.     text_box = min(watermark.size[0], watermark.size[1])  
  68.     while (n_width+n_height <  text_box):  
  69.         size += 2  
  70.         n_font = ImageFont.truetype(FONT, size=size)  
  71.         n_width, n_height = n_font.getsize(text)                                   #文字逐渐放大,但是要小于图片的宽高最小值  
  72.   
  73.     text_width = (watermark.size[0] - n_width) / 2  
  74.     text_height = (watermark.size[1] - n_height) / 2  
  75.     #watermark = watermark.resize((text_width,text_height), Image.ANTIALIAS)  
  76.     draw = ImageDraw.Draw(watermark, 'RGBA')                                       #在水印层加画笔  
  77.     draw.text((text_width,text_height),  
  78.               text, font=n_font, fill="#21ACDA")  
  79.     watermark = watermark.rotate(angle, Image.BICUBIC)  
  80.     alpha = watermark.split()[3]  
  81.     alpha = ImageEnhance.Brightness(alpha).enhance(opacity)  
  82.     watermark.putalpha(alpha)  
  83.     Image.composite(watermark, img, watermark).save(out_file, 'JPEG')  
  84.     print u"文字水印成功"  
  85.   
  86.   
  87. #等比例压缩图片  
  88. def resizeImg(img, dst_w=0, dst_h=0, qua=85):  
  89.     ''''' 
  90.     只给了宽或者高,或者两个都给了,然后取比例合适的 
  91.     如果图片比给要压缩的尺寸都要小,就不压缩了 
  92.     '''  
  93.     ori_w, ori_h = im.size  
  94.     widthRatio = heightRatio = None  
  95.     ratio = 1  
  96.   
  97.     if (ori_w and ori_w > dst_w) or (ori_h and ori_h  > dst_h):  
  98.         if dst_w and ori_w > dst_w:  
  99.             widthRatio = float(dst_w) / ori_w                                      #正确获取小数的方式  
  100.         if dst_h and ori_h > dst_h:  
  101.             heightRatio = float(dst_h) / ori_h  
  102.   
  103.         if widthRatio and heightRatio:  
  104.             if widthRatio < heightRatio:  
  105.                 ratio = widthRatio  
  106.             else:  
  107.                 ratio = heightRatio  
  108.   
  109.         if widthRatio and not heightRatio:  
  110.             ratio = widthRatio  
  111.   
  112.         if heightRatio and not widthRatio:  
  113.             ratio = heightRatio  
  114.   
  115.         newWidth = int(ori_w * ratio)  
  116.         newHeight = int(ori_h * ratio)  
  117.     else:  
  118.         newWidth = ori_w  
  119.         newHeight = ori_h  
  120.   
  121.     im.resize((newWidth,newHeight),Image.ANTIALIAS).save("test5.jpg", "JPEG", quality=qua)  
  122.     print u'等比压缩完成'  
  123.   
  124.     ''''' 
  125.     Image.ANTIALIAS还有如下值: 
  126.     NEAREST: use nearest neighbour 
  127.     BILINEAR: linear interpolation in a 2x2 environment 
  128.     BICUBIC:cubic spline interpolation in a 4x4 environment 
  129.     ANTIALIAS:best down-sizing filter 
  130.     '''  
  131.   
  132. #裁剪压缩图片  
  133. def clipResizeImg(im, dst_w, dst_h, qua=95):  
  134.     ''''' 
  135.         先按照一个比例对图片剪裁,然后在压缩到指定尺寸 
  136.         一个图片 16:5 ,压缩为 2:1 并且宽为200,就要先把图片裁剪成 10:5,然后在等比压缩 
  137.     '''  
  138.     ori_w,ori_h = im.size  
  139.   
  140.     dst_scale = float(dst_w) / dst_h  #目标高宽比  
  141.     ori_scale = float(ori_w) / ori_h #原高宽比  
  142.   
  143.     if ori_scale <= dst_scale:  
  144.         #过高  
  145.         width = ori_w  
  146.         height = int(width/dst_scale)  
  147.   
  148.         x = 0  
  149.         y = (ori_h - height) / 2  
  150.   
  151.     else:  
  152.         #过宽  
  153.         height = ori_h  
  154.         width = int(height*dst_scale)  
  155.   
  156.         x = (ori_w - width) / 2  
  157.         y = 0  
  158.   
  159.     #裁剪  
  160.     box = (x,y,width+x,height+y)  
  161.     #这里的参数可以这么认为:从某图的(x,y)坐标开始截,截到(width+x,height+y)坐标  
  162.     #所包围的图像,crop方法与php中的imagecopy方法大为不一样  
  163.     newIm = im.crop(box)  
  164.     im = None  
  165.   
  166.     #压缩  
  167.     ratio = float(dst_w) / width  
  168.     newWidth = int(width * ratio)  
  169.     newHeight = int(height * ratio)  
  170.     newIm.resize((newWidth,newHeight),Image.ANTIALIAS).save("test6.jpg", "JPEG",quality=95)  
  171.     print  "old size  %s  %s"%(ori_w, ori_h)  
  172.     print  "new size %s %s"%(newWidth, newHeight)  
  173.     print u"剪裁后等比压缩完成"  
  174.   
  175.   
  176. if __name__ == "__main__":  
  177.     ''''' 
  178.     主要是实现功能, 代码没怎么整理 
  179.     '''  
  180.     im = Image.open('test.jpg')  #image 对象  
  181.     compress_image(im)  
  182.   
  183.     im = Image.open('test.jpg')  #image 对象  
  184.     cut_image(im)  
  185.   
  186.     im = Image.open('test.jpg')  #image 对象  
  187.     logo_watermark(im, 'logo.png')  
  188.   
  189.     im = Image.open('test.jpg')  #image 对象  
  190.     text_watermark(im, 'Orangleliu')  
  191.   
  192.     im = Image.open('test.jpg')  #image 对象  
  193.     resizeImg(im, dst_w=100, qua=85)  
  194.   
  195.     im = Image.open('test.jpg')  #image 对象  
  196.     clipResizeImg(im, 100, 200)  



 

三 参考

 

 
http://www.cnblogs.com/way_testlife/archive/2011/04/17/2019013.html
http://effbot.org/imagingbook/introduction.htm
http://tech.seety.org/python/python_imaging.html
http://liluo.org/blog/2011/08/python-add-watermark-with-pil/  加水印
http://my.oschina.net/neo600/blog/136393  几种常用的小结
http://oldj.net/article/text-to-image/
posted on 2017-11-03 09:27  jujua  阅读(1818)  评论(0编辑  收藏  举报