将文件另存为未压缩的24位BMP。这些以非常规则的方式存储像素数据。从Wikipedia中检出此图的“图像数据”部分。请注意,图中的大多数复杂性仅来自标题:
例如,假设您正在存储此图像(此处显示为放大):
如果将其存储为24位未压缩的BMP,则像素数据部分的外观将是这样。请注意,由于某种原因,数据是以自下而上的方式存储的,并且以BGR格式而不是RGB格式存储,因此文件中的第一行是图像的最底行,第二行是倒数第二行,等等:
00 00 FF FF FF FF 00 00
FF 00 00 00 FF 00 00 00
该数据的解释如下:
| First column | Second Column | Padding
-----------+----------------+-----------------+-----------
Second Row | 00 00 FF | FF FF FF | 00 00
-----------+----------------+-----------------+-----------
First Row | FF 00 00 | 00 FF 00 | 00 00
-----------+----------------+-----------------+-----------
要么:
| First column | Second Column | Padding
-----------+----------------+-----------------+-----------
Second Row | red | white | 00 00
-----------+----------------+-----------------+-----------
First Row | blue | green | 00 00
-----------+----------------+-----------------+-----------
在那里填充可以将行大小填充为4字节的倍数。
因此,您要做的就是为这种特定的文件格式实现阅读器,然后计算必须开始和停止读取每一行的字节偏移量:
def calc_bytes_per_row(width, bytes_per_pixel):
res = width * bytes_per_pixel
if res % 4 != 0:
res += 4 - res % 4
return res
def calc_row_offsets(pixel_array_offset, bmp_width, bmp_height, x, y, row_width):
if x + row_width > bmp_width:
raise ValueError("This is only for calculating offsets within a row")
bytes_per_row = calc_bytes_per_row(bmp_width, 3)
whole_row_offset = pixel_array_offset + bytes_per_row * (bmp_height - y - 1)
start_row_offset = whole_row_offset + x * 3
end_row_offset = start_row_offset + row_width * 3
return (start_row_offset, end_row_offset)
然后,您只需要处理适当的字节偏移即可。例如,假设您要读取10000x10000位图中从位置500x500开始的400x400块:
def process_row_bytes(row_bytes):
... some efficient way to process the bytes ...
bmpf = open(..., "rb")
pixel_array_offset = ... extract from bmp header ...
bmp_width = 10000
bmp_height = 10000
start_x = 500
start_y = 500
end_x = 500 + 400
end_y = 500 + 400
for cur_y in xrange(start_y, end_y):
start, end = calc_row_offsets(pixel_array_offset,
bmp_width, bmp_height,
start_x, cur_y,
end_x - start_x)
bmpf.seek(start)
cur_row_bytes = bmpf.read(end - start)
process_row_bytes(cur_row_bytes)
请注意,处理字节非常重要。您可能可以使用PIL做一些聪明的事情,然后将像素数据转储到其中,但是我不确定。如果您以低效的方式进行操作,则可能不值得。如果速度是一个非常大的问题,您可以考虑使用pyrex编写它,或在C中实现以上内容,然后从Python调用它。