Search code examples
pythonborderpython-imaging-librarycroptrim

Python PIL - AttributeError: 'NoneType' object has no attribute 'save'


I use this code to delete the border of an image using PIL:

def RemoveBlackBorders(img):
    bg = Image.new(img.mode, img.size, img.getpixel((0,0)))
    diff = ImageChops.difference(img, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    if bbox:
        return img.crop(bbox)

from here

And I use this to process all images contained in a folder:

def CropImages():
    global FOLDER
    for i in range(1, len(os.listdir(FOLDER))+1):
        image = FOLDER + "\\" + str(i) + ".jpg"
        img = Image.open(image)
        img = RemoveBlackBorders(img)
        img.save(image, "JPEG")

Everything works fine and the program does his job. The problem is that if in the folder there is a full black image (which is detected as "border"), the program stuck giving me the error:

 AttributeError: 'NoneType' object has no attribute 'save'

None of the images in the folder get cropped, even if the black image is the last one of the series. Is there a way to skip this image or delete it (which would be better)?


Solution

  • The Python principle of EAFP could apply here.

    Basically you should have your code attempt to execute and then catch an AttributeError, telling it to skip that image.

    Like this:

    def CropImages():
        global FOLDER
        for i in range(1, len(os.listdir(FOLDER))+1):
            image = FOLDER + "\\" + str(i) + ".jpg"
            img = Image.open(image)
            img = RemoveBlackBorders(img)
    
            try:
                img.save(image, "JPEG")
            except AttributeError:
                print("Couldn't save image {}".format(image))
    

    This just means that if it finds that error, it'll print the message and then keep looping over the rest.