X-Git-Url: https://git.ayoreis.com/hackapet/Adafruit_Blinka_Displayio.git/blobdiff_plain/96a8f5564dce100d739e43528ecd40a10316be8d..4b1106f54733a9d304edbf87a6b5b67b6744de3f:/bitmaptools/__init__.py diff --git a/bitmaptools/__init__.py b/bitmaptools/__init__.py index e3490f6..0c9465b 100644 --- a/bitmaptools/__init__.py +++ b/bitmaptools/__init__.py @@ -1,7 +1,8 @@ import math -from typing import Optional, Tuple +import struct +from typing import Optional, Tuple, BinaryIO -from displayio import Bitmap +from displayio import Bitmap, Colorspace import circuitpython_typing @@ -224,7 +225,6 @@ def arrayblit( x1: int = 0, y1: int = 0, x2: int | None = None, y2: int | None = None, skip_index: int | None = None): - if x2 is None: x2 = bitmap.width if y2 is None: @@ -237,3 +237,185 @@ def arrayblit( value = int(data[i] % _value_count) if skip_index is None or value != skip_index: bitmap[x, y] = value + + +def readinto(bitmap: Bitmap, + file: BinaryIO, + bits_per_pixel: int, + element_size: int = 1, + reverse_pixels_in_element: bool = False, + swap_bytes: bool = False, + reverse_rows: bool = False): + + width = bitmap.width + height = bitmap.height + bits_per_value = bitmap._bits_per_value + mask = (1 << bits_per_value) - 1 + + elements_per_row = (width * bits_per_pixel + element_size * 8 - 1) // (element_size * 8) + rowsize = element_size * elements_per_row + + for y in range(height): + row_bytes = file.read(rowsize) + if len(row_bytes) != rowsize: + raise EOFError() + + # Convert the raw bytes into the appropriate type array for processing + rowdata = bytearray(row_bytes) + + if swap_bytes: + if element_size == 2: + rowdata = bytearray( + b''.join( + struct.pack('H', rowdata[i:i + 2])[0]) + for i in range(0, len(rowdata), 2) + ) + ) + elif element_size == 4: + rowdata = bytearray( + b''.join( + struct.pack('I', rowdata[i:i + 4])[0]) + for i in range(0, len(rowdata), 4) + ) + ) + + y_draw = height - 1 - y if reverse_rows else y + + for x in range(width): + value = 0 + if bits_per_pixel == 1: + byte_offset = x // 8 + bit_offset = 7 - (x % 8) if reverse_pixels_in_element else x % 8 + value = (rowdata[byte_offset] >> bit_offset) & 0x1 + elif bits_per_pixel == 2: + byte_offset = x // 4 + bit_index = 3 - (x % 4) if reverse_pixels_in_element else x % 4 + bit_offset = 2 * bit_index + value = (rowdata[byte_offset] >> bit_offset) & 0x3 + elif bits_per_pixel == 4: + byte_offset = x // 2 + bit_index = 1 - (x % 2) if reverse_pixels_in_element else x % 2 + bit_offset = 4 * bit_index + value = (rowdata[byte_offset] >> bit_offset) & 0xF + elif bits_per_pixel == 8: + value = rowdata[x] + elif bits_per_pixel == 16: + value = struct.unpack_from('> 8) & 0xFF) + sp2 = ((sp2 & 0xFF) << 8) | ((sp2 >> 8) & 0xFF) + + blend_source1 = skip_source1_index_none or sp1 != skip_source1_index + blend_source2 = skip_source2_index_none or sp2 != skip_source2_index + + if blend_source1 and blend_source2: + ifactor_blend = ifactor1 + ifactor2 - ifactor1 * ifactor2 // 256 + + red_dca = ((sp1 & r_mask) >> 8) * ifactor1 + grn_dca = ((sp1 & g_mask) >> 3) * ifactor1 + blu_dca = ((sp1 & b_mask) << 3) * ifactor1 + + red_sca = ((sp2 & r_mask) >> 8) * ifactor2 + grn_sca = ((sp2 & g_mask) >> 3) * ifactor2 + blu_sca = ((sp2 & b_mask) << 3) * ifactor2 + + if blendmode == 'screen': + red_blend = red_sca + red_dca - (red_sca * red_dca // 65536) + grn_blend = grn_sca + grn_dca - (grn_sca * grn_dca // 65536) + blu_blend = blu_sca + blu_dca - (blu_sca * blu_dca // 65536) + else: + red_blend = red_sca + red_dca * (256 - ifactor2) // 256 + grn_blend = grn_sca + grn_dca * (256 - ifactor2) // 256 + blu_blend = blu_sca + blu_dca * (256 - ifactor2) // 256 + + r = ((red_blend // ifactor_blend) << 8) & r_mask + g = ((grn_blend // ifactor_blend) << 3) & g_mask + b = ((blu_blend // ifactor_blend) >> 3) & b_mask + + pixel = (r & r_mask) | (g & g_mask) | (b & b_mask) + + if swap: + pixel = ((pixel & 0xFF) << 8) | ((pixel >> 8) & 0xFF) + + elif blend_source1: + r = ((sp1 & r_mask) * ifactor1 // 256) & r_mask + g = ((sp1 & g_mask) * ifactor1 // 256) & g_mask + b = ((sp1 & b_mask) * ifactor1 // 256) & b_mask + pixel = r | g | b + elif blend_source2: + r = ((sp2 & r_mask) * ifactor2 // 256) & r_mask + g = ((sp2 & g_mask) * ifactor2 // 256) & g_mask + b = ((sp2 & b_mask) * ifactor2 // 256) & b_mask + pixel = r | g | b + else: + pixel = dest[x, y] + + dest[x, y] = pixel