From 51b9dc0babf62ea90091eeb5bafec66e39aab910 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 2 Feb 2011 13:11:51 +0100 Subject: [PATCH 1/1] Booktoteka packager and some cover refactoring --- librarian/cover.py | 169 +++++++++++++++++++++++------- librarian/epub.py | 27 +++-- librarian/epub/cover.html | 2 +- librarian/res/cover-bookoteka.png | Bin 0 -> 56260 bytes scripts/book2partner | 35 ++++++- 5 files changed, 182 insertions(+), 51 deletions(-) create mode 100644 librarian/res/cover-bookoteka.png diff --git a/librarian/cover.py b/librarian/cover.py index 8aa9abe..e34ce62 100644 --- a/librarian/cover.py +++ b/librarian/cover.py @@ -7,12 +7,46 @@ import Image, ImageFont, ImageDraw, ImageFilter 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) @@ -39,42 +73,103 @@ def cover(author, title, 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' diff --git a/librarian/epub.py b/librarian/epub.py index a87e1d8..f2987b5 100644 --- a/librarian/epub.py +++ b/librarian/epub.py @@ -17,7 +17,7 @@ from shutil import rmtree 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 @@ -266,7 +266,7 @@ def transform_chunk(chunk_xml, chunk_no, annotations, empty=False, _empty_html_s 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 @@ -275,7 +275,7 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= output_dir: path to directory to save output file to; either this or output_file must be present make_dir: writes output to //.epub instead of /.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, """ @@ -401,16 +401,23 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= 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( '')) manifest.append(etree.fromstring( - '')) + '' % (c_name, c.mime_type()))) spine.insert(0, etree.fromstring('')) opf.getroot()[0].append(etree.fromstring('')) opf.getroot().append(etree.fromstring('')) diff --git a/librarian/epub/cover.html b/librarian/epub/cover.html index bbe8508..784067c 100644 --- a/librarian/epub/cover.html +++ b/librarian/epub/cover.html @@ -7,7 +7,7 @@
- Okładka + Okładka
\ No newline at end of file diff --git a/librarian/res/cover-bookoteka.png b/librarian/res/cover-bookoteka.png new file mode 100644 index 0000000000000000000000000000000000000000..7196bcfab6525885ff08da54d3ad8c39a4103923 GIT binary patch literal 56260 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 R(xO|G5Rnlse53Q>zW{nh8Ib@0 literal 0 HcmV?d00001 diff --git a/scripts/book2partner b/scripts/book2partner index d2a47b3..6955899 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -66,7 +66,7 @@ def virtualo(filenames, output_dir, verbose): 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')) @@ -102,7 +102,32 @@ def prestigio(filenames, output_dir, verbose): 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, @@ -123,10 +148,12 @@ if __name__ == '__main__': 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() @@ -134,6 +161,8 @@ if __name__ == '__main__': 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: -- 2.20.1