@@ -44,22 +44,10 @@ def save(self, **kwargs):
44
44
super ().save (** kwargs )
45
45
46
46
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 ):
53
49
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 )
63
51
except Exception :
64
52
# thumbnail image could not be created
65
53
return self .fallback_thumbnail_url
@@ -84,19 +72,96 @@ def orientate_top(self, image):
84
72
image = image .transpose (Image .ROTATE_90 )
85
73
return image
86
74
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
+
87
152
def crop_centered (self , image ):
88
153
width , height = image .size
89
154
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
94
159
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 ))
100
165
101
166
def crop_eccentric (self , image , crop_x , crop_y , crop_size , gravity ):
102
167
"""
0 commit comments