Last active
April 28, 2021 12:51
-
-
Save voodoojello/75bf1862417e869d2108 to your computer and use it in GitHub Desktop.
Create ebook (EPUB) from PNG, JPG, or GIF images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -w | |
# | |
my $app = { | |
'name' => 'img2epub', | |
'desc' => 'Create ebook (EPUB) from PNG, JPG, or GIF images', | |
'modified' => 'Mon Aug 15 06:03:05 CDT 2011', | |
'author' => 'mark page [[email protected]]', | |
'version' => '0.0.1.4b', | |
}; | |
my ($manifest,$spine,$uuid,$firstpage,$coverimg); | |
print '=' x 80 . "\n"; | |
print ' ' . $app->{'name'} . ' v' . $app->{'version'} . ' - ' . $app->{'desc'} . "\n"; | |
print ' ' . $app->{'modified'} . ' - ' . $app->{'author'} . "\n"; | |
print '=' x 80 . "\n\n"; | |
print ' Path: '; chomp(my $path = <STDIN>); | |
print ' Title: '; chomp(my $title = <STDIN>); | |
print ' Author: '; chomp(my $author = <STDIN>); | |
unless ($title & $path & $author) { die 'Not enough input!'; } | |
unless (stat("$path")) { die 'Invalid image path!'; } | |
print "\n"; | |
print ' >> Creating EPUB Directory structure.' . "\n"; | |
`mkdir ./"$title"`; | |
`mkdir ./"$title"/META-INF`; | |
`mkdir ./"$title"/OEBPS`; | |
`mkdir ./"$title"/OEBPS/Text`; | |
`mkdir ./"$title"/OEBPS/Images`; | |
print ' >> Generating local (pseudo) UUID.' . "\n"; | |
my $uuid_raw = '00000000-0000-0000-0000-000000000000'; | |
for my $i (0 .. length($uuid_raw)) { | |
if (substr($uuid_raw,$i,1) ne '-') { | |
$uuid .= int(rand(9)); | |
} | |
else { | |
$uuid .= substr($uuid_raw,$i,1); | |
} | |
} | |
print ' >> Copying Images and Writing OEBPS data...' . "\n"; | |
chomp(my @imgs = `ls "$path"/*.png *.jpg *.gif 2>/dev/null`); #*/ | |
for $i (0 .. (scalar(@imgs) - 1)) { | |
my $imgname = (split('/',$imgs[$i]))[-1]; | |
my $imgtype = substr($imgname,-3,3); | |
my $alttype = (split('_',$imgname))[0]; | |
my $number = (split('_',$imgname))[-1]; | |
$number =~ s/\.png//; $number =~ s/\.jpg//; $number =~ s/\.gif//; | |
if ($number =~ m/0000/i or $number =~ m/cover/i) { | |
$alttype = 'cover'; | |
$firstpage = 'content' . $number . '.xhtml'; | |
$coverimg = $imgname; | |
} | |
else { | |
$alttype = $alttype . $number; | |
} | |
`cp "$imgs[$i]" ./"$title"/OEBPS/Images/$imgname`; | |
$manifest .= "\t\t" . '<item href="Images/' . $imgname . '" id="' . $imgname . '" media-type="image/' . $imgtype . '" />' . "\n"; | |
$manifest .= "\t\t" . '<item href="Text/content' . $number . '.xhtml" id="content' . $number . '.xhtml" media-type="application/xhtml+xml" />' . "\n"; | |
$spine .= "\t\t" . '<itemref idref="content' . $number . '.xhtml" />' . "\n"; | |
open (XML,'>',"./$title/OEBPS/Text/content$number.xhtml"); | |
print XML '<?xml version="1.0" encoding="utf-8" standalone="no"?>' . "\n"; | |
print XML '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"' . "\n"; | |
print XML ' "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' . "\n\n"; | |
print XML '<html xmlns="http://www.w3.org/1999/xhtml">' . "\n"; | |
print XML '<head>' . "\n"; | |
print XML ' <title></title>' . "\n"; | |
print XML '</head>' . "\n\n"; | |
print XML '<body>' . "\n"; | |
print XML ' <div><img alt="' . $alttype . '" src="../Images/' . $imgname . '" /></div>' . "\n"; | |
print XML '</body>' . "\n"; | |
print XML '</html>' . "\n"; | |
close(XML); | |
} | |
# mimetype | |
print ' >> Writing MIMETYPE data identifier' . "\n"; | |
open(MIME,'>',"./$title/mimetype"); | |
print MIME 'application/epub+zip'; | |
close(MIME); | |
# container.xml | |
print ' >> Writing META-INF (container) data.' . "\n"; | |
open(META,'>',"./$title/META-INF/container.xml"); | |
print META '<?xml version="1.0" encoding="UTF-8"?>' . "\n"; | |
print META '<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">' . "\n"; | |
print META ' <rootfiles>' . "\n"; | |
print META ' <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>' . "\n"; | |
print META ' </rootfiles>' . "\n"; | |
print META '</container>' . "\n"; | |
close(META); | |
# toc.ncx | |
print ' >> Writing TOC/NCX data.' . "\n"; | |
open(TOC,'>',"./$title/OEBPS/toc.ncx"); | |
print TOC '<?xml version="1.0" encoding="utf-8"?>' . "\n"; | |
print TOC '<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"' . "\n"; | |
print TOC ' "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">' . "\n\n"; | |
print TOC '<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">' . "\n"; | |
print TOC '<head>' . "\n"; | |
print TOC ' <meta name="dtb:uid" content="urn:uuid:' . $uuid . '" />' . "\n"; | |
print TOC ' <meta name="dtb:depth" content="0" />' . "\n"; | |
print TOC ' <meta name="dtb:totalPageCount" content="0" />' . "\n"; | |
print TOC ' <meta name="dtb:maxPageNumber" content="0" />' . "\n"; | |
print TOC '</head>' . "\n"; | |
print TOC '<docTitle>' . "\n"; | |
print TOC ' <text></text>' . "\n"; | |
print TOC '</docTitle>' . "\n"; | |
print TOC '<navMap>' . "\n"; | |
print TOC ' <navPoint id="navPoint-1" playOrder="1">' . "\n"; | |
print TOC ' <navLabel>' . "\n"; | |
print TOC ' <text>' . $title . '</text>' . "\n"; | |
print TOC ' </navLabel>' . "\n"; | |
print TOC ' <content src="Text/' . $firstpage . '" />' . "\n"; | |
print TOC ' </navPoint>' . "\n"; | |
print TOC '</navMap>' . "\n"; | |
print TOC '</ncx>' . "\n"; | |
close(TOC); | |
# content.opf | |
print ' >> Writing OPF content data.' . "\n"; | |
open(OPF,'>',"./$title/OEBPS/content.opf"); | |
print OPF '<?xml version="1.0" encoding="utf-8" standalone="yes"?>' . "\n"; | |
print OPF '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId" version="2.0">' . "\n"; | |
print OPF ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">' . "\n"; | |
print OPF ' <dc:identifier id="BookId" opf:scheme="UUID">urn:uuid:' . $uuid . '</dc:identifier>' . "\n"; | |
print OPF ' <dc:title>' . $title . '</dc:title>' . "\n"; | |
print OPF ' <dc:creator opf:role="aut">' . $author . '</dc:creator>' . "\n"; | |
print OPF ' <dc:language>en</dc:language>' . "\n"; | |
print OPF ' <meta content="' . $coverimg . '" name="cover" />' . "\n"; | |
print OPF ' </metadata>' . "\n"; | |
print OPF ' <manifest>' . "\n"; | |
print OPF ' <item href="toc.ncx" id="ncx" media-type="application/x-dtbncx+xml" />' . "\n"; | |
print OPF $manifest . "\n"; | |
print OPF ' </manifest>' . "\n"; | |
print OPF ' <spine toc="ncx">' . "\n"; | |
print OPF $spine . "\n"; | |
print OPF ' </spine>' . "\n"; | |
print OPF ' <guide>' . "\n"; | |
print OPF ' <reference href="Text/' . $firstpage . '" title="Cover" type="cover" />' . "\n"; | |
print OPF ' </guide>' . "\n"; | |
print OPF '</package>' . "\n"; | |
close(OPF); | |
print ' >> Compressing EPUB...' . "\n"; | |
`cd ./"$title"/ \&\& zip -r -0 "../$title\.epub" *`; | |
print ' >> Done.' . "\n\n"; | |
exit; | |
__END__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This script was designed to be used in conjunction with GIMP and the "Export Layers as PNG" plugin (http://registry.gimp.org/node/18440). Images should be sized for device, non-rotated, portrait recommended. Cover may be designated with a "0000" numerical name context or by simply using the text "cover" anywhere in the file name.
Note: This will run on Linux or MacOS. Requires a base Cygwin installation on Win32/64.