python图片添加水印(转载)

转载来自:http://blog.csdn.net/orangleliu/

  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)  # -*- encoding=utf-8 -*-  
197 ''''' 
198 author: orangleliu 
199 pil处理图片,验证,处理 
200 大小,格式 过滤 
201 压缩,截图,转换 
202  
203 图片库最好用Pillow 
204 还有一个测试图片test.jpg, 一个log图片,一个字体文件 
205 '''  
206   
207 #图片的基本参数获取  
208 try:  
209     from PIL import Image, ImageDraw, ImageFont, ImageEnhance  
210 except ImportError:  
211     import Image, ImageDraw, ImageFont, ImageEnhance  
212   
213 def compress_image(img, w=128, h=128):  
214     ''''' 
215     缩略图 
216     '''  
217     img.thumbnail((w,h))  
218     im.save('test1.png', 'PNG')  
219     print u'成功保存为png格式, 压缩为128*128格式图片'  
220   
221 def cut_image(img):  
222     ''''' 
223     截图, 旋转,再粘贴 
224     '''  
225     #eft, upper, right, lower  
226     #x y z w  x,y 是起点, z,w是偏移值  
227     width, height = img.size  
228     box = (width-200, height-100, width, height)  
229     region = img.crop(box)  
230     #旋转角度  
231     region = region.transpose(Image.ROTATE_180)  
232     img.paste(region, box)  
233     img.save('test2.jpg', 'JPEG')  
234     print u'重新拼图成功'  
235   
236 def logo_watermark(img, logo_path):  
237     ''''' 
238     添加一个图片水印,原理就是合并图层,用png比较好 
239     '''  
240     baseim = img  
241     logoim = Image.open(logo_path)  
242     bw, bh = baseim.size  
243     lw, lh = logoim.size  
244     baseim.paste(logoim, (bw-lw, bh-lh))  
245     baseim.save('test3.jpg', 'JPEG')  
246     print u'logo水印组合成功'  
247   
248 def text_watermark(img, text, out_file="test4.jpg", angle=23, opacity=0.50):  
249     ''''' 
250     添加一个文字水印,做成透明水印的模样,应该是png图层合并 
251     http://www.pythoncentral.io/watermark-images-python-2x/ 
252     这里会产生著名的 ImportError("The _imagingft C module is not installed") 错误 
253     Pillow通过安装来解决 pip install Pillow 
254     '''  
255     watermark = Image.new('RGBA', img.size, (255,255,255)) #我这里有一层白色的膜,去掉(255,255,255) 这个参数就好了  
256   
257     FONT = "msyh.ttf"  
258     size = 2  
259   
260     n_font = ImageFont.truetype(FONT, size)                                       #得到字体  
261     n_width, n_height = n_font.getsize(text)  
262     text_box = min(watermark.size[0], watermark.size[1])  
263     while (n_width+n_height <  text_box):  
264         size += 2  
265         n_font = ImageFont.truetype(FONT, size=size)  
266         n_width, n_height = n_font.getsize(text)                                   #文字逐渐放大,但是要小于图片的宽高最小值  
267   
268     text_width = (watermark.size[0] - n_width) / 2  
269     text_height = (watermark.size[1] - n_height) / 2  
270     #watermark = watermark.resize((text_width,text_height), Image.ANTIALIAS)  
271     draw = ImageDraw.Draw(watermark, 'RGBA')                                       #在水印层加画笔  
272     draw.text((text_width,text_height),  
273               text, font=n_font, fill="#21ACDA")  
274     watermark = watermark.rotate(angle, Image.BICUBIC)  
275     alpha = watermark.split()[3]  
276     alpha = ImageEnhance.Brightness(alpha).enhance(opacity)  
277     watermark.putalpha(alpha)  
278     Image.composite(watermark, img, watermark).save(out_file, 'JPEG')  
279     print u"文字水印成功"  
280   
281   
282 #等比例压缩图片  
283 def resizeImg(img, dst_w=0, dst_h=0, qua=85):  
284     ''''' 
285     只给了宽或者高,或者两个都给了,然后取比例合适的 
286     如果图片比给要压缩的尺寸都要小,就不压缩了 
287     '''  
288     ori_w, ori_h = im.size  
289     widthRatio = heightRatio = None  
290     ratio = 1  
291   
292     if (ori_w and ori_w > dst_w) or (ori_h and ori_h  > dst_h):  
293         if dst_w and ori_w > dst_w:  
294             widthRatio = float(dst_w) / ori_w                                      #正确获取小数的方式  
295         if dst_h and ori_h > dst_h:  
296             heightRatio = float(dst_h) / ori_h  
297   
298         if widthRatio and heightRatio:  
299             if widthRatio < heightRatio:  
300                 ratio = widthRatio  
301             else:  
302                 ratio = heightRatio  
303   
304         if widthRatio and not heightRatio:  
305             ratio = widthRatio  
306   
307         if heightRatio and not widthRatio:  
308             ratio = heightRatio  
309   
310         newWidth = int(ori_w * ratio)  
311         newHeight = int(ori_h * ratio)  
312     else:  
313         newWidth = ori_w  
314         newHeight = ori_h  
315   
316     im.resize((newWidth,newHeight),Image.ANTIALIAS).save("test5.jpg", "JPEG", quality=qua)  
317     print u'等比压缩完成'  
318   
319     ''''' 
320     Image.ANTIALIAS还有如下值: 
321     NEAREST: use nearest neighbour 
322     BILINEAR: linear interpolation in a 2x2 environment 
323     BICUBIC:cubic spline interpolation in a 4x4 environment 
324     ANTIALIAS:best down-sizing filter 
325     '''  
326   
327 #裁剪压缩图片  
328 def clipResizeImg(im, dst_w, dst_h, qua=95):  
329     ''''' 
330         先按照一个比例对图片剪裁,然后在压缩到指定尺寸 
331         一个图片 16:5 ,压缩为 2:1 并且宽为200,就要先把图片裁剪成 10:5,然后在等比压缩 
332     '''  
333     ori_w,ori_h = im.size  
334   
335     dst_scale = float(dst_w) / dst_h  #目标高宽比  
336     ori_scale = float(ori_w) / ori_h #原高宽比  
337   
338     if ori_scale <= dst_scale:  
339         #过高  
340         width = ori_w  
341         height = int(width/dst_scale)  
342   
343         x = 0  
344         y = (ori_h - height) / 2  
345   
346     else:  
347         #过宽  
348         height = ori_h  
349         width = int(height*dst_scale)  
350   
351         x = (ori_w - width) / 2  
352         y = 0  
353   
354     #裁剪  
355     box = (x,y,width+x,height+y)  
356     #这里的参数可以这么认为:从某图的(x,y)坐标开始截,截到(width+x,height+y)坐标  
357     #所包围的图像,crop方法与php中的imagecopy方法大为不一样  
358     newIm = im.crop(box)  
359     im = None  
360   
361     #压缩  
362     ratio = float(dst_w) / width  
363     newWidth = int(width * ratio)  
364     newHeight = int(height * ratio)  
365     newIm.resize((newWidth,newHeight),Image.ANTIALIAS).save("test6.jpg", "JPEG",quality=95)  
366     print  "old size  %s  %s"%(ori_w, ori_h)  
367     print  "new size %s %s"%(newWidth, newHeight)  
368     print u"剪裁后等比压缩完成"  
369   
370   
371 if __name__ == "__main__":  
372     ''''' 
373     主要是实现功能, 代码没怎么整理 
374     '''  
375     im = Image.open('test.jpg')  #image 对象  
376     compress_image(im)  
377   
378     im = Image.open('test.jpg')  #image 对象  
379     cut_image(im)  
380   
381     im = Image.open('test.jpg')  #image 对象  
382     logo_watermark(im, 'logo.png')  
383   
384     im = Image.open('test.jpg')  #image 对象  
385     text_watermark(im, 'Orangleliu')  
386   
387     im = Image.open('test.jpg')  #image 对象  
388     resizeImg(im, dst_w=100, qua=85)  
389   
390     im = Image.open('test.jpg')  #image 对象  
391     clipResizeImg(im, 100, 200)  
原文地址:https://www.cnblogs.com/xiaoyaowuming/p/6117667.html