Compare commits

...

335 Commits

Author SHA1 Message Date
8d5b619884
full on qoi 2024-03-04 13:38:55 +01:00
2cbda6e7be
qoi lib 2024-03-04 12:41:12 +01:00
029df21423 Add 'external/qoi/qoi/' from commit '30d15d79b7726b977cd889151cc5cd6b17742f8f'
git-subtree-dir: external/qoi/qoi
git-subtree-mainline: 28b92b0f4c
git-subtree-split: 30d15d79b7
2024-03-04 12:39:30 +01:00
28b92b0f4c
prep qoi 2024-03-04 12:38:39 +01:00
Dominic Szablewski
30d15d79b7
Merge pull request #296 from RomanPro100/master
Add Uiua to "QOI Support in Other Software"
2024-01-18 20:40:14 +01:00
RomanPro100
aeb22ad898
Add Uiua to "QOI Support in Other Software" 2024-01-18 22:36:31 +03:00
Dominic Szablewski
56ee13c628
Merge pull request #295 from pfusik/imagine
Mention Imagine
2024-01-18 20:01:10 +01:00
Piotr Fusik
e28e20ea83 Mention Imagine 2024-01-17 16:57:07 +01:00
Dominic Szablewski
827a7e4418
Merge pull request #292 from finnurthorisson/Add-Lua-LIL
Add Lua LIL
2023-12-11 13:25:07 +01:00
Finnur Þórisson
bc8242a28d
Add Lua LIL 2023-12-11 10:26:13 +00:00
Dominic Szablewski
99159e0bb2
Merge pull request #291 from zertovitch/patch-1
Added implementation of QOI in Ada
2023-12-09 17:05:23 +01:00
Gautier de Montmollin
35054beeb9
Added implementation of QOI in Ada
The link refers to the Generic Image Decoder (GID) library.
2023-12-09 14:22:00 +01:00
Dominic Szablewski
d53fe6c515
Merge pull request #290 from LuisAlfredo92/patch-1
Update README.md
2023-12-02 11:15:02 +01:00
Luis Alfredo Figueroa Bracamontes
abde91410e
Update README.md
Adding SixLabors/ImageSharp
2023-12-01 19:46:19 -06:00
Dominic Szablewski
9c487be4fe
Merge pull request #288 from phlash/master
Added Swingland implementation
2023-10-20 12:25:07 +02:00
Phil Ashby
6e949186e6
Added Swingland implemenation 2023-10-19 11:12:49 +01:00
Dominic Szablewski
2f9f92f133
Merge pull request #287 from vtorri/vtorri_efl
Mention QOI encoding and decoding support in the EFL
2023-10-17 17:48:32 +02:00
Vincent Torri
26130106d9 Mention QOI support in the EFL 2023-10-17 17:31:26 +02:00
Dominic Szablewski
8d35d93cdc
Merge pull request #284 from n00bmind/master
~ Update link to n00bmind/qoi
2023-09-10 22:32:21 +02:00
n00bmind
dcfec1a44d ~ Update link to n00bmind/qoi 2023-09-10 19:19:34 +01:00
Dominic Szablewski
4b16be3941
Merge pull request #283 from colemanrgb/master
Add link to decoding and encoding QOI files on RISC OS
2023-09-06 22:22:13 +02:00
Dominic Szablewski
e020e4db76
Merge pull request #282 from n00bmind/master
+ Add link to Jai implementation
2023-09-04 14:22:24 +02:00
n00bmind
d23d8f3fea + Add link to Jai implementation 2023-09-03 23:15:36 +01:00
colemanrgb
52d9ad5024
Add link to decoding and encoding QOI files on RISC OS 2023-09-02 12:03:35 +01:00
Dominic Szablewski
351450e00d
Merge pull request #281 from Ernest1338/kde-qoi
Mention KDE's encoding support
2023-08-31 17:46:34 +02:00
Ernest Gupik
dbd68f185f KDE now has encoding support as well 2023-08-31 17:36:53 +02:00
Dominic Szablewski
41e8f84bf6
Merge pull request #280 from SpeckyYT/patch-1
Add link to spwn-qoi
2023-08-28 09:09:50 +02:00
Specky
855cd4c61e
Add link to spwn-qoi 2023-08-27 22:56:32 +02:00
Dominic Szablewski
d61e911777
Merge pull request #279 from pfusik/qoi-fu-d
qoi-fu transpiles to D
2023-08-25 10:22:14 +02:00
Piotr Fusik
972a28c955 qoi-fu transpiles to D 2023-08-25 09:27:50 +02:00
Dominic Szablewski
7e3b202f9e
Merge pull request #278 from Floessie/pam2qoi
Add link to pam2qoi
2023-08-19 20:48:53 +02:00
Flössie
4231ace045 Add link to pam2qoi 2023-08-19 11:28:21 +02:00
Dominic Szablewski
8785fe9f00
Merge pull request #274 from Ernest1338/kde-qoi
Mention QOI support in KDE
2023-08-11 23:38:46 +02:00
Ernest Gupik
a06ba04fa4 Mention QOI support in KDE 2023-08-11 23:33:22 +02:00
Dominic Szablewski
19b3b4087b
Merge pull request #272 from pfusik/qoi-fu
qoi-ci renamed to qoi-fu
2023-08-10 00:32:16 +02:00
Piotr Fusik
4adab9d4e0 qoi-ci renamed to qoi-fu 2023-08-09 14:28:11 +02:00
Dominic Szablewski
9ab99731f8
Merge pull request #271 from victoryforce/QOI-support-in-darktable
Mention QOI support in darktable
2023-07-18 15:05:25 +02:00
Victor Forsiuk
1527109c28 Mention QOI support in darktable 2023-07-17 21:33:38 +03:00
Dominic Szablewski
f65b365318
Merge pull request #269 from N-R-K/less_hardcode_bench
Less hardcoded benchmarking code
2023-06-16 15:35:38 +02:00
NRK
706ed3eb68 Less hardcoded benchmarking code
this allows people to more easily plugin their implementation for
benchmarking purposes.
2023-06-16 17:31:57 +06:00
Dominic Szablewski
c6219a5696
Merge pull request #266 from bpanthi977/master
Add link to Common Lisp implementation
2023-06-15 18:05:29 +02:00
Dominic Szablewski
ef61984291
Merge pull request #268 from N-R-K/stdio_errcheck
More strict stdio error checking
2023-06-15 18:03:53 +02:00
NRK
36190eb07d Error check qoi_read() more strictly
fseek is not guaranteed to succeed and can fail, e.g when trying to
seek a pipe. the first fseek() is not error checked since if it failed,
ftell would return 0.

