Изменение размера изображения в Python без потери EXIF-данных

StackOverflow https://stackoverflow.com/questions/400788

Вопрос

Мне нужно изменить размер изображений jpg с помощью Python без потери данных EXIF исходного изображения (метаданные о дате съемки, модели камеры и т.д.).Все поисковые запросы Google о 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')

Есть какие-нибудь идеи?Или другие библиотеки, которые я мог бы использовать?

Это было полезно?

Решение

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

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

Другие советы

Вы можете использовать pyexiv2 для копирования EXIF-данных из исходного изображения.В следующем примере размер изображения изменен с помощью библиотеки PIL, данные EXIF скопированы с помощью pyexiv2, а поля 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))

На самом деле существует действительно простой способ копирования EXIF-данных с изображения на другое только с помощью PIL.Хотя это не позволяет изменять теги 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 год. пьексиф это чистая библиотека python, которая для меня легко устанавливалась через pip (pip install piexif) и прекрасно работала (спасибо вам, сопровождающие!). https://pypi.org/project/piexif/

Использование очень простое, одна строка повторит принятый ответ и скопирует все теги 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)

Протестировано на подушке 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top