diff --git a/README b/README index 2f99ec1..91f2f19 100644 --- a/README +++ b/README @@ -1,27 +1,13 @@ -oxtools +oxtimeline - create timeline from video depends on gstreamer 0.10.30 or newer on ubuntu 10.04 you need sudo add-apt-repository ppa:gstreamer-developers/ppa -Tools - oxframe - C version in its own repos at http://code.0x2620.org/oxframe/ now - oxtimeline - create timeline from video - oxposter - render 0xdb poster - oxicon - extract icon from frame - Python API - import oxgst + import oxtimeline - video = oxgst.Video(videoFile) - video.frame(pos_in_nanoseconds) - >>> - - timeline = oxgst.Timeline(videoFile) + timeline = oxtimeline.Timeline(videoFile) timeline.extract(timeline_prefix, width, height) diff --git a/bin/oxicon b/bin/oxicon deleted file mode 100755 index 6e30b67..0000000 --- a/bin/oxicon +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 -import os -import sys - -root = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..') -if os.path.exists(os.path.join(root, 'oxgst')): - sys.path.insert(0, root) - -from oxposter import icon - -if __name__ == "__main__": - icon.main() - diff --git a/bin/oxposter b/bin/oxposter deleted file mode 100755 index 2ea45bb..0000000 --- a/bin/oxposter +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 -import os -import sys - -root = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..') -if os.path.exists(os.path.join(root, 'oxgst')): - sys.path.insert(0, root) - -from oximage import oxdb_poster - -if __name__ == "__main__": - oxdb_poster.main() - diff --git a/bin/oxtimeline b/bin/oxtimeline index 84df49e..78c317c 100755 --- a/bin/oxtimeline +++ b/bin/oxtimeline @@ -10,11 +10,11 @@ from optparse import OptionParser import Image root = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..') -if os.path.exists(os.path.join(root, 'oxgst')): +if os.path.exists(os.path.join(root, 'oxtimeline')): sys.path.insert(0, root) -import oxgst +import oxtimeline if __name__ == '__main__': parser = OptionParser() @@ -31,9 +31,9 @@ if __name__ == '__main__': timeline = oxgst.Timeline(opts.input) timeline.extract(opts.prefix, opts.width, opts.height) - oxgst.timeline.createTimelineMultiline(opts.prefix) - oxgst.timeline.makeTiles(opts.prefix, 16, 3600) - oxgst.timeline.makeTimelineOverview(opts.prefix, 1920, height=16) - oxgst.timeline.makeTimelineOverview(opts.prefix, 1920, height=64) + oxtimeline.createTimelineMultiline(opts.prefix) + oxtimeline.makeTiles(opts.prefix, 16, 3600) + oxtimeline.makeTimelineOverview(opts.prefix, 1920, height=16) + oxtimeline.makeTimelineOverview(opts.prefix, 1920, height=64) diff --git a/oximage/__init__.py b/oximage/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/oximage/data/.DS_Store b/oximage/data/.DS_Store deleted file mode 100644 index ef708fb..0000000 Binary files a/oximage/data/.DS_Store and /dev/null differ diff --git a/oximage/data/DejaVuSansCondensedBold.ttf b/oximage/data/DejaVuSansCondensedBold.ttf deleted file mode 100644 index cb48a02..0000000 Binary files a/oximage/data/DejaVuSansCondensedBold.ttf and /dev/null differ diff --git a/oximage/data/icon.mask.png b/oximage/data/icon.mask.png deleted file mode 100644 index 4e4d636..0000000 Binary files a/oximage/data/icon.mask.png and /dev/null differ diff --git a/oximage/data/logo.poster.png b/oximage/data/logo.poster.png deleted file mode 100644 index bd1cfe9..0000000 Binary files a/oximage/data/logo.poster.png and /dev/null differ diff --git a/oximage/imagetools.py b/oximage/imagetools.py deleted file mode 100644 index 092ed35..0000000 --- a/oximage/imagetools.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -from __future__ import division -import os -import Image -import ImageDraw -from ox.image import drawText, wrapText - -data_root = os.path.join(os.path.dirname(__file__), 'data') - -def render_list_icon(frames, icon): - icon_width = 256 - icon_height = 256 - icon_image = Image.new('RGBA', (icon_width, icon_height)) - frame_height = icon_height / 4 - frame_ratio = 4 / 3 - frame_width = int(round(frame_height * frame_ratio)) - for i, frame in enumerate(frames): - frame_image = Image.open(frame) - frame_image_ratio = frame_image.size[0] / frame_image.size[1] - frame_width_ = frame_width + (1 if i % 2 == 1 else 0) - if frame_ratio < frame_image_ratio: - frame_image = frame_image.resize((int(frame_height * frame_image_ratio), frame_height), Image.ANTIALIAS) - left = int((frame_image.size[0] - frame_width_) / 2) - frame_image = frame_image.crop((left, 0, left + frame_width_, frame_height)) - else: - frame_image = frame_image.resize((frame_width_, int(frame_width_ / frame_image_ratio)), Image.ANTIALIAS) - top = int((frame_image.size[1] - frame_height) / 2) - frame_image = frame_image.crop((0, top, frame_width_, top + frame_height)) - icon_image.paste(frame_image, (i % 3 * frame_width + (1 if i % 2 == 2 else 0), int(i / 3) * frame_height)) - mask_image = Image.open(ox.path.join(data_root, 'icon.mask.png')) - mask_image = mask_image.resize((icon_width, icon_height)) - icon_image.putalpha(mask_image) - icon_image.save(icon) - - -def render_movie_icon(frame, timeline, icon): - icon_width = 256 - icon_height = 256 - icon_image = Image.new('RGBA', (icon_width, icon_height)) - frame_width = icon_width - frame_ratio = 4 / 3 - frame_height = int(round(frame_width / frame_ratio)) - frame_image = Image.open(frame) - frame_image_ratio = frame_image.size[0] / frame_image.size[1] - if frame_ratio < frame_image_ratio: - frame_image = frame_image.resize((int(frame_height * frame_image_ratio), frame_height), Image.ANTIALIAS) - left = int((frame_image.size[0] - frame_width) / 2) - frame_image = frame_image.crop((left, 0, left + frame_width, frame_height)) - else: - frame_image = frame_image.resize((frame_width, int(frame_width / frame_image_ratio)), Image.ANTIALIAS) - top = int((frame_image.size[1] - frame_height) / 2) - frame_image = frame_image.crop((0, top, frame_width, top + frame_height)) - icon_image.paste(frame_image, (0, 0)) - timeline_image = Image.open(timeline) - timeline_image = timeline_image.resize((icon_width, 64), Image.ANTIALIAS) - icon_image.paste(timeline_image, (0, icon_height - 64)) - mask_image = Image.open(ox.path.join(data_root, 'icon.mask.png')) - mask_image = mask_image.resize((icon_width, icon_height)) - icon_image.putalpha(mask_image) - icon_image.save(icon) - -def render_oxdb_poster(title, director, year, series, oxdb_id, imdb_id, frame, timeline, poster): - def get_oxdb_color(oxdb_id, series=False): - i = int(round((int(oxdb_id[2:10], 16) * 762 / pow(2, 32)))) - if i < 127: - color = (127, i, 0) - elif i < 254: - color = (254 - i, 127, 0) - elif i < 381: - color = (0, 127, i - 254) - elif i < 508: - color = (0, 508 - i, 127) - elif i < 635: - color = (i - 508, 0, 127) - else: - color = (127, 0, 762 - i) - if series: - color = tuple(map(lambda x: x + 128, color)) - return color - - poster_width = 640 - poster_height = 1024 - poster_ratio = poster_width / poster_height - poster_image = Image.new('RGB', (poster_width, poster_height)) - draw = ImageDraw.Draw(poster_image) - font_file = os.path.join(data_root, 'DejaVuSansCondensedBold.ttf') - font_size = { - 'small': 28, - 'large': 42, - } - - # frame - if frame: - frame_width = poster_width - frame_ratio = 4 / 3 - frame_height = int(round(frame_width / frame_ratio)) - frame_image = Image.open(frame) - frame_image_ratio = frame_image.size[0] / frame_image.size[1] - if frame_ratio < frame_image_ratio: - frame_image = frame_image.resize((int(frame_height * frame_image_ratio), frame_height), Image.ANTIALIAS) - left = int((frame_image.size[0] - frame_width) / 2) - frame_image = frame_image.crop((left, 0, left + frame_width, frame_height)) - else: - frame_image = frame_image.resize((frame_width, int(frame_width / frame_image_ratio)), Image.ANTIALIAS) - top = int((frame_image.size[1] - frame_height) / 2) - frame_image = frame_image.crop((0, top, frame_width, top + frame_height)) - poster_image.paste(frame_image, (0, 0)) - - # timeline - timeline_width = poster_width - timeline_height = 64 - timeline_image = Image.open(timeline) - timeline_image = timeline_image.resize((timeline_width, timeline_height), Image.ANTIALIAS) - poster_image.paste(timeline_image, (0, frame_height)) - - # text - text_width = poster_width - text_height = poster_height - frame_height - timeline_height - text_top = frame_height + timeline_height - text_bottom = text_top + text_height - text_margin = 16 - text_color = get_oxdb_color(oxdb_id, series) - font_color = tuple(map(lambda x: x - 128 if series else x + 128, text_color)) - draw.rectangle([(0, text_top), (text_width, text_bottom)], fill=text_color) - offset_top = text_top + text_margin - if not director: - title_max_lines = 7 - else: - title_max_lines = min(len(wrapText(title, text_width - 2 * text_margin, 0, font_file, font_size['large'])), 6) - director_max_lines = 9 - int((title_max_lines * 3 - 1) / 2) - if director: - lines = wrapText(director, text_width - 2 * text_margin, director_max_lines, font_file, font_size['small']) - for i, line in enumerate(lines): - size = drawText(poster_image, (text_margin, offset_top), line, font_file, font_size['small'], font_color) - offset_top += font_size['small'] + 2 - offset_top += size[1] - font_size['small'] + text_margin / 2 - lines = wrapText(title, text_width - 2 * text_margin, title_max_lines, font_file, font_size['large']) - for i, line in enumerate(lines): - size = drawText(poster_image, (text_margin, offset_top + 5), line, font_file, font_size['large'], font_color) - offset_top += font_size['large'] + 3 - offset_top += size[1] - font_size['small'] + text_margin / 2 - if year: - drawText(poster_image, (text_margin, offset_top), year, font_file, font_size['small'], font_color) - drawText(poster_image, (text_margin, text_bottom - text_margin - font_size['large'] + 2), oxdb_id, font_file, font_size['large'], font_color) - - # logo - logo_height = 32 - logo_image = Image.open(os.path.join(data_root, 'logo.poster.png')) - logo_width = int(round(logo_height * logo_image.size[0] / logo_image.size[1])) - logo_image = logo_image.resize((logo_width, logo_height), Image.ANTIALIAS) - logo_left = text_width - text_margin - logo_width - logo_top = text_bottom - text_margin - logo_height - for y in range(logo_height): - for x in range(logo_width): - poster_color = poster_image.getpixel((logo_left + x, logo_top + y)) - logo_color = logo_image.getpixel((x, y))[0] - alpha = logo_image.getpixel((x, y))[3] - if series: - poster_color = tuple(map(lambda x: x - (logo_color - 16) * alpha / 255, poster_color)) - else: - poster_color = tuple(map(lambda x: x + (logo_color - 16) * alpha / 255, poster_color)) - poster_image.putpixel((logo_left + x, logo_top + y), poster_color) - - poster_image.save(poster) - -def render_padma_poster(id, title, frame, timeline, poster): - poster_width = 640 - poster_height = 1024 - poster_ratio = poster_width / poster_height - poster_color = (255, 255, 0) - poster_image = Image.new('RGB', (poster_width, poster_height)) - font_file = os.path.join(data_root, 'DejaVuSansCondensedBold.ttf') - font_size = 48 - - # timeline - timeline_height = 64 - timeline_lines = 16 - timeline_image = Image.open(timeline) - timeline_image = timeline_image.resize((10240, timeline_height), Image.ANTIALIAS) - for i in range(timeline_lines): - line_image = timeline_image.crop((i * poster_width, 0, (i + 1) * poster_width, 64)) - poster_image.paste(line_image, (0, i * timeline_height)) - - # id - text = 'Pad.ma/' + id - text_image = Image.new('RGB', (1, 1)) - text_size = drawText(text_image, (0, 0), text, font_file, font_size, poster_color) - text_width = poster_width - text_height = timeline_height - text_left = int((poster_width - text_width) / 2) - text_top = 14 * timeline_height - for y in range(text_top, text_top + text_height): - for x in range(text_left, text_left + text_width): - if y < text_top + 4 or y >= text_top + text_height - 4: - poster_image.putpixel((x, y), poster_color) - else: - pixel = list(poster_image.getpixel((x, y))) - for c in range(3): - pixel[c] = (pixel[c] + poster_color[c]) / 4 - poster_image.putpixel((x, y), tuple(pixel)) - drawText(poster_image, ((poster_width - text_size[0]) / 2, text_top + (text_height - text_size[1]) / 2), text, font_file, font_size, poster_color) - poster_image.save(poster) diff --git a/oximage/list_icon.py b/oximage/list_icon.py deleted file mode 100644 index 4bb39f9..0000000 --- a/oximage/list_icon.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -import sys -from optparse import OptionParser -from imagetools import render_list_icon - -def main(): - parser = OptionParser() - parser.add_option('-f', '--frames', dest='frames', help='Poster frames (image files to be read)', default='') - parser.add_option('-i', '--icon', dest='icon', help='Icon (image file to be written)') - (options, args) = parser.parse_args() - if options.icon == None: - parser.print_help() - sys.exit() - - frames = options.frames.replace(', ', ',').split(',') - - render_list_icon(frames, opt.icon) diff --git a/oximage/movie_icon.py b/oximage/movie_icon.py deleted file mode 100644 index de6a56a..0000000 --- a/oximage/movie_icon.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -import sys -from optparse import OptionParser -from imagetools import render_movie_icon - -def main(): - parser = OptionParser() - parser.add_option('-f', '--frame', dest='frame', help='Poster frame (image file to be read)') - parser.add_option('-l', '--timeline', dest='timeline', help='Timeline (image file to be read)') - parser.add_option('-i', '--icon', dest='icon', help='Icon (image file to be written)') - (options, args) = parser.parse_args() - if options.icon == None: - parser.print_help() - sys.exit() - render_movie_icon(opt.frame, opt.timeline, opt.icon) diff --git a/oximage/oxdb_poster.py b/oximage/oxdb_poster.py deleted file mode 100644 index 5744b93..0000000 --- a/oximage/oxdb_poster.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -import sys -from optparse import OptionParser -from imagetools import render_oxdb_poster - -def main(): - parser = OptionParser() - parser.add_option('-o', '--oxdbid', dest='oxdb_id', help='0xDB Id') - parser.add_option('-i', '--imdbid', dest='imdb_id', help='IMDb Id') - parser.add_option('-t', '--title', dest='title', help='Title') - parser.add_option('-d', '--director', dest='director', help='Director(s)', default='') - parser.add_option('-y', '--year', dest='year', help='Year') - parser.add_option('-s', '--series', dest='series', help='Movie is an episode of a series', action='store_true') - parser.add_option('-f', '--frame', dest='frame', help='Poster frame (image file to be read)') - parser.add_option('-l', '--timeline', dest='timeline', help='Timeline (image file to be read)') - parser.add_option('-p', '--poster', dest='poster', help='Poster (image file to be written)') - (options, args) = parser.parse_args() - - if None in (options.oxdb_id, options.title, options.poster): - parser.print_help() - sys.exit() - - opt = {} - for key in ('oxdb_id', 'imdb_id', 'title', 'director', 'year', 'series', 'frame', 'timeline', 'poster'): - opt[key] = getattr(options, key) - - opt['title'] = opt['title'].decode('utf-8') - opt['director'] = opt['director'].decode('utf-8') - - render_oxdb_poster(**opt) diff --git a/oximage/padma_poster.py b/oximage/padma_poster.py deleted file mode 100644 index b133aaf..0000000 --- a/oximage/padma_poster.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# vi:si:et:sw=4:sts=4:ts=4 - -import sys -from optparse import OptionParser -from imagetools import render_padma_poster - -def main(): - parser = OptionParser() - parser.add_option('-i', '--id', dest='id', help='Pad.ma Id') - parser.add_option('-t', '--title', dest='title', help='Title', default='') - parser.add_option('-f', '--frame', dest='frame', help='Poster frame (image file to be read)') - parser.add_option('-l', '--timeline', dest='timeline', help='Timeline (image file to be read)') - parser.add_option('-p', '--poster', dest='poster', help='Poster (image file to be written)') - (options, args) = parser.parse_args() - if None in (options.id, options.poster): - parser.print_help() - sys.exit() - opt = {} - for key in ('id', 'title', 'frame', 'timeline', 'poster'): - opt[key] = getattr(options, key) - - opt['title'] = opt['title'].decode('utf-8') - - render_padma_poster(**opt) diff --git a/oxgst/__init__.py b/oxtimeline/__init__.py similarity index 61% rename from oxgst/__init__.py rename to oxtimeline/__init__.py index 7690bf9..5b7bb77 100644 --- a/oxgst/__init__.py +++ b/oxtimeline/__init__.py @@ -1,7 +1,6 @@ -import timeline +from timeline import * import video import info from video import Video -from timeline import Timeline from info import Info diff --git a/oxgst/imagesink.py b/oxtimeline/imagesink.py similarity index 100% rename from oxgst/imagesink.py rename to oxtimeline/imagesink.py diff --git a/oxgst/info.py b/oxtimeline/info.py similarity index 100% rename from oxgst/info.py rename to oxtimeline/info.py diff --git a/oxgst/singledecodebin.py b/oxtimeline/singledecodebin.py similarity index 100% rename from oxgst/singledecodebin.py rename to oxtimeline/singledecodebin.py diff --git a/oxgst/timeline.py b/oxtimeline/timeline.py similarity index 100% rename from oxgst/timeline.py rename to oxtimeline/timeline.py diff --git a/oxgst/video.py b/oxtimeline/video.py similarity index 100% rename from oxgst/video.py rename to oxtimeline/video.py diff --git a/setup.py b/setup.py index 63d2195..2a6f46c 100644 --- a/setup.py +++ b/setup.py @@ -5,22 +5,17 @@ import sys from glob import glob from distutils.core import setup -setup(name="oxtools", +setup(name="oxtimeline", scripts = [ - 'bin/oxposter', 'bin/oxtimeline', ], packages = [ - 'oxgst', - 'oximage', + 'oxtimeline', ], - package_data = { - 'oximage': ['data/*.png', 'data/*.ttf'], - }, version="0.1", author="j", author_email="code@0xdb.org", - description="commandline tools and python api to extract information from movies", + description="extract timeline from videos", classifiers = [ 'Development Status :: 4 - Beta', 'Operating System :: OS Independent',