also check for fread errors too before calling qoi_decode().
2023-06-15 16:06:03 +06:00
NRK
00dfdc8b5c Error check qoi_write() more strictly
simply checking the return value of fwrite() wouldn't be enough since
stdio is typically buffered. and so force a flush and check for errors
via ferror().
2023-06-15 14:36:19 +06:00
Dominic Szablewski
dfc056e813
Merge pull request #267 from Aftersol/master
Update README.md
2023-05-18 10:23:22 +02:00
Aftersol
76e3789073
Update README.md
small change to my link
2023-05-17 13:32:51 -07:00
Bibek Panthi
1ae0c19492 Add link to Common Lisp implementation 2023-04-30 19:14:36 +05:45
Dominic Szablewski
f6dffaf1e8
Merge pull request #263 from sylikc/other-jpegview
add JPEGView to end of Other Software list
2023-03-11 18:44:55 +01:00
Kevin M
040f8a15e5 add JPEGView to end of Other Software list 2023-03-02 00:49:34 -08:00
Dominic Szablewski
3dfa66d8fd
Merge pull request #262 from LTMX/patch-1
Mention LTMX/Unity.QOI in Tools section
2023-02-24 15:35:45 +01:00
LTMX
013c745284
Mention LTMX/Unity.QOI in Tools section 2023-02-24 14:20:00 +01:00
Dominic Szablewski
0d8d07971b
Merge pull request #260 from pfusik/qoi-ci-ts
Mention qoi-ci transpiling to TypeScript
2023-02-09 11:15:34 +01:00
Piotr Fusik
6d5a7ab2fd Mention qoi-ci transpiling to TypeScript 2023-02-09 08:01:07 +01:00
Dominic Szablewski
514c259711 Mention ffmpeg support; close #259 2023-02-06 13:35:58 +01:00
Dominic Szablewski
c0a27f808f Mention ZTQOI 2023-01-22 20:03:08 +01:00
Dominic Szablewski
dc4b97471a Mention tacentview 2023-01-22 20:03:01 +01:00
Dominic Szablewski
071f0ce957
Merge pull request #257 from grego/master
Add a link to a Hare implementation to README
2023-01-20 14:44:31 +01:00
Maroš Grego
d70233b2c6 Add a link to a Hare implementation to README 2023-01-19 21:44:26 +01:00
Dominic Szablewski
c3dcfe780b
Add LICENSE file; close #250 2022-12-13 21:08:09 +01:00
Dominic Szablewski
660839cb2c
Merge pull request #247 from lbatalha/master
Add CFLAGS as per GNU Coding Standards
2022-11-16 19:51:04 +01:00
Luis Batalha
5c787e4173
add CFLAGS as per gnu standards 2022-11-16 15:52:39 +00:00
Dominic Szablewski
b8d77df1e8
Merge pull request #245 from rubikscraft/patch-1
Add a singe byte streaming C99 QOI library and NodeJS bindings
2022-09-25 18:32:08 +02:00
rubikscraft
3a0560cb77
Add a streaming C qoi library and nodejs bindings 2022-09-24 16:13:23 +02:00
Dominic Szablewski
cf90aa165c
Merge pull request #244 from LuisAlfredo92/patch-1
Adding Super QOi converter to Tools
2022-09-23 00:16:58 +02:00
Luis Alfredo Figueroa Bracamontes
07c6d6f7d7
Adding Super QOi converter to Tools
Adding Super QOI converter to Tools section, with links to console and GUI version
2022-09-20 22:22:36 -05:00
Dominic Szablewski
b40d1edbae
Merge pull request #243 from hzeller/20220920-add-timg-to-tools
Add timg to tool list; provides qoi image viewing in terminal.
2022-09-20 10:16:15 +02:00
Henner Zeller
63acdd2796 Add timg to tool list; provides qoi image viewing in terminal.
Signed-off-by: Henner Zeller <h.zeller@acm.org>
2022-09-20 00:02:59 -07:00
Dominic Szablewski
7039fcd60c
Merge pull request #241 from pfusik/qoi-ci-2.0.0
Windows Explorer, Finder, GNOME plugins released in qoi-ci
2022-09-12 12:39:47 +02:00
Piotr Fusik
21c840a2e7 Windows Explorer, Finder, GNOME plugins released in qoi-ci 2022-09-12 12:24:33 +02:00
Dominic Szablewski
23c790ce59 Add Racket implementation; close #217 2022-08-06 00:49:35 +02:00
Dominic Szablewski
425dfe1221 Add Java SPI implementation; close #210 2022-08-06 00:46:10 +02:00
Dominic Szablewski
43240dbc20 Add KDE & Nemo thumbnailers; close #174 2022-08-06 00:38:15 +02:00
Dominic Szablewski
aca9552827 Add MacOS QuickLook plugin; close #165 2022-08-06 00:34:50 +02:00
Dominic Szablewski
e4892c7aa2 Add delphi implementation; close #144 2022-08-06 00:32:41 +02:00
Dominic Szablewski
02a49e5410 Remove outdated implementations 2022-08-06 00:06:55 +02:00
Dominic Szablewski
f177c193e0 Attempt to make list of tools and implementation a bit easier to read 2022-08-06 00:05:21 +02:00
Dominic Szablewski
76583cc18d Wording 2022-08-06 00:04:49 +02:00
Dominic Szablewski
948a53e04c Link QOI plugins to releases overview page 2022-08-06 00:02:20 +02:00
Dominic Szablewski
a488d3be0f Mention Debian & Ubuntu packages; add link to Repology 2022-08-05 23:45:59 +02:00
Dominic Szablewski
bcb2fb5e48 Add note about MIME type; close #167 2022-08-05 23:44:51 +02:00
Dominic Szablewski
a4e7750d68 Add SPDX License Identifier, remove license text; close #168 2022-08-05 23:39:12 +02:00
Dominic Szablewski
a2cfc864a2
Merge pull request #237 from pfusik/qoi-ci-1.1.2
New release of qoi-ci
2022-08-03 21:50:35 +02:00
Piotr Fusik
b64209287f New release of qoi-ci 2022-08-03 20:17:24 +02:00
Dominic Szablewski
d6e88eb1be
Merge pull request #236 from AmCh-Q/patch-1
Fix small typo in qoibench.c
2022-08-02 13:28:08 +02:00
AmCh-Q
370be5c080
Fix small typo in qoibench.c 2022-08-02 06:36:17 -04:00
Dominic Szablewski
b6bf448c41
Merge pull request #235 from ryuukk/patch-1
Add gamut D library
2022-08-01 13:22:40 +02:00
ryuukk
32ac6c3c0f
Add gamut D library 2022-07-29 16:23:23 +02:00
Dominic Szablewski
3b0a7ebc5f
Merge pull request #234 from Aftersol/master
Request for Inclusion into READMD.md
2022-07-28 12:39:03 +02:00
Aftersol
583cdd311e Update README.md 2022-07-28 01:45:28 -07:00
Aftersol
376d39cc67 add my own project link to README.md 2022-07-28 01:28:28 -07:00
Dominic Szablewski
edb8d7b114
Merge pull request #226 from Ben1138/unity-qoi
Added unity-qoi to Readme
2022-06-21 08:54:17 +02:00
Ben
948a86f507 Added unity-qoi to Readme 2022-06-20 20:28:55 +02:00
Dominic Szablewski
ed5c0287e6
Merge pull request #225 from mzgreen/patch-1
Add Kotlin Multiplatform implementation to the README list
2022-06-20 16:09:32 +02:00
mzgreen
ef929be770
Add Kotlin Multiplatform implementation to the README list 2022-06-20 14:33:20 +02:00
Dominic Szablewski
11673fc39c
Merge pull request #224 from polluks2/patch-1
Fixed broken makefile
2022-06-18 15:05:09 +02:00
polluks2
9434e96f9b
Fixed broken makefile 2022-06-18 14:39:05 +02:00
Dominic Szablewski
1995afbb82
Merge pull request #223 from xiaozhuai/master
Add Jetbrains' plugin url
2022-06-14 20:04:16 +02:00
xiaozhuai, Weihang Ding
14c22321ff
Add Jetbrains' plugin url 2022-06-14 17:36:49 +08:00
Dominic Szablewski
ff148ed284
Merge pull request #222 from dgaw/patch-1
Add AmigaOS support to README
2022-06-13 01:04:20 +02:00
Damian Gaweda
fc4bec9099
Add AmigaOS support to README
Add a link to a datatype plugin that adds QOI support to AmigaOS.
2022-06-12 20:18:57 +02:00
Dominic Szablewski
1f4e585898
Merge pull request #221 from Fabien-Chouteau/patch-1
Add link to Ada/SPARK implementation
2022-06-12 09:31:15 +02:00
Fabien Chouteau
c1c46c8a76
Add link to Ada/SPARK implementation 2022-06-12 08:35:13 +02:00
Dominic Szablewski
b4fab6fbc3
Merge pull request #220 from LuisAlfredo92/patch-1
Adding links to required libreries
2022-06-11 22:10:28 +02:00
Luis Alfredo Figueroa Bracamontes
553eae423a
Adding qoi.h dependency
Adding the text to indicate that "qoi.h" is required to use this file
2022-06-11 13:26:59 -05:00
Luis Alfredo Figueroa Bracamontes
bce1a069a8
Adding links to required libreries
Adding the URLs to the repo of the required libraries to make even easier to use this program
2022-06-11 12:58:41 -05:00
Dominic Szablewski
6005c73e0a Add PureBasic implementation to readme 2022-06-07 09:37:35 +02:00
Dominic Szablewski
57628d9d4d
Merge pull request #214 from pfusik/xnviewmp
Mention XnView MP
2022-05-24 18:46:00 +02:00
Piotr Fusik
6ba3c1b42e Mention XnView MP 2022-05-24 08:52:18 +02:00
Dominic Szablewski
fa70cfc6d2
Merge pull request #213 from 418Coffee/patch-1
Add V implementation
2022-05-22 00:23:40 +02:00
418Coffee
d1875b5ac8
Add V Implementation 2022-05-21 21:16:20 +02:00
Dominic Szablewski
911ca7b65f
Merge pull request #209 from varuld/simple_makefile
Simple makefile
2022-05-17 15:53:03 +02:00
Christian Danø
5204343519 Replaced remaining := with ?= to allow CLI parameters 2022-05-12 14:53:17 +02:00
Christian Danø
06d032339b CC:= -> CC?= and removal of dependency cleaning 2022-05-12 14:08:51 +02:00
Christian Danø
9374bd61ae feat; working makefile 2022-05-12 10:07:44 +02:00
Christian Danø
b9d1e9c3eb feat; init makefile iteration 2022-05-12 09:52:51 +02:00
Dominic Szablewski
75e7f308a4
Merge pull request #208 from 0xd34df00d/patch-1
Haskell implementation synced with the spec
2022-05-09 17:40:41 +02:00
0xd34df00d
a4f498b23c
Haskell implementation synced with the spec 2022-05-07 16:22:03 -04:00
Dominic Szablewski
805953b1c7
Merge pull request #207 from 10maurycy10/patch-1
Add yet another implementation.
2022-05-04 13:19:37 +02:00
10maurycy10
2e58276f20
Add yet another implementaion 2022-05-03 14:26:19 -07:00
Dominic Szablewski
6d7eadd28c
Merge pull request #205 from JaffaKetchup/added-dart-implementation
Add 'dqoi' to the implementations list on README
2022-04-25 13:50:04 +02:00
Luka S
70894be9aa
Specified framework support
Flutter is the application framework that uses Dart. 'dqoi' provides full support for Flutter apps with custom image painters.
2022-04-25 11:54:00 +01:00
Luka S
8308c4c107
Add 'dqoi' to the implementations list on README
'dqoi' is my implementation of QOI for Dart and Flutter, based off the C code included here, and @LowLevelJavaScript's implementation.
2022-04-22 20:29:47 +01:00
Dominic Szablewski
339e11e2fd Add info about versioning and contributing 2022-04-21 21:25:59 +02:00
Dominic Szablewski
3a90672872
Merge pull request #202 from shraiwi/master
Add C streaming decoder to readme.md
2022-04-19 17:03:59 +02:00
Dominic Szablewski
477a589907
Merge pull request #201 from HappySeaFox/master
Update link to SAIL library
2022-04-19 17:03:34 +02:00
shraiwi
682273b101
Add C streaming decoder to readme.md 2022-04-16 20:38:36 -05:00
Dmitry Baryshev
e3612650c0 Update link to SAIL library 2022-04-15 11:18:01 -07:00
Dominic Szablewski
028c75fd26
Merge pull request #199 from JohannesFriedrich/master
Add R-package QOI to README.md
2022-04-12 23:51:52 +02:00
J_F
cc97aaed08
Add R-package QOI to README.md 2022-04-12 21:42:58 +02:00
Dominic Szablewski
e42b0b3022 Load/store RGBA separately instead of using a typecast; close #197
This should fix problems on big-endian machines and with ILP64
2022-04-11 23:19:04 +02:00
Dominic Szablewski
59e0575c49 Remove obsolete, unused vars; close #56 2022-04-11 22:35:39 +02:00
Dominic Szablewski
1f8d2b752d
Merge pull request #192 from Tiefseetauchner/patch-1
Added lr-paint processing qoi capable drawing program
2022-04-11 22:13:44 +02:00
Dominic Szablewski
bf50a4253a
Merge branch 'master' into patch-1 2022-04-11 22:13:38 +02:00
Dominic Szablewski
d3e2aa8b20
Merge pull request #196 from mathpn/master
include py-qoi in readme
2022-04-11 22:12:37 +02:00
Dominic Szablewski
1181570cdf
Merge pull request #190 from amstan/upstream
QOI on an FPGA (Verilog)!
2022-04-11 22:09:17 +02:00
Dominic Szablewski
4e8e5b6a70
Merge branch 'master' into upstream 2022-04-11 22:09:11 +02:00
Dominic Szablewski
c861c4b825
Merge pull request #198 from pfusik/qoi-ci-1.1.1
New release of qoi-ci
2022-04-11 22:08:08 +02:00
Piotr Fusik
1296ad8179 New release of qoi-ci 2022-04-11 21:46:56 +02:00
Matheus Pedroni
773915aefd
include py-qoi in readme
include a new native python implementation of encoder + decoder following QOI format specifications
2022-04-09 21:56:13 -03:00
Dominic Szablewski
a5075d1b6f
Merge pull request #195 from musabkilic/musabkilic-patch-1
Add musabkilic/qoi-decoder to implementations
2022-04-09 16:43:42 +02:00
Musab Kılıç
7506300a3e
Add musabkilic/qoi-decoder to implementations 2022-04-09 17:17:36 +03:00
Tiefseetauchner
fc0eef8e54
Added lr-paint processing qoi capable drawing program
I made LR-Paint in three days to proof (mainly to myself) how simple it is to implement QOI
So I wrote it in Processing
Like any madman would
It's great trust me
And this is totally serious, I want the abomination of Processing code I made to be in the QOI Readme yes yes
2022-04-07 19:10:27 +02:00
Alexandru M Stan
56be991260 QOI on an FPGA (Verilog)! 2022-04-05 02:16:00 -07:00
Dominic Szablewski
09d144f892 Mention DOjS 2022-03-28 09:28:30 +02:00
Dominic Szablewski
009b481b07
Merge pull request #180 from soywiz/patch-1
Added KorGE & KorIM support engine & library to the README
2022-03-25 09:48:00 +01:00
Carlos Ballesteros Velasco
8297ace59d
Added KorGE & KorIM support engine & library 2022-03-25 03:09:48 +01:00
Dominic Szablewski
375f3f02b4
Merge pull request #175 from DmitriySalnikov/patch-1
Add link to QOI Addon for Godot Engine
2022-03-25 01:02:17 +01:00
Dominic Szablewski
9a4a7ce5e8
Merge branch 'master' into patch-1 2022-03-25 01:02:11 +01:00
Dominic Szablewski
3d77784bd5
Merge pull request #177 from dan9er/dan9er-readme-tool-farbfeld
Add link to farbfeld-convert-qoi tool in README
2022-03-25 01:00:34 +01:00
Dominic Szablewski
777b68ab2f
Merge pull request #179 from jmaselbas/patch-2
Update readme with other software with QOI support
2022-03-25 00:59:40 +01:00
Jules Maselbas
6170f9125d
Update readme with other software with QOI support 2022-03-25 00:57:01 +01:00
Dominic Szablewski
27e433ef92
Merge pull request #178 from pfusik/irfanview
Mention IrfanView
2022-03-23 15:30:29 +01:00
Piotr Fusik
73f04c2ef9 Mention IrfanView 2022-03-23 12:18:38 +01:00
dan9er
606bf77678
Add link to farbfeld-convert-qoi tool in README 2022-03-02 04:04:04 +00:00
Dominic Szablewski
2cfe3f58fa
Merge pull request #176 from wx257osn2/patch-1
Add qoixx in implementations list
2022-02-21 11:49:32 +01:00
I
be96074eb0
Add qoixx 2022-02-21 08:56:59 +09:00
Дмитрий Сальников
6cfd82d35e
Add link to QOI Addon for Godot Engine 2022-02-09 02:35:06 +03:00
Dominic Szablewski
7094132132 Mention rTexPacker 2022-02-06 12:12:20 +01:00
Dominic Szablewski
6c0831f91f
Merge pull request #172 from orx/master
Added orx link (other software) to README.md
2022-01-31 18:35:55 +01:00
iarwain
e6195209d8
Update README.md
Added Orx link to README.md
2022-01-31 10:56:59 -05:00
Dominic Szablewski
e8a3f40993
Merge pull request #171 from mhoward540/patch-1
Update README.md to reference Nim version
2022-01-30 12:18:58 +01:00
Matt Howard
efd968caba
Update README.md to reference Nim version 2022-01-29 20:18:05 +01:00
Dominic Szablewski
ee79afbe8b Mention rTexViewer 2022-01-28 01:24:10 +01:00
Dominic Szablewski
0db7d65c83
Merge pull request #169 from aquaratixc/patch-1
Update README.md
2022-01-20 20:11:47 +01:00
aquaratixc
98d5f5187e
Update README.md 2022-01-20 20:13:19 +03:00
Dominic Szablewski
e367cb19df
Merge pull request #164 from aldanor/feature/add-qoi-rust
Add `qoi` Rust crate reference (aldanor/qoi-rust)
2022-01-06 11:50:43 +01:00
Ivan Smirnov
98e8a0237c Add qoi Rust crate reference (aldanor/qoi-rust) 2022-01-06 04:06:21 +03:00
Dominic Szablewski
fd6f6463ef Fix documentation for consecutive QOI_OP_INDEX chunks; close #112 2022-01-05 16:57:38 +01:00
Dominic Szablewski
07116e8b89 Clarify colorspace & channels header usage; #152 2022-01-05 16:55:27 +01:00
Dominic Szablewski
6804a745e4 Fix example in QOI_OP_LUMA documentation; close #161 2022-01-05 16:51:38 +01:00
Dominic Szablewski
a27f8ed459
Merge pull request #159 from kaetemi/master
Add link to QOI Bitmap I/O Plugin for 3ds Max
2022-01-04 12:52:08 +01:00
Jan Boon
0219479867
Add link to QOI Bitmap I/O Plugin for 3ds Max 2022-01-04 11:34:34 +08:00
Dominic Szablewski
ef826267cc
Merge pull request #147 from LucasMW/master
Add link to qoiConverter X
2022-01-03 13:52:22 +01:00
Lucas Menezes
2870b54937
Changed Link
Changed to the most stable link
2022-01-03 12:48:27 +00:00
Dominic Szablewski
943d2b637b
Merge pull request #157 from contriteobserver/gccwarnings
fixed gcc warnings in qoibench.c
2022-01-03 11:51:29 +01:00
Dominic Szablewski
a567e5d18e
Merge pull request #139 from HappySeaFox/master
Added link to SAIL in README
2022-01-03 11:40:49 +01:00
Dominic Szablewski
1a38a0162f
Merge pull request #141 from arian/patch-1
Add link to another Go implementation
2022-01-03 11:40:05 +01:00
Dominic Szablewski
1f19724a14
Merge branch 'master' into patch-1 2022-01-03 11:39:58 +01:00
Dominic Szablewski
82e6cc8ffc
Merge pull request #140 from kchapelier/master
Add vanilla JavaScript implementation
2022-01-03 11:39:29 +01:00
Dominic Szablewski
501cebce7c
Merge branch 'master' into master 2022-01-03 11:39:21 +01:00
Dominic Szablewski
f27dbdb94f
Merge pull request #148 from KristofferC/patch-1
add a link to the Julia bindings
2022-01-03 11:38:08 +01:00
Dominic Szablewski
729c577ca3
Merge branch 'master' into patch-1 2022-01-03 11:38:01 +01:00
Dominic Szablewski
7e5ecc8091
Merge pull request #151 from ShadowMitia/patch-1
Add C++ implementation to the README list
2022-01-03 11:32:05 +01:00
Dominic Szablewski
a46f5537c8
Merge branch 'master' into patch-1 2022-01-03 11:31:42 +01:00
Dominic Szablewski
6a1595aca2
Merge pull request #149 from MKCG/php_library
Add PHP implementation
2022-01-03 11:31:05 +01:00
contriteobserver
a4ea2819c4 fixed gcc warnings in qoibench.c
addresses issue #155
2022-01-02 01:26:42 -08:00
Dimitri Belopopsky
cf918138cf
Add C++ implementation to the README list 2022-01-01 14:18:54 +01:00
Kévin Masseix
48375ec75a Add PHP implementation 2021-12-31 14:34:55 +01:00
Kristoffer Carlsson
9ad3e1d7b4
add a link to the Julia bindings 2021-12-31 12:35:45 +01:00
Lucas Menezes
05bf89291b
Added qoiConverter X 2021-12-30 13:57:58 +00:00
Arian Stolwijk
a810fc0762
Add link to another Go implementation 2021-12-28 13:00:39 +01:00
Kevin Chapelier
a3d43a850a
Add vanilla js implementation 2021-12-27 16:36:37 +01:00
Dmitry Baryshev
96bfc2dbeb Added link to SAIL in README 2021-12-27 14:44:40 +03:00
Dominic Szablewski
00e3421744
Merge pull request #134 from jmaselbas/trailing_spaces
Style: Remove trailing whitespaces
2021-12-26 21:12:47 +01:00
Dominic Szablewski
8a27827c71
Merge pull request #133 from jmaselbas/fix_warn
Fix missing prototypes warning
2021-12-26 21:12:22 +01:00
Dominic Szablewski
aa1e345cd9
Merge pull request #136 from jsoref/spelling
Spelling
2021-12-26 21:10:05 +01:00
Dominic Szablewski
9d7977febf
Merge pull request #137 from Tom94/add-tev-tool
Add link to tev image viewer to README
2021-12-26 21:08:26 +01:00
Thomas Müller-Höhne
03d6e36d5d Add link to tev image viewer to README 2021-12-26 17:41:44 +01:00
Josh Soref
b3f738a204 spelling: mismatch
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2021-12-25 22:49:37 -05:00
Josh Soref
446d5e7008 spelling: measure
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2021-12-25 22:49:37 -05:00
Josh Soref
2fff023912 spelling: ignore
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2021-12-25 22:49:37 -05:00
Josh Soref
c3002a4d70 spelling: head
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2021-12-25 22:49:37 -05:00
Jules Maselbas
da1070a234 Fix missing prototypes warning
Functions qoi_write_32 and qoi_read_32 should either have a prototype
or be declared static. Do the latter, as theses functions are defined
in a header and should only exists in the same compilation unit as the
file including qoi.h and defining QOI_IMPLEMENTATION, ie not exported.

