Home > Net >  django - resize images with pil
django - resize images with pil

Time:02-24

In my app In the save method I am compressing uploaded images. Now I want to also resize the images if they are very large. I played around with PIL in a test environment and came up with this code that works as expected.

from PIL import Image
image = Image.open('img.jpg')

(w,h) = image.size
if (w > 2000):
    i = image.size   # current size (height,width)
    i = i[0]//2, i[1]//2  # new size
    image = image.resize(i, Image.ANTIALIAS)
    image.save('halfresizesssd.jpg')

However when I try to merge it into my django project I get this error

'int' object is not subscriptable - i = i[0]//2, i[1]//2 # new size

If i understand the error correctly it is because i am passing an int as an array, I dont really understand that because if i try and pass say 2 instead of i i get the same error. I tried to just resize the image and skip the compression but I was still getting the same error

def compress(image):
    im = Image.open(image)
    # create a BytesIO object
    im_io = BytesIO() 
    #resize image
    im = im.convert("RGB")
    im = im.save(im_io,'JPEG', quality=70, optimize=True) 
    # create a django-friendly Files object
    new_image = File(im_io, name=image.name)

    w = new_image.size
    if (w > 1000):
        i = new_image.size   # current size (height,width)
        i = i[0]//2, i[1]//2  # new size
        new_image = new_image.resize(i, Image.ANTIALIAS)

    return new_image

Starting code

def compress(image):
                im = Image.open(image)
                # create a BytesIO object
                im_io = BytesIO() 
                #resize image
                im = im.convert("RGB")
                im = im.save(im_io,'JPEG', quality=70, optimize=True) 
                # create a django-friendly Files object
                new_image = File(im_io, name=image.name)
                return new_image

class Post(models.Model):
    ....
    image = models.ImageField(storage=PublicMediaStorage(), upload_to=path_and_rename, validators=[validate_image])

def save(self, *args, **kwargs): 
    self.slug = slugify(self.title)

    if self.image:
        # call the compress function
        new_image = compress(self.image)
        # set self.image to new_image
        self.image = new_image

    super(Post,self).save(*args, **kwargs)

CodePudding user response:

I can't test it but you use two different object.

In first code you work all time with PIL.Image() and its size gives (width,height) but in second code you works with File() and its size gives number of bytes in file (single number), not (width,height) (two numbers.

You have to first resize PIL.Image and later convert it to File()

Something like this (but I can't test it)

def compress(image):
    
    # --- resize ---
    
    img = Image.open(image)
    img = img.convert("RGB")

    (w, h) = img.size   # current size (width, height)

    if w > 1000:
        new_size = (w//2, h//2)  # new size
        img = img.resize(new_size, Image.ANTIALIAS)
    
    # --- convert to File ---

    im_io = BytesIO() 
    img.save(im_io, 'JPEG', quality=70, optimize=True) 

    new_image = File(im_io, name=image.name)

    return new_image
  • Related