Skip to content

Instantly share code, notes, and snippets.

@masuidrive
Created April 5, 2010 12:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masuidrive/356303 to your computer and use it in GitHub Desktop.
Save masuidrive/356303 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'cgi'
require 'open-uri'
require 'rubygems'
require 'zipruby'
require 'rmagick'
SUPPORT_FORMAT = /\.(png|jpg)$/
def convertZip(path, epubname)
Zip::Archive.open(epubname, Zip::CREATE, Zip::NO_COMPRESSION) do |epub|
epub.add_or_replace_buffer "mimetype", "application/epub+zip"
end
Zip::Archive.open(epubname) do |epub|
epub.add_or_replace_buffer "META-INF/container.xml", container_xml
xhtmls = []
open(path) do | zipFile |
Zip::Archive.open_buffer(zipFile.read) do |zip|
images = zip.map do |f|
if f.name.match(SUPPORT_FORMAT)
[f.name] + f.name.scan(/(\d+)(\w?)/).map do |num, letter|
"0000000000000000#{num}"[-16,16]+(letter.empty? ? " " : letter)
end
else
nil
end
end
sorted_images = images.compact.sort do |a, b|
flg = nil
[a.length, b.length].min.times do |i|
flg = a[i+1]<=>b[i+1] if flg.nil? && a[i+1]!=b[i+1]
end
flg = 0 if flg.nil?
flg
end # sorted_images
images = []
sorted_images.each_with_index do |name, i|
image = Magick::Image.from_blob(zip.fopen(name.first).read)[0]
image.resize_to_fit!(768, 1024)
epub.add_or_replace_buffer "OEBPS/#{name.first}", image.to_blob
epub.add_or_replace_buffer "OEBPS/#{i}.xhtml", page_xhtml(name.first, name.first, image.columns, image.rows)
xhtmls << ["#{i}.xhtml", name.first]
end
end # open zipFile
end # open path
epub.add_or_replace_buffer "OEBPS/content.opf", content_opf(xhtmls)
epub.add_or_replace_buffer "OEBPS/toc.ncx", toc_ncx(xhtmls)
end # open epub
end
def container_xml
<<__XML__
<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml" />
</rootfiles>
</container>
__XML__
end
def content_opf(files)
<<__XML__
<?xml version="1.0"?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookID" version="2.0">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:title>samp001</dc:title>
<dc:creator opf:role="aut">sample</dc:creator>
<dc:language>ja</dc:language>
<dc:identifier id="BookID" opf:scheme="URL">http://example.com/epub/sample/sample1.epub</dc:identifier>
</metadata>
<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
#{files.map{|f| ' <item id="%s" href="%s" media-type="application/xhtml+xml"/>' % [CGI.escapeHTML(f[0]), CGI.escapeHTML(f[0])]}.join("\n")}
</manifest>
<spine toc="ncx">
#{files.map{|f| ' <itemref idref="%s"/>' % CGI.escapeHTML(f[0])}.join("\n")}
</spine>
</package>
__XML__
end
def toc_ncx(files)
xml = <<__XML__
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"
"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" dir="rtl">
<head>
<meta name="dtb:uid"
content="http://example.com/epub/sample/sample1.epub"/>
<meta name="dtb:depth" content="1"/>
<meta name="dtb:totalPageCount" content="0"/>
<meta name="dtb:maxPageNumber" content="0"/>
</head>
<docTitle>
<text>sample</text>
</docTitle>
<navMap>
__XML__
files.each_with_index do |f, i|
xml += <<__XML__
<navPoint id="navPoint-#{i+1}" playOrder="#{i+1}">
<navLabel>
<text>#{CGI.escapeHTML(f[1].to_s)}</text>
</navLabel>
<content src="#{CGI.escapeHTML(f[0])}"/>
</navPoint>
__XML__
end
xml += <<__XML__
</navMap>
</ncx>
__XML__
end
def page_xhtml(title, img, w, h)
<<__XML__
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>#{CGI.escapeHTML title}</title>
<style>
img { vertical-align: middle; }
</style>
</head>
<body><img src="#{CGI.escapeHTML img}" width="#{CGI.escapeHTML w.to_s}" height="#{CGI.escapeHTML h.to_s}"/></body>
</html>
__XML__
end
convertZip(ARGV[0], "sample.epub")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment