# Quite OK Image format encoder and decoder in Racket

**URL:** <https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042>\
**Category:** Show & Tell\
**Created:** [May 29, 2022, 8:33am UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042 "2022-05-29T08:33:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![aumouvantsillage](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/aumouvantsillage/32/567_2.png) [@aumouvantsillage](https://racket.discourse.group/u/aumouvantsillage)\
**Post date:** [May 29, 2022, 8:33am UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/1 "2022-05-29T08:33:09Z")

</div>

The [QOI (Quite OK Image) format](https://qoiformat.org/) is a new lossless image compression format that claims similar compression ratios as PNG with faster encoding and decoding.

The QOI specification is very simple and easy to implement. As an exercise, I have written a [Racket implementation](https://github.com/aumouvantsillage/qoi-racket). I have tested it against the official example images but I have not run any benchmarks yet.

The official implementation in C uses 8-bit arithmetic operations, bit shifts and bitwise logical operations. In my Racket implementation, I have used multiplications and additions instead of `arithmetic-shift` and `bitwise-ior`. I find it more readable this way but it is a matter of taste, and I have no idea how it affects performance.

At the moment, it can only perform conversions between raw RGBA image files and QOI.  
While working on the encoder, I have tried to use [`read-bitmap`](https://docs.racket-lang.org/draw/Drawing_Functions.html#%28def._%28%28lib._racket%2Fdraw..rkt%29._read-bitmap%29%29) to read PNG files, but I have found that it always applies gamma correction and does not give access to the original pixel values.  
Do you know any other image manipulation library that could allow reading PNGs without any additional processing?

---

<div class="post-metadata">

**Author:** ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)\
**Post date:** [May 29, 2022, 1:01pm UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/2 "2022-05-29T13:01:32Z")

</div>

Is this a case where macros could be swapped in to use "8-bit arithmetic operations, bit shifts and bitwise logical operations” to make the program look like it’s using "multiplications and additions” but it’s actually using low-level ops? You could even test the two against each other.

---

<div class="post-metadata">

**Author:** ![aumouvantsillage](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/aumouvantsillage/32/567_2.png) [@aumouvantsillage](https://racket.discourse.group/u/aumouvantsillage)\
**Post date:** [May 29, 2022, 2:42pm UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/3 "2022-05-29T14:42:48Z")

</div>

> [@EmEf](#):
>
> Is this a case where macros could be swapped in to use "8-bit arithmetic operations, bit shifts and bitwise logical operations”

Yes. I will try this.

After writing my post, I wondered whether my choice of operations was actually more "readable". My code uses functions with shorter names but maybe we lose the intent of these operations. I was considering wrapping some operations in macros or functions with clearer names.

---

<div class="post-metadata">

**Author:** ![simonls](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/simonls/32/170_2.png) [@simonls](https://racket.discourse.group/u/simonls)\
**Post date:** [May 29, 2022, 8:17pm UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/4 "2022-05-29T20:17:26Z")

</div>

Maybe this library may help you getting access to the raw data: [png-image: Library to view and modify PNG chunks.](https://docs.racket-lang.org/png-image/index.html) But it is a bit more lowlevel, ideally there was a way to get raw rgba data without processing.

---

<div class="post-metadata">

**Author:** ![aumouvantsillage](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/aumouvantsillage/32/567_2.png) [@aumouvantsillage](https://racket.discourse.group/u/aumouvantsillage)\
**Post date:** [May 31, 2022, 6:07pm UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/5 "2022-05-31T18:07:07Z")

</div>

I agree that `png-image` is too low-level for my purpose.  
What I need is a quick way to read PNG files to test my own library in the same conditions as the reference QOI implementation.

---

<div class="post-metadata">

**Author:** ![simonls](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/simonls/32/170_2.png) [@simonls](https://racket.discourse.group/u/simonls)\
**Post date:** [June 1, 2022, 3:50am UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/6 "2022-06-01T03:50:28Z")

</div>

[bitmap% load-file](https://docs.racket-lang.org/draw/bitmap_.html#%28meth._%28%28%28lib._racket%2Fdraw..rkt%29._bitmap~25%29._load-file%29%29)

> In all PNG-loading modes, gamma correction is applied when the file provides a gamma value, otherwise gamma correction is not applied. The current display’s gamma factor is determined by the SCREEN\_GAMMA environment variable if it is defined. If the preference and environment variable are both undefined, a platform-specific default is used.

So making sure the file doesn't have a gamma value ~~and setting `SCREEN_GAMMA` environment variable to `1.0`~~ might work?

The way I read the first sentence, if the file doesn't have a gamma value then it shouldn't do any gamma correction. So maybe there is some image editing tool that allows you to remove that / check whether the image has a gamma value set?

Here is another idea, find out the gamma value set in the image and set `SCREEN_GAMMA` to the same value, then correction should also become a no-op if it is working correctly, but the previous things might be easier.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [June 2, 2022, 5:55pm UTC](https://racket.discourse.group/t/quite-ok-image-format-encoder-and-decoder-in-racket/1042/7 "2022-06-02T17:55:59Z")

</div>

Possible tools include exiftool ([https://exiftool.org](https://exiftool.org)) or the  
ImageMagick suite ([ImageMagick – Convert, Edit, or Compose Digital Images](https://imagemagick.org/index.php)). I would try  
exiftool first.
