|
32 | 32 | __version__ = "0.0.0-auto.0" |
33 | 33 | __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git" |
34 | 34 |
|
35 | | -import math |
36 | | - |
37 | | -def load(f, width, height, data_start, colors, color_depth, *, bitmap=None, palette=None): |
| 35 | +def load(file, width, height, data_start, colors, color_depth, *, bitmap=None, palette=None): |
| 36 | + """Loads indexed bitmap data into bitmap and palette objects. |
| 37 | +
|
| 38 | + :param file file: The open bmp file |
| 39 | + :param int width: Image width in pixels |
| 40 | + :param int height: Image height in pixels |
| 41 | + :param int data_start: Byte location where the data starts (after headers) |
| 42 | + :param int colors: Number of distinct colors in the image |
| 43 | + :param int color_depth: Number of bits used to store a value""" |
| 44 | + # pylint: disable=too-many-arguments,too-many-locals |
38 | 45 | if palette: |
39 | 46 | palette = palette(colors) |
40 | 47 |
|
41 | | - f.seek(data_start - colors * 4) |
42 | | - for color in range(colors): |
43 | | - c = f.read(4) |
44 | | - palette[color] = c |
| 48 | + file.seek(data_start - colors * 4) |
| 49 | + for value in range(colors): |
| 50 | + c_bytes = file.read(4) |
| 51 | + # Need to swap red & blue bytes (bytes 0 and 2) |
| 52 | + palette[value] = bytes(b''.join([c_bytes[2:3], |
| 53 | + c_bytes[1:2], |
| 54 | + c_bytes[0:1], |
| 55 | + c_bytes[3:1]])) |
45 | 56 |
|
46 | 57 | if bitmap: |
47 | 58 | minimum_color_depth = 1 |
48 | 59 | while colors > 2 ** minimum_color_depth: |
49 | 60 | minimum_color_depth *= 2 |
50 | 61 |
|
51 | 62 | bitmap = bitmap(width, height, colors) |
52 | | - f.seek(data_start) |
| 63 | + file.seek(data_start) |
53 | 64 | line_size = width // (8 // color_depth) |
54 | 65 | if line_size % 4 != 0: |
55 | 66 | line_size += (4 - line_size % 4) |
56 | 67 |
|
57 | | - packed_pixels = None |
58 | | - if color_depth != minimum_color_depth and minimum_color_depth == 2: |
59 | | - target_line_size = width // 4 |
60 | | - if target_line_size % 4 != 0: |
61 | | - target_line_size += (4 - target_line_size % 4) |
62 | | - |
63 | | - packed_pixels = bytearray(target_line_size) |
64 | | - |
65 | | - for line in range(height-1,-1,-1): |
66 | | - chunk = f.read(line_size) |
67 | | - if packed_pixels: |
68 | | - original_pixels_per_byte = 8 // color_depth |
69 | | - packed_pixels_per_byte = 8 // minimum_color_depth |
70 | | - |
71 | | - for i in range(width // packed_pixels_per_byte): |
72 | | - packed_pixels[i] = 0 |
| 68 | + chunk = bytearray(line_size) |
| 69 | + mask = (1 << minimum_color_depth) - 1 |
73 | 70 |
|
74 | | - for i in range(width): |
75 | | - pi = i // packed_pixels_per_byte |
76 | | - ci = i // original_pixels_per_byte |
77 | | - packed_pixels[pi] |= ((chunk[ci] >> (8 - color_depth*(i % original_pixels_per_byte + 1))) & 0x3) << (8 - minimum_color_depth*(i % packed_pixels_per_byte + 1)) |
| 71 | + for y in range(height - 1, -1, -1): |
| 72 | + file.readinto(chunk) |
| 73 | + pixels_per_byte = 8 // color_depth |
| 74 | + offset = y * width |
78 | 75 |
|
79 | | - bitmap._load_row(line, packed_pixels) |
80 | | - else: |
81 | | - bitmap._load_row(line, chunk) |
| 76 | + for x in range(width): |
| 77 | + i = x // pixels_per_byte |
| 78 | + pixel = (chunk[i] >> (8 - color_depth*(x % pixels_per_byte + 1))) & mask |
| 79 | + bitmap[offset + x] = pixel |
82 | 80 |
|
83 | 81 | return bitmap, palette |
0 commit comments