remove print statement in logo.py
[mygpo.git] / mygpo / web / logo.py
blob508bc63c0f7d740ca0404bdd19a7cf431c3b16e3
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/>.
18 import os.path
19 import StringIO
20 from datetime import datetime
21 from glob import glob
22 import errno
24 from PIL import Image, ImageDraw
26 from django.conf import settings
27 from django.http import Http404, HttpResponse
28 from django.views.generic.base import View
29 from django.utils.decorators import method_decorator
30 from django.views.decorators.http import last_modified
32 import logging
33 logger = logging.getLogger(__name__)
35 LOGO_DIR = os.path.join(settings.BASE_DIR, '..', 'htdocs', 'media', 'logo')
38 def _last_modified(request, size, prefix, filename):
40 target = os.path.join(LOGO_DIR, size, prefix, filename)
42 try:
43 return datetime.fromtimestamp(os.path.getmtime(target))
45 except OSError:
46 return None
49 class CoverArt(View):
51 @method_decorator(last_modified(_last_modified))
52 def get(self, request, size, prefix, filename):
54 size = int(size)
56 target = self.get_thumbnail(size, prefix, filename)
57 original = self.get_original(prefix, filename)
59 if os.path.exists(target):
60 return self.send_file(target)
62 if not os.path.exists(original):
63 raise Http404('Cover Art not available' + original)
65 target_dir = self.get_dir(target)
67 try:
68 im = Image.open(original)
69 if im.mode not in ('RGB', 'RGBA'):
70 im = im.convert('RGB')
71 except IOError:
72 raise Http404('Cannot open cover file')
74 try:
75 im.thumbnail((size, size), Image.ANTIALIAS)
76 resized = im
77 except IOError as ex:
78 # raised when trying to read an interlaced PNG;
79 logger.warn('Could not create thumbnail: %s', str(ex))
81 # we use the original instead
82 return self.send_file(original)
84 # If it's a RGBA image, composite it onto a white background for JPEG
85 if resized.mode == 'RGBA':
86 background = Image.new('RGB', resized.size)
87 draw = ImageDraw.Draw(background)
88 draw.rectangle((-1, -1, resized.size[0]+1, resized.size[1]+1),
89 fill=(255, 255, 255))
90 del draw
91 resized = Image.composite(resized, background, resized)
93 io = StringIO.StringIO()
95 try:
96 resized.save(io, 'JPEG', optimize=True, progression=True,
97 quality=80)
98 except IOError as ex:
99 return self.send_file(original)
101 s = io.getvalue()
103 fp = open(target, 'wb')
104 fp.write(s)
105 fp.close()
107 return self.send_file(target)
109 # the length of the prefix is defined here and in web/urls.py
110 @staticmethod
111 def get_prefix(filename):
112 return filename[:3]
114 @staticmethod
115 def get_thumbnail(size, prefix, filename):
116 return os.path.join(LOGO_DIR, str(size), prefix, filename)
118 @staticmethod
119 def get_existing_thumbnails(prefix, filename):
120 files = glob(os.path.join(LOGO_DIR, '*', prefix, filename))
121 return filter(lambda f: 'original' not in f, files)
123 @staticmethod
124 def get_original(prefix, filename):
125 return os.path.join(LOGO_DIR, 'original', prefix, filename)
127 @staticmethod
128 def get_dir(filename):
129 path = os.path.dirname(filename)
130 try:
131 os.makedirs(path)
133 except OSError as ose:
134 if ose.errno != errno.EEXIST:
135 raise
137 return path
139 def send_file(self, filename):
140 resp = HttpResponse(content_type='image/jpeg')
141 resp.status_code = 200
142 f = open(filename)
143 resp.write(f.read())
144 return resp