web-dev-qa-db-ja.com

画質を損なうことなくJPGからexifを削除するにはどうすればよいですか?

私はPHP写真共有アプリケーションを持っています。このアプリケーションでは、ユーザーがアップロードした画像がImageMagickを使用してさまざまな親指形式にサイズ変更されます。

ファイルサイズを節約するための一見「スマート」な方法として、次のようにこれらの親指からexif情報を取り除きます。

$imagick = new Imagick($image);
$imagick->stripImage();
$imagick->writeImage($image);

これは機能します。 EXIF情報は削除されます。30KBの親指で12KBが節約され、18KBになります。このような親指の多くを1ページに表示すると、大幅に節約できます。

ただし、問題は、それが少しうまく機能しすぎることです。結果の画像は、ストリップされていないバージョンと比較して、多くの色情報を失い、「フラット」に見えるように見えます。

これまでの私の研究に基づくと、私の理論では、次のいずれかまたは両方が当てはまります。

  • Imagickは、ストリッピングプロセスの一環として、重要なカラープロファイル情報を破棄します
  • Imagickは保存時に画像を再圧縮し、品質を低下させます

問題の原因に関係なく、画質や色自体に影響を与えないようにEXIF情報を削除する方法を探しています。

これも可能ですか?

更新:

Gerald Schneiderの回答に基づいて、画像を「ストリップ」する前に、品質設定を100%に強制してみました。

$imagick = new Imagick($image);
$imagick->setCompression(imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(100);
$imagick->stripImage();
$imagick->writeImage($image);

残念ながら、問題は残っています。以下は、品質を100%に設定しても、画像が平坦化される出力例です。

enter image description here

19
Fer

他のすべてのEXIFデータを削除する間、ICCプロファイル(より豊かな色を引き起こす)を維持することを検討してください。

  1. ICCプロファイルを抽出します
  2. EXIFデータと画像プロファイルを削除します
  3. ICCプロファイルを追加し直します

In PHP + imagick:

_$profiles = $img->getImageProfiles("icc", true);

$img->stripImage();

if(!empty($profiles))
    $img->profileImage("icc", $profiles['icc']);
_

(重要な注意:ImageMagick 3.1.0ベータ版を使用すると、getImageProfiles()から得られた結果は documentation とは少し異なります。取得するまでパラメーターを試してみることをお勧めします実際のプロファイルとの連想配列。)

コマンドラインImageMagickの場合:

_convert image.jpg profile.icm
convert image.jpg -strip -profile profile.icm output.jpg
_

もちろん、ImageMagickを使用すると画像は再圧縮されますが、少なくとも色はそのまま残ります。

お役に立てれば。

27
Robbert

誤って保存されたファイルヘッダーのMIMEタイプに同様の変更を加えたので、標準ツールを使用してEXIFデータの長さを確認してから、マルチバイト文字列関数を使用してデータを手動で「ゼロ」にすることをお勧めします。

EXIFはJPEGファイルで最大64KBまでしか使用できませんが、正確に64KBであるかどうかはわかりませんので、これから始めます。

1
oucil