書籍をスキャンした画像ファイルを書籍ごとにzip形式で保存しているのですが、そのzipファイルを電子書籍フォーマットのepub形式に変換するPowerShellスクリプトを作りました。
実行するにあたり、圧縮しないzipファイルの作り方がわからなかったので、7-zipを使っています。7-zipを適時インストールしてください。
<#
.SYNOPSIS
zipファイルをepubに変換
.DESCRIPTION
7z.exeが必要です。
.EXAMPLE
PS>.\epub.ps1 <変換元zipファイル> <変換先epubファイル>
#>
param(
$inFileName = "H:\powershell\epub\sample.zip",
$outFileName = "H:\powershell\epub\sample_out.epub"
)
Add-Type -AssemblyName System.IO.Compression.FileSystem
$zipPath = "H:\tools\7-ZipPortable\App\7-Zip64\7z.exe"
function Convert-ZipToEpub
{
param(
$inFileName,
$outFileName
)
$tmpDir = (Join-Path (Resolve-Path ".").Path "epub")
if ((Test-Path $tmpDir) -eq $false)
{
mkdir $tmpDir | Out-Null
}
echo "application/epub+zip" | Set-Content (Join-Path $tmpDir "mimetype") -Encoding UTF8
if (Test-Path $outFileName)
{
rm $outFileName
}
& $zipPath a -mm=Copy -tzip $outFileName (Join-Path $tmpDir "mimetype")
rm (Join-Path $tmpDir "mimetype")
$metaInfDir = (Join-Path $tmpDir "META-INF")
if ((Test-Path $metaInfDir) -eq $false)
{
mkdir $metaInfDir | Out-Null
}
$textDir = (Join-Path $tmpDir "text")
if ((Test-Path $textDir) -eq $false)
{
mkdir $textDir | Out-Null
}
$imageDir = (Join-Path $tmpDir "images")
if ((Test-Path $imageDir) -eq $false)
{
mkdir $imageDir | Out-Null
}
# 目次
$navStr = @"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<title>nav</title>
</head>
<body>
<nav epub:type="toc">
<ol>
"@
# パッケージ
$title = (Get-Item $inFileName).BaseName
$guid = (New-Guid).Guid
$date = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
$bookStr = @"
<?xml version="1.0" encoding="UTF-8"?>
<package unique-identifier="pub-id" version="3.0" xmlns="http://www.idpf.org/2007/opf">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:identifier id="pub-id">urn:uuid:${guid}</dc:identifier>
<dc:title>${title}</dc:title>
<dc:language>ja-JP</dc:language>
<meta property="dcterms:modified">${date}</meta>
<meta name="cover" content="cover"/>
</metadata>
<manifest>
<item id="nav" href="./text/nav.xhtml" properties="nav" media-type="application/xhtml+xml" />
"@
$spineStr = ""
$zip = [System.IO.Compression.ZipFile]::OpenRead($inFileName)
$zip.Entries | % -Begin{ $i = 0 } -Process {
$i++
echo $_.fullName
$name = $_.Name
$fullName = $_.fullName
# ページ画像ファイル
$fs = $zip.GetEntry($fullName).Open()
$img = [System.Drawing.Image]::FromStream($fs)
$fs.Close()
$imagePath = (Join-Path $imageDir $name)
$img.Save($imagePath)
$img.Dispose()
$baseName = (Get-ChildItem $imagePath).BaseName
# ページHTML
$html = [XML]@"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>${baseName}</title>
</head>
<body>
<img src="../images/${name}"/>
</body>
</html>
"@
$htmlPath = Join-Path $textDir ($baseName + ".xhtml")
$html.Save($htmlPath)
# 目次
$navStr += @"
`n <li><a href="${baseName}.xhtml">${baseName}</a></li>
"@
# パッケージ
$mime = switch ((Get-ChildItem $imagePath).Extension.ToUpper())
{
".PNG" {"image/png"}
".JPEG" {"image/jpeg"}
".JPG" {"image/jpeg"}
".BMP" {"image/bmp"}
".TIFF" {"image/tiff"}
}
$imgID = "img_${baseName}"
if ($i -eq 1)
{
$imgID = "cover"
}
$bookStr += @"
`n <item id="${imgID}" href="./images/${name}" media-type="${mime}" />
<item id="${baseName}" href="./text/${baseName}.xhtml" media-type="application/xhtml+xml" />
"@
$spineStr += @"
`n <itemref idref="${baseName}" />
"@
}
$zip.Dispose()
# 目次
$navStr += @"
`n </ol>
</nav>
</body>
</html>
"@
$nav = [XML]$navStr
$navPath = Join-Path $textDir "nav.xhtml"
$nav.Save($navPath)
# パッケージ
$bookStr += @"
`n </manifest>
<spine page-progression-direction="rtl">
"@
$bookStr += $spineStr
$bookStr += @"
`n </spine>
</package>
"@
$book = [XML]$bookStr
$bookPath = Join-Path $tmpDir "book.opf"
$book.Save($bookPath)
# コンテナ
$container = [XML]@"
<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="book.opf" media-type="application/oebps-package+xml" />
</rootfiles>
</container>
"@
$containerPath = Join-Path $metaInfDir "container.xml"
$container.Save($containerPath)
& $zipPath u -mm=Copy -tzip -r $outFileName ($tmpDir+"\*")
# テンポラリディレクトリの削除
rmdir -Force -Recurse $tmpDir | Out-Null
}
Convert-ZipToEpub $inFileName $outFileName
epubの仕様書を読もうと努力しましたが、早々に挫折した人間が作成しているので、スクリプトの精度はご察しください。
とりあえず出来上がったepubファイルがCalibreで読み込めることを確認しています。
コメント