collect scripts in oxtools
This commit is contained in:
commit
4f9c3da160
22 changed files with 1297 additions and 0 deletions
0
oxposter/__init__.py
Normal file
0
oxposter/__init__.py
Normal file
BIN
oxposter/data/font.letter_gothic.bold.png
Normal file
BIN
oxposter/data/font.letter_gothic.bold.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
BIN
oxposter/data/font.monaco.bold.png
Normal file
BIN
oxposter/data/font.monaco.bold.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
BIN
oxposter/data/icon.mask.png
Normal file
BIN
oxposter/data/icon.mask.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
oxposter/data/logo.0xdb.large.png
Normal file
BIN
oxposter/data/logo.0xdb.large.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5 KiB |
BIN
oxposter/data/logo.0xdb.small.png
Normal file
BIN
oxposter/data/logo.0xdb.small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
54
oxposter/icon.py
Executable file
54
oxposter/icon.py
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from __future__ import division
|
||||
from optparse import OptionParser
|
||||
import os
|
||||
import sys
|
||||
|
||||
import Image
|
||||
import ImageDraw
|
||||
|
||||
data_root = os.path.join(os.path.dirname(__file__), 'data')
|
||||
|
||||
def main():
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option('-f', '--frame', dest='frame', help='Poster frame (image file to be read)')
|
||||
parser.add_option('-i', '--icon', dest='icon', help='Icon (image file to be written)')
|
||||
(opts, args) = parser.parse_args()
|
||||
if not opts.icon:
|
||||
parser.print_help()
|
||||
sys.exit()
|
||||
|
||||
iconSize = 1024
|
||||
iconImage = Image.new('RGBA', (iconSize, iconSize))
|
||||
|
||||
if opts.frame:
|
||||
frameImage = Image.open(opts.frame)
|
||||
if frameImage.size[0] >= frameImage.size[1]:
|
||||
frameWidth = int(frameImage.size[0] * iconSize / frameImage.size[1])
|
||||
frameImage = frameImage.resize((frameWidth, iconSize), Image.ANTIALIAS)
|
||||
crop = int((frameWidth - iconSize) / 2)
|
||||
frameImage = frameImage.crop((crop, 0, crop + iconSize, iconSize))
|
||||
else:
|
||||
frameHeight = int(frameImage.size[1] * iconSize / frameImage.size[0])
|
||||
frameImage = frameImage.resize((iconSize, frameHeight), Image.ANTIALIAS)
|
||||
crop = int((frameHeight - iconSize) / 2)
|
||||
frameImage = frameImage.crop((0, crop, iconSize, crop + iconSize))
|
||||
iconImage.paste(frameImage, (0, 0, iconSize, iconSize))
|
||||
else:
|
||||
draw = ImageDraw.Draw(iconImage)
|
||||
draw.polygon([(0, 0), (iconSize, 0), (iconSize, iconSize), (0, iconSize)], fill=(0, 0, 0))
|
||||
for y in range(iconSize):
|
||||
for x in range(iconSize):
|
||||
if int((x + y + 192) / 128) % 2:
|
||||
iconImage.putpixel((x, y), (32, 32, 32))
|
||||
|
||||
maskImage = Image.open(os.path.join(data_root, 'icon.mask.png'))
|
||||
iconImage.putalpha(maskImage)
|
||||
|
||||
iconImage.save(opts.icon)
|
||||
|
||||
|
||||
155
oxposter/poster.py
Normal file
155
oxposter/poster.py
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from __future__ import division
|
||||
from optparse import OptionParser
|
||||
import os
|
||||
import sys
|
||||
|
||||
import Image
|
||||
import ImageDraw
|
||||
from oxlib import truncateString, wrapString
|
||||
|
||||
data_root = os.path.join(os.path.dirname(__file__), 'data')
|
||||
|
||||
def main():
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option('-o', '--oxdb', dest='oxdb', help='0xdb Id')
|
||||
parser.add_option('-i', '--imdb', dest='imdb', help='IMDb Id')
|
||||
parser.add_option('-t', '--title', dest='title', help='Movie title')
|
||||
parser.add_option('-d', '--director', dest='director', help='Director(s)')
|
||||
parser.add_option('-f', '--frame', dest='frame', help='Poster frame (image file to be read)')
|
||||
parser.add_option('-p', '--poster', dest='poster', help='Poster (image file to be written)')
|
||||
parser.add_option('-r', '--restricted', action='store_true', dest='restricted', help='If set, poster frame will have overlay')
|
||||
(opts, args) = parser.parse_args()
|
||||
if None in (opts.oxdb, opts.title, opts.director, opts.poster):
|
||||
parser.print_help()
|
||||
sys.exit()
|
||||
opts.oxdb = '%s%s' % (opts.oxdb[:2], opts.oxdb[2:8].upper())
|
||||
opts.title = opts.title.decode('utf-8')
|
||||
opts.director = opts.director.decode('utf-8')
|
||||
if opts.imdb == None:
|
||||
id = opts.oxdb
|
||||
else:
|
||||
id = opts.imdb
|
||||
|
||||
posterWidth = 640
|
||||
posterHeight = 1024
|
||||
posterImage = Image.new('RGB', (posterWidth, posterHeight))
|
||||
fontImage = Image.open(os.path.join(data_root, 'font.monaco.bold.png'))
|
||||
oxdbImage = Image.open(os.path.join(data_root, 'logo.0xdb.large.png'))
|
||||
|
||||
# frame section
|
||||
frameHeight = int(posterWidth * 10 / 16)
|
||||
if opts.frame:
|
||||
frameImage = Image.open(opts.frame)
|
||||
if frameImage.size[0] / frameImage.size[1] > posterWidth / frameHeight:
|
||||
# poster frame is too wide
|
||||
frameImage = frameImage.resize((int(frameImage.size[0] * frameHeight / frameImage.size[1]), frameHeight), Image.ANTIALIAS)
|
||||
crop = int((frameImage.size[0] - posterWidth) / 2)
|
||||
frameImage = frameImage.crop((crop, 0, crop + posterWidth, frameHeight))
|
||||
else:
|
||||
# poster frame is not wide enough
|
||||
frameImage = frameImage.resize((posterWidth, int(frameImage.size[1] * posterWidth / frameImage.size[0])), Image.ANTIALIAS)
|
||||
crop = int((frameImage.size[1] - frameHeight) / 2)
|
||||
frameImage = frameImage.crop((0, crop, posterWidth, crop + frameHeight))
|
||||
posterImage.paste(frameImage, (0, 0, posterWidth, frameHeight))
|
||||
else:
|
||||
draw = ImageDraw.Draw(posterImage)
|
||||
draw.polygon([(0, 0), (posterWidth, 0), (posterWidth, frameHeight), (0, frameHeight)], fill=(0, 0, 0))
|
||||
for y in range(frameHeight):
|
||||
for x in range(posterWidth):
|
||||
if int((x + y + 54) / 128) % 2:
|
||||
posterImage.putpixel((x, y), (32, 32, 32))
|
||||
|
||||
# restricted
|
||||
if opts.restricted:
|
||||
for y in range(frameHeight):
|
||||
for x in range(posterWidth):
|
||||
if int((x + y + 54) / 128) % 2:
|
||||
rgb = posterImage.getpixel((x, y))
|
||||
rgb = (int(rgb[0] / 2) + 128, int(rgb[1] / 2), int(rgb[2] / 2))
|
||||
posterImage.putpixel((x, y), rgb)
|
||||
|
||||
# director section
|
||||
colorHeight = int(posterHeight / 2);
|
||||
draw = ImageDraw.Draw(posterImage)
|
||||
draw.polygon([(0, frameHeight), (posterWidth, frameHeight), (posterWidth, colorHeight), (0, colorHeight)], fill=(0, 0, 0))
|
||||
director = wrapString(opts.director, 36, '\n', True)
|
||||
while len(director.split('\n')) > 3:
|
||||
director = opts.director.split(', ')
|
||||
director.pop()
|
||||
opts.director = ', '.join(director)
|
||||
director = wrapString(opts.director, 36, '\n', True)
|
||||
posterMargin = 16
|
||||
imagewrite(posterImage, director, posterMargin, colorHeight - 8 - len(director.split('\n')) * 32, fontImage, 32)
|
||||
|
||||
# title section
|
||||
backgroundColor = getRGB(opts.oxdb)
|
||||
draw.polygon([(0, colorHeight), (posterWidth, colorHeight), (posterWidth, posterHeight), (0, posterHeight)], fill=backgroundColor)
|
||||
title = wrapString(opts.title, 24, '\n', True)
|
||||
lines = title.split('\n')
|
||||
if lines > 8:
|
||||
# following line commented out since the only known case
|
||||
# (http://0xdb.org/0071458) looks better without '...'
|
||||
# lines[7] = truncateString(lines[7] + '...', 24)
|
||||
title = '\n'.join(lines[:8])
|
||||
offset = -6
|
||||
posterimage = imagewrite(posterImage, title, posterMargin, colorHeight + posterMargin + offset, fontImage, 48)
|
||||
offset = 12
|
||||
posterimage = imagewrite(posterImage, id, posterMargin, posterHeight - posterMargin - 96 + offset, fontImage, 96)
|
||||
|
||||
# 0xdb logo
|
||||
x = posterWidth - oxdbImage.size[0] - posterMargin
|
||||
y = posterHeight - oxdbImage.size[1] - posterMargin
|
||||
for dy in range(oxdbImage.size[1]):
|
||||
for dx in range(oxdbImage.size[0]):
|
||||
rgb = posterImage.getpixel((x + dx, y + dy))
|
||||
bw = oxdbImage.getpixel((dx, dy))[0]
|
||||
rgb = tuple(map(lambda x : x + bw, rgb))
|
||||
posterImage.putpixel((x + dx, y + dy), rgb)
|
||||
|
||||
posterImage.save(opts.poster)
|
||||
|
||||
def getRGB(oxid):
|
||||
i = int(int(oxid[2:8], 16) * 762 / 16777216)
|
||||
if i < 127:
|
||||
return (127, i, 0)
|
||||
elif i < 254:
|
||||
return (254 - i, 127, 0)
|
||||
elif i < 381:
|
||||
return (0, 127, i - 254)
|
||||
elif i < 508:
|
||||
return (0, 508 - i, 127)
|
||||
elif i < 635:
|
||||
return (i - 508, 0, 127)
|
||||
else:
|
||||
return (127, 0, 762 - i)
|
||||
|
||||
def imagewrite(posterImage, string, left, top, fontImage, charHeight):
|
||||
x = left
|
||||
y = top
|
||||
fontWidth = int(fontImage.size[0] / 16)
|
||||
fontHeight = int(fontImage.size[1] / 16)
|
||||
charWidth = int(fontWidth * charHeight / fontHeight)
|
||||
for i in range(len(string)):
|
||||
char = string[i:i+1]
|
||||
if char == '\n':
|
||||
x = left
|
||||
y += charHeight
|
||||
else:
|
||||
ascii = ord(char)
|
||||
fontLeft = (ascii % 16) * fontWidth
|
||||
fontTop = int(ascii / 16) * fontHeight
|
||||
letterImage = fontImage.crop((fontLeft, fontTop, fontLeft + fontWidth, fontTop + fontHeight))
|
||||
letterImage = letterImage.resize((charWidth, charHeight), Image.ANTIALIAS)
|
||||
for dy in range(charHeight):
|
||||
for dx in range(charWidth):
|
||||
rgb = posterImage.getpixel((x + dx, y + dy))
|
||||
bw = int(letterImage.getpixel((dx, dy))[0] / 2)
|
||||
rgb = tuple(map(lambda x : x + bw, rgb))
|
||||
posterImage.putpixel((x + dx, y + dy), rgb)
|
||||
x += charWidth
|
||||
return posterImage
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue