usar texto pil libreria importar imagenes imagen como abrir python django python-imaging-library django-file-upload django-uploads

texto - pil python



¿Cómo se convierte una ''Imagen'' de PIL en un ''Archivo'' de Django? (6)

Intento convertir un objeto UploadedFile en un objeto PIL Image para convertirlo en miniatura, y luego convertir el objeto PIL Image que devuelve mi miniatura a un objeto File . ¿Cómo puedo hacer esto?


Aquí hay una aplicación que puede hacer eso: django-smartfields

from django.db import models from smartfields import fields from smartfields.dependencies import FileDependency from smartfields.processors import ImageProcessor class ImageModel(models.Model): image = fields.ImageField(dependencies=[ FileDependency(processor=ImageProcessor( scale={''max_width'': 150, ''max_height'': 150})) ])

Asegúrese de pasar keep_orphans=True al campo, si desea conservar los archivos antiguos, de lo contrario, se limpian cuando se reemplazan.


Este es un ejemplo de trabajo real para python 3.5 y django 1.10

en views.py:

from io import BytesIO from django.core.files.base import ContentFile from django.core.files.uploadedfile import InMemoryUploadedFile def pill(image_io): im = Image.open(image_io) ltrb_border = (0, 0, 0, 10) im_with_border = ImageOps.expand(im, border=ltrb_border, fill=''white'') buffer = BytesIO() im_with_border.save(fp=buffer, format=''JPEG'') buff_val = buffer.getvalue() return ContentFile(buff_val) def save_img(request) if request.POST: new_record = AddNewRecordForm(request.POST, request.FILES) pillow_image = pill(request.FILES[''image'']) image_file = InMemoryUploadedFile(pillow_image, None, ''foo.jpg'', ''image/jpeg'', pillow_image.tell, None) request.FILES[''image''] = image_file # really need rewrite img in POST for success form validation new_record.image = request.FILES[''image''] new_record.save() return redirect(...)


He tenido que hacer esto en unos pocos pasos, imagejpeg () en php requiere un proceso similar. No decir que no hay forma de mantener las cosas en la memoria, pero este método le da una referencia de archivo tanto de la imagen original como del pulgar (generalmente es una buena idea en caso de que tenga que retroceder y cambiar el tamaño de su pulgar).

  1. guarda el archivo
  2. abrirlo desde el sistema de archivos con PIL,
  3. guardar en un directorio temporal con PIL,
  4. luego abre como un archivo de Django para que esto funcione.

Modelo:

class YourModel(Model): img = models.ImageField(upload_to=''photos'') thumb = models.ImageField(upload_to=''thumbs'')

Uso:

#in upload code uploaded = request.FILES[''photo''] from django.core.files.base import ContentFile file_content = ContentFile(uploaded.read()) new_file = YourModel() #1 - get it into the DB and file system so we know the real path new_file.img.save(str(new_file.id) + ''.jpg'', file_content) new_file.save() from PIL import Image import os.path #2, open it from the location django stuck it thumb = Image.open(new_file.img.path) thumb.thumbnail(100, 100) #make tmp filename based on id of the model filename = str(new_file.id) #3. save the thumbnail to a temp dir temp_image = open(os.path.join(''/tmp'',filename), ''w'') thumb.save(temp_image, ''JPEG'') #4. read the temp file back into a File from django.core.files import File thumb_data = open(os.path.join(''/tmp'',filename), ''r'') thumb_file = File(thumb_data) new_file.thumb.save(str(new_file.id) + ''.jpg'', thumb_file)


La forma de hacerlo sin tener que volver a escribir en el sistema de archivos, y luego devolver el archivo a la memoria a través de una llamada abierta, es hacer uso de StringIO y Django InMemoryUploadedFile. Aquí hay una muestra rápida de cómo puedes hacer esto. Esto supone que ya tiene una imagen en miniatura llamada ''thumb'':

import StringIO from django.core.files.uploadedfile import InMemoryUploadedFile # Create a file-like object to write thumb data (thumb data previously created # using PIL, and stored in variable ''thumb'') thumb_io = StringIO.StringIO() thumb.save(thumb_io, format=''JPEG'') # Create a new Django file-like object to be used in models as ImageField using # InMemoryUploadedFile. If you look at the source in Django, a # SimpleUploadedFile is essentially instantiated similarly to what is shown here thumb_file = InMemoryUploadedFile(thumb_io, None, ''foo.jpg'', ''image/jpeg'', thumb_io.len, None) # Once you have a Django file-like object, you may assign it to your ImageField # and save. ...

Avíseme si necesita más aclaraciones. Tengo esto trabajando en mi proyecto en este momento, cargando a S3 usando django-storage. Esto me llevó la mayor parte del día encontrar adecuadamente la solución aquí.


Organizando comentarios y actualizaciones para Python 3+

from io import BytesIO from django.core.files.base import ContentFile import requests # Read a file in r = request.get(image_url) image = r.content scr = Image.open(BytesIO(image)) # Perform an image operation like resize: width, height = scr.size new_width = 320 new_height = int(new_width * height / width) img = scr.resize((new_width, new_height)) # Get the Django file object thumb_io = BytesIO() img.save(thumb_io, format=''JPEG'') photo_smaller = ContentFile(thumb_io.getvalue())


Para aquellos que usan django-storages/-redux para almacenar el archivo de imagen en S3, esta es la ruta que tomé (el siguiente ejemplo crea una miniatura de una imagen existente):

from PIL import Image import StringIO from django.core.files.storage import default_storage try: # example 1: use a local file image = Image.open(''my_image.jpg'') # example 2: use a model''s ImageField image = Image.open(my_model_instance.image_field) image.thumbnail((300, 200)) except IOError: pass # handle exception thumb_buffer = StringIO.StringIO() image.save(thumb_buffer, format=image.format) s3_thumb = default_storage.open(''my_new_300x200_image.jpg'', ''w'') s3_thumb.write(thumb_buffer.getvalue()) s3_thumb.close()