diff --git a/Gui.py b/Gui.py index c28fff2a..14f8adba 100644 --- a/Gui.py +++ b/Gui.py @@ -393,38 +393,106 @@ class SpriteSelector(object): def local_unofficial_sprite_dir(site): return local_path("data/sprites/unofficial") + def get_image_for_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): - return "#{0:02X}{1:02X}{2:02X}".format(*color) + def draw_sprite_into_gif(add_palette_color, set_pixel_color_index): - def drawsprite(spr, pal_as_colors, offset): - for y in range(len(spr)): - for x in range(len(spr[y])): - pal_index = spr[y][x] - if pal_index: - color = pal_as_colors[pal_index - 1] - image.put(color_to_hex(color), to=(x + offset[0], y + offset[1])) + def drawsprite(spr, pal_as_colors, offset): + for y in range(len(spr)): + for x in range(len(spr[y])): + pal_index = spr[y][x] + if pal_index: + color = pal_as_colors[pal_index - 1] + set_pixel_color_index(x + offset[0], y + offset[1], color) - shadow_palette = [(40, 40, 40)] - shadow = [ - [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 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], - [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0], - ] + add_palette_color(16, (40, 40, 40)) + shadow = [ + [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 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], + [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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() - body = sprite.decode16(0x4C0) - drawsprite(body, palettes[0], (0, 8)) - head = sprite.decode16(0x40) - drawsprite(head, palettes[0], (0, 0)) + palettes = sprite.decode_palette() + for i in range(15): + add_palette_color(i + 1, palettes[0][i]) + + 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)