【PowerShell】Dwebpで伸長したPNGをiTextSharpでPDFにまとめる

1607 語
8 分
【PowerShell】Dwebpで伸長したPNGをiTextSharpでPDFにまとめる

はじまり#

リサちゃん avatar
リサちゃん
こいつらwebp形式と来たか・・・
135ml avatar
135ml
それらをPDFにまとめたいな。

DwebpとSystem.Drawing名前空間でPDFに変換可能なJPGを作る。#

今回は、複数枚の webp 画像を PDF として一つにまとめる処理を実装する流れを紹介します。断片化した webp を PDF にまとめることで、ストレージに対してデフラグを行うことが狙いです。

PDF への変換には 「iTextSharp」 を利用していきますが、以前に、 Cwebp で圧縮した JPG が iTextSharp で PDF に変換することが出来なかったため、今回のdwebpツールを使った処理でも同様に、 PDF に変換可能な JPG は作成できないと仮定します。

そこで今回は、 Dwebp ツールで webp を png に伸長・変換して、.NET FrameworkSystem.Drawing名前空間でその png を jpg に変換する。そして、その jpg 画像を PDF にまとめるという流れで、処理を実装していきます。それではやっていきましょう。

全体的な処理のコード#

Dwebp ツールで webp を png に変換して、System.Drawing名前空間でその png を jpg に変換する。

その処理をこの関数で定義します。

Terminal window
function Optimize-ImagesWithDecompressing() {
<#
.SYNOPSIS
Converts multiple WebP images to JPEG format with specified quality.
.DESCRIPTION
This function converts WebP images to JPEG format. It first decompresses each WebP to PNG using dwebp, then compresses the PNG to JPEG using the specified quality.
.PARAMETER pathList
An array of full file paths to the WebP images to be converted.
.PARAMETER suffix
A string suffix to append to the filename before the .png extension during the decompression stage. This suffix is not used in final jpeg filename.
.PARAMETER quality
An integer representing the JPEG compression quality (0-100). 100 is highest quality.
.EXAMPLE
$images = Get-ChildItem -Path "C:\path\to\images" -Filter "*.webp"
Optimize-ImagesWithDecompressing -pathList $images.FullName -suffix "decompressed" -quality 85
.INPUTS
System.Array, System.String, System.Int32
.OUTPUTS
None. Output files are written to disk.
.NOTES
Requires the dwebp tool and System.Drawing assembly.
.LINK
dwebp, [System.Drawing.Image]
#>
[CmdletBinding()]
param (
[array]$pathList,
[string]$suffix,
[int]$quality
)
# Add-Type -AssemblyName System.Drawing
foreach ($file in $pathList) {
$extension = (Get-Item $file.FullName).Extension;
$outputImg1 = "{0}_{1:D2}{2}" -f $file.FullName.Substring(0, $file.FullName.Length - $extension.Length), $suffix, ".png";
Write-Output "<1st Source File Name: $file>";
Optimize-ImageWithDecompressing -ImagePath $file -OutputPath $outputImg1;
$extension = (Get-Item $outputImg1).Extension;
$outputImg2 = "{0}{1}" -f $outputImg1.Substring(0, $outputImg1.Length - $extension.Length), ".jpg";
Write-Output "<2nd Source File Name: $outputImg>";
Optimize-ImageWithCompressing -ImagePath $outputImg1 -OutputPath $outputImg2 -Quality $quality;
$updatedCount++;
Write-Output "----------------";
};
Write-Output("{0} .jpg images converted." -f $updatedCount);
Write-Output "----------------";
}
$targetFolder = (Get-Location).Path;
$imgPathList = Get-ChildItem -Path $targetFolder | Where-Object { $_.Extension -in @(".webp") };
$suffix = "compressed";
$quality = [int]($Args[0]); # 0-100
Optimize-ImagesWithDecompressing $imgPathList $suffix $quality;
$tmp = Read-Host "Input 'y' if you wanna move original images......";
If ($tmp -eq "y") {
Move-Item -Path $imgPathList -Destination .\5_original_files;
$imgPathList = Get-ChildItem -Path $targetFolder | Where-Object { $_.Extension -in @(".png") };
Move-Item -Path $imgPathList -Destination .\5_original_files;
}

Dwebpツールでwebpをpngに変換する。#

「Libwebp」という Google 製のパッケージに、「Dwebp」という機能があるので、その機能を使って webp を png に変換していきます。

変換処理のコードは以下の通りです。実質1行で事足りますが。

Terminal window
function Optimize-ImageWithDecompressing {
# Load System.Drawing assembly
Add-Type -AssemblyName System.Drawing
try {
dwebp $ImagePath -o $OutputPath;
Write-Host "Image decompressed and saved to: $OutputPath";
}
catch {
Write-Error "An error occurred: $_"
}
finally {
if ($image) {
$image.Dispose()
}
}
}

System.Drawing名前空間を使って圧縮する。#

そしたら次に、 Dwebp で変換した PNG ファイルを JPG ファイルとして圧縮していくことにしましょう。この処理を噛ませることで、 PDF のサイズを小さく出来ます。

.NET FrameworkSystem.Drawing名前空間を使って、 JPG を作っていきます。Image.Save メソッドで保存する画像ファイルの圧縮率を指定出来るエンコーダを引数に渡せば、 JPG を圧縮できそうです。

その公式のコードを参考に、 PowerShell として書き直します。そして、以下の関数を呼び出せば JPG に圧縮することが出来ました。

