RSSAmplifier

jesse.cafe · Jun 6, 2024

Windows 95 Icons and SVGs

0
Sign in to vote or save

Jesse Falzone · jesse.cafe

(TL;DR; I made a tool to batch convert ICO icons to SVGs.)

The Windows 95 desktop showing various icon sizes.
"My Computer" icon variants on the Windows 95 desktop.

Recently I re-discovered the beauty (no, that’s not sarcasm) of Windows 95 icons. I enjoy the simplicity of their styling which, I assume, was somewhat necessitated by the fact that icons in Win32 generally had 8-bit color depth (256 colors) and a resolution of 48, 32, or 16 pixels square. I’m sure it was a challenge in some cases to convey what was needed on such a small canvas.

To see more detail in the icons I set out to convert them to Scalable Vector Graphics (SVG). As the name implies, SVGs are infinitely scalable with no quality loss. At first I used GIMP and Inkscape with varying degrees of success. Those are great programs but it was mostly a manual operation and I wanted to process over 600 icons. They both have command-line tools, but I found them pretty unapproachable and not super fun to use.

I’d need to script my own solution! But before I get to that, let’s talk about icons and SVGs.

# An ICO Primer

Looking for some light reading? Microsoft still serves the original ICO docs from 1995.

ICO is a pretty cool format that can contain multiple icon images (in this case Windows BMPs) with different resolutions and color depths. In Windows 95 the icon variants had different purposes and were used in different places; a large variant on the desktop, a small variant in a window title bar, etc.

Take the “My Computer” icon for example. I used ImageMagick’s convert tool to extract each variant from the ICO file and spit out a couple PNGs. This command will create a new image from each layer.

# Note: your command might be different.
# I was forced to use ImageMagick@6 on my old MacBook.
convert my_computer.ico my_computer.png

Now we have two PNG images (enlarged 4x to show detail):

A
large, blurry My Computer icon. A small,
blurry My Computer icon.

# Rasterization and Interpolation

But blast! The resulting PNGs are blurry. That’s because these are raster graphics and I’ve upscaled them to 4 times their original size. Raster graphics are basically pixels baked onto a grid. Those pixels get stretched apart when an image is enlarged; a browser, image editor, or operating system must “interpolate” or add missing pixels into the empty spaces to create a cohesive image.

Firefox, for instance, uses a method called bilinear interpolation, in which an unknown pixel’s color is determined by the weighted average of the values of the nearest 2x2 grid of known pixels.

# CSS Image Rendering

Interpolation is great for photographs but we’re dealing with pixel art here. Can we turn off interpolation in the browser and just tell it to make the pixels “bigger”? Yes, with some CSS!

Let’s add a class to those images and use the image-rendering property:

.pixelated {
  image-rendering: pixelated; /* Modern browsers */
  -ms-interpolation-mode: nearest-neighbor; /* Internet Explorer, lol */
}

These should look much better now, assuming you’re using a browser from this decade. (They still might be blurry in RSS readers.)

A large My Computer icon. A small My Computer icon.

Nice and crisp. Zoom in your browser window and you’ll see the image will never get blurry. Notice that the smaller variant isn’t just a scaled down version of the larger one – it’s missing some details! That’s pretty neat.

# SVGs are Pretty Rad

I suppose I could stop there but the goal was to end up with SVGs. As mentioned above, SVG stands for Scalable Vector Graphics. As opposed to raster images that use pixels, vectors use math to generate shapes.

There are several benefits:

  • They are infinitely scalable, even with complex shapes and curves.
  • SVG files are written in XML, which appeals to the web developer in me.
  • They can be manipulated with CSS.
  • They are easily compressed without quality loss.
  • They can be animated with JavaScript or CSS.
  • Their file sizes are usually smaller than their image counterparts and the file size stays the same even if you increase the size of the image.

A simple example…

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="50" fill="#008080" />
</svg>

…that generates a nice circle:

# Scripting the Conversion

Back to the ICO -> SVG conversion. I wrote a quick Node.js script to batch process the icons. My requirements were as follows:

  1. Accept an ICO file and/or a directory as an argument.
  2. If a directory was specified, recursively search that directory for ICOs.
  3. Deconstruct each ICO into its icon variants.
  4. Convert each variant to a pixel-perfect SVG.
  5. Save SVGs to the specified directory.

So as not to reinvent the wheel, I leveraged some great NPM libraries to get this done. I used icojs to separate the ICO variants into buffered PNGs. Why PNG? Because they’re lossless and they support an alpha channel for transparency. Then I fed that into pixel-perfect-svg to extract pixels from the PNG buffer and convert them to vectors.

I haven’t published it to NPM yet, but for now head over to the GitHub repo to get the code.

# The Result

A
large SVG My Computer icon. A small SVG
My Computer icon.

Boom! This was a fun little project. Yes they look the same as the PNG without interpolation, but now I don’t need extra CSS to maintain the pixelated effect. I can properly zoom in and appreciate each pixel. Stay tuned for more on that.

Read the original on jesse.cafe

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.