mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-11-01 19:17:02 -04:00
192 lines
7.7 KiB
Python
Executable File
192 lines
7.7 KiB
Python
Executable File
## Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net
|
|
## This program is free software; you can redistribute it and/or modify
|
|
## it under the terms of the GNU General Public License as published by
|
|
## the Free Software Foundation; either version 2 of the License, or
|
|
## (at your option) any later version.
|
|
##
|
|
## This program is distributed in the hope that it will be useful,
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
## GNU General Public License for more details.
|
|
##
|
|
## You should have received a copy of the GNU General Public License along
|
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import hashlib
|
|
import re
|
|
import time
|
|
import pkg_resources
|
|
import subprocess
|
|
from tempfile import mkdtemp
|
|
from optparse import OptionParser
|
|
import xml.dom.minidom as dom
|
|
|
|
from libprs500.lrf.meta import LRFException, LRFMetaFile
|
|
from libprs500.ptempfile import PersistentTemporaryFile
|
|
|
|
_bbebook = 'BBeBook-0.2.jar'
|
|
|
|
def generate_thumbnail(path):
|
|
""" Generate a JPEG thumbnail of size ~ 128x128 (aspect ratio preserved)"""
|
|
try:
|
|
import Image
|
|
except ImportError:
|
|
raise LRFException("Unable to initialize Python Imaging Library." \
|
|
"Thumbnail generation is disabled")
|
|
im = Image.open(path)
|
|
im.thumbnail((128, 128), Image.ANTIALIAS)
|
|
thumb = PersistentTemporaryFile(prefix="makelrf_", suffix=".jpeg")
|
|
thumb.close()
|
|
im = im.convert()
|
|
im.save(thumb.name)
|
|
return thumb
|
|
|
|
def create_xml(cfg):
|
|
doc = dom.getDOMImplementation().createDocument(None, None, None)
|
|
def add_field(parent, tag, value):
|
|
elem = doc.createElement(tag)
|
|
elem.appendChild(doc.createTextNode(value))
|
|
parent.appendChild(elem)
|
|
|
|
info = doc.createElement('Info')
|
|
info.setAttribute('version', '1.0')
|
|
book_info = doc.createElement('BookInfo')
|
|
doc_info = doc.createElement('DocInfo')
|
|
info.appendChild(book_info)
|
|
info.appendChild(doc_info)
|
|
add_field(book_info, 'File', cfg['File'])
|
|
add_field(doc_info, 'Output', cfg['Output'])
|
|
for field in ['Title', 'Author', 'BookID', 'Publisher', 'Label', \
|
|
'Category', 'Classification', 'Icon', 'Cover', 'FreeText']:
|
|
if cfg.has_key(field):
|
|
add_field(book_info, field, cfg[field])
|
|
add_field(doc_info, 'Language', 'en')
|
|
add_field(doc_info, 'Creator', _bbebook)
|
|
add_field(doc_info, 'CreationDate', time.strftime('%Y-%m-%d', time.gmtime()))
|
|
doc.appendChild(info)
|
|
return doc.toxml()
|
|
|
|
def makelrf(author=None, title=None, \
|
|
thumbnail=None, src=None, odir=".",\
|
|
rasterize=True, cover=None):
|
|
src = os.path.normpath(os.path.abspath(src))
|
|
bbebook = pkg_resources.resource_filename(__name__, _bbebook)
|
|
if not os.access(src, os.R_OK):
|
|
raise LRFException("Unable to read from file: " + src)
|
|
if thumbnail:
|
|
thumb = os.path.abspath(options.thumbnail)
|
|
if not os.access(thumb, os.R_OK):
|
|
raise LRFException("Unable to read from " + thumb)
|
|
else:
|
|
thumb = pkg_resources.resource_filename(__name__, 'cover.jpg')
|
|
|
|
if not author:
|
|
author = "Unknown"
|
|
if not title:
|
|
title = os.path.basename(src)
|
|
label = os.path.basename(src)
|
|
id = hashlib.md5(os.path.basename(label)).hexdigest()
|
|
name, ext = os.path.splitext(label)
|
|
cwd = os.path.dirname(src)
|
|
dirpath = None
|
|
try:
|
|
if ext == ".rar":
|
|
dirpath = mkdtemp('','makelrf')
|
|
cwd = dirpath
|
|
cmd = " ".join(["unrar", "e", '"'+src+'"'])
|
|
proc = subprocess.Popen(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE)
|
|
if proc.wait():
|
|
raise LRFException("unrar failed with error:\n\n" + \
|
|
proc.stderr.read())
|
|
path, msize = None, 0
|
|
for root, dirs, files in os.walk(dirpath):
|
|
for name in files:
|
|
if os.path.splitext(name)[1] == ".html":
|
|
size = os.stat(os.path.join(root, name)).st_size
|
|
if size > msize:
|
|
msize, path = size, os.path.join(root, name)
|
|
if not path:
|
|
raise LRFException("Could not find .html file in rar archive")
|
|
src = path
|
|
|
|
name = re.sub("\s", "_", name)
|
|
name = os.path.abspath(os.path.join(odir, name)) + ".lrf"
|
|
cfg = { 'File' : src, 'Output' : name, 'Label' : label, 'BookID' : id, \
|
|
'Author' : author, 'Title' : title, 'Publisher' : 'Unknown' \
|
|
}
|
|
|
|
|
|
if cover:
|
|
cover = os.path.normpath(os.path.abspath(cover))
|
|
try:
|
|
thumbf = generate_thumbnail(cover)
|
|
thumb = thumbf.name
|
|
except Exception, e:
|
|
print >> sys.stderr, "WARNING: Unable to generate thumbnail:\n", \
|
|
str(e)
|
|
thumb = cover
|
|
cfg['Cover'] = cover
|
|
cfg['Icon'] = thumb
|
|
config = PersistentTemporaryFile(prefix='makelrf_', suffix='.xml')
|
|
config.write(create_xml(cfg))
|
|
config.close()
|
|
jar = '-jar "' + bbebook + '"'
|
|
cmd = " ".join(["java", jar, "-r" if rasterize else "", '"'+config.name+'"'])
|
|
proc = subprocess.Popen(cmd, \
|
|
cwd=cwd, shell=True, stderr=subprocess.PIPE)
|
|
if proc.wait():
|
|
raise LRFException("BBeBook failed with error:\n\n" + \
|
|
proc.stderr.read())
|
|
# Needed as BBeBook-0.2 doesn't handle non GIF thumbnails correctly.
|
|
lrf = open(name, "r+b")
|
|
LRFMetaFile(lrf).fix_thumbnail_type()
|
|
lrf.close()
|
|
return name
|
|
finally:
|
|
if dirpath:
|
|
shutil.rmtree(dirpath, True)
|
|
|
|
def main(cargs=None):
|
|
parser = OptionParser(usage=\
|
|
"""usage: %prog [options] mybook.[html|pdf|rar]
|
|
|
|
%prog converts mybook to mybook.lrf
|
|
If you specify a rar file you must have the unrar command line client
|
|
installed. makelrf assumes the rar file is an archive containing the
|
|
html file you want converted."""\
|
|
)
|
|
|
|
parser.add_option("-t", "--title", action="store", type="string", \
|
|
dest="title", help="Set the book title")
|
|
parser.add_option("-a", "--author", action="store", type="string", \
|
|
dest="author", help="Set the author")
|
|
parser.add_option('-r', '--rasterize', action='store_true', \
|
|
dest="rasterize",
|
|
help="Convert pdfs into image files.")
|
|
parser.add_option('-c', '--cover', action='store', dest='cover',\
|
|
help="Path to a graphic that will be set as the cover. "\
|
|
"If it is specified the thumbnail is automatically "\
|
|
"generated from it")
|
|
parser.add_option("--thumbnail", action="store", type="string", \
|
|
dest="thumbnail", \
|
|
help="Path to a graphic that will be set as the thumbnail")
|
|
if not cargs:
|
|
cargs = sys.argv
|
|
options, args = parser.parse_args()
|
|
if len(args) != 1:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
src = args[0]
|
|
root, ext = os.path.splitext(src)
|
|
if ext not in ['.html', '.pdf', '.rar']:
|
|
print >> sys.stderr, "Can only convert files ending in .html|.pdf|.rar"
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
name = makelrf(author=options.author, title=options.title, \
|
|
thumbnail=options.thumbnail, src=src, cover=options.cover, \
|
|
rasterize=options.rasterize)
|
|
print "LRF generated:", name
|