<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://alytarik.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://alytarik.github.io/" rel="alternate" type="text/html" /><updated>2026-09-27T19:12:03+00:00</updated><id>https://alytarik.github.io/feed.xml</id><title type="html">alytarik</title><subtitle>my works and observations
</subtitle><author><name>Ali Tarik</name></author><entry><title type="html">The Quite OK Image Format</title><link href="https://alytarik.github.io/qoi.html" rel="alternate" type="text/html" title="The Quite OK Image Format" /><published>2023-10-21T19:22:00+00:00</published><updated>2023-10-21T19:22:00+00:00</updated><id>https://alytarik.github.io/qoi</id><content type="html" xml:base="https://alytarik.github.io/qoi.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>The Quite OK Image Format (<a href="https://qoiformat.org/">QOI</a>) is a lossless image format
that is <em>designed to be quite ok</em>. While it is not designed to be the best format for
any particular use case, it achieves much faster speeds in both encoding and decoding
compared to png.</p>

<p>I tried implementing it in C++ as a png-to-qoi and vice versa converter following the
format specifications file (<a href="https://qoiformat.org/qoi-specification.pdf">pdf</a>).</p>

<h2 id="the-mindset">The Mindset</h2>

<p>For compression the first thing you should consider is the type of your data. And in this
case we have an image to store. Then you can start thinking about the structure of this
data. For example text may have many repeating words, some common letters and some uncommon
letters. To compress it you find a way to represent them with a smaller footprint.</p>

<p>For the qoi format, the data is an image and the most common features of images are; they
do not change tend to change slowly across neighbouring pixels. For example in a selfie your
face has similar colors within close pixels and they may even not change at all. So, one of
our goals is to minimize the size when storing close/repeating colors. And this info is actually
enough to create a decent storage system for images.</p>

<h3 id="specs">Specs</h3>

<p>QOI starts with a header that includes width, height, number of channels (RGB or RGBA)
and the colorspace. Then the image data is stored in six different type of chunks.</p>

<p>The six types of chunks in qoi can be categorised into four groups:</p>

<ul>
  <li>A raw pixel (RGB or RGBA) [4-5 bytes]</li>
  <li>A run of the previous pixel [1 byte]</li>
  <li>An index of last seen pixels array [1 byte]</li>
  <li>A difference from last pixel [1-2 bytes]</li>
</ul>

<p>We can see that for any new or unique pixels we need 1 extra byte but for similar enough or 
repeating pixels we only need 1-2 bytes. And it turns out a large portion of images include 
these kinds of pixels. With this implementation QOI achieves ~10x encode/decode speed and only
around 16% larger file size.</p>

<h2 id="further-reading">Further Reading</h2>

<ul>
  <li><a href="https://qoiformat.org/">QOI Format Website</a></li>
  <li><a href="https://qoiformat.org/benchmark/">QOI Benchmark</a></li>
  <li><a href="https://github.com/phoboslab/qoi">QOI Format Github</a></li>
</ul>]]></content><author><name>Ali Tarik</name></author><category term="C++" /><category term="c++" /><category term="images" /><category term="graphics" /><summary type="html"><![CDATA[Introduction]]></summary></entry></feed>