@@ -28,8 +28,8 @@ SOFTWARE.
28
28
29
29
-- About
30
30
31
- QOI encodes and decodes images in a lossless format. Compared to stb_image and
32
- stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
31
+ QOI encodes and decodes images in a lossless format. Compared to stb_image and
32
+ stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
33
33
20% better compression.
34
34
35
35
@@ -45,7 +45,7 @@ stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
45
45
// the input pixel data.
46
46
qoi_write("image_new.qoi", rgba_pixels, &(qoi_desc){
47
47
.width = 1920,
48
- .height = 1080,
48
+ .height = 1080,
49
49
.channels = 4,
50
50
.colorspace = QOI_SRGB
51
51
});
@@ -74,7 +74,7 @@ QOI_NO_STDIO before including this library.
74
74
This library uses malloc() and free(). To supply your own malloc implementation
75
75
you can define QOI_MALLOC and QOI_FREE before including this library.
76
76
77
- This library uses memset() to zero-initialize the index. To supply your own
77
+ This library uses memset() to zero-initialize the index. To supply your own
78
78
implementation you can define QOI_ZEROARR before including this library.
79
79
80
80
@@ -91,8 +91,8 @@ struct qoi_header_t {
91
91
uint8_t colorspace; // 0 = sRGB with linear alpha, 1 = all channels linear
92
92
};
93
93
94
- Images are encoded row by row, left to right, top to bottom. The decoder and
95
- encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
94
+ Images are encoded row by row, left to right, top to bottom. The decoder and
95
+ encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
96
96
image is complete when all pixels specified by width * height have been covered.
97
97
98
98
Pixels are encoded as
@@ -101,20 +101,20 @@ Pixels are encoded as
101
101
- a difference to the previous pixel value in r,g,b
102
102
- full r,g,b or r,g,b,a values
103
103
104
- The color channels are assumed to not be premultiplied with the alpha channel
104
+ The color channels are assumed to not be premultiplied with the alpha channel
105
105
("un-premultiplied alpha").
106
106
107
- A running array[64] (zero-initialized) of previously seen pixel values is
107
+ A running array[64] (zero-initialized) of previously seen pixel values is
108
108
maintained by the encoder and decoder. Each pixel that is seen by the encoder
109
109
and decoder is put into this array at the position formed by a hash function of
110
110
the color value. In the encoder, if the pixel value at the index matches the
111
- current pixel, this index position is written to the stream as QOI_OP_INDEX.
111
+ current pixel, this index position is written to the stream as QOI_OP_INDEX.
112
112
The hash function for the index is:
113
113
114
114
index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
115
115
116
- Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
117
- bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
116
+ Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
117
+ bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
118
118
values encoded in these data bits have the most significant bit on the left.
119
119
120
120
The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the
@@ -136,10 +136,10 @@ The possible chunks are:
136
136
6-bit index into the color index array: 0..63
137
137
138
138
A valid encoder must not issue 7 or more consecutive QOI_OP_INDEX chunks to the
139
- index 0, to avoid confusion with the 8 byte end marker.
139
+ index 0, to avoid confusion with the 8 byte end marker.
140
140
141
141
142
- .- QOI_OP_DIFF -----------.
142
+ .- QOI_OP_DIFF -----------.
143
143
| Byte[0] |
144
144
| 7 6 5 4 3 2 1 0 |
145
145
|-------+-----+-----+-----|
@@ -150,16 +150,16 @@ index 0, to avoid confusion with the 8 byte end marker.
150
150
2-bit green channel difference from the previous pixel between -2..1
151
151
2-bit blue channel difference from the previous pixel between -2..1
152
152
153
- The difference to the current channel values are using a wraparound operation,
153
+ The difference to the current channel values are using a wraparound operation,
154
154
so "1 - 2" will result in 255, while "255 + 1" will result in 0.
155
155
156
- Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as
156
+ Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as
157
157
0 (b00). 1 is stored as 3 (b11).
158
158
159
159
The alpha value remains unchanged from the previous pixel.
160
160
161
161
162
- .- QOI_OP_LUMA -------------------------------------.
162
+ .- QOI_OP_LUMA -------------------------------------.
163
163
| Byte[0] | Byte[1] |
164
164
| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
165
165
|-------+-----------------+-------------+-----------|
@@ -170,16 +170,16 @@ The alpha value remains unchanged from the previous pixel.
170
170
4-bit red channel difference minus green channel difference -8..7
171
171
4-bit blue channel difference minus green channel difference -8..7
172
172
173
- The green channel is used to indicate the general direction of change and is
173
+ The green channel is used to indicate the general direction of change and is
174
174
encoded in 6 bits. The red and blue channels (dr and db) base their diffs off
175
175
of the green channel difference and are encoded in 4 bits. I.e.:
176
176
dr_dg = (last_px.r - cur_px.r) - (last_px.g - cur_px.g)
177
177
db_dg = (last_px.b - cur_px.b) - (last_px.g - cur_px.g)
178
178
179
- The difference to the current channel values are using a wraparound operation,
179
+ The difference to the current channel values are using a wraparound operation,
180
180
so "10 - 13" will result in 253, while "250 + 7" will result in 1.
181
181
182
- Values are stored as unsigned integers with a bias of 32 for the green channel
182
+ Values are stored as unsigned integers with a bias of 32 for the green channel
183
183
and a bias of 8 for the red and blue channel.
184
184
185
185
The alpha value remains unchanged from the previous pixel.
@@ -194,8 +194,8 @@ The alpha value remains unchanged from the previous pixel.
194
194
2-bit tag b11
195
195
6-bit run-length repeating the previous pixel: 1..62
196
196
197
- The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
198
- (b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
197
+ The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
198
+ (b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
199
199
QOI_OP_RGBA tags.
200
200
201
201
@@ -238,15 +238,15 @@ Header - Public functions */
238
238
extern "C" {
239
239
#endif
240
240
241
- /* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions.
242
- It describes either the input format (for qoi_write and qoi_encode), or is
241
+ /* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions.
242
+ It describes either the input format (for qoi_write and qoi_encode), or is
243
243
filled with the description read from the file header (for qoi_read and
244
244
qoi_decode).
245
245
246
- The colorspace in this qoi_desc is an enum where
246
+ The colorspace in this qoi_desc is an enum where
247
247
0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel
248
248
1 = all channels are linear
249
- You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
249
+ You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
250
250
informative. It will be saved to the file header, but does not affect
251
251
en-/decoding in any way. */
252
252
@@ -262,11 +262,11 @@ typedef struct {
262
262
263
263
#ifndef QOI_NO_STDIO
264
264
265
- /* Encode raw RGB or RGBA pixels into a QOI image and write it to the file
266
- system. The qoi_desc struct must be filled with the image width, height,
267
- number of channels (3 = RGB, 4 = RGBA) and the colorspace.
265
+ /* Encode raw RGB or RGBA pixels into a QOI image and write it to the file
266
+ system. The qoi_desc struct must be filled with the image width, height,
267
+ number of channels (3 = RGB, 4 = RGBA) and the colorspace.
268
268
269
- The function returns 0 on failure (invalid parameters, or fopen or malloc
269
+ The function returns 0 on failure (invalid parameters, or fopen or malloc
270
270
failed) or the number of bytes written on success. */
271
271
272
272
int qoi_write (const char * filename , const void * data , const qoi_desc * desc );
@@ -277,7 +277,7 @@ number of channels from the file header is used. If channels is 3 or 4 the
277
277
output format will be forced into this number of channels.
278
278
279
279
The function either returns NULL on failure (invalid data, or malloc or fopen
280
- failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
280
+ failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
281
281
will be filled with the description from the file header.
282
282
283
283
The returned pixel data should be free()d after use. */
@@ -289,8 +289,8 @@ void *qoi_read(const char *filename, qoi_desc *desc, int channels);
289
289
290
290
/* Encode raw RGB or RGBA pixels into a QOI image in memory.
291
291
292
- The function either returns NULL on failure (invalid parameters or malloc
293
- failed) or a pointer to the encoded data on success. On success the out_len
292
+ The function either returns NULL on failure (invalid parameters or malloc
293
+ failed) or a pointer to the encoded data on success. On success the out_len
294
294
is set to the size in bytes of the encoded data.
295
295
296
296
The returned qoi data should be free()d after use. */
@@ -300,8 +300,8 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len);
300
300
301
301
/* Decode a QOI image from memory.
302
302
303
- The function either returns NULL on failure (invalid parameters or malloc
304
- failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
303
+ The function either returns NULL on failure (invalid parameters or malloc
304
+ failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
305
305
is filled with the description from the file header.
306
306
307
307
The returned pixel data should be free()d after use. */
@@ -346,8 +346,8 @@ Implementation */
346
346
#define QOI_HEADER_SIZE 14
347
347
348
348
/* 2GB is the max file size that this implementation can safely handle. We guard
349
- against anything larger than that, assuming the worst case with 5 bytes per
350
- pixel, rounded down to a nice clean value. 400 million pixels ought to be
349
+ against anything larger than that, assuming the worst case with 5 bytes per
350
+ pixel, rounded down to a nice clean value. 400 million pixels ought to be
351
351
enough for anybody. */
352
352
#define QOI_PIXELS_MAX ((unsigned int)400000000)
353
353
@@ -391,8 +391,8 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
391
391
return NULL ;
392
392
}
393
393
394
- max_size =
395
- desc -> width * desc -> height * (desc -> channels + 1 ) +
394
+ max_size =
395
+ desc -> width * desc -> height * (desc -> channels + 1 ) +
396
396
QOI_HEADER_SIZE + sizeof (qoi_padding );
397
397
398
398
p = 0 ;
@@ -418,7 +418,7 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
418
418
px_prev .rgba .b = 0 ;
419
419
px_prev .rgba .a = 255 ;
420
420
px = px_prev ;
421
-
421
+
422
422
px_len = desc -> width * desc -> height * desc -> channels ;
423
423
px_end = px_len - desc -> channels ;
424
424
channels = desc -> channels ;
@@ -466,14 +466,14 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
466
466
467
467
if (
468
468
vr > -3 && vr < 2 &&
469
- vg > -3 && vg < 2 &&
469
+ vg > -3 && vg < 2 &&
470
470
vb > -3 && vb < 2
471
471
) {
472
472
bytes [p ++ ] = QOI_OP_DIFF | (vr + 2 ) << 4 | (vg + 2 ) << 2 | (vb + 2 );
473
473
}
474
474
else if (
475
- vg_r > -9 && vg_r < 8 &&
476
- vg > -33 && vg < 32 &&
475
+ vg_r > -9 && vg_r < 8 &&
476
+ vg > -33 && vg < 32 &&
477
477
vg_b > -9 && vg_b < 8
478
478
) {
479
479
bytes [p ++ ] = QOI_OP_LUMA | (vg + 32 );
@@ -532,7 +532,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
532
532
desc -> colorspace = bytes [p ++ ];
533
533
534
534
if (
535
- desc -> width == 0 || desc -> height == 0 ||
535
+ desc -> width == 0 || desc -> height == 0 ||
536
536
desc -> channels < 3 || desc -> channels > 4 ||
537
537
desc -> colorspace > 1 ||
538
538
header_magic != QOI_MAGIC ||
@@ -598,7 +598,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
598
598
index [QOI_COLOR_HASH (px ) % 64 ] = px ;
599
599
}
600
600
601
- if (channels == 4 ) {
601
+ if (channels == 4 ) {
602
602
* (qoi_rgba_t * )(pixels + px_pos ) = px ;
603
603
}
604
604
else {
@@ -627,11 +627,11 @@ int qoi_write(const char *filename, const void *data, const qoi_desc *desc) {
627
627
if (!encoded ) {
628
628
fclose (f );
629
629
return 0 ;
630
- }
631
-
630
+ }
631
+
632
632
fwrite (encoded , 1 , size , f );
633
633
fclose (f );
634
-
634
+
635
635
QOI_FREE (encoded );
636
636
return size ;
637
637
}
0 commit comments