Improve performance by creating in-memory gifs
This commit is contained in:
parent
1d223dc0b8
commit
5dbc21ce3a
118
Gui.py
118
Gui.py
|
@ -393,38 +393,106 @@ class SpriteSelector(object):
|
||||||
def local_unofficial_sprite_dir(site):
|
def local_unofficial_sprite_dir(site):
|
||||||
return local_path("data/sprites/unofficial")
|
return local_path("data/sprites/unofficial")
|
||||||
|
|
||||||
|
|
||||||
def get_image_for_sprite(filename):
|
def get_image_for_sprite(filename):
|
||||||
sprite = Sprite(filename)
|
sprite = Sprite(filename)
|
||||||
image = PhotoImage(height=24, width=16, palette="256/256/256")
|
if not sprite.valid:
|
||||||
|
return None
|
||||||
|
height = 24
|
||||||
|
width = 16
|
||||||
|
|
||||||
def color_to_hex(color):
|
def draw_sprite_into_gif(add_palette_color, set_pixel_color_index):
|
||||||
return "#{0:02X}{1:02X}{2:02X}".format(*color)
|
|
||||||
|
|
||||||
def drawsprite(spr, pal_as_colors, offset):
|
def drawsprite(spr, pal_as_colors, offset):
|
||||||
for y in range(len(spr)):
|
for y in range(len(spr)):
|
||||||
for x in range(len(spr[y])):
|
for x in range(len(spr[y])):
|
||||||
pal_index = spr[y][x]
|
pal_index = spr[y][x]
|
||||||
if pal_index:
|
if pal_index:
|
||||||
color = pal_as_colors[pal_index - 1]
|
color = pal_as_colors[pal_index - 1]
|
||||||
image.put(color_to_hex(color), to=(x + offset[0], y + offset[1]))
|
set_pixel_color_index(x + offset[0], y + offset[1], color)
|
||||||
|
|
||||||
shadow_palette = [(40, 40, 40)]
|
add_palette_color(16, (40, 40, 40))
|
||||||
shadow = [
|
shadow = [
|
||||||
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
||||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||||
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
||||||
]
|
]
|
||||||
|
|
||||||
drawsprite(shadow, shadow_palette, (2, 17))
|
drawsprite(shadow, [16], (2, 17))
|
||||||
|
|
||||||
palettes = sprite.decode_palette()
|
palettes = sprite.decode_palette()
|
||||||
body = sprite.decode16(0x4C0)
|
for i in range(15):
|
||||||
drawsprite(body, palettes[0], (0, 8))
|
add_palette_color(i + 1, palettes[0][i])
|
||||||
head = sprite.decode16(0x40)
|
|
||||||
drawsprite(head, palettes[0], (0, 0))
|
body = sprite.decode16(0x4C0)
|
||||||
|
drawsprite(body, list(range(1, 16)), (0, 8))
|
||||||
|
head = sprite.decode16(0x40)
|
||||||
|
drawsprite(head, list(range(1, 16)), (0, 0))
|
||||||
|
|
||||||
|
def make_gif(callback):
|
||||||
|
gif_header = b'GIF89a'
|
||||||
|
|
||||||
|
gif_lsd = bytearray(7)
|
||||||
|
gif_lsd[0] = width
|
||||||
|
gif_lsd[2] = height
|
||||||
|
gif_lsd[4] = 0xF4 # 32 color palette follows. transparant + 15 for sprite + 1 for shadow=17 which rounds up to 32 as nearest power of 2
|
||||||
|
gif_lsd[5] = 0 # background color is zero
|
||||||
|
gif_lsd[6] = 0 # aspect raio not specified
|
||||||
|
gif_gct = bytearray(3 * 32)
|
||||||
|
|
||||||
|
gif_gce = bytearray(8)
|
||||||
|
gif_gce[0] = 0x21 # start of extention blocked
|
||||||
|
gif_gce[1] = 0xF9 # identifies this as the Graphics Control extension
|
||||||
|
gif_gce[2] = 4 # we are suppling only the 4 four bytes
|
||||||
|
gif_gce[3] = 0x01 # this gif includes transparency
|
||||||
|
gif_gce[4] = gif_gce[5] = 0 # animation frrame delay (unused)
|
||||||
|
gif_gce[6] = 0 # transparent color is index 0
|
||||||
|
gif_gce[7] = 0 # end of gif_gce
|
||||||
|
gif_id = bytearray(10)
|
||||||
|
gif_id[0] = 0x2c
|
||||||
|
# byte 1,2 are image left. 3,4 are image top both are left as zerosuitsamus
|
||||||
|
gif_id[5] = width
|
||||||
|
gif_id[7] = height
|
||||||
|
gif_id[9] = 0 # no local color table
|
||||||
|
|
||||||
|
gif_img_minimum_code_size = bytes([7]) # we choose 7 bits, so that each pixel is represented by a byte, for conviennce.
|
||||||
|
|
||||||
|
clear = 0x80
|
||||||
|
stop = 0x81
|
||||||
|
|
||||||
|
unchunked_image_data = bytearray(height * (width + 1) + 1)
|
||||||
|
# we technically need a Clear code once every 125 bytes, but we do it at the start of every row for simplicity
|
||||||
|
for row in range(height):
|
||||||
|
unchunked_image_data[row * (width + 1)] = clear
|
||||||
|
unchunked_image_data[-1] = stop
|
||||||
|
|
||||||
|
def add_palette_color(index, color):
|
||||||
|
gif_gct[3 * index] = color[0]
|
||||||
|
gif_gct[3 * index + 1] = color[1]
|
||||||
|
gif_gct[3 * index + 2] = color[2]
|
||||||
|
|
||||||
|
def set_pixel_color_index(x, y, color):
|
||||||
|
unchunked_image_data[y * (width + 1) + x + 1] = color
|
||||||
|
|
||||||
|
callback(add_palette_color, set_pixel_color_index)
|
||||||
|
|
||||||
|
def chunk_image(img):
|
||||||
|
for i in range(0, len(img), 255):
|
||||||
|
chunk = img[i:i + 255]
|
||||||
|
yield bytes([len(chunk)])
|
||||||
|
yield chunk
|
||||||
|
|
||||||
|
gif_img = b''.join([gif_img_minimum_code_size] + list(chunk_image(unchunked_image_data)) + [b'\x00'])
|
||||||
|
|
||||||
|
gif = b''.join([gif_header, gif_lsd, gif_gct, gif_gce, gif_id, gif_img, b'\x3b'])
|
||||||
|
|
||||||
|
return gif
|
||||||
|
|
||||||
|
gif_data = make_gif(draw_sprite_into_gif)
|
||||||
|
image = PhotoImage(data=gif_data)
|
||||||
|
|
||||||
return image.zoom(2)
|
return image.zoom(2)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue