通过将文件中的二进制值转换为 3-3-2 颜色,将 8 位颜色传输到屏幕

Blit 8-bit colour to screen by converting binary values in file to 3-3-2 colour

我最近一直在研究我希望具有图形功能的小型仿真 8 位 CPU。目前,它会在每个周期将 ram 的上部 16K 转储为二进制文件,以便将其读取为“视频内存”。我制作了一个简单的基于 pygame 的程序,该程序读取文件,然后尝试将其转换为 128x128 灰度 3d 数组,以便将其作为表面直接 blit。这没用。我想我可以直接开门见山地问,有没有办法读取二进制文件并将其字节转换为 3-3-2 颜色,而不管文件的实际内容如何?

这是我当前的代码:

import pygame

import numpy as np

from time import sleep

class Viewer:
    def __init__(self, update_func, display_size):
        self.display_size = display_size
        self.update_func = update_func
        pygame.init()
        self.display = pygame.display.set_mode(display_size)

    def set_title(self, title):
        pygame.display.set_caption(title)

    def start(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            z = self.update_func()
            surf = pygame.surfarray.make_surface(z)
            new = pygame.transform.scale(surf, self.display_size)
            self.display.blit(new, (0, 0))

            pygame.display.update()

        pygame.quit()


def update():
    file = open("core.bin", "rb")
    value = bytearray(file.read())
    lst = list(value)
    file.close()
    image = [[ [lst for col in range(len(lst))] for col in range(len(lst))] for row in range(len(lst))]
    print(image)
    sleep(0.25)
    return image


viewer = Viewer(update, (512, 512))
viewer.start()
update()

我过去曾尝试过 numpy.dstack,正常的 3d 数组适用于我的代码,但不适用于二进制文件。是的,我的 bin 文件恰好是 16k。也没有错误消息。

Not Working

My Intent

制作了一张128*128的8位图片,用于测试;假设 RRRGGGBB,而不是 BBGGGRRR。翻转它们,如果是这样的话。发现 numpy 的 reshape() 破坏图像。将值直接注入预期的 numpy 位置可获得更好的结果。应该也更快。

#! /usr/bin/env python3
import pygame
import numpy as np
from time import sleep
from random import randint

class Viewer:
    def __init__(self, update_func, display_size):
        self.display_size = display_size
        self.update_func = update_func
        pygame.init()
        self.display = pygame.display.set_mode(display_size)

    def set_title(self, title):
        pygame.display.set_caption(title)

    def start(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            z = self.update_func()
            surf = pygame.surfarray.make_surface(z)
            new = pygame.transform.scale(surf, self.display_size)
            self.display.blit(new, (0, 0))

            pygame.display.update()

        pygame.quit()

'''
32    111 000 00  = randint( 0, 7 ) << 5   r
64    000 111 00  = randint( 0, 7 ) << 2   g
96    000 000 11  = randint( 0, 3 )        b
128   111 111 11  = randint( 0, 255 )      w
'''

screenshot = bytearray( 128 *128 )  ##  128 *128 8-bit image, just for testing

for red   in range( 0,        128 *32 ):  screenshot[ red ] = randint( 0, 7 ) << 5
for green in range( 128 *32,  128 *64 ):  screenshot[ green ] = randint( 0, 7 ) << 2
for blue  in range( 128 *64,  128 *96 ):   screenshot[ blue ] = randint( 0, 3 )
for white in range( 128 *96,  128 *128 ):  screenshot[ white ] = randint( 0, 255 )

row, col = 0, 0
arr = np .zeros( ( 128, 128, 3 ) )  ##  generate empty numpy array

for byte in screenshot:
    rrr = int( ( ( byte & 0b11100000 ) >> 5 ) *36.4285714286  )  ##  red
    ggg = int( ( ( byte & 0b00011100 ) >> 2 ) *36.4285714286 )  ##  green
    bb = int( ( byte & 0b00000011 ) *85 )  ##  blue  --  multiplied to max 255 range
    
    arr[ col ][ row ][ 0 ] = rrr  ##  insert color values directly into numpy cells
    arr[ col ][ row ][ 1 ] = ggg
    arr[ col ][ row ][ 2 ] = bb

    col += 1
    if col == 128:
        col = 0  ##  \r  carriage return
        row += 1  ##  \n  newline


def update():
    image = arr
    sleep(0.25)
    return image

viewer = Viewer(update, (512, 512))
viewer.start()
update()