| 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 | 478 | eval 'require GD'; | |||
| 23 | } | ||||||
| 24 | |||||||
| 25 | 9 | 9 | 36 | use strict; | |||
| 9 | 18 | ||||||
| 9 | 317 | ||||||
| 26 | |||||||
| 27 | our $VERSION = 2011.11.26; | ||||||
| 28 | |||||||
| 29 | 9 | 9 | 6066 | use Module::Loaded; | |||
| 9 | 5220 | ||||||
| 9 | 561 | ||||||
| 30 | 9 | 9 | 6861 | use Image::BMP; | |||
| 9 | 66595 | ||||||
| 9 | 425 | ||||||
| 31 | 9 | 9 | 8089 | use Image::Size; | |||
| 9 | 45710 | ||||||
| 9 | 492 | ||||||
| 32 | 9 | 9 | 6500 | use File::Copy; | |||
| 9 | 20989 | ||||||
| 9 | 500 | ||||||
| 33 | 9 | 9 | 108 | use File::Spec; | |||
| 9 | 18 | ||||||
| 9 | 191 | ||||||
| 34 | |||||||
| 35 | 9 | 9 | 9216 | use HTML::TreeBuilder; | |||
| 9 | 240643 | ||||||
| 9 | 108 | ||||||
| 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 | 9 | my $hex = ''; | ||
| 649 | 6 | 21 | for (my $i = 0; $i < length($_[0]); $i++) { | ||||
| 650 | 122 | 145 | my $ordno = ord substr($_[0], $i, 1); | ||||
| 651 | 122 | 343 | $hex .= sprintf("%lx", $ordno); | ||||
| 652 | } | ||||||
| 653 | |||||||
| 654 | 6 | 12 | $hex =~ s/ $//;; | ||||
| 655 | 6 | 10 | $hex = "0x$hex"; | ||||
| 656 | 6 | 20 | 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__ |