djangopython-imaging-librarywebfaction

Cropping image in Django causes substantial memory increase


I've recently run into a problem with my Django project and memory usage on WebFaction.

Here is the two processes running in memory for this project on webfaction:

30396  4-20:20:00 13486 
30404  4-20:20:00 13487 

After the view is run one of the processes will increase substantially:

69720  4-20:20:22 13486 
30404  4-20:20:22 13487 

As you can see the first process more than doubled in memory usage! As this function will be used often I need to figure out what is happening. I believe I've narrowed it down to the following view (it's a 3 step process to upload an image, add details, crop a thumbnail).

Here is the view below. It gets a photo object, loads the image from the file, gets the box coordinates that the user has submitted and then creates a 200,200 sized image. This newly created image is written back to the disk with a .thumbnail in the filename and the photo object is saved.

@login_required
def upload3(request, photo_pk):
    photo = get_object_or_404(Photo, pk=photo_pk, user=request.user)
    if request.method == "POST":
        form = upload3Form(request.POST)
        if form.is_valid():
            im = Image.open(photo.image.path)
            try:
                box =(form.cleaned_data['x1'],form.cleaned_data['y1'],form.cleaned_data['x2'],form.cleaned_data['y2'])
            except:
                box = ('0','0','1000','1000')
            cropped = im.crop(box)
            cropped.thumbnail((200,200),Image.ANTIALIAS)
            result = os.path.splitext(photo.image.path)
            cropped.save(result[0] + '.thumbnail' + result[1])
            photo.status = 3
            photo.save()

Any ideas of what I may be doing wrong would be greatly appreciated.

Update 1: Images used for testing are all Jpeg and have dimensions around 3600 x 2700 and are around 2 MB per image.


Solution

  • After a lot of digging and dead-ends I tried something not suggested anywhere and it worked.

    On each object that contained an image object used in PIL I had to delete the object once I was done with it. So for example:

    im = Image.open(photo.image.path)
    try:
        box  =(form.cleaned_data['x1'],form.cleaned_data['y1'],form.cleaned_data['x2'],form.cleaned_data['y2'])
    except:
        box = ('0','0','1000','1000')
    cropped = im.crop(box)
    newimage = cropped.resize((form.cleaned_data['dw'],form.cleaned_data['dh']),Image.ANTIALIAS)
    del im
    del cropped 
    

    So once I'm done with the object I call del on that item. It seems to have fixed the problem. I no longer have memory increases and I couldn't be happier.