2023/05/04

【Python】画像ファイルのPDF変換を並列処理で高速化する

これまでに何度も画像ファイルのPDF変換の記事を書いてきたのですが、これまでの変換プログラムの中で最も高速かつ簡単に動作していたのは、「img2pdf」でした。
img2pdfの使い方や速度比較などは、下記の過去記事にて紹介していますのでご参照ください。


これまで記事を作成する中で得られた経験から、concurrent.futuresで並列処理を実装すると、(動かすマシン次第ですが、)処理速度が結構早くなる可能性が見えてきました。
本記事では、並列処理を実装することでimg2pdfの処理速度を超えることを目指した結果をご紹介します。

本記事では、下記の三通りの比較を行います。
  • Method1: img2pdfを使用する
  • Method2: pikepdfとPillowを使用する
  • Method3: Method2をconcurrent.futuresで並列処理
前回までの記事と同様に、書籍をスキャンしたpngファイル(連番ファイル名)群を、pdfに変換することを想定しています。

実行環境は、以下の通りです。
MacBook Air(8コアCPU、10コアGPU、16コアNeural Engine搭載Apple M2チップ, 16GBメモリ)
------
Python 3.10.10
img2pdf 0.4.4
pikepdf 7.1.1
Pillow 9.3.0

Method1 : img2pdfを使う


Method2: pikepdfとPillowを使用する


Method3: Method2をconcurrent.futuresで並列処理

ライブラリとして、下記のようにpic2pdfという名前で整理しました。
一部の関数はimg2pdfのように動かせます。

10個の異なるpng画像ファイル群での出力ファイルサイズと実行時間の比較は、以下の通りです。


まとめ

今回作成したMethod2やMethod3による出力は、img2pdfで作成したPDFと完全に同じサイズのPDFにはなりませんでした。 img2pdfはロスレスらしいので、今回作成したものとは異なる処理でロスレスを実現しているみたいです。
なので、Method2やMethod3による出力はロスレスではなく、注意が必要です。

Method2は、img2pdfのソースコード(4000行超)と比較すればかなりシンプルに書くことができましたが、変換処理に2~3倍時間がかかっています。
それをconcurrent.futuresで並列処理を実装して、力技で高速化したのがMethod3です。あくまで、私の環境での計測結果になりますが、Method2よりも5倍以上早くなっています。
結果的に、img2pdfと比較して、半分程度で処理されるようになりました。また、プログレスバーを実装したので、処理時間が長い場合でも処理が動いていることが分かるようになりました。

今後も改良を重ねて、行こうと考えているので気になる方はGithubの方をチェックして下さい。

下記のようなPDF変換用のプログラムも作成していますので、今回の成果は、こちらで使用しようと考えています。

2023/03/26

【商品比較】 NTM-E50 vs YRM-N50

山善が販売している平台車の比較


山善が販売している平台車は複数ありますが、以下の2つの商品は、共に連結機能とスタッキング機能を売りにしています。
最大荷重量は異なりますが、画像や商品情報を見ても非常によく似ており、違いが分かりにくいです。

商品情報を表にすると以下の通り。

品番 NTM-E50 YRM-N50
サイズ 幅27.5×奥行41×高さ7.7cm 幅27.5×奥行41×高さ7.7cm
重量 1.2kg 1.2kg
最大荷重 80kgまで 100kgまで
材質 本体:PP
キャスター:エラストマー
本体:PP耐衝撃性
キャスター:ナイロン
オリーブドラブ
ダークブラウン
モカ
ローズピンク
オリーブドラブ(OD)
ブラック(GY)
原産国 日本 日本
特徴 縦・横方向へ簡単に連結が可能
スタッキング(積み重ね)が可能
360度回転の自在キャスター
縦・横方向へ簡単に連結が可能
スタッキング(積み重ね)が可能
360度回転の自在キャスター


結論:キャスターの素材のみが異なる。連結機能に互換性あり。


実際に、二つとも商品を購入してみたところ、連結機能に互換性がありました。


NTM-E50のエラストマー製キャスターは、家庭のフローリングなどの屋内の床で使用するには適しています。逆に、工場のような環境であれば、薬品類に強いナイロンキャスターのYRM-N50が適しています。
商品の色や最大荷重以外の違いとして、ここが最も大きな点です。

