1
# -*- coding: utf-8 -*-
4
Write content to ereader pdb file.
8
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
9
__docformat__ = 'restructuredtext en'
22
from calibre.ebooks.pdb.formatwriter import FormatWriter
23
from calibre.ebooks.oeb.base import OEB_IMAGES
24
from calibre.ebooks.pdb.header import PdbHeaderBuilder
25
from calibre.ebooks.pdb.ereader import image_name
26
from calibre.ebooks.pml.pmlml import PMLMLizer
30
# This is an arbitrary number that is small enough to work. The actual maximum
31
# record size is unknown.
32
MAX_RECORD_SIZE = 3560
34
class Writer(FormatWriter):
36
def __init__(self, opts, log):
40
def write_content(self, oeb_book, out_stream, metadata=None):
41
text = self._text(oeb_book)
42
images = self._images(oeb_book.manifest)
43
metadata = [self._metadata(metadata)]
45
hr = [self._header_record(len(text), len(images))]
47
sections = hr+text+images+metadata+['MeTaInFo\x00']
49
lengths = [len(i) if i not in images else len(i[0]) + len(i[1]) for i in sections]
51
pdbHeaderBuilder = PdbHeaderBuilder(IDENTITY, metadata[0].partition('\x00')[0])
52
pdbHeaderBuilder.build_header(lengths, out_stream)
56
out_stream.write(item[0])
57
out_stream.write(item[1])
59
out_stream.write(item)
61
def _text(self, oeb_book):
62
pmlmlizer = PMLMLizer(self.log)
63
pml = unicode(pmlmlizer.extract_content(oeb_book, self.opts)).encode('cp1252', 'replace')
66
for i in range(0, (len(pml) / MAX_RECORD_SIZE) + 1):
67
pml_pages.append(zlib.compress(pml[i * MAX_RECORD_SIZE : (i * MAX_RECORD_SIZE) + MAX_RECORD_SIZE]))
71
def _images(self, manifest):
75
if item.media_type in OEB_IMAGES:
78
header += image_name(item.href)
79
header = header.ljust(62, '\x00')
81
im = Image.open(cStringIO.StringIO(item.data)).convert('P')
82
im.thumbnail((300,300), Image.ANTIALIAS)
84
data = cStringIO.StringIO()
86
data = data.getvalue()
88
if len(data) + len(header) < 65505:
89
images.append((header, data))
93
def _metadata(self, metadata):
95
Metadata takes the form:
104
author = _('Unknown')
110
if len(metadata.title) >= 1:
111
title = metadata.title[0].value
112
if len(metadata.creator) >= 1:
113
from calibre.ebooks.metadata import authors_to_string
114
author = authors_to_string([x.value for x in metadata.creator])
115
if len(metadata.rights) >= 1:
116
copyright = metadata.rights[0].value
117
if len(metadata.publisher) >= 1:
118
publisher = metadata.publisher[0].value
120
return '%s\x00%s\x00%s\x00%s\x00%s\x00' % (title, author, copyright, publisher, isbn)
122
def _header_record(self, text_items, image_items):
124
text_items = the number of text pages
125
image_items = the number of images
127
version = 10 # Zlib compression
128
non_text_offset = text_items + 1
131
image_data_offset = text_items + 1
132
meta_data_offset = image_data_offset + image_items
133
last_data_offset = meta_data_offset + 1
135
meta_data_offset = text_items + 1
136
last_data_offset = meta_data_offset + 1
137
image_data_offset = last_data_offset
141
record += struct.pack('>H', version) # [0:2] # Version. Specifies compression and drm. 2 = palmdoc, 10 = zlib. 260 and 272 = DRM
142
record += struct.pack('>H', 0) # [2:4]
143
record += struct.pack('>H', 0) # [4:6]
144
record += struct.pack('>H', 25152) # [6:8] # 25152 is MAGIC. Somehow represents the cp1252 encoding of the text
145
record += struct.pack('>H', 0) # [8:10]
146
record += struct.pack('>H', 0) # [10:12]
147
record += struct.pack('>H', non_text_offset) # [12:14] # non_text_offset
148
record += struct.pack('>H', 0) # [14:16]
149
record += struct.pack('>H', 0) # [16:18]
150
record += struct.pack('>H', 0) # [18:20]
151
record += struct.pack('>H', image_items) # [20:22] # Number of images
152
record += struct.pack('>H', 0) # [22:24]
153
record += struct.pack('>H', 1) # [24:26] # 1 if has metadata, 0 if not
154
record += struct.pack('>H', 0) # [26:28]
155
record += struct.pack('>H', 0) # [28:30] # footnote_rec
156
record += struct.pack('>H', 0) # [30:32] # sidebar_rec
157
record += struct.pack('>H', last_data_offset) # [32:34] # bookmark_offset
158
record += struct.pack('>H', 2560) # [34:36] # 2560 is MAGIC
159
record += struct.pack('>H', 0) # [36:38]
160
record += struct.pack('>H', 0) # [38:40]
161
record += struct.pack('>H', image_data_offset) # [40:42] # image_data_offset. This will be the last data offset if there are no images
162
record += struct.pack('>H', 0) # [42:44]
163
record += struct.pack('>H', meta_data_offset) # [44:46] # meta_data_offset. This will be the last data offset if there are no images
164
record += struct.pack('>H', 0) # [46:48]
165
record += struct.pack('>H', last_data_offset) # [48:50] # footnote_offset. This will be the last data offset if there are no images
166
record += struct.pack('>H', last_data_offset) # [50:52] # sidebar_offset. This will be the last data offset if there are no images
167
record += struct.pack('>H', last_data_offset) # [52:54] # last_data_offset
169
for i in range(54, 132, 2):
170
record += struct.pack('>H', 0) # [54:132]