library - pillow python documentation
Cambiar el tamaño de la imagen en Python sin perder datos EXIF (10)
¿Por qué no usar ImageMagick ?
Es una herramienta bastante estándar (por ejemplo, es la herramienta estándar utilizada por la Galería 2); Nunca lo he usado, sin embargo, también tiene una interfaz de python (o también puedes generar el comando) y, sobre todo, debe mantener la información EXIF entre todas las transformaciones.
Necesito cambiar el tamaño de las imágenes jpg con Python sin perder los datos EXIF de la imagen original (metadatos sobre la fecha tomada, el modelo de la cámara, etc.). Todas las búsquedas de google sobre python e imágenes apuntan a la biblioteca PIL que estoy usando actualmente, pero no parece poder retener los metadatos. El código que tengo hasta ahora (usando PIL) es este:
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'')
¿Algunas ideas? ¿O otras bibliotecas que podría estar usando?
Aquí hay una respuesta actualizada a partir de 2018. piexif es una biblioteca de python pura que para mí se instala fácilmente a través de pip (pip install piexif) y funcionó maravillosamente (¡gracias, mantenedores!). https://pypi.org/project/piexif/
El uso es muy simple, una sola línea replicará la respuesta aceptada y copiará todas las etiquetas EXIF de la imagen original a la imagen redimensionada:
import piexif
piexif.transplant("foo.jpg", "foo-resized.jpg")
Todavía no lo he intentado, pero parece que también podría realizar modificaciones fácilmente mediante el uso de las funciones de carga, volcado e inserción, tal como se describe en la documentación vinculada.
En realidad, hay una manera muy simple de copiar datos EXIF de una imagen a otra con solo PIL. Aunque no permite modificar las etiquetas 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)
Como puede ver, la función guardar puede tomar el argumento exif que permite copiar los datos brutos exif en la nueva imagen al guardar. En realidad, no necesitas ninguna otra lib si eso es todo lo que quieres hacer. Parece que no puedo encontrar ninguna documentación sobre las opciones de guardado y ni siquiera sé si eso es específico de Pillow o si también está trabajando con PIL. (Si alguien tiene algún tipo de enlace, me gustaría que lo publicaran en los comentarios)
PIL maneja datos EXIF, ¿no? Mire en PIL.ExifTags.
Para pyexiv2 v0.3.2, la documentación API se refiere al método de copia para transferir datos EXIF de una imagen a otra. En este caso, serían los datos EXIF de la imagen original sobre la imagen redimensionada.
Al salir de @Maksym Kozlenko, el código actualizado para copiar datos EXIF es:
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()
Parece que la solución de @Depado no funciona para mí, en mi caso, la imagen ni siquiera contiene un segmento exif.
pyexiv2 es difícil de instalar en mi Mac, en su lugar utilizo el módulo pexif https://github.com/bennoleslie/pexif/blob/master/pexif.py . Para "agregar segmento exif" a una imagen no contiene información exif, agregué la información exif contenida en una imagen que posee un segmento 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)
Puede usar pyexiv2 para copiar datos EXIF de la imagen de origen. En el siguiente ejemplo, la imagen se redimensiona utilizando la biblioteca PIL, los datos EXIF copiados con pyexiv2 y los campos EXIF de tamaño de imagen se establecen con un nuevo tamaño.
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))
Puede usar pyexiv2 para modificar el archivo después de guardarlo.
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)
Probado en Pillow 2.5.3
import jpeg
jpeg.setExif(jpeg.getExif(''foo.jpg''), ''foo-resized.jpg'')