無印良品のポリプロピレン平台車


画像や商品情報を見る限り、NTM-E50と非常に似ています。
山善では販売していない白色相当…?


山善以外が販売元の商品にも同じ型のものがありそうです。この手の情報は公式がまとめて欲しいですが、事情があるのかも知れません。

2023/03/17

【Python】自作のPythonパッケージをPyPIに登録しました!

今回は、自作のPythonパッケージをPyPIに登録することができたので報告したいと思います。

作成したパッケージは、以前の記事などで、作ってきたものを拡張したもので、自炊した漫画の画像ファイルをpdfに変換するためのプログラムです。別の記事で作ったePubからpdfに変換するプログラムも組み込んでいます。

PyPIへの登録手順は、他のサイトでも紹介されているため、ここでは割愛します。詳しい手順は、参考記事などをご確認ください。

参考記事:
setup.pyファイルの書き方も初めてだったので、ドキュメントを読みながら苦労しました。結局、setup.pyファイルでミスをしてしまい、PyPIにファイルをあげて直ぐに更新版をリリースすることになってしまいました。
似たような名前のパッケージがすでに登録されていることもあるので、パッケージ名を考えるところが難しいかもしれません。

今回、私が登録したPythonパッケージのソースコードは以下のGitHubリポジトリで閲覧することができます。また、改良のアイデアやバグ報告などがあれば、Github上でIssueを立てていただければ幸いです。

2023/02/14

【Python】foliumでGoogle Mapのマーカーアイコンを表示する

以前もfolium関連で似たような記事を書きましたが、今回は別の機能を試してみます。

folium.features.CustomIcon()は、自作のアイコンなどを表示するための機能ですが、自前の画像でなくても指定できるようなので、Googleがホストしているアイコン画像を試してみました。
また、今回の記事からGithub Gistを使って、コードだけでなく、実行結果のマップのhtmlを記事に埋め込んでいます。過去の記事の一部も書き換えました。

参考: 実装例: 実行例:

注意点:ループを使用して、複数点に同じカスタムアイコンを設定する際には、ループ内でカスタムアイコンを初期化する必要がある。

参考:
Google Chart APIで数字のアイコンを設定した例:
二桁までの数字なら問題なく表示できそうです。
実行例:

2023/01/07

【Python】複数枚のPNG画像をJPEGに圧縮してPDFに変換する

過去に何度もimg2pdfを利用した複数画像からPDFへの変換を記事にしていますが、本記事ではPNG画像をJPEG画像に圧縮してからPDFに変換する方法を試します。
PNG画像とJPEG画像の特性については解説しませんが、PDFにした時のファイルサイズの削減が目的です。 変換処理を挟むので、処理時間が増加しますがファイルサイズ低減のメリットが大きければ採用する価値があると思います。
以前の記事に倣って、またいくつかの手法を比較しました。

実行環境は、以下の通りです。
------
MacBook Air (M2, 2022, メモリ:16 GB)
Python 3.10.9
img2pdf 0.4.4
Pillow 9.3.0


Method1 : 画像変換によって圧縮してからPDFにする(PNG画像→JPEG画像→PDF):本記事のタイトルの手法

Method2 : img2pdfをだけ使う(PNG画像→PDF, ロスレス):以前の記事の中で書いたもの

Method3 : Pillowだけを使う(PNG画像→PDF, 圧縮):以前の記事の中で書いたもの

Method4 : Pillowだけを使う(PNG画像→PDF, 圧縮):Method3をconcurrent.futuresで並列化(Method1でもconcurrent.futuresを使用して並列化による高速化を試したため比較)

10個の異なるpng画像ファイル群での出力ファイルサイズと実行時間の比較は、以下の通りです。

Method1とMethod2の比較から分かりますが、JPEGに一度変換することでファイルサイズが小さくなり、処理速度も上がっています。
Method3とMethod4では、ファイル変換処理は同じなので当然出力ファイルサイズは同じですが、Method3とMethod4の比較から並列化の効果が分かります。今回使用した環境では、だいたい半分の時間で処理できています。


img2pdfで扱えないアルファチャンネルのある透過PNG画像も、Method1を使えば取り扱えそうです。