2016-04-30 21:17:08 +00:00
|
|
|
import json
|
2016-04-09 19:41:10 +00:00
|
|
|
import subprocess
|
|
|
|
from szurubooru import errors
|
|
|
|
|
|
|
|
_SCALE_FIT_FMT = \
|
|
|
|
r'scale=iw*max({width}/iw\,{height}/ih):ih*max({width}/iw\,{height}/ih)'
|
|
|
|
|
|
|
|
class Image(object):
|
|
|
|
def __init__(self, content):
|
|
|
|
self.content = content
|
2016-04-30 21:17:08 +00:00
|
|
|
self._reload_info()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def width(self):
|
|
|
|
return self.info['streams'][0]['width']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def height(self):
|
|
|
|
return self.info['streams'][0]['height']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def frames(self):
|
|
|
|
return self.info['streams'][0]['nb_read_frames']
|
2016-04-09 19:41:10 +00:00
|
|
|
|
|
|
|
def resize_fill(self, width, height):
|
|
|
|
self.content = self._execute([
|
|
|
|
'-i', '-',
|
|
|
|
'-f', 'image2',
|
|
|
|
'-vf', _SCALE_FIT_FMT.format(width=width, height=height),
|
|
|
|
'-vframes', '1',
|
|
|
|
'-vcodec', 'png',
|
|
|
|
'-',
|
|
|
|
])
|
2016-04-30 21:17:08 +00:00
|
|
|
self._reload_info()
|
2016-04-09 19:41:10 +00:00
|
|
|
|
|
|
|
def to_png(self):
|
|
|
|
return self._execute([
|
|
|
|
'-i', '-',
|
|
|
|
'-f', 'image2',
|
|
|
|
'-vframes', '1',
|
|
|
|
'-vcodec', 'png',
|
|
|
|
'-',
|
|
|
|
])
|
|
|
|
|
|
|
|
def to_jpeg(self):
|
|
|
|
return self._execute([
|
|
|
|
'-i', '-',
|
|
|
|
'-f', 'image2',
|
|
|
|
'-vframes', '1',
|
|
|
|
'-vcodec', 'mjpeg',
|
|
|
|
'-',
|
|
|
|
])
|
|
|
|
|
2016-04-30 21:17:08 +00:00
|
|
|
def _execute(self, cli, program='ffmpeg'):
|
2016-04-09 19:41:10 +00:00
|
|
|
proc = subprocess.Popen(
|
2016-04-30 21:17:08 +00:00
|
|
|
[program, '-loglevel', '24'] + cli,
|
2016-04-09 19:41:10 +00:00
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stdin=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE)
|
|
|
|
out, err = proc.communicate(input=self.content)
|
|
|
|
if proc.returncode != 0:
|
2016-04-10 15:04:25 +00:00
|
|
|
raise errors.ProcessingError(
|
|
|
|
'Error while processing image.\n' + err.decode('utf-8'))
|
2016-04-09 19:41:10 +00:00
|
|
|
return out
|
2016-04-30 21:17:08 +00:00
|
|
|
|
|
|
|
def _reload_info(self):
|
|
|
|
self.info = json.loads(self._execute([
|
|
|
|
'-of', 'json',
|
|
|
|
'-select_streams', 'v',
|
|
|
|
'-show_streams',
|
|
|
|
'-count_frames',
|
|
|
|
'-i', '-',
|
|
|
|
], program='ffprobe').decode('utf-8'))
|
|
|
|
assert 'streams' in self.info
|
|
|
|
if len(self.info['streams']) != 1:
|
|
|
|
raise errors.ProcessingError('Multiple video streams detected.')
|