from librarian import get_resource
-def cover(author, title,
- width, height, background_color, background_img,
- author_top, author_margin_left, author_margin_right, author_lineskip, author_color, author_font, author_shadow,
- title_top, title_margin_left, title_margin_right, title_lineskip, title_color, title_font, title_shadow,
- logo_width, logo_bottom
- ):
+class Cover(object):
+ width = 600
+ height = 800
+ background_color = '#fff'
+ background_img = None
+
+ author_top = 100
+ author_margin_left = 20
+ author_margin_right = 20
+ author_lineskip = 40
+ author_color = '#000'
+ author_shadow = None
+ author_font = None
+
+ title_top = 100
+ title_margin_left = 20
+ title_margin_right = 20
+ title_lineskip = 54
+ title_color = '#000'
+ title_shadow = None
+ title_font = None
+
+ logo_bottom = None
+ logo_width = None
+
+ format = 'JPEG'
+
+
+ exts = {
+ 'JPEG': 'jpg',
+ 'PNG': 'png',
+ }
+
+ mime_types = {
+ 'JPEG': 'image/jpeg',
+ 'PNG': 'image/png',
+ }
+
+
+ @staticmethod
def draw_centered_text(text, img, font, margin_left, width, pos_y, lineskip, color, shadow_color):
if shadow_color:
shadow_img = Image.new('RGBA', img.size)
return pos_y
- img = Image.new('RGB', (width, height), background_color)
+ def __init__(self, author='', title=''):
+ self.author = author
+ self.title = title
+
+ def pretty_author(self):
+ return self.author
+
+ def pretty_title(self):
+ return self.title
+
+ def image(self):
+ img = Image.new('RGB', (self.width, self.height), self.background_color)
+
+ if self.background_img:
+ background = Image.open(self.background_img)
+ img.paste(background, None, background)
+ del background
+
+ # WL logo
+ if self.logo_width:
+ logo = Image.open(get_resource('res/wl-logo.png'))
+ logo = logo.resize((self.logo_width, logo.size[1] * self.logo_width / logo.size[0]))
+ img.paste(logo, ((self.width - self.logo_width) / 2, img.size[1] - logo.size[1] - self.logo_bottom))
+
+ author_font = self.author_font or ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 30)
+ title_y = self.draw_centered_text(self.pretty_author(), img, author_font,
+ self.author_margin_left, self.width - self.author_margin_left - self.author_margin_right, self.author_top,
+ self.author_lineskip, self.author_color, self.author_shadow) + self.title_top
+ title_font = self.title_font or ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 40)
+ self.draw_centered_text(self.pretty_title(), img, title_font,
+ self.title_margin_left, self.width - self.title_margin_left - self.title_margin_right, title_y,
+ self.title_lineskip, self.title_color, self.title_shadow)
+
+ return img
+
+ def mime_type(self):
+ return self.mime_types[self.format]
+
+ def ext(self):
+ return self.exts[self.format]
+
+ def save(self, *args, **kwargs):
+ return self.image().save(*args, format=self.format, **kwargs)
+
+
+
+class VirtualoCover(Cover):
+ width = 600
+ height = 730
+ author_top = 73
+ title_top = 73
+ logo_bottom = 0
+ logo_width = 300
+
+
+class PrestigioCover(Cover):
+ width = 580
+ height = 783
+ background_img = get_resource('res/cover-prestigio.png')
- if background_img:
- background = Image.open(background_img)
- img.paste(background, None, background)
- del background
+ author_top = 446
+ author_margin_left = 118
+ author_margin_right = 62
+ author_lineskip = 60
+ author_color = '#fff'
+ author_shadow = '#000'
+ author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50)
- # WL logo
- if logo_width:
- logo = Image.open(get_resource('res/wl-logo.png'))
- logo = logo.resize((logo_width, logo.size[1] * logo_width / logo.size[0]))
- img.paste(logo, ((width - logo_width) / 2, img.size[1] - logo.size[1] - logo_bottom))
+ title_top = 0
+ title_margin_left = 118
+ title_margin_right = 62
+ title_lineskip = 60
+ title_color = '#fff'
+ title_shadow = '#000'
+ title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50)
- title_y = draw_centered_text(author, img, author_font,
- author_margin_left, width - author_margin_left - author_margin_right, author_top,
- author_lineskip, author_color, author_shadow) + title_top
- draw_centered_text(title, img, title_font,
- title_margin_left, width - title_margin_left - title_margin_right, title_y,
- title_lineskip, title_color, title_shadow)
+ def pretty_title(self):
+ return u"„%s”" % self.title
- return img
+class BookotekaCover(Cover):
+ width = 2140
+ height = 2733
+ background_img = get_resource('res/cover-bookoteka.png')
-def virtualo_cover(author, title):
- return cover(author, title,
- 600, 730, '#fff', None,
- 73, 20, 20, 40, '#000', ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 30), None,
- 73, 20, 20, 54, '#000', ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 40), None,
- 300, 0
- )
+ author_top = 480
+ author_margin_left = 307
+ author_margin_right = 233
+ author_lineskip = 156
+ author_color = '#d9d919'
+ author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 130)
-def prestigio_cover(author, title):
- return cover(author, u"„%s”" % title,
- 580, 783, '#fff', get_resource('res/cover-prestigio.png'),
- 446, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000',
- 0, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000',
- None, None
- )
+ title_top = 400
+ title_margin_left = 307
+ title_margin_right = 233
+ title_lineskip = 168
+ title_color = '#d9d919'
+ title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 140)
+ format = 'PNG'
import sys
-from librarian import XMLNamespace, RDFNS, DCNS, WLNS, NCXNS, OPFNS, NoDublinCore
+from librarian import XMLNamespace, RDFNS, DCNS, WLNS, NCXNS, OPFNS, XHTMLNS, NoDublinCore
from librarian.dcparser import BookInfo
from librarian import functions, get_resource
def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False,
- sample=None, cover_fn=None, flags=None):
+ sample=None, cover=None, flags=None):
""" produces a EPUB file
provider: a DocProvider
output_dir: path to directory to save output file to; either this or output_file must be present
make_dir: writes output to <output_dir>/<author>/<slug>.epub instead of <output_dir>/<slug>.epub
sample=n: generate sample e-book (with at least n paragraphs)
- cover_fn: function(author, title) -> cover image
+ cover: a cover.Cover object
flags: less-advertising,
"""
manifest = opf.find('.//' + OPFNS('manifest'))
spine = opf.find('.//' + OPFNS('spine'))
- if cover_fn:
- cover = StringIO()
- cover_fn(book_info.author.readable(), book_info.title).save(cover, format='JPEG')
- zip.writestr(os.path.join('OPS', 'cover.jpg'), cover.getvalue())
- del cover
- zip.writestr('OPS/cover.html', open(get_resource('epub/cover.html')).read())
+ if cover:
+ cover_file = StringIO()
+ c = cover(book_info.author.readable(), book_info.title)
+ c.save(cover_file)
+ c_name = 'cover.%s' % c.ext()
+ zip.writestr(os.path.join('OPS', c_name), cover_file.getvalue())
+ del cover_file
+
+ cover_tree = etree.parse(get_resource('epub/cover.html'))
+ cover_tree.find('//' + XHTMLNS('img')).set('src', c_name)
+ zip.writestr('OPS/cover.html', etree.tostring(
+ cover_tree, method="html", pretty_print=True))
+
manifest.append(etree.fromstring(
'<item id="cover" href="cover.html" media-type="application/xhtml+xml" />'))
manifest.append(etree.fromstring(
- '<item id="cover-image" href="cover.jpg" media-type="image/jpeg" />'))
+ '<item id="cover-image" href="%s" media-type="%s" />' % (c_name, c.mime_type())))
spine.insert(0, etree.fromstring('<itemref idref="cover" />'))
opf.getroot()[0].append(etree.fromstring('<meta name="cover" content="cover-image"/>'))
opf.getroot().append(etree.fromstring('<guide><reference href="cover.html" type="cover" title="Okładka"/></guide>'))
product_elem[4][0][1].text = utf_trunc(info.author.last_name, 100)
xml.append(product_elem)
- cover.virtualo_cover(
+ cover.VirtualoCover(
u' '.join(info.author.first_names + (info.author.last_name,)),
info.title
).save(os.path.join(outfile_dir, slug+'.jpg'))
pass
outfile = os.path.join(output_dir, slug + '.epub')
epub.transform(provider, file_path=main_input, output_file=outfile,
- cover_fn=cover.prestigio_cover, flags=('less-advertising',))
+ cover=cover.PrestigioCover, flags=('less-advertising',))
+ except ParseError, e:
+ print '%(file)s:%(name)s:%(message)s' % {
+ 'file': main_input,
+ 'name': e.__class__.__name__,
+ 'message': e.message
+ }
+
+
+def bookoteka(filenames, output_dir, verbose):
+ try:
+ for main_input in input_filenames:
+ if options.verbose:
+ print main_input
+ path, fname = os.path.realpath(main_input).rsplit('/', 1)
+ provider = DirDocProvider(path)
+ slug, ext = os.path.splitext(fname)
+
+ if output_dir != '':
+ try:
+ os.makedirs(output_dir)
+ except:
+ pass
+ outfile = os.path.join(output_dir, slug + '.epub')
+ epub.transform(provider, file_path=main_input, output_file=outfile,
+ cover=cover.BookotekaCover)
except ParseError, e:
print '%(file)s:%(name)s:%(message)s' % {
'file': main_input,
help='print status messages to stdout')
parser.add_option('-O', '--output-dir', dest='output_dir', metavar='DIR', default='',
help='specifies the directory for output')
+ parser.add_option('--bookoteka', action='store_true', dest='bookoteka', default=False,
+ help='prepare files for Bookoteka')
parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False,
help='prepare files for Virtualo API')
parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False,
- help='prepare files for prestigio')
+ help='prepare files for Prestigio')
options, input_filenames = parser.parse_args()
parser.print_help()
exit(1)
+ if options.bookoteka:
+ bookoteka(input_filenames, options.output_dir, options.verbose)
if options.virtualo:
virtualo(input_filenames, options.output_dir, options.verbose)
if options.prestigio: