def image(request, path, token, autogen=False): is_admin = False if ("is_admin=true" in token and request and request.user.has_perm('admin')) or autogen: parameters = token is_admin = True if autogen: token = image_create_token(parameters) else: parameters = request.session.get(token, token) path = os.path.normcase(path) cached_image_path = settings.IMAGE_CACHE_ROOT + "/" + path + "/" cached_image_file = cached_image_path + token response = HttpResponse() response['Content-type'] = 'image/jpeg' response['Expires'] = 'Fri, 09 Dec 2327 08:34:31 GMT' response['Last-Modified'] = 'Fri, 24 Sep 2010 11:36:29 GMT' response.status_code = 200 # If we already have the cache we send it instead of recreating it if os.path.exists(smart_unicode(cached_image_file)): if autogen: return 'Already generated' f = open(cached_image_file, "r") response.write(f.read()) f.close() return response if parameters == token and not is_admin: return HttpResponse("Forbidden", status=403) qs = QueryDict(parameters) ROOT_DIR = settings.MEDIA_ROOT try: if qs['static'] == "true": ROOT_DIR = settings.STATIC_ROOT except KeyError: pass format = qs.get('format', IMAGE_DEFAULT_FORMAT) quality = int(qs.get('quality', IMAGE_DEFAULT_QUALITY)) mask = qs.get('mask', None) if mask is not None: format = "PNG" fill = qs.get('fill', None) background = qs.get('background', None) tint = qs.get('tint', None) center = qs.get('center', ".5,.5") mode = qs.get('mode', "crop") overlays = qs.getlist('overlay') overlay_sources = qs.getlist('overlay_source') overlay_tints = qs.getlist('overlay_tint') width = int(qs.get('width', None)) height = int(qs.get('height', None)) if "video" in qs: data, http_response = generate_thumb(ROOT_DIR + "/" + smart_unicode(path), width=width, height=height) response.status_code = http_response else: try: try: f = urllib.urlopen(qs['url']) data = f.read() f.close() except KeyError: f = open(ROOT_DIR + "/" + smart_unicode(path), 'r') data = f.read() f.close() except IOError: response.status_code = 404 data = image_text(IMAGE_ERROR_NOT_FOUND, width, height) try: if mode == "scale": output_data = scale(data, width, height, overlays=overlays, overlay_sources=overlay_sources, overlay_tints=overlay_tints, mask=mask, format=format, quality=quality, fill=fill, background=background, tint=tint) else: output_data = scaleAndCrop(data, width, height, True, overlays=overlays, overlay_sources=overlay_sources, overlay_tints=overlay_tints, mask=mask, center=center, format=format, quality=quality, fill=fill, background=background, tint=tint) except IOError: response.status_code = 500 output_data = image_text(IMAGE_ERROR_NOT_VALID, width, height) if response.status_code == 200: if not os.path.exists(cached_image_path): os.makedirs(cached_image_path) f = open(cached_image_file, "w") f.write(output_data) f.close() if autogen: return 'Generated ' + str(response.status_code) else: if autogen: return 'Failed ' + cached_image_file response.write(output_data) return response
def generate_thumb(video_path, thumb_size=None, format='jpg', frames=100, width=100, height=100): histogram = [] http_status = 200 name = video_path path = video_path if not os.path.exists(video_path): return image_text(IMAGE_ERROR_VIDEO_NOT_FOUND, width, height), '404' framemask = "%s%s%s%s" % (settings.FILE_UPLOAD_TEMP_DIR, name.split('/')[-1].split('.')[0] + str(time.time()), '.%d.', format) # ffmpeg command for grabbing N number of frames cmd = "/usr/bin/ffmpeg -y -t 00:00:05 -i '%s' '%s'" % (path, framemask) # make sure that this command worked or return. if os.system(cmd) != 0: return image_text(IMAGE_ERROR_FFMPEG, width, height), '500' # loop through the generated images, open, and generate the image histogram. for i in range(1, frames + 1): fname = framemask % i if not os.path.exists(fname): break image = Image.open(fname) # Convert to RGB if necessary if image.mode not in ('L', 'RGB'): image = image.convert('RGB') # The list of image historgrams histogram.append(image.histogram()) n = len(histogram) avg = [] # Get the image average of the first image for c in range(len(histogram[0])): ac = 0.0 for i in range(n): ac = ac + (float(histogram[i][c]) / n) avg.append(ac) minn = -1 minRMSE = -1 # Compute the mean squared error for i in range(1, n + 1): results = 0.0 num = len(avg) for j in range(num): median_error = avg[j] - float(histogram[i - 1][j]) results += (median_error * median_error) / num rmse = math.sqrt(results) if minn == -1 or rmse < minRMSE: minn = i minRMSE = rmse file_location = framemask % (minn) image = Image.open(file_location) # If you want to generate a square thumbnail if not thumb_size is None: thumb_w, thumb_h = thumb_size if thumb_w == thumb_h: # quad xsize, ysize = image.size # get minimum size minsize = min(xsize, ysize) # largest square possible in the image xnewsize = (xsize - minsize) / 2 ynewsize = (ysize - minsize) / 2 # crop it image2 = image.crop((xnewsize, ynewsize, xsize - xnewsize, ysize - ynewsize)) # load is necessary after crop image2.load() # thumbnail of the cropped image (with ANTIALIAS to make it look better) image2.thumbnail(thumb_size, Image.ANTIALIAS) else: # not quad image2 = image image2.thumbnail(thumb_size, Image.ANTIALIAS) else: image2 = image io = cStringIO.StringIO() # PNG and GIF are the same, JPG is JPEG if format.upper() == 'JPG': format = 'JPEG' image2.save(io, format) # We don't know how many frames we capture. We just captured the first 5 seconds, so keep removing until not found for i in range(1, 9999): fname = framemask % i try: os.unlink(fname) except OSError: break return io.getvalue(), http_status