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

时间:2008-12-30 16:42:03

标签: python image-processing python-imaging-library exif

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

有什么想法吗?还是我可以使用的其他图书馆?

11 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分: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))

答案 2 :(得分:7)

实际上有一种非常简单的方法,只需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数据。如果你想做的话,你实际上并不需要任何其他的lib。我似乎无法找到有关保存选项的任何文档,我甚至不知道这是否特定于Pillow或使用PIL。 (如果某人有某种联系,我会很高兴,如果他们在评论中发表了这个链接)

答案 3 :(得分:4)

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

答案 4 :(得分:2)

对于pyexiv2 v0.3.2,API documentation指的是将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()

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

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

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

我还没有尝试过,但是看起来您还可以通过使用链接文档中所述的load,dump和insert函数来轻松地执行修改。

答案 7 :(得分:0)

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

答案 8 :(得分: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中测试

答案 9 :(得分:0)

似乎@Dedado的解决方案对我不起作用,在我的场景中,图像甚至不包含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)

答案 10 :(得分: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()