By adding the static keyword in the function declaration the following
command doesn't raise a missing-prototypes warning, anymore:
    cc -Wmissing-prototypes -DQOI_IMPLEMENTATION -c -o qoi.o -xc qoi.h
2021-12-25 16:50:25 +01:00
Jules Maselbas
b060b961e8 Style: Remove trailing whitespaces 2021-12-25 16:44:08 +01:00
Dominic Szablewski
c04a975e00
Merge pull request #131 from dbuenzli/ocaml-qoic
Mention qoic, an OCaml implementation.
2021-12-24 01:19:13 +01:00
Daniel Bünzli
61306d7ecd Mention qoic, an OCaml implementation. 2021-12-24 00:27:47 +01:00
Dominic Szablewski
69b6085d87 Mention xfmoulet/qoi in spec confirming; close #130 2021-12-24 00:12:53 +01:00
Dominic Szablewski
fd0d0a33ce
Merge pull request #129 from vkoskiv/master
Mention support in the c-ray rendering engine
2021-12-23 22:56:31 +01:00
Valtteri Koskivuori
f9954f5b4b
Mention support in the c-ray rendering engine 2021-12-23 23:20:16 +02:00
Dominic Szablewski
01af438e9a
Merge pull request #128 from pfusik/qoi-ci-1.1.0
Mention Imagine plugin
2021-12-23 22:08:06 +01:00
Piotr Fusik
193862433a Mention Imagine plugin. 2021-12-23 21:24:14 +01:00
Dominic Szablewski
c2c01cf5f6
Merge pull request #127 from elihwyma/patch-1
Update Swift-QOI bindings
2021-12-23 19:19:56 +01:00
Amy While
bdcaaa1fb9
Update Swift-QOI bindings 2021-12-23 16:53:32 +00:00
Dominic Szablewski
9f38cffd96 Mention DosWorld/pasqoi; close #92 2021-12-23 12:00:35 +01:00
Dominic Szablewski
f0d532c2f1 Mention takeyourhatoff/qoi; close #126 2021-12-23 11:58:21 +01:00
Dominic Szablewski
19e118d78e Mention QOI thumbnail provider; #123 2021-12-23 11:52:24 +01:00
Dominic Szablewski
56c2272dbe Clarify pixel ordering; close #120 2021-12-23 11:45:19 +01:00
Dominic Szablewski
be12bf0b50
Merge pull request #124 from MasterQ32/zig_done
Zig implementation is now spec complete.
2021-12-23 11:43:15 +01:00
Dominic Szablewski
c69cc218e5
Merge branch 'master' into zig_done 2021-12-23 11:43:01 +01:00
Dominic Szablewski
b53930ad2a
Merge pull request #116 from rbino/qoix-1.0-spec
Move Qoix to the implementations section
2021-12-23 11:40:58 +01:00
Dominic Szablewski
26365fe23c
Merge branch 'master' into qoix-1.0-spec 2021-12-23 11:40:01 +01:00
Dominic Szablewski
a8d44375ff
Merge pull request #119 from Oldes/master
Mention support in Rebol3; close #58
2021-12-23 11:38:42 +01:00
Dominic Szablewski
a53f656538
Merge pull request #121 from NUlliiON/master
Move QoiSharp to the implementations section
2021-12-23 11:38:15 +01:00
Dominic Szablewski
51cd6a56f8
Merge branch 'master' into master 2021-12-23 11:37:54 +01:00
Dominic Szablewski
82aa277606
Merge pull request #125 from zakarumych/rapid-qoi
rapid-qoi is now spec complete
2021-12-23 11:37:15 +01:00
Zakarum
45bc32524a rapid-qoi is now spec complete 2021-12-23 00:21:46 +03:00
Felix "xq" Queißner
9c720cc682 Zig implementation is now spec complete. 2021-12-22 20:27:53 +01:00
Eugene Antonov
b58a0a28c0
Move QoiSharp to the implementations section 2021-12-22 10:08:40 -06:00
Oldes
54e77bf164 Mention support in Rebol3; close #58 2021-12-22 11:12:47 +01:00
Riccardo Binetti
17dffb408c Move Qoix to the implementations section
Qoix is now aligned with v1.0 spec, see
https://github.com/rbino/qoix/pull/2/files
2021-12-22 02:34:48 +01:00
Dominic Szablewski
44fe081388
Merge pull request #113 from GithubPrankster/raylib-mention
Add Raylib as QOI supporting software
2021-12-21 22:49:35 +01:00
GithubPrankster
0d2e27d3ea Added Raylib under QOI Support in Other Software. 2021-12-21 17:57:07 -03:00
Dominic Szablewski
4d20da3282
Add QOI Logo 2021-12-21 19:22:43 +01:00
Dominic Szablewski
d006202752 Mention support in SerenityOS; close #109 2021-12-21 19:21:21 +01:00
Dominic Szablewski
52051a310f Documentation: clarify alpha handling for certain chunk types; close #105 2021-12-21 18:05:30 +01:00
Dominic Szablewski
63f43a9fc1 qoi-java is now spec conforming; close #110 2021-12-21 17:51:08 +01:00
Dominic Szablewski
c194b955d8 Split implementations list based on spec conformance; #104 2021-12-21 17:13:11 +01:00
Dominic Szablewski
63095126f8
Merge pull request #102 from superzazu/patch-1
Add C bindings (SDL2) link
2021-12-21 13:06:22 +01:00
Dominic Szablewski
97e1c1f0e1
Merge pull request #106 from tiagofilipesilva/patch-1
Replace printf() with puts()
2021-12-21 13:02:59 +01:00
Tiago Filipe Silva
e0e21e92fb
Replace printf() with puts()
The format strings are absent in these stdout prints.
They can safely be replaced with calls to _puts()_ and shave also the newlines.
2021-12-21 09:41:33 +00:00
superzazu
3cffa33c45
Add C bindings (SDL2) link 2021-12-20 22:35:13 +01:00
Dominic Szablewski
9c77051f83
Merge pull request #99 from iOrange/master
+ added mention of the very first Paint.NET file type plugin
2021-12-20 20:26:51 +01:00
iOrange
31f6fd3ca5 + added mention of the very first Paint.NET file type plugin that adds the ability to Load/Save QOI images 2021-12-20 13:31:57 -05:00
Dominic Szablewski
71ff2ac961 Add plugins for GIMP, Paint.NET and XnView MP 2021-12-20 17:26:18 +01:00
Dominic Szablewski
438c1e918f Fix typo in documentation 2021-12-20 16:17:25 +01:00
Dominic Szablewski
4192cd1351
Merge pull request #97 from pfusik/cito-transpiled
List languages transpiled from qoi-ci
2021-12-20 11:57:44 +01:00
Dominic Szablewski
f752c1a978 Clarify pixel order and image completeness 2021-12-20 11:56:19 +01:00
Dominic Szablewski
013cfa1ecd Wording 2021-12-20 11:47:04 +01:00
Piotr Fusik
0f83363f45 List languages transpiled from qoi-ci. 2021-12-20 11:43:04 +01:00
Dominic Szablewski
e276f58931 Remove obsolete padding specification; already specified above; #96 2021-12-20 11:38:09 +01:00
Dominic Szablewski
b9a9378223 Remove notice about non-final spec 2021-12-20 10:52:19 +01:00
Dominic Szablewski
4bc071df78 Fix bias for run-length in the documentation 2021-12-19 23:14:08 +01:00
Dominic Szablewski
d8201aa77e
Merge pull request #93 from Cr4xy/master
Add Lua implementation
2021-12-19 11:16:10 +01:00
Cr4xy
9dee61246f Add Lua implementation 2021-12-19 10:54:49 +01:00
Dominic Szablewski
aefa0f7a25
Merge pull request #90 from sezero/sign-compare
minor fix for sign-compare warnings.
2021-12-17 12:23:44 +01:00
Ozkan Sezer
4ca3d3ae42 minor fix for sign-compare warnings. 2021-12-17 01:12:20 +03:00
Dominic Szablewski
3a62cabad2 Change padding bytes to a unique stream-end marker; #89 2021-12-16 20:50:19 +01:00
Dominic Szablewski
bf6951036d Fix check for valid colorspace 2021-12-16 20:13:52 +01:00
Dominic Szablewski
2f255c7aff Enforce a limit of 400 million pixels, 2GB file size 2021-12-16 20:12:27 +01:00
Dominic Szablewski
11dbe1e6aa Add clang fuzzing harness. Thanks @landaire 2021-12-16 20:02:37 +01:00
Dominic Szablewski
ae07396158 Avoid UTF-8 in comments... again. 2021-12-14 21:34:33 +01:00
Dominic Szablewski
0112e3d555 Whitespace, cosmetics 2021-12-14 20:54:37 +01:00
Dominic Szablewski
296f0ef840
Merge pull request #86 from chocolate42/conv-channels
Force rarer PNG encodings to be read by qoiconv as RGBA
2021-12-14 19:19:41 +01:00
Dominic Szablewski
85078d89d6
Merge pull request #85 from chocolate42/bench-channels
Fix qoibench handling of RGB input
2021-12-14 19:19:33 +01:00
Dominic Szablewski
91cc726583 Mention Java implementation; close #59 2021-12-13 17:44:24 +01:00
anon
525f32cefe Convert all non-RGB and non-RGBA input to RGBA. 2021-12-13 16:34:39 +00:00
Dominic Szablewski
873cba791d Merge branch 'schar' 2021-12-13 17:25:55 +01:00
Dominic Szablewski
3973c549dc Remove single line comments to conform to c89 -pedantic 2021-12-13 17:23:04 +01:00
Dominic Szablewski
5983658ad4 Whitespace, wording 2021-12-13 17:16:22 +01:00
anon
b743409e06 Fix qoibench to feed RGB input to the encoders when the source image is RGB. Fix rate calculation by having the raw size of RGB input be w x h x 3 instead of w x h x 4. 2021-12-13 15:27:11 +00:00
Ozkan Sezer
2aaba8da96 make qoi.h build using c89 compilers.
also add a QOI_ZEROARR macro, wrapping around memset by default.
2021-12-13 15:56:56 +03:00
Dominic Szablewski
6a95206e35
Merge pull request #84 from xfmoulet/master
Force a RGB source to have an alpha of 255
2021-12-13 11:24:59 +01:00
Xavier-Frédéric Moulet
99fa97792f Revert "Zero-initialize previous pixel color"
This reverts commit 075ab8fe42.
Closes #30
2021-12-13 11:18:41 +01:00
Ozkan Sezer
8c77fad340 change char local vars to signed char
this accomodates toolchains where char type is unsigned by default.
2021-12-11 21:03:37 +03:00
Dominic Szablewski
2ee2169e02
Merge pull request #80 from 0xd34df00d/patch-1
Add a Haskell implementation
2021-12-11 17:29:28 +01:00
0xd34df00d
ba5c1711c7
Add a Haskell implementation 2021-12-11 11:22:41 -05:00
Dominic Szablewski
e76f25a606 Ignore stb dependencies and build artifacts 2021-12-11 15:49:14 +01:00
Dominic Szablewski
199362ed1d Add note about current specification 2021-12-11 15:48:01 +01:00
Dominic Szablewski
6310d49ee8 Merge branch experimental 2021-12-11 15:46:13 +01:00
Dominic Szablewski
c2edcd3d7a Cosmetics 2021-12-11 12:54:01 +01:00
Dominic Szablewski
0ad304d761 Be more specific with the documentation of the file format 2021-12-10 21:31:28 +01:00
Dominic Szablewski
075ab8fe42 Zero-initialize previous pixel color 2021-12-10 20:09:52 +01:00
Dominic Szablewski
03c7ab14d4
Merge pull request #66 from NUlliiON/master
Mention QOI implementation written in C#
2021-12-08 22:47:40 +01:00
Dominic Szablewski
d9518a9426
Merge branch 'master' into master 2021-12-08 22:47:32 +01:00
Dominic Szablewski
8f9c24a5e9
Merge pull request #74 from elihwyma/patch-1
Add Swift Implementation
2021-12-08 22:46:43 +01:00
Dominic Szablewski
f49dcc074d
Merge branch 'master' into patch-1 2021-12-08 22:46:35 +01:00
Dominic Szablewski
a19e0810e6
Merge pull request #68 from rbino/add-qoix
Add Elixir implementation (Qoix) to the implementations section
2021-12-08 22:45:54 +01:00
Amy While
473e467e7b
Add Swift Implementation 2021-12-08 20:22:16 +00:00
Dominic Szablewski
2103168519 Minor encoding throughput improvement 2021-12-08 15:45:18 +01:00
Dominic Szablewski
6a73cc65c5 Wording, whitespace 2021-12-08 15:45:10 +01:00
Dominic Szablewski
92f7ebd3f8 Fix qoi_desc colorspace check 2021-12-08 15:30:56 +01:00
Dominic Szablewski
6c83cf2e0c Increase padding to 8 zero-bytes 2021-12-08 15:29:46 +01:00
Dominic Szablewski
947941fbd0 Change colorspace header to an enum to avoid confusion 2021-12-08 14:14:51 +01:00
Dominic Szablewski
d6b1ec673a Add alpha channel to QOI_HASH 2021-12-08 11:30:58 +01:00
Dominic Szablewski
eb29269432 Fix typo in documentation 2021-12-08 11:25:24 +01:00
Dominic Szablewski
28954f7a9a Remove QOI_DIFF_16 and QOI_DIFF_24; better tagging of remaining ops; better hash function 2021-12-06 21:23:13 +01:00
Dominic Szablewski
66d12eb078 Add option to only print directory totals 2021-12-06 19:55:39 +01:00
Dominic Szablewski
f45f47c9f0 Recursive traversal; compression ratio; grand total; options to disable some features 2021-12-06 13:35:54 +01:00
Riccardo Binetti
259a3a36a0 Add Elixir implementation (Qoix) to the implementations section 2021-12-06 02:46:44 +01:00
Eugene
ce32dfed6e Mention QOI implementation written in C# 2021-12-05 14:23:24 -06:00
Dominic Szablewski
5039ebd678
Merge pull request #57 from zakarumych/master
Mention rapid-qoi implementation written in Rust
2021-12-05 11:24:12 +01:00
Dominic Szablewski
f6f05835c5
Merge pull request #62 from nsauzede/patch-1
Fix typo in DIFF8 documentation
2021-12-05 11:23:42 +01:00
Dominic Szablewski
8054316d78
Merge pull request #65 from kodonnell/master
Add link in readme to kodonnell/qoi (Python)
2021-12-05 11:23:20 +01:00
kodonnell
bd7d5c07bb
Add link in readme to kodonnell/qoi (Python) 2021-12-05 22:18:49 +13:00
Nicolas Sauzede
03606a0be7
Fix typo in DIFF8 documentation 2021-12-03 01:24:52 +01:00
Zakarum
2392a3423c Mention rapid-qoi implementation written in Rust 2021-12-01 17:48:53 +03:00
Dominic Szablewski
cbb62ea555 Remove QOI_RUN_16, add new QOI_GDIFF_16 op 2021-11-30 22:05:03 +01:00
Dominic Szablewski
e9069e11a4 Add notice about the format being not yet finalized 2021-11-30 17:45:48 +01:00
Dominic Szablewski
fda5167d76 Add links to Tools and Implementations 2021-11-29 11:23:33 +01:00
Dominic Szablewski
a79d03c26b
Merge pull request #45 from lbatalha/readme-packages
add AUR package and create packages section
2021-11-29 11:10:28 +01:00
Dominic Szablewski
94974653c1 Lock output file before writing; close #18 2021-11-28 17:59:51 +01:00
Dominic Szablewski
9dd60534e4 Use local var for channels to speed up encoding 2021-11-28 17:36:47 +01:00
Dominic Szablewski
80356a5aaa Improve documentation, whitespace, wording 2021-11-28 17:36:05 +01:00
Luis Batalha
4f8f59d53e
add packages section
includes aur package link
2021-11-28 15:12:08 +00:00
Dominic Szablewski
f0a38c19e5
Merge pull request #44 from Samyak2/samyak-typo-fix-1
Fix a typo: "user" -> "use"
2021-11-28 12:32:14 +01:00
Dominic Szablewski
bdfda4a5f6
Merge pull request #43 from MasterQ32/improved_docs
Documentation improval
2021-11-28 12:30:51 +01:00
Samyak S Sarnayak
8ebd4e7b6d
Fix a typo: "user" -> "use" 2021-11-28 16:18:55 +05:30
Felix "xq" Queißner
ef9ce10bc1 Adds wraparound specification 2021-11-28 01:17:24 +01:00
Felix "xq" Queißner
7053672d3a Starts to improve the documentation. 2021-11-28 01:08:52 +01:00
Dominic Szablewski
be8d23c574
Merge pull request #31 from vec4f/bug/qoi_read/fclose
Close file on allocation failure in `qoi_read()`
2021-11-27 21:04:16 +01:00
Dominic Szablewski
5506399e0d Fix HEADER_SIZE for the new header 2021-11-27 18:41:02 +01:00
Dominic Szablewski
ff542c2ae6 Change the API to supply/return channel count and colorspace info 2021-11-27 18:36:17 +01:00
Dominic Szablewski
697abf6696 Align the data format with new spec #37 2021-11-27 17:23:52 +01:00
Dominic Szablewski
a902b57ede Announce changes in the file format 2021-11-27 13:21:16 +01:00
Dominic Szablewski
ee66591452
Merge pull request #32 from pfusik/utf8
Avoid UTF-8
2021-11-27 00:26:06 +01:00
Piotr Fusik
344ba65a57 Avoid UTF-8 2021-11-26 22:51:22 +01:00
Brad Fish
7b1567cc9d Close file on allocation failure 2021-11-26 12:28:49 -08:00
Dominic Szablewski
dd0b04b319 Fix #22: avoid UB when reading ints from the stream; 2021-11-26 13:22:00 +01:00
Dominic Szablewski
30f8a39ec8 Fix qoibench avg calculation: ignore non-png entries 2021-11-25 15:14:56 +01:00
Dominic Szablewski
81b438cb56 Change header to big endian; make it independent from host byte order; close #10 2021-11-25 13:51:05 +01:00
Dominic Szablewski
c03edb2f26 Fix naming of chunks in the data format documentation; close #9 2021-11-25 09:43:11 +01:00
Dominic Szablewski
324c2243b2 Add warning about untrusted input; #4 2021-11-24 22:28:35 +01:00
Dominic Szablewski
e969322d00 Don't run past the padding of the byte stream when decoding; re #4 2021-11-24 22:09:08 +01:00
Dominic Szablewski
de17b3c2c1 Fix compile instructions 2021-11-24 11:19:49 +01:00
Dominic Szablewski
19dc63cf17 Initial 2021-11-24 11:07:17 +01:00
19 changed files with 1746 additions and 1 deletions

