Recreating ANSI Artwork from a screenshot
Within the early to mid-90s, I ran a BBS out of my bed room. It wasn’t highly regarded, however I did have numerous time on my arms and I spent numerous that point modding it. Initially, I wrote mods for myself, however ultimately I began releasing them to different folks. As a youngster, this was the primary software program that I wrote that different folks used. This was my contribution to “the scene” and now my solely declare to fame from that point is that I’m a part of the ultimate member listing of ACiD Productions below BBS Modifications.
Throughout this period, I requested certainly one of my customers to create some ANSI artwork for me:
And so they agreed!
11 days later, they uploaded the ANSI artwork to my BBS.
Chances are you’ll be questioning what the cope with these Home windows XP-era screenshots is. Effectively, I used to backup my BBS with a Colorado Tape Backup drive. Right here’s an image of 1 I discovered on the Web:
In 2001, I discovered a 250 MB tape that was the final backup of my previous BBS and restored it to my pc. Feeling nostalgic, I logged in to it regionally and took just a few screenshots. Once I first logged-in to it, it displayed the ANSI artwork that my person had made for me:
It scrolled by fairly quick, so I took a collection of screenshots of it after which used Photoshop to mix them. I made just a little webpage for it so I might have a look at it from time to time and went on with my life.
Shortly after this, my laborious drive died. I feel it was an IBM Deathstar. I do not know what occurred to the 250 MB tape, however I feel it’s secure to say that even when I do discover it, it most likely isn’t going to work.
Fortunately, because of the ability of the online, I nonetheless have these screenshots. Unluckily, I by no means truly uploaded the unique ANSI file, so I don’t have that. From time to time I’ll seek for it on the Web, however I’ve concluded that it by no means made it into an artpack and thus I had the one copy of it, till I didn’t.
It’s not essentially the most stunning ANSI artwork, however it’s one thing that somebody made for me and I’ve all the time been just a little bummed that I can’t have a look at it in one of many many ANSI viewers (or DOS emulators) that exist right now.
Let’s repair that!
The very first thing to grasp about ANSI artwork is that it combines two issues: characters from the IBM Code page 437 and ANSI escape sequences that do issues like change colours and transfer the cursor round.
I discovered this extraordinarily handy page that exhibits all of the totally different characters in Codepage 437.
Characters #0 – #31 are management characters, and #127 is DEL, so we are able to ignore these. The remainder of them are utilized in ANSI artwork, though the shade blocks and half blocks are predominately used.
The best way that you’d sort certainly one of these bizarre characters on an IBM PC is that you might maintain down ALT and sort the ASCII code in your numpad. Once you launched ALT, the character would present up. However most artists would use a program like TheDraw or ACiDDraw to design their artwork.
Talking of TheDraw, let’s check out the colour choice display screen from it:
There are sixteen foreground colours and eight background colours. Ignore 16-31, I captured this screenshot mid-blink.
Altering the foreground and background colours and writing the characters from Codepage 437 produces the ANSI artwork that we all know right now:
To precisely show ANSI artwork, it’s necessary to make use of an acceptable IBM PC font, like this one. It will be certain that your artwork seems the way in which that it was meant by the artist.
The technique for conversion that I got here up with was: cut up the screenshot into particular person characters. For every character, generate each doable permutation of background colour, foreground colour, and character from Codepage 437 and evaluate it to the character within the screenshot, then choose the one that’s the most related.
There’s most likely numerous alternative ways to do that, however I figured the simplest can be to make a webpage and use the Canvas API.
As a check case, I used a program referred to as ansilove to take an present .ANS
file and generate a PNG of it. It even got here with an instance ANS file:
The picture is 640×464. Assuming that we now have a 8×16 font, because of this it comprises 80×29 characters.
We create a canvas and cargo the picture into it:
const canvas = doc.getElementById("canvas");
const ctx = canvas.getContext("2nd", { willReadFrequently: true });
const img = new Picture();
img.addEventListener("load", (e) => {
ctx.drawImage(img, 0, 0);
});
img.src="https://bert.org/2023/02/27/recreating-ansi-art-from-a-screenshot/enter.png";
Subsequent, we now have to have a listing of the foreground and background colours. I discovered that iTerm2 has a color scheme for CGA that appears correct, so I loaded it into iTerm after which extracted the hex codes from it, double-checking towards the TheDraw colour picker. This gave me two lists:
var fgColors = [
"000000",
"aa0000",
"00aa00",
"aa5500",
"0000aa",
"aa00aa",
"00aaaa",
"aaaaaa",
"555555",
"ff5555",
"55ff55",
"ffff55",
"5555ff",
"ff55ff",
"55ffff",
"feffff"
];
var bgColors = [
"000000",
"aa0000",
"00aa00",
"aa5500",
"0000aa",
"aa00aa",
"00aaaa",
"aaaaaa",
];
Now we’d like all of the characters within the Codepage 437 to loop over. Fortunately, Unicode supplies a text file that translates all CP437 codes to their UTF-8 equivalents.
I took this textual content file, eliminated the management characters and DEL, and created an array of their UTF-8 counterparts.
Then I created one other canvas, looped over every background colour, foreground colour, and character, and wrote them to the canvas utilizing the IBM PC font.
const char1canvas = doc.getElementById("char1");
const char1ctx = char1canvas.getContext("2nd", { willReadFrequently: true });
char1ctx.fillStyle = "#000000";
char1ctx.fillRect(0,0,8,16);
var imgData = [];
for (var i = 0; i < bgColors.size; i++) {
for (var j = 0; j < fgColors.size; j++) {
if (bgColors[i] == fgColors[j]) {
proceed;
}
for (var okay = 0; okay < chars.size; okay++) {
char2ctx.fillStyle = "#" + bgColors[i];
char2ctx.fillRect(0,0,8,16);
char2ctx.fillStyle = "#" + fgColors[j];
char2ctx.font = "16px xx437";
char2ctx.fillText(chars[k], 0, 12);
if (!imgData[i]) {
imgData[i] = [];
}
if (!imgData[i][j]) {
imgData[i][j] = [];
}
imgData[i][j][k] = char2ctx.getImageData(0,0,8,16);
}
}
}
For some purpose I needed to offset the fillText
by 12 pixels to get it to accurately write it to the canvas as I might anticipate. I do not know why, however CSS has by no means been a power of mine. After every time that we write the character, we retailer the picture information of the end in a lookup desk, by background colour, foreground colour, and character.
Subsequent, we loop over every character part of the unique picture’s canvas and extract the picture information of this part:
for (var y = 0; y <= 24; y++) {
for (var x = 0; x <= 79; x++) {
char1ctx.drawImage(canvas, x*8, y*16, 8, 16, 0, 0, 8, 16);
var imgChar1 = char1ctx.getImageData(0,0,8,16);
}
}
I discovered a library referred to as pixelmatch that permits you to evaluate two units of imagedata. It returns the variety of mismatched pixels and if you would like it, a diff of the 2.
var outcome = pixelmatch(imgChar1.information, imgChar2.information, null, 8, 16, {
threshold: 0.1,
});
So then we are able to loop over each permutation of background colour, foreground colour, and character and evaluate it to the picture’s character and choose the one which has the bottom variety of mismatched pixels – ideally 0.
Subsequent we create an output canvas and utilizing the recognized combos for every character, write again the identical ANSI artwork to that canvas:
The picture on the left is the enter picture and the picture on the suitable is the generated ANSI artwork. It seems fairly good! The guts in the course of ANSI
and LOVE
has been transformed to an oblong bullet – presumably as a result of I excluded the management characters and the guts occurred to be in them.
However that is solely helpful if we are able to generate the ANSI artwork file. Let’s return to the ANSI escape codes: