/usr/lib/python3/dist-packages/construct/examples/formats/graphics/bmp.py is in python3-construct 2.8.16-0.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | """
Windows/OS2 Bitmap (BMP) this could have been a perfect show-case file format, but they had to make it ugly (all sorts of alignments)
"""
from construct import *
#===============================================================================
# pixels: uncompressed
#===============================================================================
def UncompressedRows(subcon, align_to_byte = False):
"""argh! lines must be aligned to a 4-byte boundary, and bit-pixel lines must be aligned to full bytes..."""
if align_to_byte:
line_pixels = Bitwise(Aligned(8, Array(this.width, subcon)))
else:
line_pixels = Array(this.width, subcon)
return Array(this.height, Aligned(4, line_pixels))
uncompressed_pixels = "uncompressed" / Switch(this.bpp,
{
1 : UncompressedRows(Bit, align_to_byte = True), # index
4 : UncompressedRows(Nibble, align_to_byte = True), # index
8 : UncompressedRows(Byte), # index
24 : UncompressedRows(Byte[3]), # rgb
}
)
#===============================================================================
# pixels: Run Length Encoding (RLE) 8 bit
#===============================================================================
class RunLengthAdapter(Adapter):
def _encode(self, obj):
return len(obj), obj[0]
def _decode(self, obj):
length, value = obj
return [value] * length
rle8pixel = "rle8pixel" / RunLengthAdapter(Byte >> Byte)
#===============================================================================
# file structure
#===============================================================================
bitmap_file = "bitmap_file" / Struct(
"signature" / Const(b"BM"),
"file_size" / Int32ul,
Padding(4),
"data_offset" / Int32ul,
"header_size" / Int32ul,
"version" / Enum(Computed(this.header_size),
v2 = 12,
v3 = 40,
v4 = 108,
default = Pass,
),
"width" / Int32ul,
"height" / Int32ul,
"number_of_pixels" / Computed(this.width * this.height),
"planes" / Int16ul,
"bpp" / Int16ul, # bits per pixel
"compression" / Enum(Int32ul,
Uncompressed = 0,
RLE8 = 1,
RLE4 = 2,
Bitfields = 3,
JPEG = 4,
PNG = 5,
),
"image_data_size" / Int32ul, # in bytes
"horizontal_dpi" / Int32ul,
"vertical_dpi" / Int32ul,
"colors_used" / Int32ul,
"important_colors" / Int32ul,
# palette (24 bit has no palette)
"palette" / Array(lambda ctx: 2**ctx.bpp if ctx.bpp <= 8 else 0,
Struct(
"rgb" / Byte[3],
Padding(1),
)
),
"pixels" / Pointer(this.data_offset,
Switch(this.compression,
{
"Uncompressed" : uncompressed_pixels,
},
),
),
)
|