28

我需要使用 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')

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

4

11 回答 11

15

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

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

于 2014-02-27T09:13:16.497 回答
12
import jpeg
jpeg.setExif(jpeg.getExif('foo.jpg'), 'foo-resized.jpg') 

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

于 2008-12-30T17:00:10.660 回答
10

您可以使用 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))
于 2010-11-24T19:57:13.070 回答
4

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

于 2008-12-30T19:27:17.557 回答
4

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

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

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

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

于 2018-08-09T05:43:53.193 回答
3

对于 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()
于 2013-07-09T13:24:08.497 回答
1

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

于 2008-12-31T15:59:57.600 回答
0
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 中测试

于 2014-09-04T07:18:15.457 回答
0

似乎@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)
于 2015-05-14T11:55:44.933 回答
0

Maksym Kozlenko Python3 和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()
于 2020-04-09T06:40:50.987 回答
-1

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

于 2008-12-30T17:01:28.927 回答