DhruvPathak
DhruvPathak

Reputation: 43235

How to detect if an image is progressive JPEG using Python Image Library ( PIL / Pillow )?

If an image has been saved as progressive JPEG using PIL or any tool like Photoshop. Is there any functionality present in PIL or any other python modules to detect if an input image file is progressive ?

Upvotes: 2

Views: 1904

Answers (3)

vedranm
vedranm

Reputation: 528

Alderven's solution unfortunately didn't work for me, it recognized bunch of progressive-packed images as non-progressive. So I implemented my own method which properly implements JPEG standard and should work for 100% of files (and also doesn't need PIL):

def IsImageProgressive(filename):
  with open(filename, "rb") as f:
    while True:
      blockStart = struct.unpack('B', f.read(1))[0]
      if blockStart != 0xff:
        raise ValueError('Invalid char code ' + `blockStart` + ' - not a JPEG file: ' + filename)
        return False

      blockType = struct.unpack('B', f.read(1))[0]
      if blockType == 0xd8:   # Start Of Image
        continue
      elif blockType == 0xc0: # Start of baseline frame
        return False
      elif blockType == 0xc2: # Start of progressive frame
        return True
      elif blockType >= 0xd0 and blockType <= 0xd7: # Restart
        continue
      elif blockType == 0xd9: # End Of Image
        break
      else:                   # Variable-size block, just skip it
        blockSize = struct.unpack('2B', f.read(2))
        blockSize = blockSize[0] * 256 + blockSize[1] - 2
        f.seek(blockSize, 1)
  return False

Upvotes: 4

homm
homm

Reputation: 2252

There is info property of image.

In [1]: from PIL import Image
In [2]: Image.open('ex1.p.jpg').info
Out[2]: 
{'jfif': 257,
 'jfif_density': (1, 1),
 'jfif_unit': 0,
 'jfif_version': (1, 1),
 'progression': 1,
 'progressive': 1}

Upvotes: 3

Alderven
Alderven

Reputation: 8270

Check following solution based on this conception:

image = 'c:\\images\\progressive.jpg'

def IsImageProgressive(image):

    previousXFF = False

    with open(image, "rb") as f:
        byte = f.read(1)
        while byte:
            byte = f.read(1)

            if previousXFF:
                if 'xc2' in str(byte):
                    return True

            if 'xff' in str(byte):
                previousXFF = True
            else:
                previousXFF = False

    return False

print(IsImageProgressive(image))

The solution requires no any additional modules.

Upvotes: 3

Related Questions