Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?

Creating Chess Board SVGs, PNGs, and GIFs

Probably the most versatile method to flip a string into a picture is thru a URL that is aware of what picture to return. Hoping {that a} friction-less method to serve chess pictures could be viable, I made a decision to see how rapidly an inexpensive server may convert a FEN string of any chess place into a light-weight picture.

Chess Notation Fundamentals

The usual notation for storing place info is Forsyth-Edwards Notation. A FEN string appears like rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR adopted by an area and another info that isn’t related to making a board picture.

The opening place by way of https://rnbqkbnr.com/rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR.png
  • Lowercase letters are black items and uppercase letters are white items.
  • Letters signify the anticipated items apart from n which is the knight.
  • Numbers signify the variety of consecutive empty areas.
  • The / separates rows.

Parsing these strings is comparatively easy, with only a bit of labor to deal with the numbers. Maintain observe of the present column by shifting to the subsequent column after every bit and shifting the given variety of columns when hitting an integer. Transfer to the subsequent row when the column is larger than 7 till all 8 rows are full.

let row = 0, col = 0;
for (var i=0; i<fen.size; i++) {
  swap (fen[i]) {
    case 'P': case 'N': case 'B':
    case 'R': case 'Q': case 'Okay':
    case 'p': case 'n': case 'b':
    case 'r': case 'q': case 'okay': {
      //the piece is fen[i], row is row, col is col
      //flip that information right into a graphic
      if (col > 7) {
        col = 0;
    case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': {
      //transfer the given variety of cols
      col += parseInt(fen[i]);
      if (col > 7) {
        col = 0;
    //skip over different chars like /
  if (row > 7) { break;}
Enter fullscreen mode

Exit fullscreen mode

Picture Varieties

There are a number of choices for the kind of picture to generate. By default, static pictures will probably be SVG since it’s light-weight, quite simple to create, and properly scales to any measurement.

Many social media apps don’t show SVG so a PNG choice is vital for compatibility. Lastly, I need to create GIFs in order that it’s attainable to animate just a few strikes.

SVG Creation

Creating SVGs solely requires manipulating strings, so any back-end setup works simply. All we’d like is a clean board and paths for every bit. Then each time we hit a bit as we loop by means of the FEN string simply add the suitable paths and translate to the right row and column.

case 'r': case 'n': case 'b': case 'q': case 'okay': case 'p': {
    svg += `<g remodel="translate(${col*45} ${row*45})">${items[fen[i]]}</g>`;
    //add code right here to replace row, col as above
case 'R': case 'N': case 'B': case 'Q': case 'Okay': case 'P': {
    svg += `<g remodel="translate(${col*45} ${row*45})" class="w">${this.items[this.fen[i].toLowerCase()]}</g>`;
    //every sq. is 45 models large/tall
Enter fullscreen mode

Exit fullscreen mode

Any assortment of SVG items (I assume raster pictures would work if crucial) can work by wrapping every bit inside a gaggle that will get remodeled to suit into the specified sq..

A clean board might be so simple as utilizing a checkerboard sample for the background, however you can too add a border with grid labels or the rest. So long as you already know the dimensions of every sq., it’s trivial so as to add the items on prime in the fitting areas.

<svg model="1.1" xmlns="http://www.w3.org/2000/svg"  viewBox="-9 -9 378 378">
    <sample id="bg" x="0" y="0" width="90" top="90" patternUnits="userSpaceOnUse">
      <rect fill="rgb(190,190,190)" x="0" y="0" width="90" top="90"/>
      <rect fill="rgb(150,100,75)" x="45" y="0" width="45" top="45"/>
      <rect fill="rgb(150,100,75)" x="0" y="45" width="45" top="45"/>
  <rect x="-9" y="-9" width="100%" top="100%" fill="black"/>
  <rect x="0" y="0" width="360" top="360" fill="url(#bg)" fill-opacity="0.75"></rect>
<!--Add items here-->
Enter fullscreen mode

Exit fullscreen mode

There aren’t any dependencies so this algorithm can run client-side or server-side, and the picture takes lower than a millisecond to generate whereas compressing all the way down to about 2 KB. For the manufacturing server, I ended up utilizing OpenResty (an extension of Nginx) with Lua however the course of is similar.

PNG Creation

There are lots of methods to transform an SVG to a PNG both with a browser’s built-in renderer or a software like rsvg-convert. The quickest strategy, although, is to pre-render the pixel arrays for every bit after which splice them collectively at runtime.

For simplicity, I will probably be producing PNGs with JavaScript/Node and the Sharp image library. Any library that may convert between pixel arrays and picture information will make the method fairly easy.

All 24 possible occupied squares

All 24 attainable occupied squares

There are 6 items in every colour, after which every must be on darkish and lightweight backgrounds for a complete of 24 potentialities.

I’ve created 80px by 80px pictures of every piece to suit into 90px squares with a little bit of padding. I cut up every picture into 80 Uint8Arrays, one for every row, and create a map to those arrays that I can name when wanted.

//every sq. is 90px and I solely need to change the middle 80x80 so offset by 5
//the board is 720px large and every pixel makes use of 3 cells (R,G,B)
var minRow = 5 + 90 * row;
var minCol = 5 + 90 * col;
for (var rr = 0; rr < 80; rr++) {
  //arr is a Uint8Array that begins as a clean board.
  //inputPNGs finds the right row for the right piece
  //then insert that array on the right beginning index with arr.set()
  arr.set(inputPNGs[p][rr], (rr + minRow) * 720 * 3 + minCol * 3);
Enter fullscreen mode

Exit fullscreen mode

When the server launches, I exploit Sharp to create arrays for the board and every bit. Then every time I would like a brand new board picture, Sharp generates a PNG from the generated Uint8Array. Additionally it is attainable to create JPGs, WEBPs, or another frequent format in addition to altering the dimensions and different settings.

The entire course of solely takes just a few milliseconds, however for max velocity and minimal file measurement I ended up utilizing a extra advanced course of with Rust/Actix for the manufacturing server.

Animated GIFs

For GIFs, I do require customers to generate them in a browser after which add them to a GIF server. In comparison with the static pictures, I do not assume there’s a performant technique of making GIFs on demand server-side.

With SVG paths, it’s attainable to create a very nice transition between positions. Create a path that begins with the preliminary piece, strikes alongside the board to the subsequent place, after which finishes with the piece within the new location. By animating how a lot of this path is seen at any time a pleasant clean motion is generated.

A gif of the fool's mate

A gif of the idiot’s mate

It takes a little bit of computation to get the timing proper for a clean animation, however after that work the gif.js and gifsicle libraries can output a reasonably light-weight GIF for downloading and sharing.

Step one is to take a bunch of snapshots at common intervals. We have to generate the suitable SVG for every body, render it to a canvas, after which convert the canvas to a PNG.

As soon as we’ve got an array of pictures, observe the documentation for gif.js to create the GIF. These GIFs are a bit giant, however gifsicle will considerably scale back the dimensions. By utilizing the “-O3” compression and solely 32 colours (a lot for our chess pictures) the dimensions is decreased by at the very least 80%.

Net Element

Though it requires a little bit of JavaScript, one other easy means so as to add a board picture to an internet web page is with a customized internet part. Since I already had a operate to generate the SVG, I principally simply wanted so as to add some web component boilerplate.

The library zips to about 3 KB and makes it attainable to generate or replace a number of board pictures with out extra requests. The opposite benefit is the choice to fashion the border, change the colours of the squares, and even add some arrows.

<chess-board fen="rnbqkbnr/8/8/8/8/8/8/RNBQKBNR" arrows="a1a5 b1c3,g8f6" darkish="blue" mild="grey" border="12 black white"></chess-board>
<chess-board fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" mild="orange" border="8 black black"></chess-board>
<script src="https://rnbqkbnr.com/chess-board.js"></script>
Enter fullscreen mode

Exit fullscreen mode

The boards produced by the HTML above

The boards produced by the HTML above.

Code Repositories

If you’d like customized board pictures or to see the complete code, you’ll be able to view my chess code portfolio and observe the hyperlinks to fork on Replit or view all of my repls.

There are separate repls to create the SVGs, PNGs (and render piece/board images from SVG), GIFs, and web components.

If you’d like a picture of a chess place, merely paste or sort a FEN string (with or with out the data about castling, and so on.) after the area https://rnbqkbnr.com wherever URLs are accepted: browsers, many apps and web sites, or inside an HTML img ingredient. In the event you want a PNG, then simply add .png to the tip.

Since I am probably not lively within the chess group, I’m open to any strategies from individuals who know what options could be most useful.

Add a Comment

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?