500 Byte Images: The Haiku Vector Icon Format (2016)
blog.leahhanson.us
blog.leahhanson.us
Just because you can rasterise it at any size, doesn't mean that the resulting icon makes sense at that size. When icons are really small you usually want a simpler version of the same icon for it to remain recognisable.
You can see it clearly in the examples used in the article for the 16x16 icon. Compare the bitmap version (https://www.haiku-os.org/docs/userguide/images/apps-images/i...) to the vector version (https://www.haiku-os.org/docs/userguide/images/apps-images/i...) , the bitmap version is specifically made for the low resolution and is still very clear, the vector version is a blurry mess.
To properly handle this you'd need either multiple versions or a vector format that can scale the amount of detail with the size. In either case you'd need to ensure that the rendering has pixel-perfect results at small sizes so it doesn't become a blurry-mess, kind of defeating the purpose of using a vector format.
Vector images work great for large icons, but for small ones they fall short.
On the outset that feels like a really hard problem.
[0] https://essenmitsosse.de/pixel/ [1] https://hn.algolia.com/?query=essenmitsosse.de%2Fpixel%2F&so...
For 32 px and above, vector images are a valid choice.
Now we just need a file format that combines all this. :)
Well, that depends on your screen's density and how much you care that your design is aligned to the pixel grid. For a very long time most iOS icons were hand-aligned to the pixel grid, and when they switched to vector icons in iOS 13 they looked awful because they were aligned poorly.
TTF?
I understand what they're trying to do with including the icon as metadata, but since they control the filesystem format as well, couldn't they just increase the storage available so they could store an extra kb or so? I'd expect that on modern hardware, reducing the number of reads by stuffing bytes into odd corners of each file's metadata is far less effective than just arranging a block of data to be read all at once.
if you scale the image down, you should see Marilyn, even at high resolution
So you can add a shape which just isn't rendered at all in lower resolutions. For example suppose the icon for your app is a stylised steam locomotive and you want to add your company logo on the side of the tank, this detail will look cool at 512x512 and maybe if the logo is simple at 128x128 but it will just be a blotch on the 16x16 icon - so HVIF lets you specify that the logo isn't added at all below say 128x128.
Yeah, the Icon-O-Matic application documentation[0] has some more info on this.
From the site:
> With the LOD you control the visibility of a shape depending on its size.
> That way, you can leave away details of an icon that look good on a bigger icon, but maybe not so much on its smaller version.
> The LOD is not only for leaving out detailing shapes, but also to e.g. change the stroke width at different sizes, if you feel that's needed.
> Simply duplicate a shape, make your changes and set both of their LOD settings to show either one or the other.
Looks like somewhat similar to CSS media queries.
Edit: Looks like[1] SVG has a similar feature too.
[0] https://www.haiku-os.org/docs/userguide/en/applications/icon...
https://gs.statcounter.com/screen-resolution-stats/desktop/w...
I'm sure if someone developed a hinting VM framework for vector icons (that wasn't patent-encumbered like half of the font ones), it would do a lot to help convince people that special low-resolution bitmaps weren't necessary for tiny icons to look good.
Letters have that exact issue, vector fonts were essentially unusable on computers until font hinting was invented.
This is renderer-dependent (as it's a relatively new feature), but SVG alsp supports altering the vector by scale via CSS media-queries. Oversimplified example:
<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<style>@media (max-width: 24px) { .detail { display: none; } }</style>
<path d="basic icon here" />
<path class="detail" d="extra icon details here" />
</svg>[0]: https://github.com/GNOME/adwaita-icon-theme
[1]: https://github.com/GNOME/adwaita-icon-theme/blob/mainline/sr...
But what if you're looking at 48x48 icon on a screen with triple the pixel density in each direction? Surely you'd still want an image with with the same amount of detail as you'd normally get in a 16x16 icon, even those few details are rendered with a high pixel count – basically you're running into the resolution limit of your eyeball. And this is a very common situation now because of course phones have a far higher pixel density than most traditional monitors.
So there is potentially benefit in vector icons even though, as you say, you still need two or more versions with different levels of detail.
Say you have a 16x16 SVG, and have a single-unit ("pixel") line down the middle. Render that SVG at 16px, and you get a single nice crisp pixel. Render it as 20px and now your "1px" line is like 1.3 pixels, which isn't going to look good.
There isn't really a "good" solution to this other than the above system (and it's not solved by rasters in any way)
Rasterise your icons to fixed sizes that you’ll use in your application. Of course, this has its own set of compromises (namely the inflexibility) that may or may not be acceptable for your use case.
And said vector icon will still look a whole lot better scaled from supported/optimized 16x16 size -> less favored 20x20 size than a raster icon, even if it isn't absolutely perfect.
So I don't really see this as a "problem".
Level of details is also a major issue when scaling down. Nice features of an icon at large size become sub-pixel when scaled down and their rounding up or down messes with the icon and destroys its balance.
Only when hinting became an option did vector font representation become viable at all for printing. Digital vector font display was accomplished much later.
https://www.pushing-pixels.org/2011/11/04/about-those-vector...
So instead of using a vector format, we should probably use an executable format instead to obtain full generality. Postscript does something like this.
How many pixels is a 0.5CM icon at 8K? A dell 8K display at 31.5" has a PPI of 279. at 27" it'd be 326. Does vector scaling work at 326PPI?
If so any effort is wasted handcrafting icons. Simply wait 3-4 years.
This feels like the tail wagging the dog.
Any efforts trying to adapt to the limitations of current technology are wasted.
Here's a 4K display from Phillips for $235 https://www.amazon.com/Philips-276E8VJSB-3840x2160-UltraNarr...
Edit: and a DPI calculator and reference. Notice all the old low-res displays and how most of them are behind us. https://www.sven.de/dpi/
https://gs.statcounter.com/screen-resolution-stats/desktop/w...
Infact, it seems to suggest that even 1366x768 comprises the majority.
So, can you quantify 'a few years'?
But as soon as you don't know the pixel density of the target screen, vector graphics produce much better results compared to the time you would have to invest in perfect bitmap graphics.
So if you are designing a website (potentially viewed on devices with different pixel densities), vector graphics are likely to outperform bitmap graphics.
This is a great goal, a very cool file format, and a very nice article!
That said, my main worry with this approach is that it might not be comparing or addressing the most common production workflows, which typically pack many icons into a single compressed file, and only unpack them in memory. When you pack multiple icons, you amortize all of the file reads into a single one. It’s extremely common in games, web, and even desktop apps, to also pack the images or other assets that icons represent into compressed files.
If you do pack your assets into zip files on disk, then it’s possible to lose disk space by converting to a binary icon format that might be less compressible, with no real gain in terms of disk reads or disk seeks -- and if you separate files instead of packing them so that you get icons in your inodes, you might be increasing the number of disk seeks & reads considerably.
It is worth thinking carefully about the tradeoff here. You are taking a functionality hit compared to SVG, and adding a new indirection and more tool dependencies to your pipeline in order to use HVF files. Ideally the payoff should be worth the effort, but if you zip all your SVG icons, how often is the compressed data averaging considerably more than 500 bytes per file? I just checked Google, and the first hit for free SVG sets is Feather, a 132kb zip file containing 282 icons, which clocks in at 480 bytes per icon on average.
Regarding storing icons in the data section of the binary, that is certainly one way to pack assets, but not one I would use or recommend personally. That locks you into shipping a binary if you want to update assets, it doesn't apply to web dev, or scripting languages, and it's pretty OS/platform specific. Typically what I've seen in production really is some kind of zip-like container file that is compressed and loaded separately from the application.
The network advantage is hard to disprove. But which has lower total computation cost?
A bitmap is created once, and the idea is very basic - you have a grid of pixels. The good part is that it's simple to use it. A vector image is a recipe for making an image. More calculations have to be done client-side, times the number of clients. Clients have to do the work the server didn't want to. You could say a bitmap is a compiled vector.
I think an ideal solution might be treating vectors as a source code. A web server would receive a request, including display size. Then it would "compile" the vector image into a bitmap and send the bitmap of the right size. And cache the image, so if another user with the same display size asks for the image, it's ready. Few people resize the browser window often. For the same reason, I think code highlighters shouldn't use Javascript on client side, unless the code might change (like, an in-browser REPL or pastebin).
Am I being misinformed? Pedantic? I like vector images, but would like to learn if my affection is justified.
window.onresize = function() { console.log("resizing!"); };
You could do various techniques like detecting the start of resizing and waiting for it to settle down before requesting the new image, but still, I think you may be underestimating how many resolutions there are out in the wild :)What's preventing you from running it on a laptop now?
Wi-Fi may be more reasonable, but we still depend on FreeBSD for that, so we're still behind Linux. What chipset do you have?
What do you mean by "won't boot Haiku at all"? No bootloader? Stuck on splash screen? Kernel panic?
I created this one: https://blurha.sh/
Conventionally, when displaying a folder, a file manager identifies the _type_ of each file, and then looks up the appropriate icon.
Does Haiku instead display whatever icon is in the inode? Could a wordprocessor document masquarade as a spreadsheet, and such?
I can't think of any security implications of this, nor think of any real mischief that a developer might cause, but I also can't think of any big advantage of it either. What use-case for having the whole icon in the inode instead of just a mime-type that is then used to look up the (already parsed, and shared) icon?
The Amiga did something similar except with a sidecar file (.info)
http://krashan.ppa.pl/articles/amigaicons/
> What use-case for having the whole icon in the inode
One that springs to mind is that you could put a thumbnail of the document into the icon (although I guess that's a bit tricky with only 500 byte SVG-alike icons.)
Per-file icons is a nice way to get cheap previews, especially at higher resolutions. For 2D images a fairly naive previewing method is to just flatten the whole image and scale it. For a PDF it will often but not always be useful to render the first non-empty page, then as you get into video, 3D or sounds it all starts to trickier.
However of course HVIF doesn't benefit any of these use cases, it's at its best when an artist has spent some effort learning techniques specific to the format and then hand crafts each icon accordingly.
HVIF in practice mostly gives icons to application software, so this technique lets Haiku use the directory of binaries to get back a set of icons for the applications those binaries implement, without doing a small file read per application as would happen in say Windows. A small advantage.
The performance use case is most significant to me. But I’m not sure why the OS wouldn’t look up all the icons used in a folder and only read them once for reuse. So having a thousand Word documents would only need one read of the Word icon.
I think it’s a nice packaging feature to not need to distribute a separate icon file, rather just include the icon in the file directly.
Of course that doesn't require it to be in the inode (it isn't for the Amiga - it's in <filename>.info).
On the Amiga the ".info" file can also contain additional information, such as startup instructions, as well as snapshotted location in the UI - the Amiga Workbench was close to a reasonably spatial file manager (and I really miss that..).
Security implications certainly would be different than they were at the time, in that you could trick people to start executables instead of loading the file into an application they trust, but that really is best handled by warning people on execution of "new"/downloaded files anyway.
- could change the icon for individual files/folders
- could have differently-sized icons
- different icons for unclicked + clicked state
Afaik in contemporary Mac OS, you have a directory with certain files in it. I'm not sure if anything prevents you from naming the directory PerfectlyHarmlessPhoto.jpg.app and giving it a jpeg icon. You would need to get the user to extract an archive first, which may be more or less difficult.
I think the Linux practice of having a separately identified file provide the icon is relatively rare. (I just checked Nautilus and ROX-Filer, and ROX-Filer shows .desktop icon files and allows you to execute them directly. Nautilus treats them like any other configuration file. I guess it would be relatively difficult to trick a Nautilus user into executing a script they thought was an image.)
The article claims that reading from the disk is extremely slow and so this results in a significant speed up. It is pretty quick to parse the images compared to reading the files off disk.
If the security considerations are relevant, you could presumably write the operating system not to render the icon of non-installed software tools.
Windows File Manager primarily uses the extension, e.g. all DOC files are shown with the MS Word logo.
More recently, they have generated thumbnails for a lot of media files too.
Windows File Manager (which was used till Windows 3.11 and Windows NT 3.51) doesn't show generated thumbnails, although Windows Explorer does.
http://pcdesktops.emuunlim.com/pictures/icons/beos_5.gif
https://web.archive.org/web/20070211213920/http://www.venus....
http://pcdesktops.emuunlim.com/icons11-15.shtml
It's a bit of a shame HiDPI is a thing so people use much higher resolution icons now, but you could just upscale them I guess.
Imagine my surprise when I cat'ed an .xpm file in 1996 and saw something that looked like C.
It's currently a work in progress, but the intention is to develop this for drawing simple vector graphics to the Pine Time: https://wiki.pine64.org/index.php/PineTime
So one day, I thought I would replace all bitmap icons in my application with SVG icons, because hell yes, vector, it must be better. And other projects did it alreay at that time, such as KDE/Gnome which used https://wiki.gnome.org/action/show/Projects/LibRsvg
So I added a Java library for rendering SVG to bitmaps. It brought several Megabytes of JAR dependencies. These libraries were much bigger then my whole application.
Conclusion? The whole program was much slower then before. Rendering time was really a thing. And this was not about thousands of icons or so, just a pretty standard GUI application with a few (less then ten) icons at a time.
Lession learned: Processing vector images to bitmap takes more time then just displaying bitmap. Especially on old slow computers.
The pixel-perfectness of the UI was also iconic. If it were me, I’d go back to isomorphic and go deep on a rigorous system-wide grid. You can still do vector icons but be meticulous about the grid.
Fun fact: pixel art is usually not-quite isometric because they use a vertical line and then lines that have a slope of 2:1 which is about 7 degrees larger distance between the X and Y axis[1].
1: https://en.wikipedia.org/wiki/Isometric_video_game_graphics#...
It’s special because you get very smooth, very sharp diagonals.
I think they also compressed the vertical scale though so the proportions look a little more natural.
As a designer, I ALWAYS start with vector (usually an Illustrator file).
No need to sell it to me, but I'd gently suggest using existing vector formats, like SVG.
That said, most operating systems don't support the use case described. It would be nice if they did. That may be coming, but for now, we are stuck with BitMap. I'm glad that I don't need to use the damn .ico files anymore for Web sites.
I think some of the criticism to bitmap may no longer be valid. Such as Disk Space, Access Time with Modern SSD, along with added computation required for Vector Drawing instead of Bitmap. That is also assuming vector can do low level detail hinting as good as bitmap.
Most files on Haiku don't use custom icons, they just use the icon associated with the mimetype. Application binaries the primary consumer of the icons-in-attributes feature.
It doesn't look good for this kind of icons IMO.