From 82df6efee44f3d8db3e017644c15baf7d9bee0c2 Mon Sep 17 00:00:00 2001 From: j Date: Sat, 16 Nov 2019 16:45:31 +0100 Subject: [PATCH] multiline support --- oxtimelines/timeline.py | 46 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/oxtimelines/timeline.py b/oxtimelines/timeline.py index c426e19..250c001 100644 --- a/oxtimelines/timeline.py +++ b/oxtimelines/timeline.py @@ -4,6 +4,8 @@ from __future__ import division, print_function, absolute_import from glob import glob from time import time +import multiprocessing +from multiprocessing.pool import ThreadPool try: from PIL import Image except: @@ -40,6 +42,15 @@ class Timelines(): self.modes = modes self.render_antialias = 'antialias' in modes self.render_slitscan = 'slitscan' in modes + if 'multiline' in modes: + info = ox.avinfo(video_files[0]) + self.render_multiline = info['video'][0]['width'] + self.output_h = sizes[0] + sizes = [info['video'][0]['height']] + sizes[1:] + self.render_multiline = True + self._pool = ThreadPool(multiprocessing.cpu_count()) + else: + self.render_multiline = False self.render_keyframes = 'keyframes' in modes self.render_audio = 'audio' in modes self.render_cuts = 'cuts' in modes @@ -191,6 +202,13 @@ class Timelines(): w = self.large_tile_last_w for mode in filter(lambda x: x in ['antialias', 'slitscan', 'cuts'], self.modes): self.large_tile_image[mode] = Image.new('RGB', (w, self.large_tile_h)) + if self.render_multiline: + self.large_tile_image['multiline'] = {} + t0 = time() + #print('create images') + for line in range(self.render_multiline): + self.large_tile_image['multiline'][line] = Image.new('RGB', (w, self.large_tile_h)) + #print('create images done', time()-t0) if self.render_data: self.large_tile_image['data'] = Image.new('RGB', (w * 8, 8)) paste = (large_tile_x, 0) @@ -208,6 +226,11 @@ class Timelines(): if self.render_slitscan: crop = (self.frame_center, 0, self.frame_center + 1, self.large_tile_h) self.large_tile_image['slitscan'].paste(frame_image.crop(crop), paste) + if self.render_multiline: + def chrop_line(line): + crop = (line, 0, line + 1, self.large_tile_h) + self.large_tile_image['multiline'][line].paste(frame_image.crop(crop), paste) + self._pool.map(chrop_line, list(range(self.render_multiline))) self.log and self.profiler.unset_task() # render data tile @@ -266,7 +289,7 @@ class Timelines(): # save large tile self.log and self.profiler.set_task('_video_callback()') if large_tile_x == self.large_tile_w - 1 or self.is_last_frame: - for mode in filter(lambda x: x in ['antialias', 'slitscan', 'cuts', 'data'], self.modes): + for mode in filter(lambda x: x in ['antialias', 'slitscan', 'cuts', 'data', 'multiline'], self.modes): self._save_tile(mode, self.large_tile_i) if self.render_antialias: self._save_full_tile_image('antialias') @@ -431,10 +454,23 @@ class Timelines(): if mode != 'keyframeswide' or self.render_wide_tiles: height = 8 if mode == 'data' else self.large_tile_h type = 'png' if mode == 'data' else 'jpg' - tile_file = '%stimeline%s%dp%d.%s' % ( - self.tile_path, mode, height, index, type - ) - self.large_tile_image[mode].save(tile_file) + if mode == 'multiline': + def save_line(line): + tile_file = '%s%s/timeline%s%dp%d.%s' % ( + self.tile_path, line, 'slitscan', self.output_h, index, type + ) + ox.makedirs(os.path.dirname(tile_file)) + width = self.large_tile_image[mode][line].size[1] + img = self.large_tile_image[mode][line] + if self.output_h != self.large_tile_image[mode][line].size[0]: + img = img.resize((width, self.output_h), Image.BICUBIC) + img.save(tile_file) + self._pool.map(save_line, list(range(self.render_multiline))) + else: + tile_file = '%stimeline%s%dp%d.%s' % ( + self.tile_path, mode, height, index, type + ) + self.large_tile_image[mode].save(tile_file) if self.log: print(tile_file) if self.render_small_tiles and mode in ['antialias', 'slitscan', 'keyframeswide', 'audio']: