How to get image size using standard Python class (without using external library)?

I am using Python 2.5. And using standard classes from Python, I want to determine the image size of the file.

I heard PIL (Python Image Library), but this requires installation.

How can I get image size without using any external library, just using native Python 2.5 modules?

Note. I want to support common image formats, especially JPG and PNG.

+64
python image
Nov 07 '11 at 4:11
source share
11 answers

Here is a python 3 script that returns a tuple containing the height and width of the image for .png, .gif and .jpeg without using any external libraries (i.e. what is mentioned above by Kurt McKee). It should be relatively easy to port it to Python 2.

import struct import imghdr def get_image_size(fname): '''Determine the image type of fhandle and return its size. from draco''' with open(fname, 'rb') as fhandle: head = fhandle.read(24) if len(head) != 24: return if imghdr.what(fname) == 'png': check = struct.unpack('>i', head[4:8])[0] if check != 0x0d0a1a0a: return width, height = struct.unpack('>ii', head[16:24]) elif imghdr.what(fname) == 'gif': width, height = struct.unpack('<HH', head[6:10]) elif imghdr.what(fname) == 'jpeg': try: fhandle.seek(0) # Read 0xff next size = 2 ftype = 0 while not 0xc0 <= ftype <= 0xcf: fhandle.seek(size, 1) byte = fhandle.read(1) while ord(byte) == 0xff: byte = fhandle.read(1) ftype = ord(byte) size = struct.unpack('>H', fhandle.read(2))[0] - 2 # We are at a SOFn block fhandle.seek(1, 1) # Skip `precision' byte. height, width = struct.unpack('>HH', fhandle.read(4)) except Exception: #IGNORE:W0703 return else: return return width, height 
+85
Dec 04 '13 at 16:21
source share

Kurts answer needs to be slightly modified to work for me.

First, on ubuntu: sudo apt-get install python-imaging

Then:

 from PIL import Image im=Image.open(filepath) im.size # (width,height) tuple 

See the manual for more details.

+62
Feb 29 '12 at 13:25
source share

While you can call open(filename, 'rb') and check the headers of the binary images for measurements, it seems much more useful to set PIL and spend time creating great new software! You get great support for the file format and the reliability gained from widespread use. From the PIL documentation , it looks like the code you need to execute will be:

 from PIL import Image im = Image.open('filename.png') print 'width: %d - height: %d' % im.size # returns (width, height) tuple 

As for writing code myself, I don't know about a module in the Python standard library that will do what you want. You will need to open() image in binary mode and start decoding it yourself. You can read about formats at:

+19
Nov 07 '11 at 5:32
source share

Here you can get png file sizes without the need for a third-party module. From http://coreygoldberg.blogspot.com/2013/01/python-verify-png-file-and-get-image.html

 import struct def get_image_info(data): if is_png(data): w, h = struct.unpack('>LL', data[16:24]) width = int(w) height = int(h) else: raise Exception('not a png image') return width, height def is_png(data): return (data[:8] == '\211PNG\r\n\032\n'and (data[12:16] == 'IHDR')) if __name__ == '__main__': with open('foo.png', 'rb') as f: data = f.read() print is_png(data) print get_image_info(data) 

When you run this, it will return:

 True (x, y) 

And another example that includes processing JPEG files: http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code

+18
Feb 04 '14 at
source share

If you have ImageMagick installed, you can use " authentication ". For example, you can call it like this:

 path = "//folder/image.jpg" dim = subprocess.Popen(["identify","-format","\"%w,%h\"",path], stdout=subprocess.PIPE).communicate()[0] (width, height) = [ int(x) for x in re.sub('[\t\r\n"]', '', dim).split(',') ] 
+4
May 25 '12 at 18:39
source share

Regarding Fred Fantastic answer :

Not every JPEG marker between C0 - CF is a SOF marker; I excluded DHT ( C4 ), DNL ( C8 ) and DAC ( CC ). Please note that I have not studied whether it is even possible to parse any frames except C0 and C2 in this way. However, others seem to be quite rare (I personally have not met anyone other than C0 and C2 ).

In any case, this solves the problem mentioned in Malandy's comments using Bangles.jpg (DHT is mistakenly parsed as SOF).

Another issue mentioned in 1431588037-WgsI3vK.jpg is that imghdr can detect APP0 (EXIF) and APP1 (JFIF) headers.

This can be fixed by adding a weaker test to imghdr (for example, just FFD8 or maybe FFD8FF ?)) Or something much more complicated (maybe even checking the data). With a more complex approach, I found problems only with: APP14 ( FFEE ) (Adobe); the first marker is DQT ( FFDB ); and APP2 and problems with embedded ICC_PROFILEs .

