diff options
Diffstat (limited to 'vendor/qoi/ext')
-rw-r--r-- | vendor/qoi/ext/qoi/README.md | 92 | ||||
-rw-r--r-- | vendor/qoi/ext/qoi/qoi.h | 671 | ||||
-rw-r--r-- | vendor/qoi/ext/qoi/qoibench.c | 650 | ||||
-rw-r--r-- | vendor/qoi/ext/qoi/qoiconv.c | 106 | ||||
-rw-r--r-- | vendor/qoi/ext/qoi/qoifuzz.c | 51 |
5 files changed, 0 insertions, 1570 deletions
diff --git a/vendor/qoi/ext/qoi/README.md b/vendor/qoi/ext/qoi/README.md deleted file mode 100644 index 702c342..0000000 --- a/vendor/qoi/ext/qoi/README.md +++ /dev/null @@ -1,92 +0,0 @@ -![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 - - -## 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. - - -## Tools - -- https://github.com/floooh/qoiview - native QOI viewer -- https://github.com/pfusik/qoi-ci/releases/tag/qoi-ci-1.1.0 - QOI Plugin installer for GIMP, Imagine, Paint.NET and XnView MP -- https://github.com/iOrange/QoiFileTypeNet/releases/tag/v0.2 - QOI Plugin for Paint.NET -- https://github.com/iOrange/QOIThumbnailProvider - Add thumbnails for QOI images in Windows Explorer -- https://github.com/Tom94/tev - another native QOI viewer (allows pixel peeping and comparison with other image formats) - - -## Implementations & Bindings of QOI - -- https://github.com/pfusik/qoi-ci (Ć, transpiled to C, C++, C#, Java, JavaScript, Python and Swift) -- https://github.com/kodonnell/qoi (Python) -- https://github.com/Cr4xy/lua-qoi (Lua) -- https://github.com/superzazu/SDL_QOI (C, SDL2 bindings) -- https://github.com/saharNooby/qoi-java (Java) -- https://github.com/MasterQ32/zig-qoi (Zig) -- https://github.com/rbino/qoix (Elixir) -- https://github.com/NUlliiON/QoiSharp (C#) -- https://github.com/zakarumych/rapid-qoi (Rust) -- https://github.com/takeyourhatoff/qoi (Go) -- https://github.com/DosWorld/pasqoi (Pascal) -- https://github.com/elihwyma/Swift-QOI (Swift) -- https://github.com/xfmoulet/qoi (Go) -- https://erratique.ch/software/qoic (OCaml) - - -## QOI Support in Other Software - -- [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 - - -## Packages - -[AUR](https://aur.archlinux.org/pkgbase/qoi-git/) - system-wide qoi.h, qoiconv and qoibench install as split packages. - - -## Implementations not yet conforming to the final specification - -These implementations are based on the pre-release version of QOI. Resulting files are not compatible with the current version. - -- https://github.com/steven-joruk/qoi (Rust) -- https://github.com/ChevyRay/qoi_rs (Rust) -- https://github.com/panzi/jsqoi (TypeScript) -- https://github.com/0xd34df00d/hsqoi (Haskell) - diff --git a/vendor/qoi/ext/qoi/qoi.h b/vendor/qoi/ext/qoi/qoi.h deleted file mode 100644 index 7addd70..0000000 --- a/vendor/qoi/ext/qoi/qoi.h +++ /dev/null @@ -1,671 +0,0 @@ -/* - -QOI - The "Quite OK Image" format for fast, lossless image compression - -Dominic Szablewski - https://phoboslab.org - - --- LICENSE: The MIT License(MIT) - -Copyright(c) 2021 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. - - --- 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 7 or more consecutive QOI_OP_INDEX chunks to the -index 0, to avoid confusion with the 8 byte end marker. - - -.- 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 = (last_px.r - cur_px.r) - (last_px.g - cur_px.g) - db_dg = (last_px.b - cur_px.b) - (last_px.g - cur_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 -en-/decoding in any way. */ - -#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) { - if (channels == 4) { - px = *(qoi_rgba_t *)(pixels + px_pos); - } - else { - px.rgba.r = pixels[px_pos + 0]; - px.rgba.g = pixels[px_pos + 1]; - px.rgba.b = pixels[px_pos + 2]; - } - - 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; - } - - if (channels == 4) { - *(qoi_rgba_t*)(pixels + px_pos) = px; - } - else { - pixels[px_pos + 0] = px.rgba.r; - pixels[px_pos + 1] = px.rgba.g; - pixels[px_pos + 2] = px.rgba.b; - } - } - - 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; - void *encoded; - - if (!f) { - return 0; - } - - encoded = qoi_encode(data, desc, &size); - if (!encoded) { - fclose(f); - return 0; - } - - fwrite(encoded, 1, size, f); - fclose(f); - - QOI_FREE(encoded); - return 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) { - fclose(f); - return NULL; - } - fseek(f, 0, SEEK_SET); - - data = QOI_MALLOC(size); - if (!data) { - fclose(f); - return NULL; - } - - bytes_read = fread(data, 1, size, f); - fclose(f); - - pixels = qoi_decode(data, bytes_read, desc, channels); - QOI_FREE(data); - return pixels; -} - -#endif /* QOI_NO_STDIO */ -#endif /* QOI_IMPLEMENTATION */ diff --git a/vendor/qoi/ext/qoi/qoibench.c b/vendor/qoi/ext/qoi/qoibench.c deleted file mode 100644 index 2c3df68..0000000 --- a/vendor/qoi/ext/qoi/qoibench.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - -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 - -Dominic Szablewski - https://phoboslab.org - - --- LICENSE: The MIT License(MIT) - -Copyright(c) 2021 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. - -*/ - -#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 %d 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; - - -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 libpng; - benchmark_lib_result_t stbi; - benchmark_lib_result_t qoi; -} benchmark_result_t; - - -void benchmark_print_result(benchmark_result_t res) { - res.px /= res.count; - res.raw_size /= res.count; - res.libpng.encode_time /= res.count; - res.libpng.decode_time /= res.count; - res.libpng.size /= res.count; - res.stbi.encode_time /= res.count; - res.stbi.decode_time /= res.count; - res.stbi.size /= res.count; - res.qoi.encode_time /= res.count; - res.qoi.decode_time /= res.count; - res.qoi.size /= res.count; - - double px = res.px; - printf(" decode ms encode ms decode mpps encode mpps size kb rate\n"); - if (!opt_nopng) { - printf( - "libpng: %8.1f %8.1f %8.2f %8.2f %8d %4.1f%%\n", - (double)res.libpng.decode_time/1000000.0, - (double)res.libpng.encode_time/1000000.0, - (res.libpng.decode_time > 0 ? px / ((double)res.libpng.decode_time/1000.0) : 0), - (res.libpng.encode_time > 0 ? px / ((double)res.libpng.encode_time/1000.0) : 0), - res.libpng.size/1024, - ((double)res.libpng.size/(double)res.raw_size) * 100.0 - ); - printf( - "stbi: %8.1f %8.1f %8.2f %8.2f %8d %4.1f%%\n", - (double)res.stbi.decode_time/1000000.0, - (double)res.stbi.encode_time/1000000.0, - (res.stbi.decode_time > 0 ? px / ((double)res.stbi.decode_time/1000.0) : 0), - (res.stbi.encode_time > 0 ? px / ((double)res.stbi.encode_time/1000.0) : 0), - res.stbi.size/1024, - ((double)res.stbi.size/(double)res.raw_size) * 100.0 - ); - } - printf( - "qoi: %8.1f %8.1f %8.2f %8.2f %8d %4.1f%%\n", - (double)res.qoi.decode_time/1000000.0, - (double)res.qoi.encode_time/1000000.0, - (res.qoi.decode_time > 0 ? px / ((double)res.qoi.decode_time/1000.0) : 0), - (res.qoi.encode_time > 0 ? px / ((double)res.qoi.encode_time/1000.0) : 0), - res.qoi.size/1024, - ((double)res.qoi.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 decoding %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.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.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.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.libpng.encode_time, { - int enc_size; - void *enc_p = libpng_encode(pixels, w, h, channels, &enc_size); - res.libpng.size = enc_size; - free(enc_p); - }); - - BENCHMARK_FN(opt_nowarmup, opt_runs, res.stbi.encode_time, { - int enc_size = 0; - stbi_write_png_to_func(stbi_write_callback, &enc_size, w, h, channels, pixels, 0); - res.stbi.size = enc_size; - }); - } - - BENCHMARK_FN(opt_nowarmup, opt_runs, res.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.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); - } - - float total_percentage = 0; - int total_size = 0; - - 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; - dir_total.libpng.encode_time += res.libpng.encode_time; - dir_total.libpng.decode_time += res.libpng.decode_time; - dir_total.libpng.size += res.libpng.size; - dir_total.stbi.encode_time += res.stbi.encode_time; - dir_total.stbi.decode_time += res.stbi.decode_time; - dir_total.stbi.size += res.stbi.size; - dir_total.qoi.encode_time += res.qoi.encode_time; - dir_total.qoi.decode_time += res.qoi.decode_time; - dir_total.qoi.size += res.qoi.size; - - grand_total->count++; - grand_total->raw_size += res.raw_size; - grand_total->px += res.px; - grand_total->libpng.encode_time += res.libpng.encode_time; - grand_total->libpng.decode_time += res.libpng.decode_time; - grand_total->libpng.size += res.libpng.size; - grand_total->stbi.encode_time += res.stbi.encode_time; - grand_total->stbi.decode_time += res.stbi.decode_time; - grand_total->stbi.size += res.stbi.size; - grand_total->qoi.encode_time += res.qoi.encode_time; - grand_total->qoi.decode_time += res.qoi.decode_time; - grand_total->qoi.size += res.qoi.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; -} diff --git a/vendor/qoi/ext/qoi/qoiconv.c b/vendor/qoi/ext/qoi/qoiconv.c deleted file mode 100644 index 79aa75c..0000000 --- a/vendor/qoi/ext/qoi/qoiconv.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - -Command line tool to convert between png <> qoi format - -Requires "stb_image.h" and "stb_image_write.h" -Compile with: - gcc qoiconv.c -std=c99 -O3 -o qoiconv - -Dominic Szablewski - https://phoboslab.org - - --- LICENSE: The MIT License(MIT) - -Copyright(c) 2021 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. - -*/ - - -#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; -} diff --git a/vendor/qoi/ext/qoi/qoifuzz.c b/vendor/qoi/ext/qoi/qoifuzz.c deleted file mode 100644 index 1b5c792..0000000 --- a/vendor/qoi/ext/qoi/qoifuzz.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - -clang fuzzing harness for qoi_decode - -Compile and run with: - clang -fsanitize=address,fuzzer -g -O0 qoifuzz.c && ./a.out - -Dominic Szablewski - https://phoboslab.org - - --- LICENSE: The MIT License(MIT) - -Copyright(c) 2021 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. - -*/ - - -#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; -} |