我正在使用Python 2.5。使用Python的标准类,我想确定一个文件的图像大小。如何使用标准Python类获取图像大小(不使用外部库)?
我听说过PIL(Python Image Library),但它需要安装才能正常工作。
如何在不使用任何外部库的情况下获取图像大小,仅使用Python 2.5自带的模块?
注意我想支持常见的图像格式,特别是JPG和PNG。
我正在使用Python 2.5。使用Python的标准类,我想确定一个文件的图像大小。如何使用标准Python类获取图像大小(不使用外部库)?
我听说过PIL(Python Image Library),但它需要安装才能正常工作。
如何在不使用任何外部库的情况下获取图像大小,仅使用Python 2.5自带的模块?
注意我想支持常见的图像格式,特别是JPG和PNG。
尽管可以调用open(filename, 'rb')
并检查二维图像标题的尺寸,但安装PIL并花时间编写出色的新软件似乎更有用!您可以获得更大的文件格式支持以及广泛使用的可靠性。 From the PIL documentation,看来该代码,你需要完成你的任务将是:
from PIL import Image
im = Image.open('filename.png')
print 'width: %d - height: %d' % im.size # returns (width, height) tuple
至于自己编写代码,我不知道在Python标准库的模块会做你想要什么。你将不得不open()
图像在二进制模式,并开始解码它自己。你可以在阅读的格式:
需要Kurts回答稍微修改为我工作。
首先,在Ubuntu:sudo apt-get install python-imaging
然后:
from PIL import Image
im=Image.open(filepath)
im.size # (width,height) tuple
退房的handbook以获得更多信息。
不回答问题 - “(不使用外部库)?”是在标题中指定的,然后问题用“我听说过PIL(Python图像库)”来澄清,但它需要安装库。“ –
@RossAllan:当然可以,但这个问题是#1在谷歌的'Python的图像dimensions'变种,所以+1从我无重塑 - -的轮需要的答案:) –
如果您碰巧安装了ImageMagick,那么您可以使用'identify'。例如,你可以这样调用:
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(',') ]
这里有一个python脚本3,返回包含.png和.gif和JPEG格式的图像高度和宽度的元组,而无需使用任何外部库(即什么库尔特麦基在上面引用)。应该是比较容易将其传送到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
该代码并完成两两件事:
获取图像尺寸
找到真正的EOF一个jpg文件
当谷歌搜索时,我对后面的一个更感兴趣。 这个任务是从数据流中剪下一个jpg文件。由于我没有找到任何方法来使用Pythons'image'来获得如此jpg文件的EOF,所以我编写了这个文件。
有趣/更改/笔记该样品中:
延伸至与该方法UINT16 使源代码更好可读性和可维护性的普通的Python文件类。 与struct.unpack乱搞()迅速使得代码看起来丑陋
替换读over'uninteresting”区域/块以谋求
柜面你只是想获得 你可以删除行尺寸:
hasChunk = ord(byte) not in range(0xD0, 0xDA) + [0x00]
- >自
阅读过的图像数据块 和评论时只能得到重要的210只要找到该维度即可停止阅读。 ......但微笑我要告诉 - 你的编码器;)
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()
这里有一种方式来获得一个PNG文件的尺寸,而无需第三方模块。从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)
当你运行它,它会返回:
True
(x, y)
这包括JPEG格式的处理,以及另外一个例子: http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code
如果您需要的只是标题数据,那么读取整个图像数据是否有点低效? –
要解决这个问题,一个可以重构'''get_image_info()'''把文件名作为参数(而不是二进制数据),然后就去做了'''f.read(25)'''仅阅读标题信息。 –
偶然发现了这一个,但你可以得到只要你输入numpy,就可以使用下面的方法。
import numpy as np
[y, x] = np.shape(img[:,:,0])
它的工作原理是因为您忽略了除一种颜色以外的所有颜色,然后图像只是2D,所以形状会告诉您如何出价。对Python来说还是一个新手,但似乎是一个简单的方法。
关于Fred the Fantastic's answer:
不C0
之间的每一个JPEG标记 - CF
是SOF
标记;我排除了DHT(C4
),DNL(C8
)和DAC(CC
)。请注意,我还没有研究过是否可以用这种方式解析除C0
和C2
以外的任何帧。然而,其他人似乎相当罕见(我个人还没有遇到除C0
和C2
以外)。
无论哪种方式,这解决了在注释中提到的问题Malandy与Bangles.jpg
(DHT错误地解析为SOF)。
1431588037-WgsI3vK.jpg
提到的另一个问题是由于imghdr
只能够检测到APP0(EXIF)和APP1(JFIF)标头。
这可以通过向imghdr添加更宽松的测试(例如简单的FFD8
或FFD8FF
?)或更复杂的(甚至可能是数据验证)来解决。使用更复杂的方法,我只发现了以下问题:APP14(FFEE
)(Adobe);第一个标记是DQT(FFDB
);和APP2和issues with embedded ICC_PROFILEs。
以下修改后的代码,也改变了调用imghdr.what()
略:
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
注:创建一个完整的答案,而不是评论,因为我还没有获准。
发现在另一#1后一个很好的解决方案(只使用标准库+含jpg处理以及):对于那些谁能够负担得起运行“文件JohnTESlade answer
而另一种解决方案(快捷方式) '蟒内命令,运行:
import os
info = os.popen("file foo.jpg").read()
print info
输出:
foo.jpg: JPEG image data...density 28x28, segment length 16, baseline, precision 8, 352x198, frames 3
现在你要做的就是格式化输出捕获尺寸。 352x198在我的情况。
由于图像存储在阵列简单地用
height = len(img)
width = len(img[0])
你想学的什么大小格式* *图像的任何建议? –
常见的图像格式(PNG和JPG) – eros
参见[我的回答对一个问题(http://stackoverflow.com/a/34704661/562769),如果你不关心使用外部(但通常使用的)库 –