Skip to content

Instantly share code, notes, and snippets.

@hsk
Created March 24, 2026 06:29
Show Gist options
  • Select an option

  • Save hsk/0a769426f26993442f80cceb07f03d29 to your computer and use it in GitHub Desktop.

Select an option

Save hsk/0a769426f26993442f80cceb07f03d29 to your computer and use it in GitHub Desktop.
japan map rle
from PIL import Image
def load_binary_image(path):
img = Image.open(path).convert("1") # 2値化
w, h = img.size
pixels = img.load()
data = []
for y in range(h):
byte = 0
bit_count = 0
for x in range(w):
bit = 1 if pixels[x, y] == 0 else 0 # 黒=1
byte = (byte << 1) | bit
bit_count += 1
if bit_count == 8:
data.append(byte)
byte = 0
bit_count = 0
if bit_count != 0:
byte <<= (8 - bit_count)
data.append(byte)
return data
def rle_compress(data):
out = []
i = 0
while i < len(data):
val = data[i]
count = 1
while i + count < len(data) and data[i + count] == val and count < 255:
count += 1
out.append(count)
out.append(val)
i += count
return bytes(out)
if __name__ == "__main__":
data = load_binary_image("japan2.png")
comp = rle_compress(data)
with open("bitmap_rle.bin", "wb") as f:
f.write(comp)
print("raw:", len(data), "compressed:", len(comp))
from PIL import Image
TILE_SIZE = 8
def get_tile(img, tx, ty):
tile = []
pixels = img.load()
for y in range(TILE_SIZE):
byte = 0
for x in range(TILE_SIZE):
px = tx * TILE_SIZE + x
py = ty * TILE_SIZE + y
bit = 1 if pixels[px, py] == 0 else 0
byte = (byte << 1) | bit
tile.append(byte)
return tuple(tile)
def extract_tiles(img):
w, h = img.size
tiles = []
tilemap = []
tile_dict = {}
tile_list = []
for ty in range(h // TILE_SIZE):
for tx in range(w // TILE_SIZE):
t = get_tile(img, tx, ty)
if t not in tile_dict:
tile_dict[t] = len(tile_list)
tile_list.append(t)
tilemap.append(tile_dict[t])
return tile_list, tilemap
def save_tiles(tile_list, tilemap):
# --- タイルをRLE圧縮して保存 ---
def flatten_tiles(tile_list):
data = []
for t in tile_list:
data.extend(t)
return data
def rle_compress(data):
out = []
i = 0
while i < len(data):
val = data[i]
count = 1
while i + count < len(data) and data[i + count] == val and count < 255:
count += 1
out.append(count)
out.append(val)
i += count
return bytes(out)
raw_tiles = flatten_tiles(tile_list)
comp_tiles = rle_compress(raw_tiles)
with open("tiles_rle.bin", "wb") as f:
f.write(comp_tiles)
# --- tilemapをRLE圧縮(16bit値)して保存 ---
def rle_compress_16(data):
out = []
i = 0
while i < len(data):
val = data[i]
count = 1
while i + count < len(data) and data[i + count] == val and count < 255:
count += 1
out.append(count)
out.extend(val.to_bytes(2, "little"))
i += count
return bytes(out)
comp_map = rle_compress_16(tilemap)
with open("map_rle.bin", "wb") as f:
f.write(comp_map)
print("map raw:", len(tilemap) * 2)
print("map compressed:", len(comp_map))
print("tiles raw:", len(raw_tiles))
print("tiles compressed:", len(comp_tiles))
print("all compressed size:",len(comp_map)+len(comp_tiles))
print("map compressed and raw tiles size:",len(comp_map)+len(raw_tiles))
if __name__ == "__main__":
img = Image.open("japan2.png").convert("1")
tiles, tilemap = extract_tiles(img)
print("unique tiles:", len(tiles),"size:",len(tiles)*8)
print("map size:", len(tilemap),"size:",len(tilemap)*2)
print("all size:",len(tiles)*8+len(tilemap)*2)
save_tiles(tiles, tilemap)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment