EXIFデータを失うことなく、Pythonで画像のサイズを変更します
-
03-07-2019 - |
質問
元の画像のEXIFデータ(撮影日、カメラモデルなどに関するメタデータ)を失うことなく、Pythonでjpg画像のサイズを変更する必要があります。 Pythonと画像に関するすべてのGoogle検索は、現在使用しているPILライブラリを指しますが、メタデータを保持できないようです。これまでに(PILを使用して)持っているコードは次のとおりです。
img = Image.open('foo.jpg')
width,height = 800,600
if img.size[0] < img.size[1]:
width,height = height,width
resized_img = img.resize((width, height), Image.ANTIALIAS) # best down-sizing filter
resized_img.save('foo-resized.jpg')
アイデアはありますか?または私が使用できる他のライブラリ?
解決
import jpeg
jpeg.setExif(jpeg.getExif('foo.jpg'), 'foo-resized.jpg')
他のヒント
pyexiv2を使用して、ソースイメージからEXIFデータをコピーできます。次の例では、PILライブラリを使用して画像のサイズが変更され、pyexiv2でコピーされたEXIFデータと画像サイズのEXIFフィールドが新しいサイズに設定されます。
def resize_image(source_path, dest_path, size):
# resize image
image = Image.open(source_path)
image.thumbnail(size, Image.ANTIALIAS)
image.save(dest_path, "JPEG")
# copy EXIF data
source_image = pyexiv2.Image(source_path)
source_image.readMetadata()
dest_image = pyexiv2.Image(dest_path)
dest_image.readMetadata()
source_image.copyMetadataTo(dest_image)
# set EXIF image size info to resized size
dest_image["Exif.Photo.PixelXDimension"] = image.size[0]
dest_image["Exif.Photo.PixelYDimension"] = image.size[1]
dest_image.writeMetadata()
# resizing local file
resize_image("41965749.jpg", "resized.jpg", (600,400))
実際には、PILのみでEXIFデータを画像から別の画像にコピーする非常に簡単な方法があります。ただし、exifタグを変更することはできません。
image = Image.open('test.jpg')
exif = image.info['exif']
# Your picture process here
image = image.rotate(90)
image.save('test_rotated.jpg', 'JPEG', exif=exif)
ご覧のとおり、保存機能はexif引数を取ることができ、保存時に新しい画像に生のexifデータをコピーできます。それがやりたいのであれば、実際には他のライブラリは必要ありません。保存オプションに関するドキュメントが見つからないようで、それがPillowに固有なのかPILでの作業なのかさえわかりません。 (誰かが何らかのリンクを持っているなら、コメントでそれを投稿していただければ幸いです)
ImageMagick を使用しないのはなぜですか?
これは非常に標準的なツールです(たとえば、Gallery 2で使用される標準的なツールです)。使用したことはありませんが、 pythonインターフェースも備えています(または、また、単にコマンドを生成します)、そして何よりも、すべての変換の間でEXIF情報を維持する必要があります。
pyexiv2 v0.3.2の場合、 APIドキュメントは、あるイメージから別のイメージにEXIFデータを引き継ぐためのコピー方法を指します。この場合、元の画像のEXIFデータからサイズ変更された画像になります。
@Maksym Kozlenkoを終了すると、EXIFデータをコピーするための更新されたコードは次のとおりです。
source_image = pyexiv2.ImageMetadata(source_path)
source_image.read()
dest_image = pyexiv2.ImageMetadata(dest_path)
dest_image.read()
source_image.copy(dest_image,exif=True)
dest_image.write()
pyexiv2を使用して、保存後にファイルを変更できます。
2018年現在の更新された回答です。 piexif は、pip(pip install piexif)を使用して簡単にインストールでき、きれいに機能する(メンテナーに感謝!)純粋なpythonライブラリです。 https://pypi.org/project/piexif/
使用方法は非常に簡単です。1行で受け入れられた回答を複製し、すべてのEXIFタグを元の画像からサイズ変更された画像にコピーします。
import piexif
piexif.transplant("foo.jpg", "foo-resized.jpg")
まだ試していませんが、リンクされたドキュメントに記載されているように、load、dump、およびinsert関数を使用して簡単に変更を実行できるようです。
PILはEXIFデータを処理しますか? PIL.ExifTagsを見てください。
from PIL import Image
img_path = "/tmp/img.jpg"
img = Image.open(img_path)
exif = img.info['exif']
img.save("output_"+img_path, exif=exif)
Pillow 2.5.3でテスト済み
@Depadoのソリューションは私には機能しないようです。私のシナリオでは、画像にはexifセグメントさえ含まれていません。
pyexiv2をMacにインストールするのは難しいですが、代わりにモジュールpexif httpsを使用します://github.com/bennoleslie/pexif/blob/master/pexif.py 。 「exifセグメントを追加」するには画像にexif情報が含まれていない場合、exifセグメントを所有する画像に含まれるexif情報を追加しました
from pexif import JpegFile
#get exif segment from an image
jpeg = JpegFile.fromFile(path_with_exif)
jpeg_exif = jpeg.get_exif()
#import the exif segment above to the image file which does not contain exif segment
jpeg = JpegFile.fromFile(path_without_exif)
exif = jpeg.import_exif(jpeg_exif)
jpeg.writeFile(path_without_exif)