View File

@ -17,4 +17,5 @@ add_subdirectory(./imgui)
add_subdirectory(./stb) add_subdirectory(./stb)
add_subdirectory(./libwebp) add_subdirectory(./libwebp)
add_subdirectory(./qoi)

11
external/qoi/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.13...3.24 FATAL_ERROR)
project(qoi C CXX)
add_library(qoi_interface INTERFACE)
target_include_directories(qoi_interface SYSTEM INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
# static lib with impl
add_library(qoi "qoi.cpp")
target_link_libraries(qoi qoi_interface)

3
external/qoi/qoi.cpp vendored Normal file
View File

@ -0,0 +1,3 @@
#define QOI_IMPLEMENTATION
#include <qoi/qoi.h>

5
external/qoi/qoi/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
images/
stb_image.h
stb_image_write.h
qoibench
qoiconv

21
external/qoi/qoi/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Dominic Szablewski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

22
external/qoi/qoi/Makefile vendored Normal file
View File

@ -0,0 +1,22 @@
CC ?= gcc
CFLAGS_BENCH ?= -std=gnu99 -O3
LFLAGS_BENCH ?= -lpng
CFLAGS_CONV ?= -std=c99 -O3
TARGET_BENCH ?= qoibench
TARGET_CONV ?= qoiconv
all: $(TARGET_BENCH) $(TARGET_CONV)
bench: $(TARGET_BENCH)
$(TARGET_BENCH):$(TARGET_BENCH).c
$(CC) $(CFLAGS_BENCH) $(CFLAGS) $(TARGET_BENCH).c -o $(TARGET_BENCH) $(LFLAGS_BENCH)
conv: $(TARGET_CONV)
$(TARGET_CONV):$(TARGET_CONV).c
$(CC) $(CFLAGS_CONV) $(CFLAGS) $(TARGET_CONV).c -o $(TARGET_CONV)
.PHONY: clean
clean:
$(RM) $(TARGET_BENCH) $(TARGET_CONV)

179
external/qoi/qoi/README.md vendored Normal file
View File

@ -0,0 +1,179 @@
![QOI Logo](https://qoiformat.org/qoi-logo.svg)
# QOI - The “Quite OK Image Format” for fast, lossless image compression
Single-file MIT licensed library for C/C++
See [qoi.h](https://github.com/phoboslab/qoi/blob/master/qoi.h) for
the documentation and format specification.
More info at https://qoiformat.org
## Why?
Compared to stb_image and stb_image_write QOI offers 20x-50x faster encoding,
3x-4x faster decoding and 20% better compression. It's also stupidly simple and
fits in about 300 lines of C.
## Example Usage
- [qoiconv.c](https://github.com/phoboslab/qoi/blob/master/qoiconv.c)
converts between png <> qoi
- [qoibench.c](https://github.com/phoboslab/qoi/blob/master/qoibench.c)
a simple wrapper to benchmark stbi, libpng and qoi
## MIME Type, File Extension
The recommended MIME type for QOI images is `image/qoi`. While QOI is not yet
officially registered with IANA, I believe QOI has found enough adoption to
prevent any future image format from choosing the same name, thus making a
MIME type collision highly unlikely ([see #167](https://github.com/phoboslab/qoi/issues/167)).
The recommended file extension for QOI images is `.qoi`
## Limitations
The QOI file format allows for huge images with up to 18 exa-pixels. A streaming
en-/decoder can handle these with minimal RAM requirements, assuming there is
enough storage space.
This particular implementation of QOI however is limited to images with a
maximum size of 400 million pixels. It will safely refuse to en-/decode anything
larger than that. This is not a streaming en-/decoder. It loads the whole image
file into RAM before doing any work and is not extensively optimized for
performance (but it's still very fast).
If this is a limitation for your use case, please look into any of the other
implementations listed below.
## Improvements, New Versions and Contributing
The QOI format has been finalized. It was a conscious decision to **not** have a
version number in the file header. If you have a working QOI implementation today,
you can rest assured that it will be compatible with all QOI files tomorrow.
There are a lot of interesting ideas for a successor of QOI, but none of these will
be implemented here. That doesn't mean you shouldn't experiment with QOI, but please
be aware that pull requests that change the format will not be accepted.
Likewise, pull requests for performance improvements will probably not be accepted
either, as this "reference implementation" tries to be as easy to read as possible.
## Tools
- [floooh/qoiview](https://github.com/floooh/qoiview) - native QOI viewer
- [pfusik/qoi-fu](https://github.com/pfusik/qoi-fu/releases) - QOI Plugin installer for Windows Explorer, Finder, GNOME, GIMP, Paint.NET and XnView
- [iOrange/QoiFileTypeNet](https://github.com/iOrange/QoiFileTypeNet/releases) - QOI Plugin for Paint.NET
- [iOrange/QOIThumbnailProvider](https://github.com/iOrange/QOIThumbnailProvider) - Add thumbnails for QOI images in Windows Explorer
- [Tom94/tev](https://github.com/Tom94/tev) - another native QOI viewer (allows pixel peeping and comparison with other image formats)
- [qoiconverterx](https://apps.apple.com/br/app/qoiconverterx/id1602159820) QOI <=> PNG converter available on the Mac App Store
- [kaetemi/qoi-ma](https://github.com/kaetemi/qoi-max) - QOI Bitmap I/O Plugin for 3ds Max
- [rtexviewer](https://raylibtech.itch.io/rtexviewer) - texture viewer, supports QOI
- [rtexpacker](https://raylibtech.itch.io/rtexpacker) - texture packer, supports QOI
- [DmitriySalnikov/godot_qoi](https://github.com/DmitriySalnikov/godot_qoi) - QOI GDNative Addon for Godot Engine
- [dan9er/farbfeld-convert-qoi](https://gitlab.com/dan9er/farbfeld-convert-qoi) - QOI <=> farbfeld converter
- [LTMX/Unity.QOI](https://github.com/LTMX/Unity.QOI) - QOI Importer and Exporter for the Unity3D Game Engine
- [Ben1138/unity-qoi](https://github.com/Ben1138/unity-qoi) - QOI Importer(only) support for the Unity3D Game Engine
- [xiaozhuai/jetbrains-qo](https://github.com/xiaozhuai/jetbrains-qoi) - [QOI Support](https://plugins.jetbrains.com/plugin/19352-qoi-support) for Jetbrains' IDE.
- [serge-ivamov/QOIql](https://github.com/serge-ivamov/QOIql) - MacOS QuickLook plugin for QOI
- [tobozo/kde-thumbnailer-qoi](https://github.com/tobozo/kde-thumbnailer-qoi) - QOI Thumbnailer for KDE
- [walksanatora/qoi-thumbnailer-nemo](https://github.com/walksanatora/qoi-thumbnailer-nemo) - QOI Thumbnailer for Nemo
- [hzeller/timg](https://github.com/hzeller/timg) - a terminal image viewer with QOI support
- [LuisAlfredo92/Super-QOI-converter](https://github.com/LuisAlfredo92/Super-QOI-converter "LuisAlfredo92/Super-QOI-converter") - A program to convert JPG, JPEG, BMP, and PNG to QOI
- [Console version](https://github.com/LuisAlfredo92/Super-QOI-converter-Console- "Console version"): Available for Linux, OSX and Windows
- [GUI version](https://github.com/LuisAlfredo92/Super-QOI-converter-GUI- "GUI version"): Available only for windows
- [tacent view](https://github.com/bluescan/tacentview) - Image and texture viewer, supports QOI
- [colemanrgb/qoi2spr](https://github.com/colemanrgb/qoi2spr) - A variety of applications for decoding and encoding of QOI images on [RISC OS](https://www.riscosopen.org/)
## Implementations & Bindings of QOI
- [pfusik/qoi-fu](https://github.com/pfusik/qoi-fu) - Fusion, transpiling to C, C++, C#, D, Java, JavaScript, Python, Swift and TypeScript
- [kodonnell/qoi](https://github.com/kodonnell/qoi) - Python
- [JaffaKetchup/dqoi](https://github.com/JaffaKetchup/dqoi) - Dart, with Flutter support
- [Cr4xy/lua-qoi](https://github.com/Cr4xy/lua-qoi) - Lua
- [superzazu/SDL_QOI](https://github.com/superzazu/SDL_QOI) - C, SDL2 bindings
- [saharNooby/qoi-java](https://github.com/saharNooby/qoi-java) - Java
- [MasterQ32/zig-qoi](https://github.com/MasterQ32/zig-qoi) - Zig
- [rbino/qoix](https://github.com/rbino/qoix) - Elixir
- [NUlliiON/QoiSharp](https://github.com/NUlliiON/QoiSharp) - C#
- [aldanor/qoi-rust](https://github.com/aldanor/qoi-rust) - Rust
- [zakarumych/rapid-qoi](https://github.com/zakarumych/rapid-qoi) - Rust
- [takeyourhatoff/qoi](https://github.com/takeyourhatoff/qoi) - Go
- [DosWorld/pasqoi](https://github.com/DosWorld/pasqoi) - Pascal
- [elihwyma/Swift-QOI](https://github.com/elihwyma/Swift-QOI) - Swift
- [xfmoulet/qoi](https://github.com/xfmoulet/qoi) - Go
- [erratique.ch/qoic](https://erratique.ch/software/qoic) - OCaml
- [arian/go-qoi](https://github.com/arian/go-qoi) - Go
- [kchapelier/qoijs](https://github.com/kchapelier/qoijs) - JavaScript
- [KristofferC/QOI.jl](https://github.com/KristofferC/QOI.jl) - Julia
- [shadowMitia/libqoi](https://github.com/shadowMitia/libqoi) - C++
- [MKCG/php-qoi](https://github.com/MKCG/php-qoi) - PHP
- [LightHouseSoftware/qoiformats](https://github.com/LightHouseSoftware/qoiformats) - D
- [mhoward540/qoi-nim](https://github.com/mhoward540/qoi-nim) - Nim
- [wx257osn2/qoixx](https://github.com/wx257osn2/qoixx) - C++
- [Tiefseetauchner/lr-paint](https://github.com/Tiefseetauchner/lr-paint) - Processing
- [amstan/qoi-fpga](https://github.com/amstan/qoi-fpga) - FPGA: verilog
- [musabkilic/qoi-decoder](https://github.com/musabkilic/qoi-decoder) - Python
- [mathpn/py-qoi](https://github.com/mathpn/py-qoi) - Python
- [JohannesFriedrich/qoi4R](https://github.com/JohannesFriedrich/qoi4R) - R
- [shraiwi/mini-qoi](https://github.com/shraiwi/mini-qoi) - C, streaming decoder
- [10maurycy10/libqoi/](https://github.com/10maurycy10/libqoi/) - Rust
- [0xd34df00d/hsqoi](https://github.com/0xd34df00d/hsqoi) - Haskell
- [418Coffee/qoi-v](https://github.com/418Coffee/qoi-v) - V
- [Imagine-Programming/QoiImagePlugin](https://github.com/Imagine-Programming/QoiImagePlugin) - PureBasic
- [Fabien-Chouteau/qoi-spark](https://github.com/Fabien-Chouteau/qoi-spark) - Ada/SPARK formally proven
- [mzgreen/qoi-kotlin](https://github.com/mzgreen/qoi-kotlin) - Kotlin Multiplatform
- [Aftersol/Simplified-QOI-Codec](https://github.com/Aftersol/Simplified-QOI-Codec) - C99, encoder and decoder, freestanding
- [AuburnSounds/gamut](https://github.com/AuburnSounds/gamut) - D
- [AngusJohnson/TQoiImage](https://github.com/AngusJohnson/TQoiImage) - Delphi
- [MarkJeronimus/qoi-java-spi](https://github.com/MarkJeronimus/qoi-java-spi) - Java SPI
- [aumouvantsillage/qoi-racket](https://github.com/aumouvantsillage/qoi-racket) - Racket
- [rubikscraft/qoi-stream](https://github.com/rubikscraft/qoi-stream) - C99, one byte at a time streaming encoder and decoder
- [rubikscraft/qoi-img](https://github.com/rubikscraft/qoi-img) - NodeJS typescript, bindings to both [QOIxx](https://github.com/wx257osn2/qoixx) and [qoi-stream](https://github.com/rubikscraft/qoi-stream)
- [grego/hare-qoi](https://git.sr.ht/~grego/hare-qoi) - Hare
- [MrNocole/ZTQOI](https://github.com/MrNocole/ZTQOI) - Objective-C
- [bpanthi977/qoi](https://github.com/bpanthi977/qoi) - Common Lisp
- [Floessie/pam2qoi](https://github.com/Floessie/pam2qoi) - C++
- [SpeckyYT/spwn-qoi](https://github.com/SpeckyYT/spwn-qoi) - SPWN
- [n00bmind/qoi](https://github.com/n00bmind/qoi) - Jai
- [SixLabors/ImageSharp](https://github.com/SixLabors/ImageSharp) - C# image proccesing library
- [zertovitch/gid](https://github.com/zertovitch/gid) - Ada
- [nazrin/lil](https://codeberg.org/nazrin/lil) - Lua image library
## QOI Support in Other Software
- [Amiga OS QOI datatype](https://github.com/dgaw/qoi-datatype) - adds support for decoding QOI images to the Amiga operating system.
- [SerenityOS](https://github.com/SerenityOS/serenity) - supports decoding QOI system wide through a custom [cpp implementation in LibGfx](https://github.com/SerenityOS/serenity/blob/master/Userland/Libraries/LibGfx/QOILoader.h)
- [Raylib](https://github.com/raysan5/raylib) - supports decoding and encoding QOI textures through its [rtextures module](https://github.com/raysan5/raylib/blob/master/src/rtextures.c)
- [Rebol3](https://github.com/Oldes/Rebol3/issues/39) - supports decoding and encoding QOI using a native codec
- [c-ray](https://github.com/vkoskiv/c-ray) - supports QOI natively
- [SAIL](https://sail.software) - image decoding library, supports decoding and encoding QOI images
- [Orx](https://github.com/orx/orx) - 2D game engine, supports QOI natively
- [IrfanView](https://www.irfanview.com) - supports decoding and encoding QOI through its Formats plugin
- [ImageMagick](https://github.com/ImageMagick/ImageMagick) - supports decoding and encoding QOI, since 7.1.0-20
- [barebox](https://barebox.org) - bootloader, supports decoding QOI images for splash logo, since v2022.03.0
- [KorGE](https://korge.org) - & KorIM Kotlin 2D game engine and imaging library, supports decoding and encoding QOI natively since 2.7.0
- [DOjS](https://github.com/SuperIlu/DOjS) - DOS JavaScript Canvas implementation supports loading QOI files
- [XnView MP](https://www.xnview.com/en/xnviewmp/) - supports decoding QOI since 1.00
- [ffmpeg](https://ffmpeg.org/) - supports decoding and encoding QOI since 5.1
- [JPEGView](https://github.com/sylikc/jpegview) - lightweight Windows image viewer, supports decoding and encoding of QOI natively, since 1.1.44
- [darktable](https://github.com/darktable-org/darktable) - photography workflow application and raw developer, supports decoding since 4.4.0
- [KDE](https://kde.org) - supports decoding and encoding QOI images. Implemented in [KImageFormats](https://invent.kde.org/frameworks/kimageformats)
- [EFL](https://www.enlightenment.org) - supports decoding and encoding QOI images since 1.27.
- [Swingland](https://git.sr.ht/~phlash/swingland) - supports QOI decoding/loading via the `ImageIO` API of this Java Swing reimplemenation for Wayland
- [Imagine](https://www.nyam.pe.kr/dev/imagine/) - supports decoding and encoding QOI images since 1.3.9
- [Uiua](https://uiua.org) - supports decoding and encoding QOI images since 0.8.0
## Packages
- [AUR](https://aur.archlinux.org/pkgbase/qoi-git/) - system-wide qoi.h, qoiconv and qoibench install as split packages.
- [Debian](https://packages.debian.org/bookworm/source/qoi) - packages for binaries and qoi.h
- [Ubuntu](https://launchpad.net/ubuntu/+source/qoi) - packages for binaries and qoi.h
Packages for other systems [tracked at Repology](https://repology.org/project/qoi/versions).

649
external/qoi/qoi/qoi.h vendored Normal file
View File

@ -0,0 +1,649 @@
/*
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
SPDX-License-Identifier: MIT
QOI - The "Quite OK Image" format for fast, lossless image compression
-- About
QOI encodes and decodes images in a lossless format. Compared to stb_image and
stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
20% better compression.
-- Synopsis
// Define `QOI_IMPLEMENTATION` in *one* C/C++ file before including this
// library to create the implementation.
#define QOI_IMPLEMENTATION
#include "qoi.h"
// Encode and store an RGBA buffer to the file system. The qoi_desc describes
// the input pixel data.
qoi_write("image_new.qoi", rgba_pixels, &(qoi_desc){
.width = 1920,
.height = 1080,
.channels = 4,
.colorspace = QOI_SRGB
});
// Load and decode a QOI image from the file system into a 32bbp RGBA buffer.
// The qoi_desc struct will be filled with the width, height, number of channels
// and colorspace read from the file header.
qoi_desc desc;
void *rgba_pixels = qoi_read("image.qoi", &desc, 4);
-- Documentation
This library provides the following functions;
- qoi_read -- read and decode a QOI file
- qoi_decode -- decode the raw bytes of a QOI image from memory
- qoi_write -- encode and write a QOI file
- qoi_encode -- encode an rgba buffer into a QOI image in memory
See the function declaration below for the signature and more information.
If you don't want/need the qoi_read and qoi_write functions, you can define
QOI_NO_STDIO before including this library.
This library uses malloc() and free(). To supply your own malloc implementation
you can define QOI_MALLOC and QOI_FREE before including this library.
This library uses memset() to zero-initialize the index. To supply your own
implementation you can define QOI_ZEROARR before including this library.
-- Data Format
A QOI file has a 14 byte header, followed by any number of data "chunks" and an
8-byte end marker.
struct qoi_header_t {
char magic[4]; // magic bytes "qoif"
uint32_t width; // image width in pixels (BE)
uint32_t height; // image height in pixels (BE)
uint8_t channels; // 3 = RGB, 4 = RGBA
uint8_t colorspace; // 0 = sRGB with linear alpha, 1 = all channels linear
};
Images are encoded row by row, left to right, top to bottom. The decoder and
encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
image is complete when all pixels specified by width * height have been covered.
Pixels are encoded as
- a run of the previous pixel
- an index into an array of previously seen pixels
- a difference to the previous pixel value in r,g,b
- full r,g,b or r,g,b,a values
The color channels are assumed to not be premultiplied with the alpha channel
("un-premultiplied alpha").
A running array[64] (zero-initialized) of previously seen pixel values is
maintained by the encoder and decoder. Each pixel that is seen by the encoder
and decoder is put into this array at the position formed by a hash function of
the color value. In the encoder, if the pixel value at the index matches the
current pixel, this index position is written to the stream as QOI_OP_INDEX.
The hash function for the index is:
index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
values encoded in these data bits have the most significant bit on the left.
The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the
presence of an 8-bit tag first.
The byte stream's end is marked with 7 0x00 bytes followed a single 0x01 byte.
The possible chunks are:
.- QOI_OP_INDEX ----------.
| Byte[0] |
| 7 6 5 4 3 2 1 0 |
|-------+-----------------|
| 0 0 | index |
`-------------------------`
2-bit tag b00
6-bit index into the color index array: 0..63
A valid encoder must not issue 2 or more consecutive QOI_OP_INDEX chunks to the
same index. QOI_OP_RUN should be used instead.
.- QOI_OP_DIFF -----------.
| Byte[0] |
| 7 6 5 4 3 2 1 0 |
|-------+-----+-----+-----|
| 0 1 | dr | dg | db |
`-------------------------`
2-bit tag b01
2-bit red channel difference from the previous pixel between -2..1
2-bit green channel difference from the previous pixel between -2..1
2-bit blue channel difference from the previous pixel between -2..1
The difference to the current channel values are using a wraparound operation,
so "1 - 2" will result in 255, while "255 + 1" will result in 0.
Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as
0 (b00). 1 is stored as 3 (b11).
The alpha value remains unchanged from the previous pixel.
.- QOI_OP_LUMA -------------------------------------.
| Byte[0] | Byte[1] |
| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
|-------+-----------------+-------------+-----------|
| 1 0 | green diff | dr - dg | db - dg |
`---------------------------------------------------`
2-bit tag b10
6-bit green channel difference from the previous pixel -32..31
4-bit red channel difference minus green channel difference -8..7
4-bit blue channel difference minus green channel difference -8..7
The green channel is used to indicate the general direction of change and is
encoded in 6 bits. The red and blue channels (dr and db) base their diffs off
of the green channel difference and are encoded in 4 bits. I.e.:
dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g)
db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g)
The difference to the current channel values are using a wraparound operation,
so "10 - 13" will result in 253, while "250 + 7" will result in 1.
Values are stored as unsigned integers with a bias of 32 for the green channel
and a bias of 8 for the red and blue channel.
The alpha value remains unchanged from the previous pixel.
.- QOI_OP_RUN ------------.
| Byte[0] |
| 7 6 5 4 3 2 1 0 |
|-------+-----------------|
| 1 1 | run |
`-------------------------`
2-bit tag b11
6-bit run-length repeating the previous pixel: 1..62
The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
(b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
QOI_OP_RGBA tags.
.- QOI_OP_RGB ------------------------------------------.
| Byte[0] | Byte[1] | Byte[2] | Byte[3] |
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|-------------------------+---------+---------+---------|
| 1 1 1 1 1 1 1 0 | red | green | blue |
`-------------------------------------------------------`
8-bit tag b11111110
8-bit red channel value
8-bit green channel value
8-bit blue channel value
The alpha value remains unchanged from the previous pixel.
.- QOI_OP_RGBA ---------------------------------------------------.
| Byte[0] | Byte[1] | Byte[2] | Byte[3] | Byte[4] |
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|-------------------------+---------+---------+---------+---------|
| 1 1 1 1 1 1 1 1 | red | green | blue | alpha |
`-----------------------------------------------------------------`
8-bit tag b11111111
8-bit red channel value
8-bit green channel value
8-bit blue channel value
8-bit alpha channel value
*/
/* -----------------------------------------------------------------------------
Header - Public functions */
#ifndef QOI_H
#define QOI_H
#ifdef __cplusplus
extern "C" {
#endif
/* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions.
It describes either the input format (for qoi_write and qoi_encode), or is
filled with the description read from the file header (for qoi_read and
qoi_decode).
The colorspace in this qoi_desc is an enum where
0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel
1 = all channels are linear
You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
informative. It will be saved to the file header, but does not affect
how chunks are en-/decoded. */
#define QOI_SRGB 0
#define QOI_LINEAR 1
typedef struct {
unsigned int width;
unsigned int height;
unsigned char channels;
unsigned char colorspace;
} qoi_desc;
#ifndef QOI_NO_STDIO
/* Encode raw RGB or RGBA pixels into a QOI image and write it to the file
system. The qoi_desc struct must be filled with the image width, height,
number of channels (3 = RGB, 4 = RGBA) and the colorspace.
The function returns 0 on failure (invalid parameters, or fopen or malloc
failed) or the number of bytes written on success. */
int qoi_write(const char *filename, const void *data, const qoi_desc *desc);
/* Read and decode a QOI image from the file system. If channels is 0, the
number of channels from the file header is used. If channels is 3 or 4 the
output format will be forced into this number of channels.
The function either returns NULL on failure (invalid data, or malloc or fopen
failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
will be filled with the description from the file header.
The returned pixel data should be free()d after use. */
void *qoi_read(const char *filename, qoi_desc *desc, int channels);
#endif /* QOI_NO_STDIO */
/* Encode raw RGB or RGBA pixels into a QOI image in memory.
The function either returns NULL on failure (invalid parameters or malloc
failed) or a pointer to the encoded data on success. On success the out_len
is set to the size in bytes of the encoded data.
The returned qoi data should be free()d after use. */
void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len);
/* Decode a QOI image from memory.
The function either returns NULL on failure (invalid parameters or malloc
failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
is filled with the description from the file header.
The returned pixel data should be free()d after use. */
void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels);
#ifdef __cplusplus
}
#endif
#endif /* QOI_H */
/* -----------------------------------------------------------------------------
Implementation */
#ifdef QOI_IMPLEMENTATION
#include <stdlib.h>
#include <string.h>
#ifndef QOI_MALLOC
#define QOI_MALLOC(sz) malloc(sz)
#define QOI_FREE(p) free(p)
#endif
#ifndef QOI_ZEROARR
#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
#endif
#define QOI_OP_INDEX 0x00 /* 00xxxxxx */
#define QOI_OP_DIFF 0x40 /* 01xxxxxx */
#define QOI_OP_LUMA 0x80 /* 10xxxxxx */
#define QOI_OP_RUN 0xc0 /* 11xxxxxx */
#define QOI_OP_RGB 0xfe /* 11111110 */
#define QOI_OP_RGBA 0xff /* 11111111 */
#define QOI_MASK_2 0xc0 /* 11000000 */
#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
#define QOI_MAGIC \
(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
((unsigned int)'i') << 8 | ((unsigned int)'f'))
#define QOI_HEADER_SIZE 14
/* 2GB is the max file size that this implementation can safely handle. We guard
against anything larger than that, assuming the worst case with 5 bytes per
pixel, rounded down to a nice clean value. 400 million pixels ought to be
enough for anybody. */
#define QOI_PIXELS_MAX ((unsigned int)400000000)
typedef union {
struct { unsigned char r, g, b, a; } rgba;
unsigned int v;
} qoi_rgba_t;
static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
bytes[(*p)++] = (0xff000000 & v) >> 24;
bytes[(*p)++] = (0x00ff0000 & v) >> 16;
bytes[(*p)++] = (0x0000ff00 & v) >> 8;
bytes[(*p)++] = (0x000000ff & v);
}
static unsigned int qoi_read_32(const unsigned char *bytes, int *p) {
unsigned int a = bytes[(*p)++];
unsigned int b = bytes[(*p)++];
unsigned int c = bytes[(*p)++];
unsigned int d = bytes[(*p)++];
return a << 24 | b << 16 | c << 8 | d;
}
void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
int i, max_size, p, run;
int px_len, px_end, px_pos, channels;
unsigned char *bytes;
const unsigned char *pixels;
qoi_rgba_t index[64];
qoi_rgba_t px, px_prev;
if (
data == NULL || out_len == NULL || desc == NULL ||
desc->width == 0 || desc->height == 0 ||
desc->channels < 3 || desc->channels > 4 ||
desc->colorspace > 1 ||
desc->height >= QOI_PIXELS_MAX / desc->width
) {
return NULL;
}
max_size =
desc->width * desc->height * (desc->channels + 1) +
QOI_HEADER_SIZE + sizeof(qoi_padding);
p = 0;
bytes = (unsigned char *) QOI_MALLOC(max_size);
if (!bytes) {
return NULL;
}
qoi_write_32(bytes, &p, QOI_MAGIC);
qoi_write_32(bytes, &p, desc->width);
qoi_write_32(bytes, &p, desc->height);
bytes[p++] = desc->channels;
bytes[p++] = desc->colorspace;
pixels = (const unsigned char *)data;
QOI_ZEROARR(index);
run = 0;
px_prev.rgba.r = 0;
px_prev.rgba.g = 0;
px_prev.rgba.b = 0;
px_prev.rgba.a = 255;
px = px_prev;
px_len = desc->width * desc->height * desc->channels;
px_end = px_len - desc->channels;
channels = desc->channels;
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
px.rgba.r = pixels[px_pos + 0];
px.rgba.g = pixels[px_pos + 1];
px.rgba.b = pixels[px_pos + 2];
if (channels == 4) {
px.rgba.a = pixels[px_pos + 3];
}
if (px.v == px_prev.v) {
run++;
if (run == 62 || px_pos == px_end) {
bytes[p++] = QOI_OP_RUN | (run - 1);
run = 0;
}
}
else {
int index_pos;
if (run > 0) {
bytes[p++] = QOI_OP_RUN | (run - 1);
run = 0;
}
index_pos = QOI_COLOR_HASH(px) % 64;
if (index[index_pos].v == px.v) {
bytes[p++] = QOI_OP_INDEX | index_pos;
}
else {
index[index_pos] = px;
if (px.rgba.a == px_prev.rgba.a) {
signed char vr = px.rgba.r - px_prev.rgba.r;
signed char vg = px.rgba.g - px_prev.rgba.g;
signed char vb = px.rgba.b - px_prev.rgba.b;
signed char vg_r = vr - vg;
signed char vg_b = vb - vg;
if (
vr > -3 && vr < 2 &&
vg > -3 && vg < 2 &&
vb > -3 && vb < 2
) {
bytes[p++] = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2);
}
else if (
vg_r > -9 && vg_r < 8 &&
vg > -33 && vg < 32 &&
vg_b > -9 && vg_b < 8
) {
bytes[p++] = QOI_OP_LUMA | (vg + 32);
bytes[p++] = (vg_r + 8) << 4 | (vg_b + 8);
}
else {
bytes[p++] = QOI_OP_RGB;
bytes[p++] = px.rgba.r;
bytes[p++] = px.rgba.g;
bytes[p++] = px.rgba.b;
}
}
else {
bytes[p++] = QOI_OP_RGBA;
bytes[p++] = px.rgba.r;
bytes[p++] = px.rgba.g;
bytes[p++] = px.rgba.b;
bytes[p++] = px.rgba.a;
}
}
}
px_prev = px;
}
for (i = 0; i < (int)sizeof(qoi_padding); i++) {
bytes[p++] = qoi_padding[i];
}
*out_len = p;
return bytes;
}
void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
const unsigned char *bytes;
unsigned int header_magic;
unsigned char *pixels;
qoi_rgba_t index[64];
qoi_rgba_t px;
int px_len, chunks_len, px_pos;
int p = 0, run = 0;
if (
data == NULL || desc == NULL ||
(channels != 0 && channels != 3 && channels != 4) ||
size < QOI_HEADER_SIZE + (int)sizeof(qoi_padding)
) {
return NULL;
}
bytes = (const unsigned char *)data;
header_magic = qoi_read_32(bytes, &p);
desc->width = qoi_read_32(bytes, &p);
desc->height = qoi_read_32(bytes, &p);
desc->channels = bytes[p++];
desc->colorspace = bytes[p++];
if (
desc->width == 0 || desc->height == 0 ||
desc->channels < 3 || desc->channels > 4 ||
desc->colorspace > 1 ||
header_magic != QOI_MAGIC ||
desc->height >= QOI_PIXELS_MAX / desc->width
) {
return NULL;
}
if (channels == 0) {
channels = desc->channels;
}
px_len = desc->width * desc->height * channels;
pixels = (unsigned char *) QOI_MALLOC(px_len);
if (!pixels) {
return NULL;
}
QOI_ZEROARR(index);
px.rgba.r = 0;
px.rgba.g = 0;
px.rgba.b = 0;
px.rgba.a = 255;
chunks_len = size - (int)sizeof(qoi_padding);
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
if (run > 0) {
run--;
}
else if (p < chunks_len) {
int b1 = bytes[p++];
if (b1 == QOI_OP_RGB) {
px.rgba.r = bytes[p++];
px.rgba.g = bytes[p++];
px.rgba.b = bytes[p++];
}
else if (b1 == QOI_OP_RGBA) {
px.rgba.r = bytes[p++];
px.rgba.g = bytes[p++];
px.rgba.b = bytes[p++];
px.rgba.a = bytes[p++];
}
else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) {
px = index[b1];
}
else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) {
px.rgba.r += ((b1 >> 4) & 0x03) - 2;
px.rgba.g += ((b1 >> 2) & 0x03) - 2;
px.rgba.b += ( b1 & 0x03) - 2;
}
else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) {
int b2 = bytes[p++];
int vg = (b1 & 0x3f) - 32;
px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f);
px.rgba.g += vg;
px.rgba.b += vg - 8 + (b2 & 0x0f);
}
else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) {
run = (b1 & 0x3f);
}
index[QOI_COLOR_HASH(px) % 64] = px;
}
pixels[px_pos + 0] = px.rgba.r;
pixels[px_pos + 1] = px.rgba.g;
pixels[px_pos + 2] = px.rgba.b;
if (channels == 4) {
pixels[px_pos + 3] = px.rgba.a;
}
}
return pixels;
}
#ifndef QOI_NO_STDIO
#include <stdio.h>
int qoi_write(const char *filename, const void *data, const qoi_desc *desc) {
FILE *f = fopen(filename, "wb");
int size, err;
void *encoded;
if (!f) {
return 0;
}
encoded = qoi_encode(data, desc, &size);
if (!encoded) {
fclose(f);
return 0;
}
fwrite(encoded, 1, size, f);
fflush(f);
err = ferror(f);
fclose(f);
QOI_FREE(encoded);
return err ? 0 : size;
}
void *qoi_read(const char *filename, qoi_desc *desc, int channels) {
FILE *f = fopen(filename, "rb");
int size, bytes_read;
void *pixels, *data;
if (!f) {
return NULL;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
if (size <= 0 || fseek(f, 0, SEEK_SET) != 0) {
fclose(f);
return NULL;
}
data = QOI_MALLOC(size);
if (!data) {
fclose(f);
return NULL;
}
bytes_read = fread(data, 1, size, f);
fclose(f);
pixels = (bytes_read != size) ? NULL : qoi_decode(data, bytes_read, desc, channels);
QOI_FREE(data);
return pixels;
}
#endif /* QOI_NO_STDIO */
#endif /* QOI_IMPLEMENTATION */

610
external/qoi/qoi/qoibench.c vendored Normal file
View File

@ -0,0 +1,610 @@
/*
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
SPDX-License-Identifier: MIT
Simple benchmark suite for png, stbi and qoi
Requires libpng, "stb_image.h" and "stb_image_write.h"
Compile with:
gcc qoibench.c -std=gnu99 -lpng -O3 -o qoibench
*/
#include <stdio.h>
#include <dirent.h>
#include <png.h>
#define STB_IMAGE_IMPLEMENTATION
#define STBI_ONLY_PNG
#define STBI_NO_LINEAR
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define QOI_IMPLEMENTATION
#include "qoi.h"
// -----------------------------------------------------------------------------
// Cross platform high resolution timer
// From https://gist.github.com/ForeverZer0/0a4f80fc02b96e19380ebb7a3debbee5
#include <stdint.h>
#if defined(__linux)
#define HAVE_POSIX_TIMER
#include <time.h>
#ifdef CLOCK_MONOTONIC
#define CLOCKID CLOCK_MONOTONIC
#else
#define CLOCKID CLOCK_REALTIME
#endif
#elif defined(__APPLE__)
#define HAVE_MACH_TIMER
#include <mach/mach_time.h>
#elif defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
static uint64_t ns() {
static uint64_t is_init = 0;
#if defined(__APPLE__)
static mach_timebase_info_data_t info;
if (0 == is_init) {
mach_timebase_info(&info);
is_init = 1;
}
uint64_t now;
now = mach_absolute_time();
now *= info.numer;
now /= info.denom;
return now;
#elif defined(__linux)
static struct timespec linux_rate;
if (0 == is_init) {
clock_getres(CLOCKID, &linux_rate);
is_init = 1;
}
uint64_t now;
struct timespec spec;
clock_gettime(CLOCKID, &spec);
now = spec.tv_sec * 1.0e9 + spec.tv_nsec;
return now;
#elif defined(_WIN32)
static LARGE_INTEGER win_frequency;
if (0 == is_init) {
QueryPerformanceFrequency(&win_frequency);
is_init = 1;
}
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (uint64_t) ((1e9 * now.QuadPart) / win_frequency.QuadPart);
#endif
}
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define ERROR(...) printf("abort at line " TOSTRING(__LINE__) ": " __VA_ARGS__); printf("\n"); exit(1)
// -----------------------------------------------------------------------------
// libpng encode/decode wrappers
// Seriously, who thought this was a good abstraction for an API to read/write
// images?
typedef struct {
int size;
int capacity;
unsigned char *data;
} libpng_write_t;
void libpng_encode_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
libpng_write_t *write_data = (libpng_write_t*)png_get_io_ptr(png_ptr);
if (write_data->size + length >= write_data->capacity) {
ERROR("PNG write");
}
memcpy(write_data->data + write_data->size, data, length);
write_data->size += length;
}
void *libpng_encode(void *pixels, int w, int h, int channels, int *out_len) {
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png) {
ERROR("png_create_write_struct");
}
png_infop info = png_create_info_struct(png);
if (!info) {
ERROR("png_create_info_struct");
}
if (setjmp(png_jmpbuf(png))) {
ERROR("png_jmpbuf");
}
// Output is 8bit depth, RGBA format.
png_set_IHDR(
png,
info,
w, h,
8,
channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT
);
png_bytep row_pointers[h];
for(int y = 0; y < h; y++){
row_pointers[y] = ((unsigned char *)pixels + y * w * channels);
}
libpng_write_t write_data = {
.size = 0,
.capacity = w * h * channels,
.data = malloc(w * h * channels)
};
png_set_rows(png, info, row_pointers);
png_set_write_fn(png, &write_data, libpng_encode_callback, NULL);
png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
png_destroy_write_struct(&png, &info);
*out_len = write_data.size;
return write_data.data;
}
typedef struct {
int pos;
int size;
unsigned char *data;
} libpng_read_t;
void png_decode_callback(png_structp png, png_bytep data, png_size_t length) {
libpng_read_t *read_data = (libpng_read_t*)png_get_io_ptr(png);
if (read_data->pos + length > read_data->size) {
ERROR("PNG read %ld bytes at pos %d (size: %d)", length, read_data->pos, read_data->size);
}
memcpy(data, read_data->data + read_data->pos, length);
read_data->pos += length;
}
void png_warning_callback(png_structp png_ptr, png_const_charp warning_msg) {
// Ignore warnings about sRGB profiles and such.
}
void *libpng_decode(void *data, int size, int *out_w, int *out_h) {
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, png_warning_callback);
if (!png) {
ERROR("png_create_read_struct");
}
png_infop info = png_create_info_struct(png);
if (!info) {
ERROR("png_create_info_struct");
}
libpng_read_t read_data = {
.pos = 0,
.size = size,
.data = data
};
png_set_read_fn(png, &read_data, png_decode_callback);
png_set_sig_bytes(png, 0);
png_read_info(png, info);
png_uint_32 w, h;
int bitDepth, colorType, interlaceType;
png_get_IHDR(png, info, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
// 16 bit -> 8 bit
png_set_strip_16(png);
// 1, 2, 4 bit -> 8 bit
if (bitDepth < 8) {
png_set_packing(png);
}
if (colorType & PNG_COLOR_MASK_PALETTE) {
png_set_expand(png);
}
if (!(colorType & PNG_COLOR_MASK_COLOR)) {
png_set_gray_to_rgb(png);
}
// set paletted or RGB images with transparency to full alpha so we get RGBA
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png);
}
// make sure every pixel has an alpha value
if (!(colorType & PNG_COLOR_MASK_ALPHA)) {
png_set_filler(png, 255, PNG_FILLER_AFTER);
}
png_read_update_info(png, info);
unsigned char* out = malloc(w * h * 4);
*out_w = w;
*out_h = h;
// png_uint_32 rowBytes = png_get_rowbytes(png, info);
png_bytep row_pointers[h];
for (png_uint_32 row = 0; row < h; row++ ) {
row_pointers[row] = (png_bytep)(out + (row * w * 4));
}
png_read_image(png, row_pointers);
png_read_end(png, info);
png_destroy_read_struct( &png, &info, NULL);
return out;
}
// -----------------------------------------------------------------------------
// stb_image encode callback
void stbi_write_callback(void *context, void *data, int size) {
int *encoded_size = (int *)context;
*encoded_size += size;
// In theory we'd need to do another malloc(), memcpy() and free() here to
// be fair to the other decode functions...
}
// -----------------------------------------------------------------------------
// function to load a whole file into memory
void *fload(const char *path, int *out_size) {
FILE *fh = fopen(path, "rb");
if (!fh) {
ERROR("Can't open file");
}
fseek(fh, 0, SEEK_END);
int size = ftell(fh);
fseek(fh, 0, SEEK_SET);
void *buffer = malloc(size);
if (!buffer) {
ERROR("Malloc for %d bytes failed", size);
}
if (!fread(buffer, size, 1, fh)) {
ERROR("Can't read file %s", path);
}
fclose(fh);
*out_size = size;
return buffer;
}
// -----------------------------------------------------------------------------
// benchmark runner
int opt_runs = 1;
int opt_nopng = 0;
int opt_nowarmup = 0;
int opt_noverify = 0;
int opt_nodecode = 0;
int opt_noencode = 0;
int opt_norecurse = 0;
int opt_onlytotals = 0;
enum {
LIBPNG,
STBI,
QOI,
BENCH_COUNT /* must be the last element */
};
static const char *const lib_names[BENCH_COUNT] = {
// NOTE: pad with spaces so everything lines up properly
[LIBPNG] = "libpng: ",
[STBI] = "stbi: ",
[QOI] = "qoi: ",
};
typedef struct {
uint64_t size;
uint64_t encode_time;
uint64_t decode_time;
} benchmark_lib_result_t;
typedef struct {
int count;
uint64_t raw_size;
uint64_t px;
int w;
int h;
benchmark_lib_result_t libs[BENCH_COUNT];
} benchmark_result_t;
void benchmark_print_result(benchmark_result_t res) {
res.px /= res.count;
res.raw_size /= res.count;
double px = res.px;
printf(" decode ms encode ms decode mpps encode mpps size kb rate\n");
for (int i = 0; i < BENCH_COUNT; ++i) {
if (opt_nopng && (i == LIBPNG || i == STBI)) {
continue;
}
res.libs[i].encode_time /= res.count;
res.libs[i].decode_time /= res.count;
res.libs[i].size /= res.count;
printf(
"%s %8.1f %8.1f %8.2f %8.2f %8ld %4.1f%%\n",
lib_names[i],
(double)res.libs[i].decode_time/1000000.0,
(double)res.libs[i].encode_time/1000000.0,
(res.libs[i].decode_time > 0 ? px / ((double)res.libs[i].decode_time/1000.0) : 0),
(res.libs[i].encode_time > 0 ? px / ((double)res.libs[i].encode_time/1000.0) : 0),
res.libs[i].size/1024,
((double)res.libs[i].size/(double)res.raw_size) * 100.0
);
}
printf("\n");
}
// Run __VA_ARGS__ a number of times and measure the time taken. The first
// run is ignored.
#define BENCHMARK_FN(NOWARMUP, RUNS, AVG_TIME, ...) \
do { \
uint64_t time = 0; \
for (int i = NOWARMUP; i <= RUNS; i++) { \
uint64_t time_start = ns(); \
__VA_ARGS__ \
uint64_t time_end = ns(); \
if (i > 0) { \
time += time_end - time_start; \
} \
} \
AVG_TIME = time / RUNS; \
} while (0)
benchmark_result_t benchmark_image(const char *path) {
int encoded_png_size;
int encoded_qoi_size;
int w;
int h;
int channels;
// Load the encoded PNG, encoded QOI and raw pixels into memory
if(!stbi_info(path, &w, &h, &channels)) {
ERROR("Error decoding header %s", path);
}
if (channels != 3) {
channels = 4;
}
void *pixels = (void *)stbi_load(path, &w, &h, NULL, channels);
void *encoded_png = fload(path, &encoded_png_size);
void *encoded_qoi = qoi_encode(pixels, &(qoi_desc){
.width = w,
.height = h,
.channels = channels,
.colorspace = QOI_SRGB
}, &encoded_qoi_size);
if (!pixels || !encoded_qoi || !encoded_png) {
ERROR("Error encoding %s", path);
}
// Verify QOI Output
if (!opt_noverify) {
qoi_desc dc;
void *pixels_qoi = qoi_decode(encoded_qoi, encoded_qoi_size, &dc, channels);
if (memcmp(pixels, pixels_qoi, w * h * channels) != 0) {
ERROR("QOI roundtrip pixel mismatch for %s", path);
}
free(pixels_qoi);
}
benchmark_result_t res = {0};
res.count = 1;
res.raw_size = w * h * channels;
res.px = w * h;
res.w = w;
res.h = h;
// Decoding
if (!opt_nodecode) {
if (!opt_nopng) {
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[LIBPNG].decode_time, {
int dec_w, dec_h;
void *dec_p = libpng_decode(encoded_png, encoded_png_size, &dec_w, &dec_h);
free(dec_p);
});
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[STBI].decode_time, {
int dec_w, dec_h, dec_channels;
void *dec_p = stbi_load_from_memory(encoded_png, encoded_png_size, &dec_w, &dec_h, &dec_channels, 4);
free(dec_p);
});
}
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[QOI].decode_time, {
qoi_desc desc;
void *dec_p = qoi_decode(encoded_qoi, encoded_qoi_size, &desc, 4);
free(dec_p);
});
}
// Encoding
if (!opt_noencode) {
if (!opt_nopng) {
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[LIBPNG].encode_time, {
int enc_size;
void *enc_p = libpng_encode(pixels, w, h, channels, &enc_size);
res.libs[LIBPNG].size = enc_size;
free(enc_p);
});
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[STBI].encode_time, {
int enc_size = 0;
stbi_write_png_to_func(stbi_write_callback, &enc_size, w, h, channels, pixels, 0);
res.libs[STBI].size = enc_size;
});
}
BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[QOI].encode_time, {
int enc_size;
void *enc_p = qoi_encode(pixels, &(qoi_desc){
.width = w,
.height = h,
.channels = channels,
.colorspace = QOI_SRGB
}, &enc_size);
res.libs[QOI].size = enc_size;
free(enc_p);
});
}
free(pixels);
free(encoded_png);
free(encoded_qoi);
return res;
}
void benchmark_directory(const char *path, benchmark_result_t *grand_total) {
DIR *dir = opendir(path);
if (!dir) {
ERROR("Couldn't open directory %s", path);
}
struct dirent *file;
if (!opt_norecurse) {
for (int i = 0; (file = readdir(dir)) != NULL; i++) {
if (
file->d_type & DT_DIR &&
strcmp(file->d_name, ".") != 0 &&
strcmp(file->d_name, "..") != 0
) {
char subpath[1024];
snprintf(subpath, 1024, "%s/%s", path, file->d_name);
benchmark_directory(subpath, grand_total);
}
}
rewinddir(dir);
}
benchmark_result_t dir_total = {0};
int has_shown_head = 0;
for (int i = 0; (file = readdir(dir)) != NULL; i++) {
if (strcmp(file->d_name + strlen(file->d_name) - 4, ".png") != 0) {
continue;
}
if (!has_shown_head) {
has_shown_head = 1;
printf("## Benchmarking %s/*.png -- %d runs\n\n", path, opt_runs);
}
char *file_path = malloc(strlen(file->d_name) + strlen(path)+8);
sprintf(file_path, "%s/%s", path, file->d_name);
benchmark_result_t res = benchmark_image(file_path);
if (!opt_onlytotals) {
printf("## %s size: %dx%d\n", file_path, res.w, res.h);
benchmark_print_result(res);
}
free(file_path);
dir_total.count++;
dir_total.raw_size += res.raw_size;
dir_total.px += res.px;
for (int i = 0; i < BENCH_COUNT; ++i) {
dir_total.libs[i].encode_time += res.libs[i].encode_time;
dir_total.libs[i].decode_time += res.libs[i].decode_time;
dir_total.libs[i].size += res.libs[i].size;
}
grand_total->count++;
grand_total->raw_size += res.raw_size;
grand_total->px += res.px;
for (int i = 0; i < BENCH_COUNT; ++i) {
grand_total->libs[i].encode_time += res.libs[i].encode_time;
grand_total->libs[i].decode_time += res.libs[i].decode_time;
grand_total->libs[i].size += res.libs[i].size;
}
}
closedir(dir);
if (dir_total.count > 0) {
printf("## Total for %s\n", path);
benchmark_print_result(dir_total);
}
}
int main(int argc, char **argv) {
if (argc < 3) {
printf("Usage: qoibench <iterations> <directory> [options]\n");
printf("Options:\n");
printf(" --nowarmup ... don't perform a warmup run\n");
printf(" --nopng ...... don't run png encode/decode\n");
printf(" --noverify ... don't verify qoi roundtrip\n");
printf(" --noencode ... don't run encoders\n");
printf(" --nodecode ... don't run decoders\n");
printf(" --norecurse .. don't descend into directories\n");
printf(" --onlytotals . don't print individual image results\n");
printf("Examples\n");
printf(" qoibench 10 images/textures/\n");
printf(" qoibench 1 images/textures/ --nopng --nowarmup\n");
exit(1);
}
for (int i = 3; i < argc; i++) {
if (strcmp(argv[i], "--nowarmup") == 0) { opt_nowarmup = 1; }
else if (strcmp(argv[i], "--nopng") == 0) { opt_nopng = 1; }
else if (strcmp(argv[i], "--noverify") == 0) { opt_noverify = 1; }
else if (strcmp(argv[i], "--noencode") == 0) { opt_noencode = 1; }
else if (strcmp(argv[i], "--nodecode") == 0) { opt_nodecode = 1; }
else if (strcmp(argv[i], "--norecurse") == 0) { opt_norecurse = 1; }
else if (strcmp(argv[i], "--onlytotals") == 0) { opt_onlytotals = 1; }
else { ERROR("Unknown option %s", argv[i]); }
}
opt_runs = atoi(argv[1]);
if (opt_runs <=0) {
ERROR("Invalid number of runs %d", opt_runs);
}
benchmark_result_t grand_total = {0};
benchmark_directory(argv[2], &grand_total);
if (grand_total.count > 0) {
printf("# Grand total for %s\n", argv[2]);
benchmark_print_result(grand_total);
}
else {
printf("No images found in %s\n", argv[2]);
}
return 0;
}

91
external/qoi/qoi/qoiconv.c vendored Normal file
View File

@ -0,0 +1,91 @@
/*
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
SPDX-License-Identifier: MIT
Command line tool to convert between png <> qoi format
Requires:
-"stb_image.h" (https://github.com/nothings/stb/blob/master/stb_image.h)
-"stb_image_write.h" (https://github.com/nothings/stb/blob/master/stb_image_write.h)
-"qoi.h" (https://github.com/phoboslab/qoi/blob/master/qoi.h)
Compile with:
gcc qoiconv.c -std=c99 -O3 -o qoiconv
*/
#define STB_IMAGE_IMPLEMENTATION
#define STBI_ONLY_PNG
#define STBI_NO_LINEAR
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define QOI_IMPLEMENTATION
#include "qoi.h"
#define STR_ENDS_WITH(S, E) (strcmp(S + strlen(S) - (sizeof(E)-1), E) == 0)
int main(int argc, char **argv) {
if (argc < 3) {
puts("Usage: qoiconv <infile> <outfile>");
puts("Examples:");
puts(" qoiconv input.png output.qoi");
puts(" qoiconv input.qoi output.png");
exit(1);
}
void *pixels = NULL;
int w, h, channels;
if (STR_ENDS_WITH(argv[1], ".png")) {
if(!stbi_info(argv[1], &w, &h, &channels)) {
printf("Couldn't read header %s\n", argv[1]);
exit(1);
}
// Force all odd encodings to be RGBA
if(channels != 3) {
channels = 4;
}
pixels = (void *)stbi_load(argv[1], &w, &h, NULL, channels);
}
else if (STR_ENDS_WITH(argv[1], ".qoi")) {
qoi_desc desc;
pixels = qoi_read(argv[1], &desc, 0);
channels = desc.channels;
w = desc.width;
h = desc.height;
}
if (pixels == NULL) {
printf("Couldn't load/decode %s\n", argv[1]);
exit(1);
}
int encoded = 0;
if (STR_ENDS_WITH(argv[2], ".png")) {
encoded = stbi_write_png(argv[2], w, h, channels, pixels, 0);
}
else if (STR_ENDS_WITH(argv[2], ".qoi")) {
encoded = qoi_write(argv[2], pixels, &(qoi_desc){
.width = w,
.height = h,
.channels = channels,
.colorspace = QOI_SRGB
});
}
if (!encoded) {
printf("Couldn't write/encode %s\n", argv[2]);
exit(1);
}
free(pixels);
return 0;
}

32
external/qoi/qoi/qoifuzz.c vendored Normal file
View File

@ -0,0 +1,32 @@
/*
Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
SPDX-License-Identifier: MIT
clang fuzzing harness for qoi_decode
Compile and run with:
clang -fsanitize=address,fuzzer -g -O0 qoifuzz.c && ./a.out
*/
#define QOI_IMPLEMENTATION
#include "qoi.h"
#include <stddef.h>
#include <stdint.h>
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
int w, h;
if (size < 4) {
return 0;
}
qoi_desc desc;
void* decoded = qoi_decode((void*)(data + 4), (int)(size - 4), &desc, *((int *)data));
if (decoded != NULL) {
free(decoded);
}
return 0;
}

View File

@ -25,6 +25,8 @@ add_executable(tomato
./image_loader_stb.cpp ./image_loader_stb.cpp
./image_loader_webp.hpp ./image_loader_webp.hpp
./image_loader_webp.cpp ./image_loader_webp.cpp
./image_loader_qoi.hpp
./image_loader_qoi.cpp
./texture_uploader.hpp ./texture_uploader.hpp
./sdlrenderer_texture_uploader.hpp ./sdlrenderer_texture_uploader.hpp
@ -90,5 +92,6 @@ target_link_libraries(tomato PUBLIC
stb_image_write stb_image_write
webpdemux webpdemux
libwebpmux # the f why (needed for anim encode) libwebpmux # the f why (needed for anim encode)
qoi
) )

View File

@ -613,6 +613,7 @@ float ChatGui4::render(float time_delta) {
"image/gif", "image/gif",
"image/jpeg", "image/jpeg",
"image/bmp", "image/bmp",
"image/qoi",
}; };
for (const char* mime_type : image_mime_types) { for (const char* mime_type : image_mime_types) {

91
src/image_loader_qoi.cpp Normal file
View File

@ -0,0 +1,91 @@
#include "./image_loader_qoi.hpp"
#include <cstdint>
#include <qoi/qoi.h>
#include <iostream>
ImageLoaderQOI::ImageInfo ImageLoaderQOI::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) {
ImageInfo res;
qoi_desc desc;
// TODO: only read the header
auto* ret = qoi_decode(data, data_size, &desc, 4);
if (ret == nullptr) {
return res;
}
free(ret);
res.width = desc.width;
res.height = desc.height;
//desc.colorspace;
return res;
}
ImageLoaderQOI::ImageResult ImageLoaderQOI::loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) {
ImageResult res;
qoi_desc desc;
uint8_t* img_data = static_cast<uint8_t*>(
qoi_decode(data, data_size, &desc, 4)
);
if (img_data == nullptr) {
// not readable
return res;
}
res.width = desc.width;
res.height = desc.height;
auto& new_frame = res.frames.emplace_back();
new_frame.ms = 0;
new_frame.data.insert(new_frame.data.cbegin(), img_data, img_data+(desc.width*desc.height*4));
free(img_data);
return res;
}
std::vector<uint8_t> ImageEncoderQOI::encodeToMemoryRGBA(const ImageResult& input_image, const std::map<std::string, float>&) {
if (input_image.frames.empty()) {
std::cerr << "IEQOI error: empty image\n";
return {};
}
if (input_image.frames.size() > 1) {
std::cerr << "IEQOI warning: image with animation, only first frame will be encoded!\n";
return {};
}
// TODO: look into RDO (eg https://github.com/richgel999/rdopng)
//int png_compression_level = 8;
//if (extra_options.count("png_compression_level")) {
//png_compression_level = extra_options.at("png_compression_level");
//}
qoi_desc desc;
desc.width = input_image.width;
desc.height = input_image.height;
desc.channels = 4;
desc.colorspace = QOI_SRGB; // TODO: decide
int out_len {0};
uint8_t* enc_data = static_cast<uint8_t*>(qoi_encode(
input_image.frames.front().data.data(),
&desc,
&out_len
));
if (enc_data == nullptr) {
std::cerr << "IEQOI error: qoi_encode failed!\n";
return {};
}
std::vector<uint8_t> new_data(enc_data, enc_data+out_len);
free(enc_data); // TODO: a streaming encoder would be better
return new_data;
}

13
src/image_loader_qoi.hpp Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "./image_loader.hpp"
struct ImageLoaderQOI : public ImageLoaderI {
ImageInfo loadInfoFromMemory(const uint8_t* data, uint64_t data_size) override;
ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) override;
};
struct ImageEncoderQOI : public ImageEncoderI {
std::vector<uint8_t> encodeToMemoryRGBA(const ImageResult& input_image, const std::map<std::string, float>& extra_options = {}) override;
};

View File

@ -2,6 +2,7 @@
#include "./image_loader_webp.hpp" #include "./image_loader_webp.hpp"
#include "./image_loader_sdl_bmp.hpp" #include "./image_loader_sdl_bmp.hpp"
#include "./image_loader_qoi.hpp"
#include "./image_loader_stb.hpp" #include "./image_loader_stb.hpp"
#include <solanaceae/message3/components.hpp> #include <solanaceae/message3/components.hpp>
@ -77,6 +78,7 @@ MediaMetaInfoLoader::MediaMetaInfoLoader(RegistryMessageModel& rmm) : _rmm(rmm)
// HACK: make them be added externally? // HACK: make them be added externally?
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>()); _image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct); _rmm.subscribe(this, RegistryMessageModel_Event::message_construct);

View File

@ -1,6 +1,7 @@
#include "./message_image_loader.hpp" #include "./message_image_loader.hpp"
#include "./image_loader_sdl_bmp.hpp" #include "./image_loader_sdl_bmp.hpp"
#include "./image_loader_qoi.hpp"
#include "./image_loader_stb.hpp" #include "./image_loader_stb.hpp"
#include "./image_loader_webp.hpp" #include "./image_loader_webp.hpp"
#include "./media_meta_info_loader.hpp" #include "./media_meta_info_loader.hpp"
@ -19,6 +20,7 @@ uint64_t getTimeMS(void);
MessageImageLoader::MessageImageLoader(void) { MessageImageLoader::MessageImageLoader(void) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>()); _image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
} }

View File

@ -3,6 +3,7 @@
#include "./image_loader_sdl_bmp.hpp" #include "./image_loader_sdl_bmp.hpp"
#include "./image_loader_stb.hpp" #include "./image_loader_stb.hpp"
#include "./image_loader_webp.hpp" #include "./image_loader_webp.hpp"
#include "./image_loader_qoi.hpp"
#include <imgui/imgui.h> #include <imgui/imgui.h>
@ -13,6 +14,7 @@ uint64_t getTimeMS(void);
SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) { SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>()); _image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
} }
@ -421,7 +423,7 @@ void SendImagePopup::render(float time_delta) {
if (compress) { if (compress) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Combo("##compression_type", &current_compressor, "webp\0jpeg\0png\n"); ImGui::Combo("##compression_type", &current_compressor, "webp\0jpeg\0png\0qoi\0");
ImGui::Indent(); ImGui::Indent();
// combo "webp""webp-lossless""png""jpg?" // combo "webp""webp-lossless""png""jpg?"
@ -486,6 +488,11 @@ void SendImagePopup::render(float time_delta) {
if (!new_data.empty()) { if (!new_data.empty()) {
_on_send(new_data, ".png"); _on_send(new_data, ".png");
} }
} else if (current_compressor == 3) {
new_data = ImageEncoderQOI{}.encodeToMemoryRGBA(tmp_img, {});;
if (!new_data.empty()) {
_on_send(new_data, ".qoi");
}
} }
// error // error

View File

@ -1,6 +1,7 @@
#include "./tox_avatar_loader.hpp" #include "./tox_avatar_loader.hpp"
#include "./image_loader_sdl_bmp.hpp" #include "./image_loader_sdl_bmp.hpp"
#include "./image_loader_qoi.hpp"
#include "./image_loader_stb.hpp" #include "./image_loader_stb.hpp"
#include "./image_loader_webp.hpp" #include "./image_loader_webp.hpp"
@ -21,6 +22,7 @@ uint64_t getTimeMS(void);
ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) { ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>()); _image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
} }