mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Minor bug fixes in lrf.meta as well as an initial import of code to create LRF files. Will work more on this only if BBeBook-0.3 proves insufficient.
This commit is contained in:
parent
fa758e1b2c
commit
eb07f9c91f
68
src/libprs500/lrf/lrfcreator.py
Normal file
68
src/libprs500/lrf/lrfcreator.py
Normal file
@ -0,0 +1,68 @@
|
||||
## 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.
|
||||
|
||||
from cStringIO import StringIO
|
||||
from zlib import compress
|
||||
from xml.dom import minidom as dom
|
||||
|
||||
from libprs500.lrf.meta import LRFMetaFile, LRFException
|
||||
|
||||
GIF_PIXEL = 'GIF89a\x01\x00\x01\x00\xf0\x00\x00Mhh\x00\x00\x00!\xf9\x04\x00\x00'\
|
||||
'\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;'
|
||||
|
||||
def create_lrf_file():
|
||||
buff = StringIO()
|
||||
buff.write(LRFMetaFile.LRF_HEADER)
|
||||
buff.write("".join(['\0' for i in range(0x56 - 6)]))
|
||||
lrf = LRFMetaFile(buff)
|
||||
lrf.version = 999 # No reason
|
||||
lrf.xor_key = 0x30 # No reason
|
||||
lrf.root_object_id = 0x32 # No reason
|
||||
lrf.binding = 0x01 # front to back 0x10 for back to front
|
||||
lrf.dpi = 1600 # TODO: Play with this
|
||||
lrf.width = 600 # TODO: Play with this
|
||||
lrf.height = 800 # TODO: Play with this
|
||||
lrf.color_depth = 24 # Seems like a good idea
|
||||
lrf.toc_object_id = 0x42 # No reason
|
||||
lrf.thumbnail_type = 0x14 # GIF
|
||||
lrf.thumbnail_size = len(GIF_PIXEL)
|
||||
|
||||
doc = dom.getDOMImplementation().createDocument(None, None, None)
|
||||
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)
|
||||
info = doc.toxml(encoding='utf-16')
|
||||
stream = compress(info)
|
||||
lrf.compressed_info_size = 4 + len(stream)
|
||||
lrf.uncompressed_info_size = len(info)
|
||||
buff.write(stream + GIF_PIXEL)
|
||||
pos = buff.tell()
|
||||
if pos%16 != 0:
|
||||
buff.write("".join(['\0' for i in range(16 - pos%16)]))
|
||||
|
||||
|
||||
buff.seek(0)
|
||||
return lrf
|
||||
|
||||
|
||||
|
||||
class LRFCreator(object):
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
open('test.lrf', 'wb').write(create_lrf_file()._file.read())
|
93
src/libprs500/lrf/lrftypes.py
Normal file
93
src/libprs500/lrf/lrftypes.py
Normal file
@ -0,0 +1,93 @@
|
||||
## 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 struct
|
||||
|
||||
from libprs500.prstypes import field
|
||||
from libprs500.lrf.meta import WORD, DWORD
|
||||
|
||||
class LRFTag(list):
|
||||
"""
|
||||
Base class for all LRF tags.
|
||||
|
||||
An LRFTag is simply a sequence of bytes. The first two bytes are the tag id.
|
||||
Tag ids are always of the form (encoded little endian) # f5 where # is a byte.
|
||||
Thus there can be atmost 256 distinct tags.
|
||||
"""
|
||||
id = field(fmt=WORD, start=0)
|
||||
|
||||
def __init__(self, _id, size):
|
||||
"""
|
||||
@param _id: The tag id should be an integer
|
||||
@param _size: The initial size of this tag
|
||||
"""
|
||||
list.__init__(self, ['\0' for i in range(size+4)])
|
||||
self.id = _id
|
||||
|
||||
def pack(self, val, fmt=DWORD, start=0):
|
||||
"""
|
||||
Encode C{val} and write it to buffer.
|
||||
|
||||
@param fmt: See U{struct<http://docs.python.org/lib/module-struct.html>}
|
||||
@param start: Position in buffer at which to write encoded data
|
||||
"""
|
||||
self[start:start+struct.calcsize(fmt)] = struct.pack(fmt, val)
|
||||
|
||||
def unpack(self, fmt=DWORD, start=0):
|
||||
"""
|
||||
Return decoded data from buffer.
|
||||
|
||||
@param fmt: See U{struct<http://docs.python.org/lib/module-struct.html>}
|
||||
@param start: Position in buffer from which to decode
|
||||
"""
|
||||
end = start + struct.calcsize(fmt)
|
||||
return struct.unpack(fmt, "".join(list.__getslice__(self, start, end)))
|
||||
|
||||
class ObjectStart(LRFTag):
|
||||
""" Tag that marks the start of an LRFObject """
|
||||
ID = 0xf500
|
||||
|
||||
# Stored in 4 bytes. Thus there can be only 1024*1024*1024 objects in an LRF file
|
||||
object_id = field(fmt=DWORD, start=0)
|
||||
# Stored in 2 bytes. Thus there can be at most 256**2 distinct object types.
|
||||
object_type = field(fmt=WORD, start=4)
|
||||
|
||||
def __init__(self, _id, _type):
|
||||
LRFTag.__init__(self, ObjectStart.ID, 6)
|
||||
self.object_id = _id
|
||||
self.object_type = _type
|
||||
|
||||
class ObjectEnd(LRFTag):
|
||||
""" Tag that marks the end of an LRFObject """
|
||||
ID = 0xf501
|
||||
|
||||
def __init__(self):
|
||||
LRFTag.__init__(self, ObjectEnd.ID, 0)
|
||||
|
||||
class LRFObject(list):
|
||||
"""
|
||||
Base class for all LRF objects. An LRF object is simply a sequence of
|
||||
L{LRFTag}s. It must start with an L{ObjectStart} tag and end with
|
||||
an L{ObjectEnd} tag.
|
||||
"""
|
||||
def __str__(self):
|
||||
return "".join(self)
|
||||
|
||||
class BookAttr(LRFObject):
|
||||
"""
|
||||
Global properties for an LRF ebook. Root element of the LRF element
|
||||
structure.
|
||||
"""
|
||||
|
@ -77,7 +77,7 @@ def makelrf(author=None, title=None, \
|
||||
if not os.access(src, os.R_OK):
|
||||
raise LRFException("Unable to read from file: " + src)
|
||||
if thumbnail:
|
||||
thumb = os.path.abspath(options.thumbnail)
|
||||
thumb = os.path.abspath(thumbnail)
|
||||
if not os.access(thumb, os.R_OK):
|
||||
raise LRFException("Unable to read from " + thumb)
|
||||
else:
|
||||
@ -88,7 +88,7 @@ def makelrf(author=None, title=None, \
|
||||
if not title:
|
||||
title = os.path.basename(src)
|
||||
label = os.path.basename(src)
|
||||
id = hashlib.md5(os.path.basename(label)).hexdigest()
|
||||
id = 'FB' + hashlib.md5(os.path.basename(label)).hexdigest()[:14]
|
||||
name, ext = os.path.splitext(label)
|
||||
cwd = os.path.dirname(src)
|
||||
dirpath = None
|
||||
@ -163,7 +163,7 @@ def main(cargs=None):
|
||||
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', \
|
||||
parser.add_option('-r', '--rasterize', action='store_false', \
|
||||
dest="rasterize",
|
||||
help="Convert pdfs into image files.")
|
||||
parser.add_option('-c', '--cover', action='store', dest='cover',\
|
||||
|
@ -213,13 +213,14 @@ class LRFMetaFile(object):
|
||||
|
||||
title = xml_field("Title", parent="BookInfo")
|
||||
author = xml_field("Author", parent="BookInfo")
|
||||
# 16 characters. First two chars should be FB for personal use ebooks.
|
||||
book_id = xml_field("BookID", parent="BookInfo")
|
||||
publisher = xml_field("Publisher", parent="BookInfo")
|
||||
label = xml_field("Label", parent="BookInfo")
|
||||
category = xml_field("Category", parent="BookInfo")
|
||||
classification = xml_field("Classification", parent="BookInfo")
|
||||
free_text = xml_field("FreeText", parent="BookInfo")
|
||||
|
||||
# Should use ISO 639 language codes
|
||||
language = xml_field("Language", parent="DocInfo")
|
||||
creator = xml_field("Creator", parent="DocInfo")
|
||||
# Format is %Y-%m-%d
|
||||
@ -296,7 +297,7 @@ class LRFMetaFile(object):
|
||||
else:
|
||||
candidate = candidate.encode('utf-16')
|
||||
return candidate.strip()
|
||||
except zlib.error, e:
|
||||
except zlib.error:
|
||||
raise LRFException("Unable to decompress document meta information")
|
||||
|
||||
def fset(self, info):
|
||||
@ -453,6 +454,22 @@ class LRFMetaFile(object):
|
||||
slice = self.thumbnail[0:16]
|
||||
self.thumbnail_type = self._detect_thumbnail_type(slice)
|
||||
|
||||
def seek(self, *args):
|
||||
""" See L{file.seek} """
|
||||
return self._file.seek(*args)
|
||||
|
||||
def tell(self):
|
||||
""" See L{file.tell} """
|
||||
return self._file.tell()
|
||||
|
||||
def read(self):
|
||||
""" See L{file.read} """
|
||||
return self._file.read()
|
||||
|
||||
def write(self, val):
|
||||
""" See L{file.write} """
|
||||
self._file.write(val)
|
||||
|
||||
|
||||
def main():
|
||||
import sys, os.path
|
||||
@ -520,11 +537,3 @@ def main():
|
||||
print str(f[1]) + ":", lrf.__getattribute__(f[0])
|
||||
if options.get_thumbnail:
|
||||
print "Thumbnail:", td
|
||||
|
||||
def zeroes(num):
|
||||
temp = [ '\0' for i in range(num) ]
|
||||
return "".join(temp)
|
||||
|
||||
def create_lrf_header():
|
||||
buffer = StringIO()
|
||||
buffer.write()
|
||||
|
Loading…
x
Reference in New Issue
Block a user