##// END OF EJS Templates
fix issue #3
chedge -
r92:e0b54648 default
parent child Browse files
Show More
@@ -1,164 +1,160 b''
1 1 # -*- encoding: utf-8 -*-
2 2 """
3 3 django-thumbs by Antonio Melé
4 4 http://django.es
5 5 """
6 6 from django.db.models import ImageField
7 7 from django.db.models.fields.files import ImageFieldFile
8 8 from PIL import Image
9 9 from django.core.files.base import ContentFile
10 10 import cStringIO
11 11
12 12 def generate_thumb(img, thumb_size, format):
13 13 """
14 14 Generates a thumbnail image and returns a ContentFile object with the thumbnail
15 15
16 16 Parameters:
17 17 ===========
18 18 img File object
19 19
20 20 thumb_size desired thumbnail size, ie: (200,120)
21 21
22 22 format format of the original image ('jpeg','gif','png',...)
23 23 (this format will be used for the generated thumbnail, too)
24 24 """
25 25
26 26 img.seek(0) # see http://code.djangoproject.com/ticket/8222 for details
27 27 image = Image.open(img)
28 28
29 # Convert to RGB if necessary
30 if image.mode not in ('L', 'RGB'):
31 image = image.convert('RGB')
32
33 29 # get size
34 30 thumb_w, thumb_h = thumb_size
35 31 # If you want to generate a square thumbnail
36 32 if thumb_w == thumb_h:
37 33 # quad
38 34 xsize, ysize = image.size
39 35 # get minimum size
40 36 minsize = min(xsize,ysize)
41 37 # largest square possible in the image
42 38 xnewsize = (xsize-minsize)/2
43 39 ynewsize = (ysize-minsize)/2
44 40 # crop it
45 41 image2 = image.crop((xnewsize, ynewsize, xsize-xnewsize, ysize-ynewsize))
46 42 # load is necessary after crop
47 43 image2.load()
48 44 # thumbnail of the cropped image (with ANTIALIAS to make it look better)
49 45 image2.thumbnail(thumb_size, Image.ANTIALIAS)
50 46 else:
51 47 # not quad
52 48 image2 = image
53 49 image2.thumbnail(thumb_size, Image.ANTIALIAS)
54 50
55 51 io = cStringIO.StringIO()
56 52 # PNG and GIF are the same, JPG is JPEG
57 53 if format.upper()=='JPG':
58 54 format = 'JPEG'
59 55
60 56 image2.save(io, format)
61 57 return ContentFile(io.getvalue())
62 58
63 59 class ImageWithThumbsFieldFile(ImageFieldFile):
64 60 """
65 61 See ImageWithThumbsField for usage example
66 62 """
67 63 def __init__(self, *args, **kwargs):
68 64 super(ImageWithThumbsFieldFile, self).__init__(*args, **kwargs)
69 65 self.sizes = self.field.sizes
70 66
71 67 if self.sizes:
72 68 def get_size(self, size):
73 69 if not self:
74 70 return ''
75 71 else:
76 72 split = self.url.rsplit('.',1)
77 73 thumb_url = '%s.%sx%s.%s' % (split[0],w,h,split[1])
78 74 return thumb_url
79 75
80 76 for size in self.sizes:
81 77 (w,h) = size
82 78 setattr(self, 'url_%sx%s' % (w,h), get_size(self, size))
83 79
84 80 def save(self, name, content, save=True):
85 81 super(ImageWithThumbsFieldFile, self).save(name, content, save)
86 82
87 83 if self.sizes:
88 84 for size in self.sizes:
89 85 (w,h) = size
90 86 split = self.name.rsplit('.',1)
91 87 thumb_name = '%s.%sx%s.%s' % (split[0],w,h,split[1])
92 88
93 89 # you can use another thumbnailing function if you like
94 90 thumb_content = generate_thumb(content, size, split[1])
95 91
96 92 thumb_name_ = self.storage.save(thumb_name, thumb_content)
97 93
98 94 if not thumb_name == thumb_name_:
99 95 raise ValueError('There is already a file named %s' % thumb_name)
100 96
101 97 def delete(self, save=True):
102 98 name=self.name
103 99 super(ImageWithThumbsFieldFile, self).delete(save)
104 100 if self.sizes:
105 101 for size in self.sizes:
106 102 (w,h) = size
107 103 split = name.rsplit('.',1)
108 104 thumb_name = '%s.%sx%s.%s' % (split[0],w,h,split[1])
109 105 try:
110 106 self.storage.delete(thumb_name)
111 107 except:
112 108 pass
113 109
114 110 class ImageWithThumbsField(ImageField):
115 111 attr_class = ImageWithThumbsFieldFile
116 112 """
117 113 Usage example:
118 114 ==============
119 115 photo = ImageWithThumbsField(upload_to='images', sizes=((125,125),(300,200),)
120 116
121 117 To retrieve image URL, exactly the same way as with ImageField:
122 118 my_object.photo.url
123 119 To retrieve thumbnails URL's just add the size to it:
124 120 my_object.photo.url_125x125
125 121 my_object.photo.url_300x200
126 122
127 123 Note: The 'sizes' attribute is not required. If you don't provide it,
128 124 ImageWithThumbsField will act as a normal ImageField
129 125
130 126 How it works:
131 127 =============
132 128 For each size in the 'sizes' atribute of the field it generates a
133 129 thumbnail with that size and stores it following this format:
134 130
135 131 available_filename.[width]x[height].extension
136 132
137 133 Where 'available_filename' is the available filename returned by the storage
138 134 backend for saving the original file.
139 135
140 136 Following the usage example above: For storing a file called "photo.jpg" it saves:
141 137 photo.jpg (original file)
142 138 photo.125x125.jpg (first thumbnail)
143 139 photo.300x200.jpg (second thumbnail)
144 140
145 141 With the default storage backend if photo.jpg already exists it will use these filenames:
146 142 photo_.jpg
147 143 photo_.125x125.jpg
148 144 photo_.300x200.jpg
149 145
150 146 Note: django-thumbs assumes that if filename "any_filename.jpg" is available
151 147 filenames with this format "any_filename.[widht]x[height].jpg" will be available, too.
152 148
153 149 To do:
154 150 ======
155 151 Add method to regenerate thubmnails
156 152
157 153 """
158 154 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, sizes=None, **kwargs):
159 155 self.verbose_name=verbose_name
160 156 self.name=name
161 157 self.width_field=width_field
162 158 self.height_field=height_field
163 159 self.sizes = sizes
164 160 super(ImageField, self).__init__(**kwargs) No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now