[Qt] QPixmap::save()で保存したpng形式ファイルのサイズが大きすぎるのでpngquantで圧縮した

問題

現象

当ブログのスクリーンショットには主にPNG形式で作成しています。
しかし、自作のQtアプリケーションで保存した大きめのサイズのスクリーンショットが、WordPressの画像管理プラグインにより、JPG形式に変換されていることに気づきました。
これはPNG形式でのファイル容量が設定値を超えていたことにより、JPG形式に圧縮されていたことによるものです。

原因

このアプリケーションは、

  • 画面上でドラッグして範囲選択を行い
  • 選択された範囲の大きさのQPixmapを生成して
  • 指定範囲のスクリーンショットを貼り付け、
  • QPixmap::saveで保存する

という処理を行います。
今回困った点は、上記の処理で保存したpngファイルのサイズが大きくなってしまうことです。

追記 2019/1/25
pngは可逆圧縮が可能なフォーマットで、例えば白色一色の画像などはかなりサイズを小さくできるのですが、QPixmap::saveではそうなりません。単純に画像サイズに比例して容量も大きくなります。
QPixmap::saveにはqualityが指定できますが、これはJPGなどの非可逆圧縮を行うファイル形式のときにのみ関係するものです。

Twitterにてタグ付きでぼやいてみたところ、@hermit4氏よりリプライを頂きました。
その内容をヒントにQtソースコードを確認したところ、Qt単体で「qualityが非可逆圧縮を行うファイル形式のときにのみ関係する」という私の認識が誤りであったことがわかりました。
QPixmap::saveにて、quality=0を指定すると、きちんと圧縮されたpng形式のファイルが出力されるようになっています。詳細はリプライツリーを御覧ください。
その日のうちに解決するとは思っておりませんでした。
@hermit4さん、ありがとうございました。

解決法

力技ですが、餅は餅屋ということで、pngquantを使って圧縮することにしました。
ファイルの保存を終わらせたあと、QProcessを使って作業フォルダにあるpngquant.exeを叩くという方式です。
pngquantのソースをプロジェクトに含める等してもいいのですが、自分用のアプリケーションということもありちょっと横着しています。

// 設定から読み込んでいる変数
QString filepath = "path/to/file";
QString filetype = "png";
// 保存したいスクリーンショット
QPixmap image = ...;

// ファイルの保存
image.save(filepath + "." + filetype, filetype);

// ファイルタイプがpngのとき、pngquantで圧縮
if(filetype == "png"){
    QString command = "./pngquant.exe";
    QStringList args;
    args << "--force" << "--output" << filepath << filepath;
    // コマンド実行(./pngquant.exe --force --output path/to/file.png path/to/file.png)
    QProcess::execute(command, args);
}

これで無事キレイでファイルサイズが最低限のスクリーンショットを保存することが出来るようになりました。