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

时间:2021-07-21 21:49:36

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?

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

10 个解决方案

#1


9  

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

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

#2


10  

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))

#3


7  

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)

如您所见,save函数可以使用exif参数,该参数允许在保存时复制新图像中的原始exif数据。如果你想做的话,你实际上并不需要任何其他的lib。我似乎无法找到有关保存选项的任何文档,我甚至不知道这是否特定于Pillow或使用PIL。 (如果有人有某种联系,我会很高兴,如果他们在评论中发布了它)

#4


4  

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 interface as 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信息。

#5


2  

For pyexiv2 v0.3.2, the API documentation refers 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文档是指将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()

#6


1  

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

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

#7


0  

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

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)

Tested in Pillow 2.5.3

在枕头2.5.3中测试

#9


0  

It seems @Depado's solution does not work for me, in my scenario the image does not even contain an exif segment.

似乎@Dedado的解决方案对我不起作用,在我的场景中,图像甚至不包含exif段。

pyexiv2 is hard to install on my Mac, instead I use the module pexif https://github.com/bennoleslie/pexif/blob/master/pexif.py. To "add exif segment" to an image does not contain exif info, I added the exif info contained in an image which owns a exif segment

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  

Here's an updated answer as of 2018. piexif is 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年的更新答案.pixxif是一个纯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.

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

#1


9  

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

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

#2


10  

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))

#3


7  

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)

如您所见,save函数可以使用exif参数,该参数允许在保存时复制新图像中的原始exif数据。如果你想做的话,你实际上并不需要任何其他的lib。我似乎无法找到有关保存选项的任何文档,我甚至不知道这是否特定于Pillow或使用PIL。 (如果有人有某种联系,我会很高兴,如果他们在评论中发布了它)

#4


4  

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 interface as 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信息。

#5


2  

For pyexiv2 v0.3.2, the API documentation refers 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文档是指将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()

#6


1  

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

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

#7


0  

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

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)

Tested in Pillow 2.5.3

在枕头2.5.3中测试

#9


0  

It seems @Depado's solution does not work for me, in my scenario the image does not even contain an exif segment.

似乎@Dedado的解决方案对我不起作用,在我的场景中,图像甚至不包含exif段。

pyexiv2 is hard to install on my Mac, instead I use the module pexif https://github.com/bennoleslie/pexif/blob/master/pexif.py. To "add exif segment" to an image does not contain exif info, I added the exif info contained in an image which owns a exif segment

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  

Here's an updated answer as of 2018. piexif is 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年的更新答案.pixxif是一个纯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.

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