aboutsummaryrefslogtreecommitdiff
path: root/cgi/img.py
diff options
context:
space:
mode:
Diffstat (limited to 'cgi/img.py')
-rw-r--r--cgi/img.py133
1 files changed, 76 insertions, 57 deletions
diff --git a/cgi/img.py b/cgi/img.py
index ef64ac0..1c57e37 100644
--- a/cgi/img.py
+++ b/cgi/img.py
@@ -4,6 +4,7 @@ import math
#import random
import os
import subprocess
+import logging
from StringIO import StringIO
from settings import Settings
@@ -30,6 +31,7 @@ def processImage(post, data, t, originalname, spoiler=False):
# get image information
content_type, width, height, size, extra = getImageInfo(data)
+ logging.info("{} {} {}".format(content_type, width, height))
# check the size is fine
if size > int(board["maxsize"])*1024:
@@ -87,66 +89,63 @@ def processImage(post, data, t, originalname, spoiler=False):
# Do we need to thumbnail it?
if not used_filetype['image']:
# make thumbnail
+ logging.debug("Generating thumbnail")
file_thumb_width, file_thumb_height = getThumbDimensions(
width, height, maxsize)
-
- if used_filetype['ffmpeg_thumb'] == '1':
- # use ffmpeg to make thumbnail
- logTime("Generating thumbnail")
-
- if used_filetype['mime'][:5] == 'video':
- retcode = subprocess.call([
- Settings.FFMPEG_PATH, '-strict', '-2', '-ss', '0', '-i', file_path,
- '-v', 'quiet', '-an', '-vframes', '1', '-f', 'mjpeg', '-vf', 'scale=%d:%d' % (
- file_thumb_width, file_thumb_height),
- '-threads', '1', file_thumb_path])
- if spoiler:
- args = [Settings.CONVERT_PATH, file_thumb_path, "-limit", "thread", "1", "-background", "white", "-flatten", "-resize", "%dx%d" % (file_thumb_width, file_thumb_height), "-blur", "0x12", "-gravity", "center", "-fill", "rgba(0,0,0, .6)", "-draw", "rectangle 0,%d,%d,%d" % (
- (file_thumb_height/2)-10, file_thumb_width, (file_thumb_height/2)+7), "-fill", "white", "-annotate", "0", "Alerta de spoiler", "-quality", str(Settings.THUMB_QUALITY), file_thumb_path]
- retcode = subprocess.call(args)
- elif used_filetype['mime'][:5] == 'audio':
- # we do an exception and use png for audio waveform thumbnails since they
- # 1. are smaller 2. allow for transparency
- file_thumb_name = file_thumb_name[:-3] + "png"
- file_thumb_path = file_thumb_path[:-3] + "png"
- file_mobile_path = file_mobile_path[:-3] + "png"
- file_cat_path = file_cat_path[:-3] + "png"
-
- if int(board['thumb_px']) > 149:
- file_thumb_width = board['thumb_px']
- file_thumb_height = float(int(board['thumb_px'])/2)
- else:
- file_thumb_width = 150
- file_thumb_height = 75
-
- retcode = subprocess.call([
- Settings.FFMPEG_PATH, '-t', '300', '-i', file_path,
- '-filter_complex', 'showwavespic=s=%dx%d:split_channels=1' % (
+
+ try:
+ if used_filetype['ffmpeg_thumb'] == '1':
+ # use ffmpeg to make thumbnail
+ if used_filetype['mime'][:5] == 'video':
+ # Create preview for video AND spoiler it if necessary
+ call_wrap([
+ Settings.FFMPEG_PATH, '-strict', '-2', '-ss', '0', '-i', file_path,
+ '-v', 'quiet', '-an', '-vframes', '1', '-f', 'mjpeg', '-vf', 'scale=%d:%d' % (
+ file_thumb_width, file_thumb_height),
+ '-threads', '1', file_thumb_path])
+ if spoiler:
+ call_wrap([Settings.CONVERT_PATH, file_thumb_path, "-limit", "thread",
+ "1", "-background", "white", "-flatten", "-resize",
+ "%dx%d" % (file_thumb_width, file_thumb_height), "-blur", "0x12",
+ "-gravity", "center", "-fill", "rgba(0,0,0, .6)",
+ "-draw", "rectangle 0,%d,%d,%d" % ((file_thumb_height/2)-10, file_thumb_width, (file_thumb_height/2)+7),
+ "-fill", "white", "-font", "Liberation-Sans", "-annotate", "0", "Alerta de spoiler",
+ "-quality", str(Settings.THUMB_QUALITY), file_thumb_path])
+ elif used_filetype['mime'][:5] == 'audio':
+ # we do an exception and use png for audio waveform thumbnails since they
+ # 1. are smaller 2. allow for transparency
+ file_thumb_name = file_thumb_name[:-3] + "png"
+ file_thumb_path = file_thumb_path[:-3] + "png"
+ file_mobile_path = file_mobile_path[:-3] + "png"
+ file_cat_path = file_cat_path[:-3] + "png"
+
+ if int(board['thumb_px']) > 149:
+ file_thumb_width = board['thumb_px']
+ file_thumb_height = float(int(board['thumb_px'])/2)
+ else:
+ file_thumb_width = 150
+ file_thumb_height = 75
+
+ call_wrap([Settings.FFMPEG_PATH, '-t', '300', '-i', file_path,
+ '-filter_complex', 'showwavespic=s=%dx%d:split_channels=1' % (
int(file_thumb_width), int(file_thumb_height)),
- '-frames:v', '1', '-threads', '1', file_thumb_path])
-# elif used_filetype['mime'] == 'application/x-shockwave-flash' or used_filetype['mime'] == 'mime/x-shockwave-flash':
-# retcode = subprocess.call([
-# './ffmpeg', '-i', file_path, '-vcodec', 'mjpeg', '-vframes', '1', '-an', '-f', 'rawvideo',
-# '-vf', 'scale=%d:%d' % (file_thumb_width, file_thumb_height), '-threads', '1', file_thumb_path])
-
- if retcode != 0:
- os.remove(file_path)
- raise UserError, _("Thumbnail creation failure.") + ' ('+str(retcode)+')'
- else:
- # use imagemagick to make thumbnail
- args = [Settings.CONVERT_PATH, file_path, "-limit", "thread", "1", "-background",
- "white", "-flatten", "-resize", "%dx%d" % (file_thumb_width, file_thumb_height)]
- if spoiler:
- args += ["-blur", "0x12", "-gravity", "center", "-fill", "rgba(0,0,0, .6)", "-draw", "rectangle 0,%d,%d,%d" % (
- (file_thumb_height/2)-10, file_thumb_width, (file_thumb_height/2)+7), "-fill", "white", "-annotate", "0", "Alerta de spoiler"]
- args += ["-quality", str(Settings.THUMB_QUALITY), file_thumb_path]
-
- # generate thumbnails
- logTime("Generating thumbnail")
- retcode = subprocess.call(args)
- if retcode != 0:
- os.remove(file_path)
- raise UserError, _("Thumbnail creation failure.") + ' ('+str(retcode)+')'
+ '-frames:v', '1', '-threads', '1', file_thumb_path])
+ else:
+ # use imagemagick to make thumbnail
+ args = [Settings.CONVERT_PATH, file_path, "-limit", "thread", "1", "-background",
+ "white", "-flatten", "-resize", "%dx%d" % (file_thumb_width, file_thumb_height)]
+ if spoiler:
+ args += ["-blur", "0x12", "-gravity", "center", "-fill", "rgba(0,0,0, .6)", "-draw", "rectangle 0,%d,%d,%d" % (
+ (file_thumb_height/2)-10, file_thumb_width, (file_thumb_height/2)+7), "-fill", "white",
+ "-font", "Liberation-Sans", "-annotate", "0", "Alerta de spoiler"]
+ args += ["-quality", str(Settings.THUMB_QUALITY), file_thumb_path]
+
+ # generate thumbnails
+ call_wrap(args)
+ except subprocess.CalledProcessError, e:
+ os.remove(file_path)
+ logging.error("Thumbnail creation failure: " + e.output)
+ raise UserError, _("Thumbnail creation failure.") + ' ('+str(e.returncode)+')'
# check if thumbnail was truly created
try:
@@ -293,6 +292,22 @@ def getImageInfo(data):
except ValueError:
pass
+ # handle WebP
+ if data[:4] == b'RIFF' and data[8:12] == b'WEBP':
+ chunk = data[12:]
+ if chunk[:4] == b"VP8 " and chunk[11:14] == b"\x9d\x01\x2a":
+ # Lossy VP8
+ w, h = struct.unpack("HH", chunk[14:18])
+ width = w & 0x3fff
+ height = h & 0x3fff
+ content_type = "image/webp"
+ elif chunk[:4] == b"VP8L":
+ # Lossless VP8
+ b0, b1, b2, b3 = struct.unpack("BBBB", chunk[9:13])
+ width = 1 + (((b1 & 0x3F) << 8) | b0)
+ height = 1 + (((b3 & 0xF) << 10) | (b2 << 2) | ((b1 & 0xC0) >> 6))
+ content_type = "image/webp"
+
# handle WebM
elif (size >= 4) and data.startswith("\x1A\x45\xDF\xA3"):
content_type = "video/webm"
@@ -371,6 +386,10 @@ def ffprobe_f(filename):
return json.loads(out)
+def call_wrap(args):
+ subprocess.check_output(args, stderr=subprocess.STDOUT)
+
+
def getThumbDimensions(width, height, maxsize):
"""
Calculate dimensions to use for a thumbnail with maximum width/height of