Last active
March 27, 2017 09:07
-
-
Save orangle/2f336674fa8630143822 to your computer and use it in GitHub Desktop.
图片处理代码
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- encoding=utf-8 -*- | |
import os | |
from time import time | |
from tempfile import NamedTemporaryFile | |
try: | |
from PIL import Image | |
except ImportError: | |
import Image | |
from settings import MEDIA_ROOT | |
from django.db import models | |
from django.core.files import File | |
from django.contrib.auth.models import User | |
''' | |
对图片进行处理之后再保存的原始方法,集成在django中 | |
''' | |
def generate_food(instance, filename): | |
ext = filename.split('.')[-1] | |
nname = str(int(time())) + '.' + ext | |
return os.path.join("food", nname) | |
class Activity(models.Model): | |
user = models.ForeignKey(User) | |
content = models.CharField(max_length=40, default='') | |
def __unicode__(self): | |
return self.content | |
class Food(models.Model): | |
user = models.ForeignKey(User) | |
name = models.CharField(max_length=20, default='') | |
image = models.ImageField(max_length=255, default='', upload_to=generate_food) | |
small = models.ImageField(max_length=255, default='', upload_to="food") #small 为空的时候报错!! | |
price = models.IntegerField() | |
discount = models.IntegerField() | |
note = models.CharField(max_length=50, default='') | |
def __unicode__(self): | |
return self.name | |
def save(self, *args, **kwargs): | |
#windows 下会有问题,linxu可以正常运行 | |
super(Food, self).save(*args, **kwargs) | |
im = Image.open(os.path.join(MEDIA_ROOT, self.image.name)) | |
self.width, self.height = im.size | |
#im.thumbnail((200,100), Image.ANTIALIAS) #这种方式质量损坏很大 | |
fn, ext = os.path.splitext(self.image.name) | |
x, y, w, h = resize_image(self.width, self.height) | |
box = (x,y,w+x,h+y) | |
ratio = float(300) / w | |
newWidth = int(w * ratio) | |
newHeight = int(h * ratio) | |
newIm = im.crop(box) | |
im = None | |
#newIm.resize((newWidth,newHeight),Image.ANTIALIAS) #压缩图片 | |
print box | |
print self.width, self.height | |
simage_name = fn + "-s" + ext | |
tf = NamedTemporaryFile(delete=True) | |
newIm.save(tf.name, "JPEG", quality=95) | |
self.small.save(simage_name, File(open(tf.name)), save=False) | |
tf.close() | |
super(Food, self).save(*args, **kwargs) | |
def resize_image(ori_w, ori_h, dst_w=200, dst_h=100): | |
''' | |
计算裁剪尺度 | |
''' | |
dst_scale = float(dst_h) / dst_w #目标高宽比 | |
ori_scale = float(ori_h) / ori_w #原高宽比 | |
if ori_scale >= dst_scale: | |
#过高 | |
width = ori_w | |
height = int(width*dst_scale) | |
x = 0 | |
y = (ori_h - height) / 3 | |
else: | |
#过宽 | |
height = ori_h | |
width = int(height*(1/dst_scale)) | |
x = (ori_w - width) / 2 | |
y = 0 | |
return x,y,width,height |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- encoding=utf-8 -*- | |
''' | |
author: orangleliu | |
pil处理图片,验证,处理 | |
大小,格式 过滤 | |
压缩,截图,转换 | |
图片库最好用Pillow | |
还有一个测试图片test.jpg, 一个log图片,一个字体文件 | |
''' | |
#图片的基本参数获取 | |
try: | |
from PIL import Image, ImageDraw, ImageFont, ImageEnhance | |
except ImportError: | |
import Image, ImageDraw, ImageFont, ImageEnhance | |
def compress_image(img, w=128, h=128): | |
''' | |
缩略图 | |
''' | |
img.thumbnail((w,h)) | |
im.save('test1.png', 'PNG') | |
print u'成功保存为png格式, 压缩为128*128格式图片' | |
def cut_image(img): | |
''' | |
截图, 旋转,再粘贴 | |
''' | |
#eft, upper, right, lower | |
#x y z w x,y 是起点, z,w是偏移值 | |
width, height = img.size | |
box = (width-200, height-100, width, height) | |
region = img.crop(box) | |
#旋转角度 | |
region = region.transpose(Image.ROTATE_180) | |
img.paste(region, box) | |
img.save('test2.jpg', 'JPEG') | |
print u'重新拼图成功' | |
def logo_watermark(img, logo_path): | |
''' | |
添加一个图片水印,原理就是合并图层,用png比较好 | |
''' | |
baseim = img | |
logoim = Image.open(logo_path) | |
bw, bh = baseim.size | |
lw, lh = logoim.size | |
baseim.paste(logoim, (bw-lw, bh-lh)) | |
baseim.save('test3.jpg', 'JPEG') | |
print u'logo水印组合成功' | |
def text_watermark(img, text, out_file="test4.jpg", angle=23, opacity=0.50): | |
''' | |
添加一个文字水印,做成透明水印的模样,应该是png图层合并 | |
http://www.pythoncentral.io/watermark-images-python-2x/ | |
这里会产生著名的 ImportError("The _imagingft C module is not installed") 错误 | |
Pillow通过安装来解决 pip install Pillow | |
''' | |
watermark = Image.new('RGBA', img.size, (255,255,255)) | |
FONT = "msyh.ttf" | |
size = 2 | |
n_font = ImageFont.truetype(FONT, size) #得到字体 | |
n_width, n_height = n_font.getsize(text) | |
text_box = min(watermark.size[0], watermark.size[1]) | |
while (n_width+n_height < text_box): | |
size += 2 | |
n_font = ImageFont.truetype(FONT, size=size) | |
n_width, n_height = n_font.getsize(text) #文字逐渐放大,但是要小于图片的宽高最小值 | |
text_width = (watermark.size[0] - n_width) / 2 | |
text_height = (watermark.size[1] - n_height) / 2 | |
#watermark = watermark.resize((text_width,text_height), Image.ANTIALIAS) | |
draw = ImageDraw.Draw(watermark, 'RGBA') #在水印层加画笔 | |
draw.text((text_width,text_height), | |
text, font=n_font, fill="#21ACDA") | |
watermark = watermark.rotate(angle, Image.BICUBIC) | |
alpha = watermark.split()[3] | |
alpha = ImageEnhance.Brightness(alpha).enhance(opacity) | |
watermark.putalpha(alpha) | |
Image.composite(watermark, img, watermark).save(out_file, 'JPEG') | |
print u"文字水印成功" | |
#等比例压缩图片 | |
def resizeImg(img, dst_w=0, dst_h=0, qua=85): | |
''' | |
只给了宽或者高,或者两个都给了,然后取比例合适的 | |
如果图片比给要压缩的尺寸都要小,就不压缩了 | |
''' | |
ori_w, ori_h = im.size | |
widthRatio = heightRatio = None | |
ratio = 1 | |
if (ori_w and ori_w > dst_w) or (ori_h and ori_h > dst_h): | |
if dst_w and ori_w > dst_w: | |
widthRatio = float(dst_w) / ori_w #正确获取小数的方式 | |
if dst_h and ori_h > dst_h: | |
heightRatio = float(dst_h) / ori_h | |
if widthRatio and heightRatio: | |
if widthRatio < heightRatio: | |
ratio = widthRatio | |
else: | |
ratio = heightRatio | |
if widthRatio and not heightRatio: | |
ratio = widthRatio | |
if heightRatio and not widthRatio: | |
ratio = heightRatio | |
newWidth = int(ori_w * ratio) | |
newHeight = int(ori_h * ratio) | |
else: | |
newWidth = ori_w | |
newHeight = ori_h | |
im.resize((newWidth,newHeight),Image.ANTIALIAS).save("test5.jpg", "JPEG", quality=qua) | |
print u'等比压缩完成' | |
''' | |
Image.ANTIALIAS还有如下值: | |
NEAREST: use nearest neighbour | |
BILINEAR: linear interpolation in a 2x2 environment | |
BICUBIC:cubic spline interpolation in a 4x4 environment | |
ANTIALIAS:best down-sizing filter | |
''' | |
#裁剪压缩图片 | |
def clipResizeImg(im, dst_w, dst_h, qua=95): | |
''' | |
先按照一个比例对图片剪裁,然后在压缩到指定尺寸 | |
一个图片 16:5 ,压缩为 2:1 并且宽为200,就要先把图片裁剪成 10:5,然后在等比压缩 | |
''' | |
ori_w,ori_h = im.size | |
dst_scale = float(dst_w) / dst_h #目标高宽比 | |
ori_scale = float(ori_w) / ori_h #原高宽比 | |
if ori_scale <= dst_scale: | |
#过高 | |
width = ori_w | |
height = int(width/dst_scale) | |
x = 0 | |
y = (ori_h - height) / 2 | |
else: | |
#过宽 | |
height = ori_h | |
width = int(height*dst_scale) | |
x = (ori_w - width) / 2 | |
y = 0 | |
#裁剪 | |
box = (x,y,width+x,height+y) | |
#这里的参数可以这么认为:从某图的(x,y)坐标开始截,截到(width+x,height+y)坐标 | |
#所包围的图像,crop方法与php中的imagecopy方法大为不一样 | |
newIm = im.crop(box) | |
im = None | |
#压缩 | |
ratio = float(dst_w) / width | |
newWidth = int(width * ratio) | |
newHeight = int(height * ratio) | |
newIm.resize((newWidth,newHeight),Image.ANTIALIAS).save("test6.jpg", "JPEG",quality=95) | |
print "old size %s %s"%(ori_w, ori_h) | |
print "new size %s %s"%(newWidth, newHeight) | |
print u"剪裁后等比压缩完成" | |
if __name__ == "__main__": | |
''' | |
主要是实现功能, 代码没怎么整理 | |
''' | |
im = Image.open('test.jpg') #image 对象 | |
compress_image(im) | |
im = Image.open('test.jpg') #image 对象 | |
cut_image(im) | |
im = Image.open('test.jpg') #image 对象 | |
logo_watermark(im, 'logo.png') | |
im = Image.open('test.jpg') #image 对象 | |
text_watermark(im, 'Orangleliu') | |
im = Image.open('test.jpg') #image 对象 | |
resizeImg(im, dst_w=100, qua=85) | |
im = Image.open('test.jpg') #image 对象 | |
clipResizeImg(im, 100, 200) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment