Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show more characters at a time on the screen #29

Open
zhs628 opened this issue Feb 28, 2024 · 5 comments
Open

Show more characters at a time on the screen #29

zhs628 opened this issue Feb 28, 2024 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@zhs628
Copy link

zhs628 commented Feb 28, 2024

First of all, thank you to this project for unlocking greater potential for iDotMatrix in the hands of users.

While researching the library you’ve written, I intend to implement a small feature that can monitor keyboard inputs in real time and update them to iDotMatrix. However, I unexpectedly found that the _StringToBitmaps implemented in the Text class seems to only display two characters on the screen. Based on this, I made some modifications so that the program can arrange as many characters as possible on the screen based on the set character size (“char_width”, “char_height”).

def string_to_bitmaps(string, font, char_width=10, char_height=10):
    
    images = []
    
    for char in string:
        image = Image.new("1", (char_width, char_height), 0)
        draw = ImageDraw.Draw(image)
        _, _, text_width, text_height = draw.textbbox((0, 0), text=char, font=font)
        text_x = (char_width - text_width) // 2
        text_y = (char_height - text_height) // 2
        draw.text((text_x, text_y), char, fill=1, font=font)
        images.append(image)
    
    screen_image = join_images(images, char_width, char_height)
    
    width, height = screen_image.size
    half_width = width // 2
    
    left_half_image = screen_image.crop((0, 0, half_width, height))
    right_half_image = screen_image.crop((half_width, 0, width, height))
    
    return (construct_bit_map(left_half_image), construct_bit_map(right_half_image))

def join_images(images, char_width=10, char_height=10):
    width, height = images[0].size
    images = [ImageOps.fit(img.convert('1'), (width, height)) for img in images]

    result_width = 32  # My device is 32x32 pixels.
    result_height = 32
    result = Image.new('1', (result_width, result_height), color=0)  # 0: black

    x_char_num = 32 // char_width
    y_char_num = 32 // char_height
    

    for i, img in enumerate(images):
        x = (i % x_char_num) * width
        y = (i // y_char_num ) * height
        result.paste(img, (x, y))

    return result


def construct_bit_map(image:Image):
    """Converts half screen images (16x32) to bitmap images which suitable for iDotMatrix devices."""
    bitmap = bytearray()
    for y in range(32):
        for x in range(16):
            if x % 8 == 0:
                byte = 0
            pixel = image.getpixel((x, y))
            byte |= (pixel & 1) << (x % 8)
            if x % 8 == 7:
                bitmap.append(byte)
        
    return bitmap


# -----------
# tools for print binary image 
# -----------
# def decimal_to_binary_list(num):
#     binary_str = bin(num)[2:].zfill(8)
#     binary_list = ["#" if bit == "1" else "." for bit in binary_str]
#     return binary_list



# def print_binary_image(image: Image):
#     width, height = image._size
#
#     ascii_symbols = ['.', '#']
#     for y in range(height):
#         row_str = ''
#         for x in range(width):
#             pixel_value = image.getpixel((x, y))
#             row_str += ascii_symbols[pixel_value] + " "
#         print(row_str)


class NewText(Text):
    
    def _StringToBitmaps(self,text: str,font_path: Optional[str] = None, font_size: Optional[int] = 20) -> bytearray:
        """Converts text to bitmap images suitable for iDotMatrix devices."""
        # using open source font from https://www.fontspace.com/rain-font-f22577
        font_path = font_path or "./fonts/Rain-DRM3.otf"
        font_size = font_size or 20
        font = ImageFont.truetype(font_path, font_size)

        text = text.upper()  # In low resolution, uppercase letters are easier to recognize.
        
        # Construct bitmap from text, and split it into two halves (16x32)   
        left, right = string_to_bitmaps(text, font)
        
        # Join the two halves of the bitmap in a way that is compatible with iDotMatrix
        byte_stream = bytearray(b"\x05\xff\xff\xff" + left + b"\x05\xff\xff\xff" + right) 
        return byte_stream

I only have a 32x32 screen, sorry for not being able to adapt to 16x16 and 64x64 screens, hope the above content can bring you some convenience for your development❤️.

@zhs628
Copy link
Author

zhs628 commented Feb 28, 2024

image

@derkalle4
Copy link
Owner

Thanks, that was actually a ToDo which is open ;) I'll check on this over the next days and push an update to the library :)

@derkalle4 derkalle4 self-assigned this Mar 3, 2024
@derkalle4 derkalle4 added the enhancement New feature or request label Mar 3, 2024
@derkalle4
Copy link
Owner

Hi @zhs628,

I currently do not understand why it shows more characters for you. Can you explain it to me? I also looked into the topic and added newly found things to #14 - where you can see my latest attempts to update the library. We would need something that works with all display sizes (16x16, 32x32 and 64x64) :)

@zhs628
Copy link
Author

zhs628 commented Mar 5, 2024

Sorry, I didn’t specify the functionality and process. I will further explain how to transmit a 32x32 image to a 32x32 screen through the text interface.

First, I generate a complete 32x32 image based on the input text, then I cut it along the vertical midline into two halves (16x32), and then convert each of them into a bitmap. Finally, I prepend b"\x05\xff\xff\xff" to each of the bitmaps and concatenate them to create a byte_stream that can display a perfect 32x32 image on a 32x32 screen.

image

@zhs628
Copy link
Author

zhs628 commented Mar 5, 2024

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants