40f52bbf256c306090de76ece034551ab4a36abd
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
20 from datetime
import datetime
27 from django
.conf
import settings
28 from django
.http
import Http404
, HttpResponse
29 from django
.views
.generic
.base
import View
30 from django
.utils
.decorators
import method_decorator
31 from django
.views
.decorators
.http
import last_modified
34 LOGO_DIR
= os
.path
.join(settings
.BASE_DIR
, '..', 'htdocs', 'media', 'logo')
37 def _last_modified(request
, size
, prefix
, filename
):
39 target
= os
.path
.join(LOGO_DIR
, size
, prefix
, filename
)
42 return datetime
.fromtimestamp(os
.path
.getmtime(target
))
50 @method_decorator(last_modified(_last_modified
))
51 def get(self
, request
, size
, prefix
, filename
):
55 target
= self
.get_thumbnail(size
, prefix
, filename
)
56 original
= self
.get_original(prefix
, filename
)
58 if os
.path
.exists(target
):
59 return self
.send_file(target
)
61 if not os
.path
.exists(original
):
62 raise Http404('Cover Art not available' + original
)
64 target_dir
= self
.get_dir(target
)
67 im
= Image
.open(original
)
68 if im
.mode
not in ('RGB', 'RGBA'):
69 im
= im
.convert('RGB')
71 raise Http404('Cannot open cover file')
74 im
.thumbnail((size
, size
), Image
.ANTIALIAS
)
78 # raised when trying to read an interlaced PNG;
79 # we use the original instead
80 return self
.send_file(original
)
82 # If it's a RGBA image, composite it onto a white background for JPEG
83 if resized
.mode
== 'RGBA':
84 background
= Image
.new('RGB', resized
.size
)
85 draw
= ImageDraw
.Draw(background
)
86 draw
.rectangle((-1, -1, resized
.size
[0]+1, resized
.size
[1]+1),
89 resized
= Image
.composite(resized
, background
, resized
)
91 io
= StringIO
.StringIO()
94 resized
.save(io
, 'JPEG', optimize
=True, progression
=True,
97 return self
.send_file(original
)
101 fp
= open(target
, 'wb')
105 return self
.send_file(target
)
107 # the length of the prefix is defined here and in web/urls.py
109 def get_prefix(filename
):
113 def get_thumbnail(size
, prefix
, filename
):
114 return os
.path
.join(LOGO_DIR
, str(size
), prefix
, filename
)
117 def get_existing_thumbnails(prefix
, filename
):
118 files
= glob(os
.path
.join(LOGO_DIR
, '*', prefix
, filename
))
119 return filter(lambda f
: 'original' not in f
, files
)
122 def get_original(prefix
, filename
):
123 return os
.path
.join(LOGO_DIR
, 'original', prefix
, filename
)
126 def get_dir(filename
):
127 path
= os
.path
.dirname(filename
)
131 except OSError as ose
:
132 if ose
.errno
!= errno
.EEXIST
:
137 def send_file(self
, filename
):
138 resp
= HttpResponse(content_type
='image/jpeg')
139 resp
.status_code
= 200