I read JPG's from an IP-camera and want to detect corrupt images. This is my function to load the image:
from PIL import Image
def getImage(self):
r=self.http.request('GET', self.snapshotURL, headers=self.headers)
tmp=io.BytesIO(r.data)
self.saveTmp(tmp.getvalue())
image=Image.open(tmp)
return(image)
If I receive a corrupt image, it's loaded to "image" without an error message by Pillow's Image.open().
The result of image.verify() is None in this case.
To be able to inspect the received raw data, it's saved to a file with saveTmp().
Here is such an image: http://dahlgrimm.de/Arduino/ip_cam/corrupt_image.jpg
If I look into the raw data of a corrupt file, the file starts with FF D8 FF E0 10 4A 46 49 46 and ends with FF D9.
Thats normal and does not help.
ImageMagick's identify gives this:
corrupt_image.bin JPEG 640x480 640x480+0+0 8-bit sRGB 42KB 0.000u 0:00.000
And the returncode is 0 == no help!
But if I open the file with gimp, gimp tells me: "Corrupt JPEG data: premature end of data segment".
How can I (fast!) detect corrupt images with Pillow...or even any other library that's available for Python3?
Edit:
It's much better now with this function:
def isValid(self):
if self.valid is None:
t=datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S-%f")
fn="/ramdisk/%s__corrupt.jpg"%(t,)
f=open(fn, "wb")
f.write(self.raw)
f.close()
if self.raw[-2:]!=bytes([255, 217]):
self.valid=False
#print("FF D9")
else:
rc=subprocess.call(["identify", "-verbose", fn],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
self.valid=(rc==0)
#if not self.valid:
# print("identify")
if(self.valid): # temp. not remove corrupt images
os.remove(fn)
return(self.valid)
But I still get corrupt images. Neither identify -verbose nor gimp complain about these images.
Like this one: http://dahlgrimm.de/Arduino/ip_cam/corrupt_image2.jpg
Maybe someone has an idea, how to also detect these remaining images !?