結果は 目視で差異はない!
でした。左側が JPEG 圧縮『1回』、右側が JPEG 圧縮『100万回』です。目視での差異はなさそうです。
もっと劇的に差が出ると思っていたので、これはこれでビックリです。
検証内容
手作業で 100 万回 JPEG 圧縮を試すのもナチュラルに狂ってて一興かと思いましたが、仮に1秒に1回圧縮できたとしても 228 時間(11日半)かかることが分かったので、今回はプログラムを書きました。(プログラムって素晴らしい)
プログラムは Node.js 環境で動作する TypeScript のコードです。JPEG 圧縮には sharp というライブラリを使用しています。
以下にメインコードを載せます。
import * as sharp from "sharp";
async function main() {
// 元の画像を読み込んでバッファーとして保持
let buffer = await sharp(`./assets/src.jpg`).toBuffer();
// 100万回試行する
for (let i = 0; i < 1000000; i++) {
// jpeg圧縮を行う
buffer = await sharp(buffer)
.jpeg({ quality: 30 })
.toBuffer();
// ログ表示
console.log(` i="${i}"`);
}
// jpeg圧縮を行った画像を保存する
await sharp(buffer).toFile(`out.jpg`);
}
main();
(1) import 部分
import * as sharp from "sharp";
JPEG 圧縮を行うために sharp というパッケージをインポートしています。
sharp は Node.js で様々な画像処理を行うためのライブラリですが、今回はファイルの読み込み・JPEG圧縮・保存処理を任せています。
(2) 画像ファイルの読み込み
// 元の画像を読み込んでバッファーとして保持
let buffer = await sharp(`./assets/src.jpg`).toBuffer();
sharp で、元となる画像ファイルを読み込んで、バッファー形式でメモリ上に保持しています。
(3) 100万回 JPEG 圧縮を行う
// 100万回試行する
for (let i = 0; i < 1000000; i++) {
// jpeg圧縮を行う
buffer = await sharp(buffer)
.jpeg({ quality: 30 })
.toBuffer();
// ログ表示
console.log(` i="${i}"`);
}
for
文で 100 万回繰り返しています。.jpeg({ quality: 30 })
で JPEG 品質を指定して圧縮を行い、.toBuffer()
でメモリ上で保持できる形式にしています。
プログラムを駆使しても 100 万回の JPEG 圧縮には時間がかかるので、console.log( … )
にて試行回数を表示しています。
(4) 画像ファイルの保存
// jpeg圧縮を行った画像を保存する
await sharp(buffer).toFile(`out.jpg`);
100 万回 JPEG 圧縮が終わった画像データをファイルに保存しています。
おわりに
結果は冒頭に記載した通り、目視での差異は見られませんでした。試す前は『圧縮を繰り返すことで、どんどん劣化する』と思っていただけに以外な結果でした。
なお、今回検証のために作成したプログラムは GitHub でも公開してあります。
MIT ライセンスとしていますので、ご自由にお使いください。