LoginSignup
1
1

More than 3 years have passed since last update.

PowerShellでPDFをPocketMod形式に再レイアウト (PDFSharp版)

Posted at

PowerShellからPDFSharpを呼び出してPDFをPocketMod形式にレイアウトし直します。

オリジナル(拙作)は
https://qiita.com/acknpop/items/dd03f9e9df18eb05b18c
ですが、iTextSharpの利用が信条的に受け入れがたい人のために。

下準備

まず始めに pdfsharp.dll を入手してください。

nugetするのが本筋ですが、下記はスクリプトを置くフォルダにlibというサブフォルダを作って、その下に pdfsharp.dll を入れる方式です。

普通はInstall-Moduleして、Get-Moduleで使うはず。

スクリプト

以下を ConvertTo-PocketMod.ps1 として保存。

ConvertTo-PocketMod.ps1
# Convert PDF To PocketMod style
param(
    [parameter(mandatory=$true)][string]$sourceDataPath,
    [parameter(mandatory=$true)][string]$destinationPath
)

function ConvertTo-PocketMod($sourceDataPath, $destinationPath)
{
    # path of pdfsharp.dll
    [System.Reflection.Assembly]::LoadFrom((Join-Path (Split-Path $script:MyInvocation.MyCommand.Path) "\lib\PdfSharp.dll")) | Out-Null

    [PdfSharp.Drawing.XPdfForm]$form = [PdfSharp.Drawing.XPdfForm]::FromFile([string]$sourceDataPath)

    $pen = New-Object PdfSharp.Drawing.XPen([PdfSharp.Drawing.XColors]::Black, 0.01)
    $dash = New-Object PdfSharp.Drawing.XPen([PdfSharp.Drawing.XColors]::Black, 0.01)
    $dash.DashPattern = @(300, 300)

    try {
        # Output page size
        $pagesize = [PdfSharp.PageSize]::A4
        $doc = New-Object PdfSharp.Pdf.PdfDocument

        for($i = 0; $i -lt $form.PageCount; $i++) {

            if(($i % 8) -eq 0){
                $dst = $doc.AddPage()
                $dst.Size = $pagesize
                [float]$dw = $dst.Width.Value
                [float]$dh = $dst.Height.Value
            }
            [PdfSharp.Drawing.XGraphics]$gfx = [PdfSharp.Drawing.XGraphics]::FromPdfPage($dst)

            $form.PageNumber = $i + 1

            [PdfSharp.Pdf.PdfPage]$src = $form.Page
            [float]$sw = $src.Width.Value
            [float]$sh = $src.Height.Value

            if($sw -gt $sh){
                $isLandscape = $TRUE
            }
            else{
                $isLandscape = $FALSE
            }

            if($isLandscape -eq $TRUE){
                [float]$scale = $dh / ($sh * 4)
                [float]$offset = (($dw / 2) - ($scale * $sw)) / 2
            }
            else{
                [float]$scale = $dh / ( $sw * 4)
                [float]$offset = (($dw / 2) - ($scale * $sh)) / 2
            }

            # Affine translation of PocketMod style
            [float]$px = $dw / 2
            [float]$py = $dh / 4
            [float]$pw = $sw * $scale
            [float]$ph = $sh * $scale

            $rot = $src.Rotate

            if(($isLandscape -eq $TRUE) -or (($rot -eq 90) -or ($rot -eq 270))){
                switch($i % 8){
                    # Left side
                    # Rotate 180 degrees
                    0 {
                        $box = New-Object PdfSharp.Drawing.XRect(-($px - $offset), -($py * 1), $pw, $ph)
                        $gfx.RotateTransform(-180)
                    }
                    7 {
                        $box = New-Object PdfSharp.Drawing.XRect(-($px - $offset), -($py * 2), $pw, $ph)
                        $gfx.RotateTransform(-180)
                    }
                    6 {
                        $box = New-Object PdfSharp.Drawing.XRect(-($px - $offset), -($py * 3), $pw, $ph)
                        $gfx.RotateTransform(-180)
                    }
                    5 {
                        $box = New-Object PdfSharp.Drawing.XRect(-($px - $offset), -($py * 4), $pw, $ph)
                        $gfx.RotateTransform(-180)
                    }

                    # Right side
                    # No rotation
                    1 {
                        $box = New-Object PdfSharp.Drawing.XRect(($px + $offset), ($py * 0), $pw, $ph)
                    }
                    2 {
                        $box = New-Object PdfSharp.Drawing.XRect(($px + $offset), ($py * 1), $pw, $ph)
                    }
                    3 {
                        $box = New-Object PdfSharp.Drawing.XRect(($px + $offset), ($py * 2), $pw, $ph)
                    }
                    4 {
                        $box = New-Object PdfSharp.Drawing.XRect(($px + $offset), ($py * 3), $pw, $ph)
                    }
                }
            }
            else{
                switch($i % 8){
                    # Left side
                    # Rotate counterclockwise 90 degrees
                    0 {
                        $box = New-Object PdfSharp.Drawing.XRect((($py * 0) - $offset), -$px, $pw, $ph)
                        $gfx.RotateTransform(90)
                    }
                    7 {
                        $box = New-Object PdfSharp.Drawing.XRect((($py * 1) - $offset), -$px, $pw, $ph)
                        $gfx.RotateTransform(90)
                    }
                    6 {
                        $box = New-Object PdfSharp.Drawing.XRect((($py * 2) - $offset), -$px, $pw, $ph)
                        $gfx.RotateTransform(90)
                    }
                    5 {
                        $box = New-Object PdfSharp.Drawing.XRect((($py * 3) - $offset), -$px, $pw, $ph)
                        $gfx.RotateTransform(90)
                    }

                    # Right side
                    # Rotate clockwise 90 degrees
                    1 {
                        $box = New-Object PdfSharp.Drawing.XRect(-(($py * 1) + $offset), $px, $pw, $ph)
                        $gfx.RotateTransform(-90)
                    }
                    2 {
                        $box = New-Object PdfSharp.Drawing.XRect(-(($py * 2) + $offset), $px, $pw, $ph)
                        $gfx.RotateTransform(-90)
                    }
                    3 {
                        $box = New-Object PdfSharp.Drawing.XRect(-(($py * 3) + $offset), $px, $pw, $ph)
                        $gfx.RotateTransform(-90)
                    }
                    4 {
                        $box = New-Object PdfSharp.Drawing.XRect(-(($py * 4) + $offset), $px, $pw, $ph)
                        $gfx.RotateTransform(-90)
                    }
                }
            }
            $gfx.DrawImage($form, $box)
            $gfx.Dispose()

            # Draw guide line for folding
            if((($i % 8) -eq 7) -or ($i -eq ($form.PageCount - 1))){

                [PdfSharp.Drawing.XGraphics]$gfx = [PdfSharp.Drawing.XGraphics]::FromPdfPage($dst)

                # draw outside border
                $gfx.DrawRectangle($pen, 0, 0, $dw, $dh)

                # horizontal lines
                $gfx.DrawLine($pen, 0, $dh * 3 / 4, $dw, $dh * 3 / 4)
                $gfx.DrawLine($pen, 0, $dh * 2 / 4, $dw, $dh * 2 / 4)
                $gfx.DrawLine($pen, 0, $dh * 1 / 4, $dw, $dh * 1 / 4)

                # vertical lines
                $gfx.DrawLine($pen, $dw / 2, 0, $dw / 2, $dh * 1 / 4)
                $gfx.DrawLine($pen, $dw / 2, $dh * 3 / 4, $dw / 2, $dh)

                # dashed vertical line
                $gfx.DrawLine($dash, $dw / 2, $dh * 1 / 4, $dw / 2, $dh * 3 / 4)

                $gfx.Dispose()
            }
        }

        $doc.Save($destinationPath)
    }
    catch {
        Write-Error("Error: " + $_.Exception)
    }
}

ConvertTo-PocketMod (Convert-Path $sourceDataPath) $destinationPath

pdfsharp.dllを置いた場所によっては、LoadFromのくだりを書き換える必要があります。

あと、出力ページサイズをA4にハードコーディングしているので、こちらも必要に応じて書き換えてください。

使用例

PowerShellを立ち上げて、

PS> ConvertTo-PocketMod.ps1 PDFファイル (Join-Path $PWD 出力先PDFファイル)

みたいに使います。
※PowerShellは基本絶対パス指定なので、相対パスを使いたい時はConvert-PathやJoin-Pathを組み合わせるようです
※Convert-Pathは指定したフォルダやファイルが存在しないとエラーになるので注意

あとがき

http://www.pdfsharp.net/
にC#で書かれたSampleがあるので、参考にできるかと。

あと、通常PDFの世界では左下が原点(0,0)なのですが、PDFSharpでは左上が原点になるので要注意。
描画位置合わせは強引にやってるので、あまり参考にはならないかも。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1