Cub's Contraption - Hermit-Tools/Thumbnail-Maker GitHub Wiki

v0 to v1.0 is directed towards making cubfan135's thumbnail-maker. Cub is the veteran of veterans. His thumbnails are so simple yet so outstanding.

Analysis

We have analyzed his thumbnails from his first HC season to the current season. Following is a typical thumbnail. cubfan135's Ep 31 Hermitcraft S7 Thumbnail
His thumbnail consists of a background image(namely a screenshot), the season logo, and the episode number.

How we did it?

Cubfan's thumbnail-maker is up and running here. It is fully functional. We are also working on the next version of Cub's Contraption. The pieces of code you see below are from the stable version. Once the beta code gets deployed, we will update the code to match the latest.

We are using the HTML canvas element for previewing the result. Ultimately the same preview gets converted into a PNG image as the final result. Hence it is a What You See Is What You Get editor. The canvas is sized to 1920x1080. It is scaled down to 360p by CSS. Thus the preview is in 360p but the result is in 1080p.
Note that the preview gets scaled down further to match the device's size. The result is always in 1080p though.

Step 1

Cub's Contraption is a 3 step editor. Step one is to choose the background image. We allow the user to choose an image via a simple <input type="file"> line. The canvas automatically updates itself once the user chooses an image with the help of the onchange listener of the input tag. This javasript code continues the process.

function addBgImage() {
  let bgImage = new Image();
  bgImage.addEventListener(
    "load",
    () => {
      ctx.drawImage(bgImage, 0, 0, 1920, 1080);
      hcLogo();
      episodeNum();
    },
    false
  );
  bgImage.src = URL.createObjectURL(bgInput.files[0]);
}

The above code creates a new Image(), defines its source to the file selected from the input tag, waits for the image to load, when the image loads it scales the image to 1080p, draws the image, and finally it calls hcLogo() and episodeNum() to add the season logo and episode number if asked by the user.

Step 2

Step 2 is to add the episode number. The user enters the episode number and on input, the canvas updates to show the episode number. This is achieved by this simple piece of code.

function episodeNum() {
  let epNum = epNumSelector.value;

  ctx.fillStyle = "#fff";
  ctx.strokeStyle = "#000";
  ctx.lineWidth = 12;
  ctx.font = "1000 401px Tahoma";
  ctx.textBaseline = "bottom";

  ctx.save();
  ctx.scale(1.05, 0.98);
  ctx.fillText(epNum, 15, 1120);
  ctx.strokeText(epNum, 15, 1120);
  ctx.restore();
  
  ctx.fill();
  ctx.stroke();
}

First of all, this function gets the episode number from input type="text" named epNumSelector. The next blocks of code style text to match Cub's style, place the text at the correct position, and fill & stroke the text.

Step 3

This final steps added the Hermitcraft logo Cub uses. This is the code.

function hcLogo() {
  if (hcLogoToggler.checked) {
    let hc7Logo = new Image();
    hc7Logo.addEventListener("load", () => {
      ctx.drawImage(hc7Logo, 15.7, 40, 1887.5, 244);
    });
    hc7Logo.src =
      "https://hermit-tools.github.io/Thumbnail-Maker/Resources/Hermitcraft Logos/HC7 Logo.png";
    hc7Logo.crossOrigin = "Anonymous";
  }
}

Nothing too special to see here. It is very similar to the code specified in Step 1. But instead of taking the image from an input tag, it takes the image from a URL. The last line is required as it stops CORB(a browser security system) from blocking the image to load.

Downloading the image

This piece of code triggers when clicking on the download button. This code may change in the future.

function finishEditing() {
  const downloadShow = document.getElementById("downloadShow");
  downloadShow.style.opacity = "1";
  setTimeout(() => {
    downloadShow.style.opacity = "0";
  }, 5000);
  downloader.download = `Ep${epNumSelector.value} HC7 Cub's Contraption.jpg`;
  downloader.href = canvas
    .toDataURL("image/png")
    .replace("data:image/png", "data:concorp>sahara");
}

downloadShow is a div that shows when downloading the image and automatically disappears after 5 seconds. The next line of code smartly names the downloaded file.

Automatically filling episode number

Cub's Contraption fills the episode number automatically. This is done using cookies, although we are looking forward to switching to local storage.

let epNumValueFromCookie;

downloader.addEventListener("click", () => {
  document.cookie = `epNumCookie=${epNumSelector.value}`;
});

if (document.cookie.length === 0) {
  epNumValueFromCookie = "";
} else {
  epNumValueFromCookie = document.cookie.split("=")[1];
  epNumSelector.value = Number(epNumValueFromCookie) + 1;
}