The revised code below also slightly changed the imghdr.what() call:

 import struct import imghdr def test_jpeg(h, f): # SOI APP2 + ICC_PROFILE if h[0:4] == '\xff\xd8\xff\xe2' and h[6:17] == b'ICC_PROFILE': print "A" return 'jpeg' # SOI APP14 + Adobe if h[0:4] == '\xff\xd8\xff\xee' and h[6:11] == b'Adobe': return 'jpeg' # SOI DQT if h[0:4] == '\xff\xd8\xff\xdb': return 'jpeg' imghdr.tests.append(test_jpeg) def get_image_size(fname): '''Determine the image type of fhandle and return its size. from draco''' with open(fname, 'rb') as fhandle: head = fhandle.read(24) if len(head) != 24: return what = imghdr.what(None, head) if what == 'png': check = struct.unpack('>i', head[4:8])[0] if check != 0x0d0a1a0a: return width, height = struct.unpack('>ii', head[16:24]) elif what == 'gif': width, height = struct.unpack('<HH', head[6:10]) elif what == 'jpeg': try: fhandle.seek(0) # Read 0xff next size = 2 ftype = 0 while not 0xc0 <= ftype <= 0xcf or ftype in (0xc4, 0xc8, 0xcc): fhandle.seek(size, 1) byte = fhandle.read(1) while ord(byte) == 0xff: byte = fhandle.read(1) ftype = ord(byte) size = struct.unpack('>H', fhandle.read(2))[0] - 2 # We are at a SOFn block fhandle.seek(1, 1) # Skip `precision' byte. height, width = struct.unpack('>HH', fhandle.read(4)) except Exception: #IGNORE:W0703 return else: return return width, height 

Note. A complete answer was created instead of a comment, since I have not yet been allowed.

+4
Sep 29 '16 at 19:46
source share

This code does two things:

  • Get image size

  • Find real EOF file jpg

Well, when in googling I was more interested in later. The task was to cut the jpg file from the data stream. Since I did not find a way to use Pythons' image to get EOF, so jpg-File I compiled this.

Interesting things / changes / notes in this example:

  • Extending the regular Python file class using the uInt16 method, making the source code more readable and maintainable. By using struct.unpack (), you quickly make the code look ugly.

  • Replaced reading over "interests" of areas / fragments using search

  • If you just want to get the dimensions you can delete the line:

     hasChunk = ord(byte) not in range( 0xD0, 0xDA) + [0x00] 

    ->, since it only gets meaning when reading a piece of image data and a comment in

     #break 

    to stop reading as soon as a measurement is detected. ... but I smile that I say - you are an encoder;)

      import struct import io,os class myFile(file): def byte( self ): return file.read( self, 1); def uInt16( self ): tmp = file.read( self, 2) return struct.unpack( ">H", tmp )[0]; jpeg = myFile('grafx_ui.s00_\\08521678_Unknown.jpg', 'rb') try: height = -1 width = -1 EOI = -1 type_check = jpeg.read(2) if type_check != b'\xff\xd8': print("Not a JPG") else: byte = jpeg.byte() while byte != b"": while byte != b'\xff': byte = jpeg.byte() while byte == b'\xff': byte = jpeg.byte() # FF D8 SOI Start of Image # FF D0..7 RST DRI Define Restart Interval inside CompressedData # FF 00 Masked FF inside CompressedData # FF D9 EOI End of Image # http://en.wikipedia.org/wiki/JPEG#Syntax_and_structure hasChunk = ord(byte) not in range( 0xD0, 0xDA) + [0x00] if hasChunk: ChunkSize = jpeg.uInt16() - 2 ChunkOffset = jpeg.tell() Next_ChunkOffset = ChunkOffset + ChunkSize # Find bytes \xFF \xC0..C3 That marks the Start of Frame if (byte >= b'\xC0' and byte <= b'\xC3'): # Found SOF1..3 data chunk - Read it and quit jpeg.seek(1, os.SEEK_CUR) h = jpeg.uInt16() w = jpeg.uInt16() #break elif (byte == b'\xD9'): # Found End of Image EOI = jpeg.tell() break else: # Seek to next data chunk print "Pos: %.4x %x" % (jpeg.tell(), ChunkSize) if hasChunk: jpeg.seek(Next_ChunkOffset) byte = jpeg.byte() width = int(w) height = int(h) print("Width: %s, Height: %s JpgFileDataSize: %x" % (width, height, EOI)) finally: jpeg.close() 
+1
Jan 30 '14 at 19:38
source share

Found a nice solution in another Stackoverflow post (using only standard + libraries working with jpg): JohnTESlade answer

And another solution (quick way) for those who can let the file command run in python, run:

 import os info = os.popen("file foo.jpg").read() print info 

Exit

 foo.jpg: JPEG image data...density 28x28, segment length 16, baseline, precision 8, 352x198, frames 3 

All you have to do is format the output to capture sizes. 352x198 in my case.

+1
Nov 02 '16 at 10:56
source share

It depends on the output of the file, which, I'm not sure, is standardized on all systems. Some JPEGs do not report image size

 import subprocess, re image_size = list(map(int, re.findall('(\d+)x(\d+)', subprocess.getoutput("file" + filename))[-1])) 
0
Jul 23 '19 at 16:30
source share

Since the image is stored in an array, just use

 height = len(img) width = len(img[0]) 
-one
Sep 13 '17 at 1:06 on
source share

Came across this one, but you can get it using the following while you import numpy.

 import numpy as np [y, x] = np.shape(img[:,:,0]) 

This works because you ignore everything except one color, and then the image is just 2D, so the form tells you how to do it. Still new to Python, but looks like an easy way to do this.

-2
Sep 02 '16 at 20:43
source share



All Articles