Ответ 1
import jpeg
jpeg.setExif(jpeg.getExif('foo.jpg'), 'foo-resized.jpg')
Мне нужно изменить размер 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')
Вы можете использовать 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 в новом изображении при сохранении. На самом деле вам не нужен какой-либо другой lib, если это все, что вы хотите сделать. Я не могу найти какую-либо документацию по параметрам сохранения, и я даже не знаю, относится ли это к подушке или работает с PIL. (Если у кого-то есть какая-то ссылка, мне понравилось бы, если бы они разместили ее в комментариях)
Почему бы не использовать ImageMagick?
Это довольно стандартный инструмент (например, это стандартный инструмент, используемый в Gallery 2); Я никогда не использовал его, однако он также имеет интерфейс python (или вы также можете просто вызвать команду) и, самое главное, должен поддерживать информацию EXIF между всеми преобразованиями.
Вы можете использовать pyexiv2 для изменения файла после его сохранения.
Для pyexiv2 v0.3.2 документация API относится к методу копирования для переноса EXIF-данных с одного изображения на другое. В этом случае это будет EXIF-данные исходного изображения для измененного изображения.
Отключение @Максим Козленко, обновленный код для копирования 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()
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)