Terminal window
function Optimize-ImageWithCompressing {
param (
[string]$ImagePath,
[string]$OutputPath,
[int]$Quality # 0-100, 100 is highest quality (least compression)
)
# Load System.Drawing assembly
Add-Type -AssemblyName System.Drawing
try {
# Load the image
$image = [System.Drawing.Image]::FromFile($ImagePath)
# Create an EncoderParameter object for quality
$qualityParam = New-Object System.Drawing.Imaging.EncoderParameter(
[System.Drawing.Imaging.Encoder]::Quality, $Quality
)
# Get the JPEG codec
$jpegCodec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageDecoders() | Where-Object { $_.FormatID -eq [System.Drawing.Imaging.ImageFormat]::Jpeg.Guid }
# Create an EncoderParameters object
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
$encoderParams.Param[0] = $qualityParam
# Save the image with the specified quality
$image.Save($OutputPath, $jpegCodec[0], $encoderParams)
Write-Host "Image compressed and saved to: $OutputPath"
}
catch {
Write-Error "An error occurred: $_"
}
finally {
if ($image) {
$image.Dispose()
}
}
}

iTextSharpでPDFにまとめる。#

そしたら次に、圧縮した JPG を iTextSharp で PDF に変換します。

Terminal window
function Merge-ImagesIntoPdfWithITextSharp([array]$imgPathList, [string]$iTextSharpPath) {
Unblock-File -Path $iTextSharpPath;
# [System.Reflection.Assembly]::LoadFrom($iTextSharpPath);
# Add-Type -Path $iTextSharpPath
Add-Type -LiteralPath $iTextSharpPath
# $error[0].Exception.GetBaseException().LoaderExceptions
$ext = ".pdf";
$pdfName = "{0}\{1}{2}" -f $imgPathList[0].DirectoryName, $imgPathList[0].BaseName, $ext;
Write-Output $imgPathList;
Write-Host ("{0}: decided PDF file name`n" -f $MyInvocation.MyCommand.Name);
Write-Output $pdfName;
$doc = New-Object iTextSharp.text.Document;
$pdfWriter = [iTextSharp.text.pdf.PdfWriter]::GetInstance($doc, [System.IO.File]::Create($pdfName))
$doc.Open()
# Get image files to add into PDF.
foreach ($path in $imgPathList) {
Write-Output $path;
Write-Output $path.GetType().FullName;
Write-Output $path.FullName.GetType().FullName;
Write-Host ("{0}: adding an image into a PDF...`n" -f $MyInvocation.MyCommand.Name);
$image = [iTextSharp.text.Image]::GetInstance($path.FullName);
# Scale images to each page size.
$doc.SetPageSize($image);
$doc.NewPage();
$image.SetAbsolutePosition(0, 0);
# $image.ScaleToFit($doc.PageSize.Width, $doc.PageSize.Height);
$image.Alignment = [iTextSharp.text.Image]::ALIGN_CENTER;
$doc.Add($image);
}
$doc.Close();
$pdfWriter.Close();
Write-Host ("{0}: completed adding images into a PDF`n" -f $MyInvocation.MyCommand.Name);
}

今までの一連の処理を行えば、複数の WEBP 画像を1つの PDF にまとめることが出来るようになりました! めでたしめでたし。

ちなみに、Dwebpを飛ばすと失敗する。#

今回、以下の流れで処理を実装しました。

  1. Dwebp で webp を png に変換する。
  2. System.Drawing名前空間で png を jpg に変換する。
  3. iTextSharp で jpg を pdf に変換する。

ちなみに、上記の工程で1の工程をすっ飛ばして、System.Drawing名前空間で webp を jpg に変換しようとすると失敗します。

Optimize-ImageWithDecompressing : An error occurred: "1" 個の引数を指定して "FromFile" を呼び出し中に例外が発生しました : "メモリが不足しています。"
発生場所 C:\Users\...\Z5-9_decompress_webp_to_jpg_with_sys_draw.ps1:88 文字:5 + Optimize-ImageWithDecompressing -ImagePath $file -OutputPath $out ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Optimize-ImageWithDecompressing

まとめ#

今回は、 iTextSharp を PowerShell で叩いて、複数枚の Webp 画像を一つの PDF にまとめる処理を実装する試みでした。

以下が、本記事のまとめです。

  • iTextSharp パッケージで複数の画像ファイルを PDF にまとめることが可能である。 JPG 画像でまとめればサイズをより減らせる。
  • Libwebp パッケージのdwebpツールで、 WEBP 画像ファイルを PNG 画像に変換することが可能である。
  • System.Drawing名前空間で PNG 画像を JPG 画像に変換することが可能である。しかし、 WEBP 画像を変換しようとすると失敗する。

Webp ファイルは高品質で低サイズの画像ファイルを構成できますが、フラグメンテーションを放置するのは勿体ないとも思います。そんな時に使えそうなツールでした。

その他のPowerShell関連の記事#

おしまい#

リサちゃん avatar
リサちゃん
こんなこともあるんだなぁ
135ml avatar
135ml
これでPDFにまとめられます。

以上になります!

記事を共有

この記事が役に立ったなら、ぜひ他の人と共有してください!

【PowerShell】Dwebpで伸長したPNGをiTextSharpでPDFにまとめる
https://endorphinbath.com/posts/powershell-dwebp-into-pdf-itextsharp/
著者
kinkinbeer135ml
公開日
2025-01-02
ライセンス
CC BY-NC-SA 4.0
Profile Image of the Author
kinkinbeer135ml
SIerをやめて、プログラミングを勉強しています。※Amazonアソシエイトに参加しています。
お知らせ
私のブログへようこそ!これはサンプルのお知らせです。
音楽
カバー

音楽

再生中なし

0:00 0:00
歌詞なし
カテゴリ
タグ
サイト統計
記事
287
カテゴリー
8
タグ
93
総文字数
486,174
運用日数
0
最終活動
0 日前

目次