在 Python 中调整图像大小而不会丢失 EXIF 数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/400788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:00:58  来源:igfitidea点击:

Resize image in Python without losing EXIF data

pythonimage-processingpython-imaging-libraryexif

提问by Einar Egilsson

I need to resize jpg images with Python without losing the original image's EXIF data (metadata about date taken, camera model etc.). All google searches about python and images point to the PIL library which I'm currently using, but doesn't seem to be able to retain the metadata. The code I have so far (using PIL) is this:

我需要使用 Python 调整 jpg 图像的大小,而不会丢失原始图像的 EXIF 数据(有关拍摄日期、相机型号等的元数据)。所有关于 python 和图像的谷歌搜索都指向我目前使用的 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')

Any ideas? Or other libraries that I could be using?

有任何想法吗?或者我可以使用的其他库?

采纳答案by jfs

import jpeg
jpeg.setExif(jpeg.getExif('foo.jpg'), 'foo-resized.jpg') 

http://www.emilas.com/jpeg/

http://www.emilas.com/jpeg/

回答by Maksym Kozlenko

You can use pyexiv2 to copy EXIF data from source image. In the following example image is resized using PIL library, EXIF data copied with pyexiv2 and image size EXIF fields are set with new size.

您可以使用 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))

回答by Depado

There is actually a really simple way of copying EXIF data from a picture to another with only PIL. Though it doesn't permit to modify the exif tags.

实际上有一种非常简单的方法可以仅使用 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)

As you can see, the save function can take the exif argument which permits to copy the raw exif data in the new image when saving. You don't actually need any other lib if that's all you want to do. I can't seem to find any documentation on the save options and I don't even know if that's specific to Pillow or working with PIL too. (If someone has some kind of link, I would enjoy if they posted it in the comments)

如您所见,保存函数可以采用 exif 参数,该参数允许在保存时复制新图像中的原始 exif 数据。如果这就是您想要做的,您实际上并不需要任何其他库。我似乎找不到有关保存选项的任何文档,我什至不知道这是否特定于 Pillow 或是否也与 PIL 一起使用。(如果有人有某种链接,如果他们将其发布在评论中,我会很高兴)

回答by rob

Why not using ImageMagick?
It is quite a standard tool (for instance, it is the standard tool used by Gallery 2); I have never used it, however it has a python interfaceas well (or, you can also simply spawn the command) and most of all, should maintain EXIF information between all transformation.

为什么不使用ImageMagick
它是一个非常标准的工具(例如,它是 Gallery 2 使用的标准工具);我从未使用过它,但是它也有一个python 接口(或者,您也可以简单地生成命令),最重要的是,应该在所有转换之间维护 EXIF 信息。

回答by bgeo

For pyexiv2 v0.3.2, the API documentationrefers to the copy method to carry over EXIF data from one image to another. In this case it would be the EXIF data of the original image over to the resized image.

对于pyexiv2 v0.3.2,API文档参考了copy方法将EXIF数据从一张图片转移到另一张图片。在这种情况下,它将是原始图像的 EXIF 数据到调整大小的图像。

Going off @Maksym Kozlenko, the updated code for copying EXIF data is:

离开@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()

回答by iny

You can use pyexiv2 to modify the file after saving it.

保存后可以使用pyexiv2修改文件。

回答by biomiker

Here's an updated answer as of 2018. piexifis a pure python library that for me installed easily via pip (pip install piexif) and worked beautifully (thank you, maintainers!). https://pypi.org/project/piexif/

这是截至 2018 年的更新答案 。piexif是一个纯 python 库,对我来说,它可以通过 pip 轻松安装(pip install piexif)并且运行良好(谢谢维护者!)。 https://pypi.org/project/piexif/

The usage is very simple, a single line will replicate the accepted answer and copy all EXIF tags from the original image to the resized image:

用法很简单,一行将复制接受的答案并将所有 EXIF 标签从原始图像复制到调整大小的图像:

import piexif
piexif.transplant("foo.jpg", "foo-resized.jpg")

I haven't tried yet, but it looks like you could also perform modifcations easily by using the load, dump, and insert functions as described in the linked documentation.

我还没有尝试过,但看起来您也可以通过使用链接文档中描述的加载、转储和插入功能轻松地执行修改。

回答by Juanma Font

Updated version of Maksym KozlenkoPython3 and py3exiv2 v0.7

Maksym KozlenkoPython3 和py3exiv2 v0.7 的更新版本

# Resize image and update Exif data
from PIL import Image
import pyexiv2

def resize_image(source_path, dest_path, size):
    # resize image
    image = Image.open(source_path)
    # Using thumbnail, then 'size' is MAX width or weight
    # so will retain aspect ratio
    image.thumbnail(size, Image.ANTIALIAS)
    image.save(dest_path, "JPEG")

    # copy EXIF data
    source_exif = pyexiv2.ImageMetadata(source_path)
    source_exif.read()
    dest_exif = pyexiv2.ImageMetadata(dest_path)
    dest_exif.read()
    source_exif.copy(dest_exif,exif=True)

    # set EXIF image size info to resized size
    dest_exif["Exif.Photo.PixelXDimension"] = image.size[0]
    dest_exif["Exif.Photo.PixelYDimension"] = image.size[1]
    dest_exif.write()

回答by PEZ

PIL handles EXIF data, doesn't it? Look in PIL.ExifTags.

PIL 处理 EXIF 数据,不是吗?查看 PIL.ExifTags。

回答by Cody

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)

Tested in Pillow 2.5.3

在 Pillow 2.5.3 中测试