blib/lib/EBook/MOBI/MobiPerl/Util.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 29 | 375 | 7.7 |
branch | 0 | 120 | 0.0 |
condition | 0 | 54 | 0.0 |
subroutine | 9 | 22 | 40.9 |
pod | 0 | 14 | 0.0 |
total | 38 | 585 | 6.5 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package EBook::MOBI::MobiPerl::Util; | ||||||
2 | |||||||
3 | # Copyright (C) 2007 Tommy Persson, tpe@ida.liu.se | ||||||
4 | # | ||||||
5 | # MobiPerl/Util.pm, Copyright (C) 2007 Tommy Persson, tpe@ida.liu.se | ||||||
6 | # | ||||||
7 | # This program is free software: you can redistribute it and/or modify | ||||||
8 | # it under the terms of the GNU General Public License as published by | ||||||
9 | # the Free Software Foundation, either version 2 of the License, or | ||||||
10 | # (at your option) any later version. | ||||||
11 | # | ||||||
12 | # This program is distributed in the hope that it will be useful, | ||||||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
15 | # GNU General Public License for more details. | ||||||
16 | # | ||||||
17 | # You should have received a copy of the GNU General Public License | ||||||
18 | # along with this program. If not, see |
||||||
19 | |||||||
20 | BEGIN { | ||||||
21 | # Optionally load GD | ||||||
22 | 9 | 9 | 572 | eval 'require GD'; | |||
23 | } | ||||||
24 | |||||||
25 | 9 | 9 | 51 | use strict; | |||
9 | 22 | ||||||
9 | 461 | ||||||
26 | |||||||
27 | our $VERSION = 2011.11.26; | ||||||
28 | |||||||
29 | 9 | 9 | 9843 | use Module::Loaded; | |||
9 | 6052 | ||||||
9 | 623 | ||||||
30 | 9 | 9 | 9178 | use Image::BMP; | |||
9 | 91370 | ||||||
9 | 694 | ||||||
31 | 9 | 9 | 11622 | use Image::Size; | |||
9 | 54581 | ||||||
9 | 707 | ||||||
32 | 9 | 9 | 9508 | use File::Copy; | |||
9 | 31131 | ||||||
9 | 726 | ||||||
33 | 9 | 9 | 64 | use File::Spec; | |||
9 | 20 | ||||||
9 | 177 | ||||||
34 | |||||||
35 | 9 | 9 | 11992 | use HTML::TreeBuilder; | |||
9 | 303022 | ||||||
9 | 376 | ||||||
36 | |||||||
37 | my $rescale_large_images = 0; | ||||||
38 | |||||||
39 | |||||||
40 | sub is_cover_image { | ||||||
41 | 0 | 0 | 0 | 0 | my $file = shift; | ||
42 | |||||||
43 | 0 | 0 | 0 | die 'ERROR: GD not available ' unless is_loaded('GD'); | |||
44 | |||||||
45 | 0 | 0 | my $res = 0; | ||||
46 | 0 | 0 | 0 | if (not -e "$file") { | |||
47 | 0 | 0 | die "ERROR: File does not exist: $file"; | ||||
48 | } | ||||||
49 | 0 | 0 | my $p = new GD::Image ($file); | ||||
50 | 0 | 0 | 0 | if (not defined $p) { | |||
51 | 0 | 0 | print STDERR "Could not read image file: $file\n"; | ||||
52 | 0 | 0 | return $res; | ||||
53 | } | ||||||
54 | 0 | 0 | my ($x, $y) = $p->getBounds(); | ||||
55 | # my $x = $p->width; | ||||||
56 | # my $y = $p->height; | ||||||
57 | 0 | 0 | 0 | 0 | if ($x == 510 and $y == 680) { | ||
58 | 0 | 0 | print STDERR "GUESSING COVERIMAGE: $file\n"; | ||||
59 | 0 | 0 | $res = 1; | ||||
60 | } | ||||||
61 | 0 | 0 | 0 | 0 | if ($x == 600 and $y == 800) { | ||
62 | 0 | 0 | print STDERR "GUESSING COVERIMAGE: $file\n"; | ||||
63 | 0 | 0 | $res = 1; | ||||
64 | } | ||||||
65 | 0 | 0 | return $res; | ||||
66 | } | ||||||
67 | |||||||
68 | # | ||||||
69 | # OPF related functions | ||||||
70 | # | ||||||
71 | |||||||
72 | sub get_tree_from_opf { | ||||||
73 | 0 | 0 | 0 | 0 | my $file = shift; | ||
74 | 0 | 0 | my $config = shift; | ||||
75 | 0 | 0 | my $linksinfo = shift; | ||||
76 | |||||||
77 | # my ($vol,$dir,$basefile) = File::Spec->splitpath ($file); | ||||||
78 | # print STDERR "OPFFILE: $vol - $dir - $basefile\n"; | ||||||
79 | |||||||
80 | 0 | 0 | my $opf = new MobiPerl::Opf ($file); | ||||
81 | 0 | 0 | my $tochref = $opf->get_toc_href (); | ||||
82 | 0 | 0 | my @opf_spine_ids = $opf->get_spine_ids (); | ||||
83 | 0 | 0 | my @opf_manifest_ids = $opf->get_manifest_ids (); | ||||
84 | 0 | 0 | my $title = $opf->get_title (); | ||||
85 | 0 | 0 | print STDERR "OPFTITLE: $title\n"; | ||||
86 | 0 | 0 | 0 | if ($config->title ()) { | |||
87 | 0 | 0 | $title = $config->title (); | ||||
88 | } | ||||||
89 | 0 | 0 | $title = $config->prefix_title () . $title; | ||||
90 | 0 | 0 | $config->title ($title); | ||||
91 | |||||||
92 | 0 | 0 | my $author = $opf->get_author (); | ||||
93 | 0 | 0 | print STDERR "OPFAUTHOR: $author\n"; | ||||
94 | 0 | 0 | 0 | if (not $config->author ()) { | |||
95 | 0 | 0 | $config->author ($author); | ||||
96 | } | ||||||
97 | |||||||
98 | |||||||
99 | |||||||
100 | # | ||||||
101 | # If cover image not assigned search all files in current dir | ||||||
102 | # and see if some file is a coverimage | ||||||
103 | # | ||||||
104 | |||||||
105 | 0 | 0 | my $coverimage = $opf->get_cover_image (); | ||||
106 | 0 | 0 | 0 | if ($coverimage eq "") { | |||
107 | 0 | 0 | opendir DIR, "."; | ||||
108 | 0 | 0 | my @files = readdir (DIR); | ||||
109 | 0 | 0 | foreach my $f (@files) { | ||||
110 | 0 | 0 | 0 | 0 | if ($f =~ /\.jpg/ or | ||
0 | |||||||
111 | $f =~ /\.JPG/ or | ||||||
112 | $f =~ /\.gif/) { | ||||||
113 | # print STDERR "Checking if file is coverimage: $f\n"; | ||||||
114 | 0 | 0 | 0 | if (MobiPerl::Util::is_cover_image ($f)) { | |||
115 | 0 | 0 | $coverimage = $f; | ||||
116 | } | ||||||
117 | } | ||||||
118 | } | ||||||
119 | } | ||||||
120 | 0 | 0 | print STDERR "Coverimage: $coverimage\n"; | ||||
121 | |||||||
122 | 0 | 0 | my $html = HTML::Element->new('html'); | ||||
123 | 0 | 0 | my $head = HTML::Element->new('head'); | ||||
124 | |||||||
125 | # | ||||||
126 | # Generate guide tag, specific for Mobipocket and is | ||||||
127 | # not understood by HTML::TreeBuilder... | ||||||
128 | # | ||||||
129 | |||||||
130 | |||||||
131 | 0 | 0 | my $guide = HTML::Element->new('guide'); | ||||
132 | 0 | 0 | 0 | if ($tochref) { | |||
133 | 0 | 0 | print STDERR "Util.pm: GENERATE GUIDE SECTION: $tochref\n"; | ||||
134 | 0 | 0 | my $tocref = HTML::Element->new('reference', | ||||
135 | title=>"Table of Contents", | ||||||
136 | type=>"toc", | ||||||
137 | href=>"\#$tochref"); | ||||||
138 | 0 | 0 | $guide->push_content ($tocref); | ||||
139 | } | ||||||
140 | |||||||
141 | 0 | 0 | 0 | if ($config->add_cover_link ()) { | |||
142 | 0 | 0 | print STDERR "Util.pm: GENERATE GUIDE SECTION ADDCOVVERLINK\n"; | ||||
143 | 0 | 0 | my $coverref = HTML::Element->new('reference', | ||||
144 | title=>"Cover", | ||||||
145 | type=>"cover", | ||||||
146 | href=>"\#addedcoverlink"); | ||||||
147 | 0 | 0 | $guide->push_content ($coverref); | ||||
148 | } | ||||||
149 | 0 | 0 | $head->push_content ($guide); | ||||
150 | |||||||
151 | 0 | 0 | my $titleel = HTML::Element->new('title'); | ||||
152 | 0 | 0 | $titleel->push_content ($title); | ||||
153 | 0 | 0 | $head->push_content ($titleel); | ||||
154 | |||||||
155 | # | ||||||
156 | # Generate body | ||||||
157 | # | ||||||
158 | |||||||
159 | 0 | 0 | my $body = HTML::Element->new('body'); | ||||
160 | |||||||
161 | # topmargin => "0", | ||||||
162 | # leftmargin => "0", | ||||||
163 | # bottommargin => "0", | ||||||
164 | # rightmargin => "0"); | ||||||
165 | |||||||
166 | |||||||
167 | 0 | 0 | my $coverp = HTML::Element->new('p', | ||||
168 | id=>"addedcoverlink", | ||||||
169 | align=>"center"); | ||||||
170 | 0 | 0 | my $coverimageel = HTML::Element->new('a', | ||||
171 | onclick => | ||||||
172 | "document.goto_page_relative(1)"); | ||||||
173 | 0 | 0 | $coverp->push_content ($coverimageel); | ||||
174 | |||||||
175 | 0 | 0 | 0 | if ($config->add_cover_link ()) { | |||
176 | 0 | 0 | $body->push_content ($coverp); | ||||
177 | 0 | 0 | $body->push_content (HTML::Element->new('mbp:pagebreak')); | ||||
178 | } | ||||||
179 | |||||||
180 | # | ||||||
181 | |||||||
182 | # | ||||||
183 | # Add TOC first also if --tocfirst | ||||||
184 | # | ||||||
185 | 0 | 0 | 0 | 0 | if ($tochref and $config->toc_first ()) { | ||
186 | 0 | 0 | print STDERR "ADDING TOC FIRST ALSO: $tochref\n"; | ||||
187 | 0 | 0 | my $tree = new HTML::TreeBuilder (); | ||||
188 | 0 | 0 | $tree->ignore_unknown (0); | ||||
189 | 0 | 0 | 0 | $tree->parse_file ($tochref) || die "1-Could not find file: $tochref\n"; | |||
190 | ### check_for_links ($tree); | ||||||
191 | 0 | 0 | $linksinfo->check_for_links ($tree); | ||||
192 | 0 | 0 | my $b = $tree->find ("body"); | ||||
193 | 0 | 0 | $body->push_content ($b->content_list()); | ||||
194 | 0 | 0 | $body->push_content (HTML::Element->new('mbp:pagebreak')); | ||||
195 | } | ||||||
196 | |||||||
197 | |||||||
198 | # | ||||||
199 | # All files in manifest | ||||||
200 | # | ||||||
201 | |||||||
202 | 0 | 0 | foreach my $id (@opf_spine_ids) { | ||||
203 | 0 | 0 | my $filename = $opf->get_href ($id); | ||||
204 | 0 | 0 | my $mediatype = $opf->get_media_type ($id); | ||||
205 | |||||||
206 | 0 | 0 | print STDERR "SPINE: adding $id - $filename - $mediatype\n"; | ||||
207 | |||||||
208 | 0 | 0 | 0 | next unless ($mediatype =~ /text/); # only include text content | |||
209 | |||||||
210 | 0 | 0 | my $tree = new HTML::TreeBuilder (); | ||||
211 | 0 | 0 | $tree->ignore_unknown (0); | ||||
212 | |||||||
213 | 0 | 0 | 0 | open FILE, "<$filename" or die "2-Could not find file: $filename\n"; | |||
214 | { | ||||||
215 | 0 | 0 | local $/; | ||||
0 | 0 | ||||||
216 | 0 | 0 | my $content = |
||||
217 | 0 | 0 | $content =~ s/&\#226;&\#8364;&\#166;/&\#8230;/g; | ||||
218 | # fixes bug in coding | ||||||
219 | 0 | 0 | $tree->parse ($content); | ||||
220 | 0 | 0 | $tree->eof(); | ||||
221 | } | ||||||
222 | |||||||
223 | 0 | 0 | 0 | if ($config->{FIXHTMLBR}) { | |||
224 | 0 | 0 | fix_html_br ($tree, $config); | ||||
225 | } | ||||||
226 | |||||||
227 | 0 | 0 | $linksinfo->check_for_links ($tree); | ||||
228 | |||||||
229 | 0 | 0 | print STDERR "Adding: $filename - $id\n"; | ||||
230 | |||||||
231 | # print STDERR "FILETOLINKCHECK:$filename:\n"; | ||||||
232 | 0 | 0 | 0 | if ($linksinfo->link_exists ($filename)) { | |||
233 | # print STDERR "FILETOLINKCHECK:$filename: SUCCESS\n"; | ||||||
234 | 0 | 0 | my $a = HTML::Element->new('a', name => $filename); | ||||
235 | 0 | 0 | $body->push_content ($a); | ||||
236 | } | ||||||
237 | 0 | 0 | print STDERR "+"; | ||||
238 | 0 | 0 | my $b = $tree->find ("body"); | ||||
239 | 0 | 0 | print STDERR "+"; | ||||
240 | 0 | 0 | my @content = $b->content_list(); | ||||
241 | 0 | 0 | print STDERR "+"; | ||||
242 | 0 | 0 | foreach my $c (@content) { | ||||
243 | 0 | 0 | $body->push_content ($c); | ||||
244 | # print STDERR $c; | ||||||
245 | 0 | 0 | print STDERR "."; | ||||
246 | } | ||||||
247 | 0 | 0 | print STDERR "+"; | ||||
248 | } | ||||||
249 | 0 | 0 | print STDERR "All spine elements have been added\n"; | ||||
250 | |||||||
251 | 0 | 0 | 0 | if ($config->cover_image ()) { | |||
252 | 0 | 0 | $coverimage = $config->cover_image (); | ||||
253 | } | ||||||
254 | |||||||
255 | 0 | 0 | 0 | if ($coverimage) { | |||
256 | 0 | 0 | copy ("../$coverimage", $coverimage); # copy if specified --coverimage | ||||
257 | 0 | 0 | $linksinfo->add_cover_image ($coverimage); | ||||
258 | 0 | 0 | 0 | if ($config->add_cover_link ()) { | |||
259 | 0 | 0 | my $el = HTML::Element->new ('img', src => "$coverimage"); | ||||
260 | 0 | 0 | $coverimageel->push_content ($el); | ||||
261 | 0 | 0 | $linksinfo->check_for_links ($coverimageel); | ||||
262 | } | ||||||
263 | } | ||||||
264 | |||||||
265 | 0 | 0 | 0 | if ($config->thumb_image ()) { | |||
266 | 0 | 0 | $linksinfo->add_thumb_image ($config->thumb_image ()); | ||||
267 | } else { | ||||||
268 | 0 | 0 | 0 | if ($coverimage) { | |||
269 | 0 | 0 | $linksinfo->add_thumb_image ($coverimage); | ||||
270 | } | ||||||
271 | } | ||||||
272 | |||||||
273 | # | ||||||
274 | # Fix anchor to positions given by id="III"... | ||||||
275 | # | ||||||
276 | # filepos="0000057579" | ||||||
277 | # | ||||||
278 | |||||||
279 | 0 | 0 | my @refs = $body->look_down ("href", qr/^\#/); | ||||
280 | 0 | 0 | push @refs, $head->look_down ("href", qr/^\#/); | ||||
281 | 0 | 0 | my @hrefs = (); | ||||
282 | 0 | 0 | my @refels = (); | ||||
283 | 0 | 0 | my %href_to_ref = (); | ||||
284 | 0 | 0 | foreach my $r (@refs) { | ||||
285 | 0 | 0 | $r->attr ("filepos", "0000000000"); | ||||
286 | 0 | 0 | my $key = $r->attr ("href"); | ||||
287 | 0 | 0 | $key =~ s/\#//g; | ||||
288 | 0 | 0 | push @hrefs, $key; | ||||
289 | 0 | 0 | push @refels, $r; | ||||
290 | # $r->attr ("href", undef); | ||||||
291 | } | ||||||
292 | |||||||
293 | 0 | 0 | $html->push_content ($head); | ||||
294 | 0 | 0 | $html->push_content ($body); | ||||
295 | 0 | 0 | my $data = $html->as_HTML (); | ||||
296 | 0 | 0 | foreach my $i (0..$#hrefs) { | ||||
297 | 0 | 0 | my $h = $hrefs[$i]; | ||||
298 | 0 | 0 | my $r = $refels[$i]; | ||||
299 | 0 | 0 | my $searchfor1 = "id=\"$h\""; | ||||
300 | 0 | 0 | my $searchfor2 = " | ||||
301 | |||||||
302 | ### print STDERR "SEARCHFOR1: $searchfor1\n"; | ||||||
303 | 0 | 0 | my $pos = index ($data, $searchfor1); | ||||
304 | 0 | 0 | 0 | if ($pos >= 0) { | |||
305 | # | ||||||
306 | # search backwards for < | ||||||
307 | # | ||||||
308 | |||||||
309 | 0 | 0 | while (substr ($data, $pos, 1) ne "<") { | ||||
310 | 0 | 0 | $pos--; | ||||
311 | } | ||||||
312 | |||||||
313 | ## $pos -=4; # back 4 positions to get to | ||||||
314 | 0 | 0 | my $form = "0" x (10-length($pos)) . "$pos"; | ||||
315 | 0 | 0 | print STDERR "POSITION: $pos - $searchfor1 - $form\n"; | ||||
316 | 0 | 0 | $r->attr ("filepos", "$form"); | ||||
317 | } else { | ||||||
318 | ### print STDERR "SEARCHFOR2: $searchfor2\n"; | ||||||
319 | 0 | 0 | $pos = index ($data, $searchfor2); | ||||
320 | 0 | 0 | 0 | if ($pos >= 0) { | |||
321 | 0 | 0 | my $form = "0" x (10-length($pos)) . "$pos"; | ||||
322 | ### print STDERR "POSITION: $pos - $searchfor2 - $form\n"; | ||||||
323 | 0 | 0 | $r->attr ("filepos", "$form"); | ||||
324 | } else { | ||||||
325 | } | ||||||
326 | } | ||||||
327 | } | ||||||
328 | |||||||
329 | |||||||
330 | # my @anchors = $body->look_down ("id", qr/./); | ||||||
331 | # foreach my $a (@anchors) { | ||||||
332 | # my $name = $a->attr("id"); | ||||||
333 | # my $tag = $a->tag (); | ||||||
334 | # my $text = $a->as_trimmed_text (); | ||||||
335 | # if ($link_exists{$name}) { | ||||||
336 | # $a->delete_content (); | ||||||
337 | # my $ael = HTML::Element->new('a', name => $name); | ||||||
338 | # $ael->push_content ($text); | ||||||
339 | # $a->push_content ($ael); | ||||||
340 | # } | ||||||
341 | # print STDERR "ANCHORS: $tag - $name - $text\n"; | ||||||
342 | # } | ||||||
343 | |||||||
344 | |||||||
345 | |||||||
346 | # $html->push_content ($head); | ||||||
347 | # $html->push_content ($body); | ||||||
348 | 0 | 0 | return $html; | ||||
349 | } | ||||||
350 | |||||||
351 | |||||||
352 | # | ||||||
353 | # lit file functons | ||||||
354 | # | ||||||
355 | |||||||
356 | sub unpack_lit_file { | ||||||
357 | 0 | 0 | 0 | 0 | my $litfile = shift; | ||
358 | 0 | 0 | my $unpackdir = shift; | ||||
359 | |||||||
360 | 0 | 0 | print STDERR "Unpack file $litfile in dir $unpackdir\n"; | ||||
361 | |||||||
362 | 0 | 0 | mkdir $unpackdir; | ||||
363 | |||||||
364 | 0 | 0 | opendir DIR, $unpackdir; | ||||
365 | 0 | 0 | my @files = readdir (DIR); | ||||
366 | 0 | 0 | foreach my $f (@files) { | ||||
367 | 0 | 0 | 0 | if ($f =~ /^\./) { | |||
368 | 0 | 0 | next; | ||||
369 | } | ||||||
370 | 0 | 0 | 0 | if ($f =~ /^\.\./) { | |||
371 | 0 | 0 | next; | ||||
372 | } | ||||||
373 | # print STDERR "FILE: $f\n"; | ||||||
374 | 0 | 0 | unlink "$unpackdir/$f"; | ||||
375 | } | ||||||
376 | |||||||
377 | 0 | 0 | 0 | system ("clit \"$litfile\" $unpackdir") == 0 | |||
378 | or die "system (clit $litfile $unpackdir) failed: $?"; | ||||||
379 | |||||||
380 | } | ||||||
381 | |||||||
382 | sub get_thumb_cover_image_data { | ||||||
383 | 0 | 0 | 0 | 0 | my $filename = shift; | ||
384 | |||||||
385 | 0 | 0 | 0 | die 'ERROR: GD not available ' unless is_loaded('GD'); | |||
386 | |||||||
387 | ## print STDERR "COVERIMAGE: $filename\n"; | ||||||
388 | 0 | 0 | my $data = ""; | ||||
389 | |||||||
390 | 0 | 0 | 0 | if (not -e $filename) { | |||
391 | 0 | 0 | print STDERR "Image file does not exist: $filename\n"; | ||||
392 | 0 | 0 | return $data; | ||||
393 | } | ||||||
394 | |||||||
395 | 0 | 0 | my $p = new GD::Image ("$filename"); | ||||
396 | 0 | 0 | my ($x, $y) = $p->getBounds(); | ||||
397 | # my $x = $p->width; | ||||||
398 | # my $y = $p->height; | ||||||
399 | ## add_text_to_image ($p, $opt_covertext); | ||||||
400 | |||||||
401 | # pdurrant | ||||||
402 | # Make thumb 320 high and proportional width | ||||||
403 | # latest Mobipocket Creator makes Thumbnails 320 high | ||||||
404 | 0 | 0 | my $scaled = scale_gd_image ($p, 320/$y); | ||||
405 | 0 | 0 | print STDERR "Resizing image $x x $y -> $x*320/$y x 320 -> scaled.jpg\n"; | ||||
406 | |||||||
407 | # my $scaled = scale_gd_image ($p, 180, 240); | ||||||
408 | # print STDERR "Resizing image $x x $y -> 180 x 240 -> scaled.jpg\n"; | ||||||
409 | 0 | 0 | return $scaled->jpeg (); | ||||
410 | } | ||||||
411 | |||||||
412 | sub scale_gd_image { | ||||||
413 | 0 | 0 | 0 | 0 | my $im = shift; | ||
414 | 0 | 0 | my $x = shift; | ||||
415 | 0 | 0 | my $y = shift; | ||||
416 | |||||||
417 | 0 | 0 | 0 | die 'ERROR: GD not available ' unless is_loaded('GD'); | |||
418 | |||||||
419 | 0 | 0 | my ($w0, $h0) = $im->getBounds(); | ||||
420 | # my $w0 = $im->width; | ||||||
421 | # my $h0 = $im->height; | ||||||
422 | 0 | 0 | my $w1 = $w0*$x; | ||||
423 | 0 | 0 | my $h1 = $h0*$x; | ||||
424 | 0 | 0 | print STDERR "SCALE GD: $w0 $h0 -> $w1 $h1\n"; | ||||
425 | 0 | 0 | 0 | if (defined $y) { | |||
426 | 0 | 0 | $w1 = $x; | ||||
427 | 0 | 0 | $h1 = $y; | ||||
428 | } | ||||||
429 | 0 | 0 | my $res = new GD::Image ($w1, $h1); | ||||
430 | 0 | 0 | $res->copyResized ($im, 0, 0, 0, 0, $w1, $h1, $w0, $h0); | ||||
431 | 0 | 0 | return $res; | ||||
432 | } | ||||||
433 | |||||||
434 | |||||||
435 | sub get_text_image { | ||||||
436 | 0 | 0 | 0 | 0 | my $width = shift; | ||
437 | 0 | 0 | my $height = shift; | ||||
438 | 0 | 0 | my $text = shift; | ||||
439 | # my $image = Image::Magick->new; | ||||||
440 | # $image->Set(size=>"$width x $height"); | ||||||
441 | # $image->ReadImage('xc:white'); | ||||||
442 | # $image->Draw (pen => "red", | ||||||
443 | # primitive => "text", | ||||||
444 | # x => 200, | ||||||
445 | # y => 200, | ||||||
446 | # font => "Bookman-DemiItalic", | ||||||
447 | # text => "QQQQ$text, 200, 200", | ||||||
448 | # fill => "black", | ||||||
449 | # pointsize => 40); | ||||||
450 | # $image->Draw(pen => 'red', fill => 'red', primitive => 'rectangle', | ||||||
451 | # points => '20,20 100,100'); | ||||||
452 | # $image->Write (filename => "draw2.jpg"); | ||||||
453 | } | ||||||
454 | |||||||
455 | sub get_gd_image_data { | ||||||
456 | 0 | 0 | 0 | 0 | my $im = shift; | ||
457 | 0 | 0 | my $filename = shift; | ||||
458 | 0 | 0 | my $quality = shift; | ||||
459 | |||||||
460 | 0 | 0 | 0 | $quality = -1 if not defined $quality; | |||
461 | |||||||
462 | # | ||||||
463 | # For some strange reason it does not work if using | ||||||
464 | # the gif file with size 600x800 | ||||||
465 | # | ||||||
466 | |||||||
467 | ## if ($filename =~ /\.gif/ or $filename =~ /\.GIF/) { | ||||||
468 | ## return $im->gif (); | ||||||
469 | ## } | ||||||
470 | |||||||
471 | 0 | 0 | 0 | if ($quality <= 0) { | |||
472 | 0 | 0 | return $im->jpeg (); | ||||
473 | } else { | ||||||
474 | 0 | 0 | return $im->jpeg ($quality); | ||||
475 | } | ||||||
476 | } | ||||||
477 | |||||||
478 | sub add_text_to_image { | ||||||
479 | 0 | 0 | 0 | 0 | my $im = shift; | ||
480 | 0 | 0 | my $text = shift; | ||||
481 | 0 | 0 | my $x = $im->Get ("width"); | ||||
482 | 0 | 0 | my $y = $im->Get ("height"); | ||||
483 | |||||||
484 | 0 | 0 | 0 | 0 | if (defined $text and $text) { | ||
485 | 0 | 0 | print STDERR "DRAW TEXT: $text\n"; | ||||
486 | 0 | 0 | my $textim = get_text_image ($x, $y, $text); | ||||
487 | 0 | 0 | $im->Draw (primitive => "text", | ||||
488 | text => $text, | ||||||
489 | points => "50,50", | ||||||
490 | fill => "red", | ||||||
491 | pointsize => 72); | ||||||
492 | } | ||||||
493 | 0 | 0 | $im->Write (filename => "draw.jpg"); | ||||
494 | |||||||
495 | } | ||||||
496 | |||||||
497 | sub get_image_data { | ||||||
498 | 0 | 0 | 0 | 0 | my $filename = shift; | ||
499 | 0 | 0 | my $rescale = shift; | ||||
500 | 0 | 0 | my $config = shift; | ||||
501 | |||||||
502 | 0 | 0 | 0 | die 'ERROR: GD not available ' unless is_loaded('GD'); | |||
503 | |||||||
504 | 0 | 0 | 0 | $rescale_large_images = $rescale if defined $rescale; | |||
505 | |||||||
506 | 0 | 0 | my $scale_factor; | ||||
507 | 0 | 0 | 0 | $scale_factor = $config->scale_all_images() if defined $config; | |||
508 | |||||||
509 | # pdurrant | ||||||
510 | # make maxsize exactly 60KiB | ||||||
511 | |||||||
512 | 0 | 0 | my $maxsize = 61440; | ||||
513 | 0 | 0 | 0 | $maxsize = $config->get_image_max_bytes () if defined $config; | |||
514 | 0 | 0 | print STDERR "GET IMAGE DATA (file - maxsize): $filename - $maxsize\n"; | ||||
515 | |||||||
516 | # my $maxsize = 61000; | ||||||
517 | 0 | 0 | my $maxwidth = 480; | ||||
518 | 0 | 0 | my $maxheight = 640; | ||||
519 | |||||||
520 | 0 | 0 | my $data = ""; | ||||
521 | |||||||
522 | 0 | 0 | 0 | if (not -e $filename) { | |||
523 | 0 | 0 | print STDERR "Image file does not exist: $filename\n"; | ||||
524 | 0 | 0 | return $data; | ||||
525 | } | ||||||
526 | |||||||
527 | 0 | 0 | my $filesize = -s $filename; | ||||
528 | 0 | 0 | my ($x, $y, $type) = imgsize ($filename); | ||||
529 | |||||||
530 | 0 | 0 | print STDERR "Reading data from file: $filename - $x x $y - $type\n"; | ||||
531 | |||||||
532 | # if ($filesize < $maxsize and $x < $maxwidth and $y<$maxheight | ||||||
533 | # and $type ne "PNG") { | ||||||
534 | |||||||
535 | # pdurrant | ||||||
536 | # do not resize large images if the filesize is OK, | ||||||
537 | # even if pixel dimensions are large | ||||||
538 | 0 | 0 | 0 | 0 | if ($filesize < $maxsize and | ||
0 | |||||||
0 | |||||||
0 | |||||||
0 | |||||||
539 | ((not $rescale_large_images) || ($x <= $maxwidth and $y <= $maxheight)) | ||||||
540 | and $type ne "PNG" | ||||||
541 | and (not defined $scale_factor or $scale_factor == 1.0)) { | ||||||
542 | |||||||
543 | # No transformation has to be done, keep data as is | ||||||
544 | 0 | 0 | print STDERR "No transformation: $filename - $x x $y\n"; | ||||
545 | 0 | 0 | 0 | open(IMG, $filename) or die "can't open $filename: $!"; | |||
546 | 0 | 0 | binmode(IMG); # now DOS won't mangle binary input from GIF | ||||
547 | 0 | 0 | my $buff; | ||||
548 | 0 | 0 | while (read(IMG, $buff, 8 * 2**10)) { | ||||
549 | 0 | 0 | $data .= $buff; | ||||
550 | } | ||||||
551 | 0 | 0 | return $data; | ||||
552 | } | ||||||
553 | |||||||
554 | |||||||
555 | 0 | 0 | my $p = new GD::Image ("$filename"); | ||||
556 | 0 | 0 | 0 | if (not defined $p) { | |||
557 | 0 | 0 | my $im = new Image::BMP (file => "$filename"); | ||||
558 | 0 | 0 | 0 | if (defined $im) { | |||
559 | 0 | 0 | my $w = $im->{Width}; | ||||
560 | 0 | 0 | my $h = $im->{Height}; | ||||
561 | 0 | 0 | print STDERR "BMP IMAGE $filename: $w x $h\n"; | ||||
562 | 0 | 0 | $p = new GD::Image ($w, $h); | ||||
563 | 0 | 0 | foreach my $x (0..$w-1) { | ||||
564 | 0 | 0 | foreach my $y (0..$h-1) { | ||||
565 | 0 | 0 | my ($r,$g,$b) = $im->xy_rgb ($x, $y); | ||||
566 | 0 | 0 | my $index = $p->colorExact ($r, $g, $b); | ||||
567 | 0 | 0 | 0 | if ($index == -1) { | |||
568 | 0 | 0 | $index = $p->colorAllocate ($r, $g, $b); | ||||
569 | } | ||||||
570 | 0 | 0 | $p->setPixel ($x, $y, $index); | ||||
571 | } | ||||||
572 | } | ||||||
573 | } | ||||||
574 | ## open IMAGE, ">dummy-$filename.jpg"; | ||||||
575 | ## print IMAGE $p->jpeg (); | ||||||
576 | ## close IMAGE; | ||||||
577 | } | ||||||
578 | 0 | 0 | ($x, $y) = $p->getBounds(); # reuse of $x and $y... | ||||
579 | # my $x = $p->width; | ||||||
580 | # my $y = $p->height; | ||||||
581 | |||||||
582 | # | ||||||
583 | # If I do not resize 600x800 images it does not work on Gen3 | ||||||
584 | # | ||||||
585 | # check this one more time, 600x800 gif and jpeg with size | ||||||
586 | # less than 64K does not work on Gen3 | ||||||
587 | # | ||||||
588 | # pdurrant | ||||||
589 | # as of July 2008, | ||||||
590 | # 600x800 with size less than 61440 does work on Gen3 | ||||||
591 | # so must use the --imagerescale argument to get 600x800. | ||||||
592 | |||||||
593 | 0 | 0 | 0 | 0 | if (defined $scale_factor and $scale_factor != 1.0) { | ||
594 | 0 | 0 | print STDERR "SCALE IMAGE: $scale_factor\n"; | ||||
595 | 0 | 0 | $p = MobiPerl::Util::scale_gd_image ($p, $scale_factor); | ||||
596 | } | ||||||
597 | |||||||
598 | 0 | 0 | 0 | if ($rescale_large_images) { | |||
599 | 0 | 0 | my $xdiff = $x-$maxwidth; | ||||
600 | 0 | 0 | my $ydiff = $y-$maxheight; | ||||
601 | 0 | 0 | 0 | if ($ydiff > $xdiff) { | |||
602 | 0 | 0 | 0 | if ($y > $maxheight) { | |||
603 | 0 | 0 | my $scale = $maxheight*1.0/$y; | ||||
604 | 0 | 0 | $p = MobiPerl::Util::scale_gd_image ($p, $scale); | ||||
605 | } | ||||||
606 | } else { | ||||||
607 | 0 | 0 | 0 | if ($x > $maxwidth) { | |||
608 | 0 | 0 | my $scale = $maxwidth*1.0/$x; | ||||
609 | 0 | 0 | $p = MobiPerl::Util::scale_gd_image ($p, $scale); | ||||
610 | } | ||||||
611 | } | ||||||
612 | } | ||||||
613 | |||||||
614 | # | ||||||
615 | # Scale if scale option given | ||||||
616 | # or does it work just setting width? | ||||||
617 | # | ||||||
618 | |||||||
619 | ## $filename =~ s/\....$/\.gif/; | ||||||
620 | ## print STDERR "UTIL FILENAME: $filename\n"; | ||||||
621 | |||||||
622 | 0 | 0 | my $quality = -1; | ||||
623 | 0 | 0 | my $size = length (MobiPerl::Util::get_gd_image_data ($p, $filename)); | ||||
624 | |||||||
625 | 0 | 0 | 0 | if ($size > $maxsize) { | |||
626 | 0 | 0 | $quality = 100; | ||||
627 | 0 | 0 | 0 | while (length (MobiPerl::Util::get_gd_image_data ($p, $filename, $quality)) > | |||
628 | $maxsize and $quality >= 0) { | ||||||
629 | 0 | 0 | $quality -= 10; | ||||
630 | } | ||||||
631 | 0 | 0 | 0 | if ($quality < 0) { | |||
632 | 0 | 0 | die "Could not shrink image file size for $filename"; | ||||
633 | } | ||||||
634 | } | ||||||
635 | |||||||
636 | ## if ($y < 640 and $x < 480 and defined $opt_scale) { | ||||||
637 | ## my $scale = $opt_scale; | ||||||
638 | ## $p = MobiPerl::Util::scale_gd_image ($p, $scale); | ||||||
639 | ## print STDERR "Rescaling $$scale\n"; | ||||||
640 | ## } | ||||||
641 | |||||||
642 | |||||||
643 | 0 | 0 | $data = MobiPerl::Util::get_gd_image_data ($p, $filename, $quality); | ||||
644 | 0 | 0 | return $data; | ||||
645 | } | ||||||
646 | |||||||
647 | sub iso2hex($) { | ||||||
648 | 6 | 6 | 0 | 10 | my $hex = ''; | ||
649 | 6 | 23 | for (my $i = 0; $i < length($_[0]); $i++) { | ||||
650 | 122 | 168 | my $ordno = ord substr($_[0], $i, 1); | ||||
651 | 122 | 350 | $hex .= sprintf("%lx", $ordno); | ||||
652 | } | ||||||
653 | |||||||
654 | 6 | 16 | $hex =~ s/ $//;; | ||||
655 | 6 | 12 | $hex = "0x$hex"; | ||||
656 | 6 | 23 | return $hex; | ||||
657 | } | ||||||
658 | |||||||
659 | sub fix_html { | ||||||
660 | 0 | 0 | 0 | my $tree = shift; | |||
661 | |||||||
662 | 0 | print STDERR "FIX HTML\n"; | |||||
663 | |||||||
664 | # | ||||||
665 | # Fix strange HTML code | ||||||
666 | # | ||||||
667 | |||||||
668 | 0 | my @paras = $tree->find ("p"); | |||||
669 | 0 | my $inside_para = 0; | |||||
670 | 0 | my $newp; | |||||
671 | 0 | foreach my $p (@paras) { | |||||
672 | 0 | 0 | if (not $inside_para) { | ||||
673 | 0 | $newp = HTML::Element->new("p"); | |||||
674 | 0 | $inside_para = 1; | |||||
675 | } | ||||||
676 | 0 | my $html = $p->as_HTML (); | |||||
677 | ## print STDERR "$html\n"; | ||||||
678 | 0 | 0 | if ($html =~ /\ \;/) { | ||||
679 | ## print STDERR $newp->as_HTML (); | ||||||
680 | 0 | my $h = $newp->as_HTML (); | |||||
681 | ## if ($h =~ /All three Stewards/) { | ||||||
682 | ## last; | ||||||
683 | ## } | ||||||
684 | 0 | $p->replace_with ($newp); | |||||
685 | 0 | $inside_para = 0; | |||||
686 | 0 | print STDERR "P"; | |||||
687 | } else { | ||||||
688 | 0 | my @span = $p->find ("span"); | |||||
689 | 0 | foreach my $span (@span) { | |||||
690 | 0 | $span->replace_with ($span->content_list ()); | |||||
691 | } | ||||||
692 | 0 | $p->normalize_content (); | |||||
693 | 0 | $newp->push_content ($p->content_list ()); | |||||
694 | 0 | $newp->push_content (" "); | |||||
695 | 0 | $p->delete (); | |||||
696 | 0 | print STDERR "+"; | |||||
697 | } | ||||||
698 | } | ||||||
699 | } | ||||||
700 | |||||||
701 | sub fix_html_br { | ||||||
702 | 0 | 0 | 0 | my $tree = shift; | |||
703 | 0 | my $config = shift; | |||||
704 | |||||||
705 | 0 | print STDERR "FIX HTML BR\n"; | |||||
706 | |||||||
707 | # | ||||||
708 | # Fix strange HTML code with instead if
|
||||||
709 | # | ||||||
710 | |||||||
711 | 0 | my $b = $tree->find ("body"); | |||||
712 | 0 | print STDERR "+"; | |||||
713 | 0 | my @content = $b->content_list(); | |||||
714 | 0 | print STDERR "+"; | |||||
715 | 0 | my @paras = (); | |||||
716 | 0 | my $p = HTML::Element->new("p"); | |||||
717 | 0 | push @paras, $p; | |||||
718 | 0 | my $i = 0; | |||||
719 | 0 | while ($i <= $#content) { | |||||
720 | # print STDERR "-"; | ||||||
721 | 0 | my $c = $content[$i]; | |||||
722 | 0 | 0 | 0 | if ($c and ref($c) eq "HTML::Element") { | |||
723 | 0 | my $tag = $c->tag; | |||||
724 | 0 | 0 | 0 | if ($tag eq "br" and ref($c) eq "HTML::Element" and | |||
0 | |||||||
0 | |||||||
0 | |||||||
725 | defined $content[$i+1] and ref ($content[$i+1]) and | ||||||
726 | $content[$i+1]->tag eq "br") { | ||||||
727 | 0 | $p = HTML::Element->new("p"); | |||||
728 | 0 | push @paras, $p; | |||||
729 | 0 | 0 | if ($config->{KEEPBR}) { | ||||
730 | # $p->push_content (HTML::Element->new("br")); | ||||||
731 | 0 | $p->push_content (HTML::Element->new("br")); | |||||
732 | } | ||||||
733 | 0 | $i++; | |||||
734 | 0 | 0 | if ($i % 10 == 0) { | ||||
735 | 0 | print STDERR "P"; | |||||
736 | } | ||||||
737 | } else { | ||||||
738 | # print STDERR $c->as_HTML; | ||||||
739 | 0 | $p->push_content ($c); | |||||
740 | } | ||||||
741 | ## print STDERR "TAG:$tag:\n"; | ||||||
742 | } else { | ||||||
743 | 0 | 0 | if (ref($c)) { | ||||
744 | # print STDERR $c->as_HTML; | ||||||
745 | } else { | ||||||
746 | # print STDERR $c; | ||||||
747 | } | ||||||
748 | 0 | $p->push_content ($c); | |||||
749 | } | ||||||
750 | 0 | $i++; | |||||
751 | } | ||||||
752 | 0 | $b->delete_content (); | |||||
753 | 0 | $b->push_content (@paras); | |||||
754 | } | ||||||
755 | |||||||
756 | sub fix_pre_tags { | ||||||
757 | 0 | 0 | 0 | my $tree = shift; | |||
758 | |||||||
759 | 0 | print STDERR "FIX PRE TAGS\n"; | |||||
760 | |||||||
761 | 0 | my @pres = $tree->find ("pre"); | |||||
762 | |||||||
763 | 0 | foreach my $pre (@pres) { | |||||
764 | 0 | print STDERR "FIX PRE TAGS: $pre\n"; | |||||
765 | 0 | my $p = HTML::Element->new("p", align => "left"); | |||||
766 | |||||||
767 | 0 | my @content = $pre->content_list (); | |||||
768 | 0 | my $text = $content[0]; | |||||
769 | |||||||
770 | |||||||
771 | 0 | my @lines = split ("\n", $text); | |||||
772 | 0 | foreach my $line (@lines) { | |||||
773 | 0 | my $br = HTML::Element->new("br"); | |||||
774 | 0 | $line =~ s/\s/ \;/g; | |||||
775 | |||||||
776 | ## print STDERR $line; | ||||||
777 | 0 | $p->push_content ($line); | |||||
778 | 0 | $p->push_content ($br); | |||||
779 | 0 | $p->push_content ("\n"); | |||||
780 | } | ||||||
781 | 0 | $pre->replace_with ($p); | |||||
782 | } | ||||||
783 | |||||||
784 | } | ||||||
785 | |||||||
786 | sub remove_java_script { | ||||||
787 | 0 | 0 | 0 | my $tree = shift; | |||
788 | |||||||
789 | 0 | print STDERR "REMOVE SCRIPT CODE\n"; | |||||
790 | |||||||
791 | 0 | my @scripts = $tree->find ("script"); | |||||
792 | |||||||
793 | 0 | foreach my $script (@scripts) { | |||||
794 | 0 | print STDERR "REMOVING SCRIPT NODE: $script\n"; | |||||
795 | 0 | $script->detach (); | |||||
796 | } | ||||||
797 | } | ||||||
798 | |||||||
799 | |||||||
800 | return 1; | ||||||
801 | |||||||
802 | __END__ |