Skip to content

Instantly share code, notes, and snippets.

@beefy
Last active January 2, 2021 14:43
Show Gist options
  • Save beefy/ca4845df3c8de0bf203b343d0cb0c451 to your computer and use it in GitHub Desktop.
Save beefy/ca4845df3c8de0bf203b343d0cb0c451 to your computer and use it in GitHub Desktop.
convert a chess pgn file to a gif
import chess.pgn
import chess.svg
import subprocess
import lichess.pgn
import lichess.api
import os
import io
import imageio
import numpy as np
import cv2
from tqdm import tqdm
import sys
lichess_link = sys.argv[1] if len(sys.argv) > 1 else None
# animation speed
frame_rate = 0.5
# board orientation
as_black = False
# input / output files
game_pgn_file = "game.pgn"
gif_file = "game.gif"
# temporary files
html_file = "pos.html"
image_file = "pos.png"
# function for converting html to image
#bash = ("webkit2png "+html_file+" -o "+image_file).split()
path = os.getcwd()
html_file_full = "file://"+path+"/"+html_file
bash = ("firefox --headless --screenshot "+image_file+" "+html_file_full).split()
html2image = lambda: subprocess.Popen(bash).communicate()
def get_frames(game):
""" get image frames in chess game """
images = []
board = game.board()
images.append(write_board(board))
moves = list(game.mainline_moves())
prog_bar = tqdm(range(len(moves)))
for i in prog_bar:
board.push(moves[i]) # next move
images.append(write_board(board))
return np.array(images)
def write_board(board):
""" get the image of a board position """
# write html board position
pos = chess.svg.board(board,flipped=as_black)
f = open(html_file,"wb")
f.write(bytes(pos, 'UTF-8'))
# write image board position
html2image()
# read and return image
return cv2.imread(image_file)
def cleanup():
""" remove temporary files """
os.remove(html_file)
os.remove(image_file)
#os.remove("webkit2png.log")
if __name__ == "__main__":
if lichess_link:
# get pgn from lichess.org
game_id = lichess_link.split("/")[-1][0:8]
lichess_game = lichess.api.game(game_id,with_moves=1)
pgn = lichess.pgn.from_game(lichess_game)
game = chess.pgn.read_game(io.StringIO(pgn))
else:
# read chess pgn file
with open(game_pgn_file) as pgn:
game = chess.pgn.read_game(pgn)
# get image frames per move
frames = get_frames(game)
# write images to gif file
imageio.mimsave(gif_file,frames,duration=frame_rate)
# remove temporary files
cleanup()
@beefy
Copy link
Author

beefy commented May 22, 2019

alternative tools:
https://github.com/dn1z/pgn2gif
https://github.com/ninception/chess-pgn-gif
https://github.com/aherve/giflichess

setup:

pip3 install imageio
pip3 install python-chess 
pip3 install opencv-python 

usage:
read pgn from file: python3 chess_game_to_gif.py
read pgn from lichess link: python3 chess_game_to_gif.py https://lichess.org/WO8COwNBMA6q

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment