@@ -44,22 +44,10 @@ def save(self, **kwargs):
4444 super ().save (** kwargs )
4545
4646 def get_thumbnail_url (self ):
47- crop_x , crop_y , crop_size , gravity = (
48- self .meta_data .get ('crop_x' ), self .meta_data .get ('crop_y' ), self .meta_data .get ('crop_size' ),
49- self .meta_data .get ('gravity' )
50- )
51- thumbnail_path = self .get_thumbnail_path (crop_x , crop_y , crop_size , gravity )
52- if not default_storage .exists (thumbnail_path ):
47+ thumbnail_path = self .get_thumbnail_path (self .thumbnail_size , self .thumbnail_size )
48+ if str (self .id ) == 'XXX-561d6907-5fd7-40b9-a6f2-5db45a67eda6' or not default_storage .exists (thumbnail_path ):
5349 try :
54- image = Image .open (default_storage .open (self .file_path ))
55- image = self .orientate_top (image )
56- if crop_x is None or crop_y is None or crop_size is None :
57- image = self .crop_centered (image )
58- else :
59- image = self .crop_eccentric (image , crop_x , crop_y , crop_size , gravity )
60- image .thumbnail ((self .thumbnail_size , self .thumbnail_size ))
61- (default_storage .base_location / thumbnail_path .parent ).mkdir (parents = True , exist_ok = True )
62- image .save (default_storage .open (thumbnail_path , 'wb' ), image .format )
50+ self .crop (thumbnail_path , self .thumbnail_size , self .thumbnail_size * 0.75 )
6351 except Exception :
6452 # thumbnail image could not be created
6553 return self .fallback_thumbnail_url
@@ -84,19 +72,96 @@ def orientate_top(self, image):
8472 image = image .transpose (Image .ROTATE_90 )
8573 return image
8674
75+ def crop (self , thumbnail_path , width , height ):
76+ aspect_ratio = width / height
77+ image = Image .open (default_storage .open (self .file_path ))
78+ image = self .orientate_top (image )
79+ print (f"Wanted site: width={ width } , height={ height } , aspect_ratio={ aspect_ratio } orig={ image .size } " )
80+ orig_width , orig_height = image .size
81+ crop_x , crop_y , crop_size , gravity = (
82+ self .meta_data .get ('crop_x' ),
83+ self .meta_data .get ('crop_y' ),
84+ self .meta_data .get ('crop_size' ),
85+ self .meta_data .get ('gravity' ),
86+ )
87+ if crop_x is None or crop_y is None or crop_size is None :
88+ # crop in the center of the image
89+ if orig_width > orig_height :
90+ crop_x = (orig_width - orig_height ) / 2
91+ crop_y = 0
92+ crop_size = orig_height
93+ else :
94+ crop_x = 0
95+ crop_y = (orig_height - orig_width ) / 2
96+ crop_size = orig_width
97+
98+ print (f"Crop parameters: crop_x={ crop_x } , crop_y={ crop_y } , crop_size={ crop_size } , gravity={ gravity } " )
99+
100+ # horizontal thumbnailing
101+ if aspect_ratio < 1 :
102+ min_width = max (crop_size * aspect_ratio * 3 / 2 , width )
103+ else :
104+ min_width = max (crop_size , width )
105+ if aspect_ratio < 1 :
106+ min_x = crop_x + (crop_size - min_width ) / 2
107+ elif crop_size < min_width :
108+ min_x = crop_y - (min_width - crop_size ) / 2
109+ else :
110+ min_x = crop_x
111+ if crop_size < min_width :
112+ if gravity in ('e' , 'ne' , 'se' ):
113+ max_x = min (crop_x + min_width , image .width )
114+ min_x = max (max_x - min_width , 0 )
115+ elif gravity in ('w' , 'nw' , 'sw' ):
116+ min_x = max (crop_x - min_width + crop_size , 0 )
117+ if min_x + min_width > image .width :
118+ min_x = max (image .width - min_width , 0 )
119+ max_x = image .width
120+ else :
121+ max_x = min_x + min_width
122+
123+ # vertical thumbnailing
124+ if orig_width < orig_height :
125+ min_height = max (crop_size / aspect_ratio , height )
126+ else :
127+ min_height = max (min_width / aspect_ratio , height )
128+ if aspect_ratio > 1 :
129+ min_y = crop_y + (crop_size - min_height ) / 2
130+ elif crop_size < min_height :
131+ min_y = crop_y - (min_height - crop_size ) / 2
132+ else :
133+ min_y = crop_y
134+ if crop_size < min_height :
135+ if gravity in ('s' , 'se' , 'sw' ):
136+ max_y = min (crop_y + min_height , image .height )
137+ min_y = max (max_y - min_height , 0 )
138+ elif gravity in ('n' , 'ne' , 'nw' ):
139+ min_y = max (crop_y - min_height + crop_size , 0 )
140+ if min_y + min_height > image .height :
141+ min_y = max (image .height - min_height , 0 )
142+ max_y = image .height
143+ else :
144+ max_y = min_y + min_height
145+
146+ print (f"Crop area: ({ min_x } , { min_y } ) to ({ max_x } , { max_y } ) = { max_x - min_x } x { max_y - min_y } " )
147+ image = image .crop ((min_x , min_y , max_x , max_y ))
148+ image .thumbnail ((width , height ))
149+ (default_storage .base_location / thumbnail_path .parent ).mkdir (parents = True , exist_ok = True )
150+ image .save (default_storage .open (thumbnail_path , 'wb' ), image .format )
151+
87152 def crop_centered (self , image ):
88153 width , height = image .size
89154 if width > height :
90- left = (width - height ) / 2
91- top = 0
92- right = (width + height ) / 2
93- bottom = height
155+ min_x = (width - height ) / 2
156+ min_y = 0
157+ max_x = (width + height ) / 2
158+ max_y = height
94159 else :
95- left = 0
96- top = (height - width ) / 2
97- right = width
98- bottom = (height + width ) / 2
99- return image .crop ((left , top , right , bottom ))
160+ min_x = 0
161+ min_y = (height - width ) / 2
162+ max_x = width
163+ max_y = (height + width ) / 2
164+ return image .crop ((min_x , min_y , max_x , max_y ))
100165
101166 def crop_eccentric (self , image , crop_x , crop_y , crop_size , gravity ):
102167 """
0 commit comments