3 from datetime
import datetime
9 from PIL
import Image
, ImageDraw
11 from django
.core
.urlresolvers
import reverse
12 from django
.conf
import settings
13 from django
.http
import Http404
, HttpResponse
, HttpResponseNotFound
14 from django
.views
.generic
.base
import View
15 from django
.utils
.decorators
import method_decorator
16 from django
.views
.decorators
.http
import last_modified
19 logger
= logging
.getLogger(__name__
)
21 LOGO_DIR
= os
.path
.join(settings
.BASE_DIR
, '..', 'htdocs', 'media', 'logo')
24 def _last_modified(request
, size
, prefix
, filename
):
26 target
= os
.path
.join(LOGO_DIR
, size
, prefix
, filename
)
29 return datetime
.fromtimestamp(os
.path
.getmtime(target
))
37 @method_decorator(last_modified(_last_modified
))
38 def get(self
, request
, size
, prefix
, filename
):
42 target
= self
.get_thumbnail(size
, prefix
, filename
)
43 original
= self
.get_original(prefix
, filename
)
45 if os
.path
.exists(target
):
46 return self
.send_file(target
)
48 if not os
.path
.exists(original
):
49 raise Http404('Cover Art not available' + original
)
51 target_dir
= self
.get_dir(target
)
54 im
= Image
.open(original
)
55 if im
.mode
not in ('RGB', 'RGBA'):
56 im
= im
.convert('RGB')
58 raise Http404('Cannot open cover file')
61 im
.thumbnail((size
, size
), Image
.ANTIALIAS
)
63 except (struct
.error
, IOError, IndexError) as ex
:
64 # raised when trying to read an interlaced PNG;
65 logger
.warn('Could not create thumbnail: %s', str(ex
))
67 # we use the original instead
68 return self
.send_file(original
)
70 # If it's a RGBA image, composite it onto a white background for JPEG
71 if resized
.mode
== 'RGBA':
72 background
= Image
.new('RGB', resized
.size
)
73 draw
= ImageDraw
.Draw(background
)
74 draw
.rectangle((-1, -1, resized
.size
[0]+1, resized
.size
[1]+1),
77 resized
= Image
.composite(resized
, background
, resized
)
82 resized
.save(sio
, 'JPEG', optimize
=True, progression
=True,
85 return self
.send_file(original
)
89 fp
= open(target
, 'wb')
93 return self
.send_file(target
)
95 # the length of the prefix is defined here and in web/urls.py
97 def get_prefix(filename
):
101 def get_thumbnail(size
, prefix
, filename
):
102 return os
.path
.join(LOGO_DIR
, str(size
), prefix
, filename
)
105 def get_existing_thumbnails(prefix
, filename
):
106 files
= glob(os
.path
.join(LOGO_DIR
, '*', prefix
, filename
))
107 return [f
for f
in files
if 'original' not in f
]
110 def get_original(prefix
, filename
):
111 return os
.path
.join(LOGO_DIR
, 'original', prefix
, filename
)
114 def get_dir(filename
):
115 path
= os
.path
.dirname(filename
)
119 except OSError as ose
:
120 if ose
.errno
!= errno
.EEXIST
:
125 def send_file(self
, filename
):
127 f
= open(filename
, 'rb')
129 return HttpResponseNotFound()
131 resp
= HttpResponse(content_type
='image/jpeg')
132 resp
.status_code
= 200
137 def get_logo_url(podcast
, size
):
138 """ Return the logo URL for the podcast """
141 filename
= hashlib
.sha1(podcast
.logo_url
.encode('utf-8')).hexdigest()
143 filename
= 'podcast-%d.png' % (hash(podcast
.title
) % 5, )
145 prefix
= CoverArt
.get_prefix(filename
)
147 return reverse('logo', args
=[size
, prefix
, filename
])