forked from 0x2620/pandora
join timelines for multipart
This commit is contained in:
parent
ea13a9db8b
commit
b2c94dfafd
2 changed files with 105 additions and 2 deletions
|
@ -30,8 +30,9 @@ import ox.image
|
|||
import managers
|
||||
import utils
|
||||
import tasks
|
||||
from archive import extract
|
||||
from .timelines import join_timelines
|
||||
|
||||
from archive import extract
|
||||
from annotation.models import Annotation, Layer
|
||||
from person.models import get_name_sort
|
||||
from app.models import site_config
|
||||
|
@ -863,7 +864,8 @@ class Item(models.Model):
|
|||
def make_timeline(self):
|
||||
streams = self.streams()
|
||||
if len(streams) > 1:
|
||||
print "FIXME, needs to build timeline from parts"
|
||||
timelines = [s.timeline_prefix for s in self.streams()]
|
||||
join_timelines(timelines, self.timeline_prefix)
|
||||
|
||||
def make_poster(self, force=False):
|
||||
if not self.poster or force:
|
||||
|
|
101
pandora/item/timelines.py
Normal file
101
pandora/item/timelines.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from __future__ import division, with_statement
|
||||
|
||||
from glob import glob
|
||||
|
||||
import Image
|
||||
|
||||
def loadTimeline(timeline_prefix, height=64):
|
||||
files = sorted(glob('%s.%s.*.png' % (timeline_prefix, height)))
|
||||
f = Image.open(files[0])
|
||||
width = f.size[0]
|
||||
f = Image.open(files[-1])
|
||||
duration = f.size[0] + (len(files)-1)*width
|
||||
timeline = Image.new("RGB", (duration, height))
|
||||
pos = 0
|
||||
for f in files:
|
||||
part = Image.open(f)
|
||||
timeline.paste(part, (pos, 0, pos + part.size[0], height))
|
||||
pos += part.size[0]
|
||||
return timeline
|
||||
|
||||
def makeTiles(timeline_prefix, height=16, width=3600):
|
||||
files = glob('%s.64.*.png' % timeline_prefix)
|
||||
fps = 25
|
||||
part_step = 60
|
||||
output_width = width
|
||||
width = len(files) * part_step
|
||||
timeline = Image.new("RGB", (width, height))
|
||||
|
||||
pos = 0
|
||||
for f in sorted(files):
|
||||
part = Image.open(f)
|
||||
part_width = int(part.size[0] / fps)
|
||||
part = part.resize((part_width, height), Image.ANTIALIAS)
|
||||
timeline.paste(part, (pos, 0, pos+part_width, height))
|
||||
pos += part_width
|
||||
|
||||
timeline = timeline.crop((0, 0, pos, height))
|
||||
|
||||
pos = 0
|
||||
i = 0
|
||||
while pos < timeline.size[0]:
|
||||
end = min(pos+output_width, timeline.size[0])
|
||||
timeline.crop((pos, 0, end, timeline.size[1])).save('%s.%s.%04d.png' % (timeline_prefix, timeline.size[1], i))
|
||||
pos += output_width
|
||||
i += 1
|
||||
|
||||
def makeTimelineOverview(timeline_prefix, width, inpoint=0, outpoint=0, duration=-1, height=16):
|
||||
input_scale = 25
|
||||
|
||||
timeline_file = '%s.%s.png' % (timeline_prefix, height)
|
||||
if outpoint > 0:
|
||||
timeline_file = '%s.overview.%s.%d-%d.png' % (timeline_prefix, height, inpoint, outpoint)
|
||||
|
||||
timeline = loadTimeline(timeline_prefix)
|
||||
duration = timeline.size[0]
|
||||
|
||||
if inpoint<=0:
|
||||
inpoint = 0
|
||||
else:
|
||||
inpoint = inpoint * input_scale
|
||||
if outpoint<=0:
|
||||
outpoint = duration
|
||||
else:
|
||||
outpoint = outpoint * input_scale
|
||||
|
||||
timeline = timeline.crop((inpoint, 0, outpoint, timeline.size[1])).resize((width, height), Image.ANTIALIAS)
|
||||
timeline.save(timeline_file)
|
||||
|
||||
|
||||
def join_timelines(timelines, prefix):
|
||||
height = 64
|
||||
width = 1500
|
||||
|
||||
tiles = []
|
||||
for timeline in timelines:
|
||||
tiles += sorted(glob('%s.%s.*.png'%(timeline, height)))
|
||||
|
||||
tiles = map(Image.open, tiles)
|
||||
duration = sum(map(lambda i: i.size[0], tiles))
|
||||
timeline = Image.new("RGB", (duration, height))
|
||||
pos = 0
|
||||
for tile in tiles:
|
||||
timeline.paste(tile, (pos, 0, pos+tile.size[0], height))
|
||||
pos += tile.size[0]
|
||||
|
||||
pos = 0
|
||||
i = 0
|
||||
while pos < timeline.size[0]:
|
||||
end = min(pos+width, timeline.size[0])
|
||||
timeline_name = '%s.%s.%04d.png' % (prefix, timeline.size[1], i)
|
||||
timeline.crop((pos, 0, end, timeline.size[1])).save(timeline_name)
|
||||
pos += width
|
||||
i += 1
|
||||
|
||||
makeTiles(prefix, 16, 3600)
|
||||
makeTimelineOverview(prefix, 1920, height=16)
|
||||
makeTimelineOverview(prefix, 1920, height=64)
|
||||
|
Loading…
Reference in a new issue