LiteRGSS 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/LiteRGSS/Bitmap.cpp +316 -0
- data/ext/LiteRGSS/Bitmap.h +24 -0
- data/ext/LiteRGSS/BlendMode.cpp +202 -0
- data/ext/LiteRGSS/BlendMode.h +20 -0
- data/ext/LiteRGSS/CBitmap_Element.cpp +50 -0
- data/ext/LiteRGSS/CBitmap_Element.h +17 -0
- data/ext/LiteRGSS/CDrawable_Element.cpp +38 -0
- data/ext/LiteRGSS/CDrawable_Element.h +30 -0
- data/ext/LiteRGSS/CRect_Element.h +15 -0
- data/ext/LiteRGSS/CShaderSprite_Element.cpp +17 -0
- data/ext/LiteRGSS/CShaderSprite_Element.h +17 -0
- data/ext/LiteRGSS/CSprite_Element.cpp +15 -0
- data/ext/LiteRGSS/CSprite_Element.h +36 -0
- data/ext/LiteRGSS/CText_Element.cpp +12 -0
- data/ext/LiteRGSS/CText_Element.h +29 -0
- data/ext/LiteRGSS/CTone_Element.h +17 -0
- data/ext/LiteRGSS/CViewport_Element.cpp +224 -0
- data/ext/LiteRGSS/CViewport_Element.h +57 -0
- data/ext/LiteRGSS/Color.cpp +200 -0
- data/ext/LiteRGSS/Color.h +22 -0
- data/ext/LiteRGSS/Fonts.cpp +126 -0
- data/ext/LiteRGSS/Fonts.h +20 -0
- data/ext/LiteRGSS/Graphics.cpp +314 -0
- data/ext/LiteRGSS/Graphics.h +31 -0
- data/ext/LiteRGSS/Graphics.local.cpp +365 -0
- data/ext/LiteRGSS/Graphics.local.h +37 -0
- data/ext/LiteRGSS/Image.cpp +460 -0
- data/ext/LiteRGSS/Image.h +32 -0
- data/ext/LiteRGSS/Input.cpp +664 -0
- data/ext/LiteRGSS/Input.h +38 -0
- data/ext/LiteRGSS/LiteRGSS.cpp +34 -0
- data/ext/LiteRGSS/LiteRGSS.h +113 -0
- data/ext/LiteRGSS/Rect.cpp +324 -0
- data/ext/LiteRGSS/Rect.h +24 -0
- data/ext/LiteRGSS/Shader.cpp +279 -0
- data/ext/LiteRGSS/Shader.h +13 -0
- data/ext/LiteRGSS/ShaderSprite.cpp +78 -0
- data/ext/LiteRGSS/ShaderSprite.h +8 -0
- data/ext/LiteRGSS/Sprite.cpp +495 -0
- data/ext/LiteRGSS/Sprite.h +43 -0
- data/ext/LiteRGSS/Table.cpp +228 -0
- data/ext/LiteRGSS/Table.h +29 -0
- data/ext/LiteRGSS/Table32.cpp +228 -0
- data/ext/LiteRGSS/Table32.h +29 -0
- data/ext/LiteRGSS/Text.cpp +574 -0
- data/ext/LiteRGSS/Text.h +52 -0
- data/ext/LiteRGSS/Texture.hpp +735 -0
- data/ext/LiteRGSS/Tone.cpp +228 -0
- data/ext/LiteRGSS/Tone.h +22 -0
- data/ext/LiteRGSS/Viewport.cpp +491 -0
- data/ext/LiteRGSS/Viewport.h +33 -0
- data/ext/LiteRGSS/Yuki.cpp +29 -0
- data/ext/LiteRGSS/Yuki.h +8 -0
- data/ext/LiteRGSS/Yuki_Gif.cpp +218 -0
- data/ext/LiteRGSS/Yuki_Gif.h +25 -0
- data/ext/LiteRGSS/extconf.rb +8 -0
- data/ext/LiteRGSS/libnsgif.c +1169 -0
- data/ext/LiteRGSS/libnsgif.h +183 -0
- data/ext/LiteRGSS/libnsgif.hpp +184 -0
- data/ext/LiteRGSS/lodepng.cpp +6245 -0
- data/ext/LiteRGSS/lodepng.h +1769 -0
- data/ext/LiteRGSS/lzw.c +377 -0
- data/ext/LiteRGSS/lzw.h +105 -0
- data/ext/LiteRGSS/sf_Text2.cpp +690 -0
- data/ext/LiteRGSS/sf_Text2.hpp +549 -0
- data/ext/LiteRGSS/utils/log.h +21 -0
- metadata +112 -0
data/ext/LiteRGSS/lzw.c
ADDED
@@ -0,0 +1,377 @@
|
|
1
|
+
/*
|
2
|
+
* This file is part of NetSurf's LibNSGIF, http://www.netsurf-browser.org/
|
3
|
+
* Licensed under the MIT License,
|
4
|
+
* http://www.opensource.org/licenses/mit-license.php
|
5
|
+
*
|
6
|
+
* Copyright 2017 Michael Drake <michael.drake@codethink.co.uk>
|
7
|
+
*/
|
8
|
+
|
9
|
+
#include <assert.h>
|
10
|
+
#include <stdint.h>
|
11
|
+
#include <stdlib.h>
|
12
|
+
#include <stdbool.h>
|
13
|
+
|
14
|
+
#include "lzw.h"
|
15
|
+
|
16
|
+
/**
|
17
|
+
* \file
|
18
|
+
* \brief LZW decompression (implementation)
|
19
|
+
*
|
20
|
+
* Decoder for GIF LZW data.
|
21
|
+
*/
|
22
|
+
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Context for reading LZW data.
|
26
|
+
*
|
27
|
+
* LZW data is split over multiple sub-blocks. Each sub-block has a
|
28
|
+
* byte at the start, which says the sub-block size, and then the data.
|
29
|
+
* Zero-size sub-blocks have no data, and the biggest sub-block size is
|
30
|
+
* 255, which means there are 255 bytes of data following the sub-block
|
31
|
+
* size entry.
|
32
|
+
*
|
33
|
+
* Note that an individual LZW code can be split over up to three sub-blocks.
|
34
|
+
*/
|
35
|
+
struct lzw_read_ctx {
|
36
|
+
const uint8_t *data; /**< Pointer to start of input data */
|
37
|
+
uint32_t data_len; /**< Input data length */
|
38
|
+
uint32_t data_sb_next; /**< Offset to sub-block size */
|
39
|
+
|
40
|
+
const uint8_t *sb_data; /**< Pointer to current sub-block in data */
|
41
|
+
uint32_t sb_bit; /**< Current bit offset in sub-block */
|
42
|
+
uint32_t sb_bit_count; /**< Bit count in sub-block */
|
43
|
+
};
|
44
|
+
|
45
|
+
/**
|
46
|
+
* LZW dictionary entry.
|
47
|
+
*
|
48
|
+
* Records in the dictionary are composed of 1 or more entries.
|
49
|
+
* Entries point to previous entries which can be followed to compose
|
50
|
+
* the complete record. To compose the record in reverse order, take
|
51
|
+
* the `last_value` from each entry, and move to the previous entry.
|
52
|
+
* If the previous_entry's index is < the current clear_code, then it
|
53
|
+
* is the last entry in the record.
|
54
|
+
*/
|
55
|
+
struct lzw_dictionary_entry {
|
56
|
+
uint8_t last_value; /**< Last value for record ending at entry. */
|
57
|
+
uint8_t first_value; /**< First value for entry's record. */
|
58
|
+
uint16_t previous_entry; /**< Offset in dictionary to previous entry. */
|
59
|
+
};
|
60
|
+
|
61
|
+
/**
|
62
|
+
* LZW decompression context.
|
63
|
+
*/
|
64
|
+
struct lzw_ctx {
|
65
|
+
/** Input reading context */
|
66
|
+
struct lzw_read_ctx input;
|
67
|
+
|
68
|
+
uint32_t previous_code; /**< Code read from input previously. */
|
69
|
+
uint32_t previous_code_first; /**< First value of previous code. */
|
70
|
+
|
71
|
+
uint32_t initial_code_size; /**< Starting LZW code size. */
|
72
|
+
uint32_t current_code_size; /**< Current LZW code size. */
|
73
|
+
uint32_t current_code_size_max; /**< Max code value for current size. */
|
74
|
+
|
75
|
+
uint32_t clear_code; /**< Special Clear code value */
|
76
|
+
uint32_t eoi_code; /**< Special End of Information code value */
|
77
|
+
|
78
|
+
uint32_t current_entry; /**< Next position in table to fill. */
|
79
|
+
|
80
|
+
/** Output value stack. */
|
81
|
+
uint8_t stack_base[1 << LZW_CODE_MAX];
|
82
|
+
|
83
|
+
/** LZW decode dictionary. Generated during decode. */
|
84
|
+
struct lzw_dictionary_entry table[1 << LZW_CODE_MAX];
|
85
|
+
};
|
86
|
+
|
87
|
+
|
88
|
+
/* Exported function, documented in lzw.h */
|
89
|
+
lzw_result lzw_context_create(struct lzw_ctx **ctx)
|
90
|
+
{
|
91
|
+
struct lzw_ctx *c = malloc(sizeof(*c));
|
92
|
+
if (c == NULL) {
|
93
|
+
return LZW_NO_MEM;
|
94
|
+
}
|
95
|
+
|
96
|
+
*ctx = c;
|
97
|
+
return LZW_OK;
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
/* Exported function, documented in lzw.h */
|
102
|
+
void lzw_context_destroy(struct lzw_ctx *ctx)
|
103
|
+
{
|
104
|
+
free(ctx);
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Advance the context to the next sub-block in the input data.
|
110
|
+
*
|
111
|
+
* \param[in] ctx LZW reading context, updated on success.
|
112
|
+
* \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
|
113
|
+
*/
|
114
|
+
static lzw_result lzw__block_advance(struct lzw_read_ctx *ctx)
|
115
|
+
{
|
116
|
+
uint32_t block_size;
|
117
|
+
uint32_t next_block_pos = ctx->data_sb_next;
|
118
|
+
const uint8_t *data_next = ctx->data + next_block_pos;
|
119
|
+
|
120
|
+
if (next_block_pos >= ctx->data_len) {
|
121
|
+
return LZW_NO_DATA;
|
122
|
+
}
|
123
|
+
|
124
|
+
block_size = *data_next;
|
125
|
+
|
126
|
+
if ((next_block_pos + block_size) >= ctx->data_len) {
|
127
|
+
return LZW_NO_DATA;
|
128
|
+
}
|
129
|
+
|
130
|
+
ctx->sb_bit = 0;
|
131
|
+
ctx->sb_bit_count = block_size * 8;
|
132
|
+
|
133
|
+
if (block_size == 0) {
|
134
|
+
ctx->data_sb_next += 1;
|
135
|
+
return LZW_OK_EOD;
|
136
|
+
}
|
137
|
+
|
138
|
+
ctx->sb_data = data_next + 1;
|
139
|
+
ctx->data_sb_next += block_size + 1;
|
140
|
+
|
141
|
+
return LZW_OK;
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
/**
|
146
|
+
* Get the next LZW code of given size from the raw input data.
|
147
|
+
*
|
148
|
+
* Reads codes from the input data stream coping with GIF data sub-blocks.
|
149
|
+
*
|
150
|
+
* \param[in] ctx LZW reading context, updated.
|
151
|
+
* \param[in] code_size Size of LZW code to get from data.
|
152
|
+
* \param[out] code_out Returns an LZW code on success.
|
153
|
+
* \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
|
154
|
+
*/
|
155
|
+
static inline lzw_result lzw__next_code(
|
156
|
+
struct lzw_read_ctx *ctx,
|
157
|
+
uint8_t code_size,
|
158
|
+
uint32_t *code_out)
|
159
|
+
{
|
160
|
+
uint32_t code = 0;
|
161
|
+
uint8_t current_bit = ctx->sb_bit & 0x7;
|
162
|
+
uint8_t byte_advance = (current_bit + code_size) >> 3;
|
163
|
+
|
164
|
+
assert(byte_advance <= 2);
|
165
|
+
|
166
|
+
if (ctx->sb_bit + code_size < ctx->sb_bit_count) {
|
167
|
+
/* Fast path: code fully inside this sub-block */
|
168
|
+
const uint8_t *data = ctx->sb_data + (ctx->sb_bit >> 3);
|
169
|
+
switch (byte_advance) {
|
170
|
+
case 2: code |= data[2] << 16; /* Fall through */
|
171
|
+
case 1: code |= data[1] << 8; /* Fall through */
|
172
|
+
case 0: code |= data[0] << 0;
|
173
|
+
}
|
174
|
+
ctx->sb_bit += code_size;
|
175
|
+
} else {
|
176
|
+
/* Slow path: code spans sub-blocks */
|
177
|
+
uint8_t byte = 0;
|
178
|
+
uint8_t bits_remaining_0 = (code_size < (8 - current_bit)) ?
|
179
|
+
code_size : (8 - current_bit);
|
180
|
+
uint8_t bits_remaining_1 = code_size - bits_remaining_0;
|
181
|
+
uint8_t bits_used[3] = {
|
182
|
+
[0] = bits_remaining_0,
|
183
|
+
[1] = bits_remaining_1 < 8 ? bits_remaining_1 : 8,
|
184
|
+
[2] = bits_remaining_1 - 8,
|
185
|
+
};
|
186
|
+
|
187
|
+
while (true) {
|
188
|
+
const uint8_t *data = ctx->sb_data;
|
189
|
+
lzw_result res;
|
190
|
+
|
191
|
+
/* Get any data from end of this sub-block */
|
192
|
+
while (byte <= byte_advance &&
|
193
|
+
ctx->sb_bit < ctx->sb_bit_count) {
|
194
|
+
code |= data[ctx->sb_bit >> 3] << (byte << 3);
|
195
|
+
ctx->sb_bit += bits_used[byte];
|
196
|
+
byte++;
|
197
|
+
}
|
198
|
+
|
199
|
+
/* Check if we have all we need */
|
200
|
+
if (byte > byte_advance) {
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
|
204
|
+
/* Move to next sub-block */
|
205
|
+
res = lzw__block_advance(ctx);
|
206
|
+
if (res != LZW_OK) {
|
207
|
+
return res;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
*code_out = (code >> current_bit) & ((1 << code_size) - 1);
|
213
|
+
return LZW_OK;
|
214
|
+
}
|
215
|
+
|
216
|
+
|
217
|
+
/**
|
218
|
+
* Clear LZW code dictionary.
|
219
|
+
*
|
220
|
+
* \param[in] ctx LZW reading context, updated.
|
221
|
+
* \param[out] stack_pos_out Returns current stack position.
|
222
|
+
* \return LZW_OK or error code.
|
223
|
+
*/
|
224
|
+
static lzw_result lzw__clear_codes(
|
225
|
+
struct lzw_ctx *ctx,
|
226
|
+
const uint8_t ** const stack_pos_out)
|
227
|
+
{
|
228
|
+
uint32_t code;
|
229
|
+
uint8_t *stack_pos;
|
230
|
+
|
231
|
+
/* Reset dictionary building context */
|
232
|
+
ctx->current_code_size = ctx->initial_code_size + 1;
|
233
|
+
ctx->current_code_size_max = (1 << ctx->current_code_size) - 1;;
|
234
|
+
ctx->current_entry = (1 << ctx->initial_code_size) + 2;
|
235
|
+
|
236
|
+
/* There might be a sequence of clear codes, so process them all */
|
237
|
+
do {
|
238
|
+
lzw_result res = lzw__next_code(&ctx->input,
|
239
|
+
ctx->current_code_size, &code);
|
240
|
+
if (res != LZW_OK) {
|
241
|
+
return res;
|
242
|
+
}
|
243
|
+
} while (code == ctx->clear_code);
|
244
|
+
|
245
|
+
/* The initial code must be from the initial dictionary. */
|
246
|
+
if (code > ctx->clear_code) {
|
247
|
+
return LZW_BAD_ICODE;
|
248
|
+
}
|
249
|
+
|
250
|
+
/* Record this initial code as "previous" code, needed during decode. */
|
251
|
+
ctx->previous_code = code;
|
252
|
+
ctx->previous_code_first = code;
|
253
|
+
|
254
|
+
/* Reset the stack, and add first non-clear code added as first item. */
|
255
|
+
stack_pos = ctx->stack_base;
|
256
|
+
*stack_pos++ = code;
|
257
|
+
|
258
|
+
*stack_pos_out = stack_pos;
|
259
|
+
return LZW_OK;
|
260
|
+
}
|
261
|
+
|
262
|
+
|
263
|
+
/* Exported function, documented in lzw.h */
|
264
|
+
lzw_result lzw_decode_init(
|
265
|
+
struct lzw_ctx *ctx,
|
266
|
+
const uint8_t *compressed_data,
|
267
|
+
uint32_t compressed_data_len,
|
268
|
+
uint32_t compressed_data_pos,
|
269
|
+
uint8_t code_size,
|
270
|
+
const uint8_t ** const stack_base_out,
|
271
|
+
const uint8_t ** const stack_pos_out)
|
272
|
+
{
|
273
|
+
struct lzw_dictionary_entry *table = ctx->table;
|
274
|
+
|
275
|
+
/* Initialise the input reading context */
|
276
|
+
ctx->input.data = compressed_data;
|
277
|
+
ctx->input.data_len = compressed_data_len;
|
278
|
+
ctx->input.data_sb_next = compressed_data_pos;
|
279
|
+
|
280
|
+
ctx->input.sb_bit = 0;
|
281
|
+
ctx->input.sb_bit_count = 0;
|
282
|
+
|
283
|
+
/* Initialise the dictionary building context */
|
284
|
+
ctx->initial_code_size = code_size;
|
285
|
+
|
286
|
+
ctx->clear_code = (1 << code_size) + 0;
|
287
|
+
ctx->eoi_code = (1 << code_size) + 1;
|
288
|
+
|
289
|
+
/* Initialise the standard dictionary entries */
|
290
|
+
for (uint32_t i = 0; i < ctx->clear_code; ++i) {
|
291
|
+
table[i].first_value = i;
|
292
|
+
table[i].last_value = i;
|
293
|
+
}
|
294
|
+
|
295
|
+
*stack_base_out = ctx->stack_base;
|
296
|
+
return lzw__clear_codes(ctx, stack_pos_out);
|
297
|
+
}
|
298
|
+
|
299
|
+
|
300
|
+
/* Exported function, documented in lzw.h */
|
301
|
+
lzw_result lzw_decode(struct lzw_ctx *ctx,
|
302
|
+
const uint8_t ** const stack_pos_out)
|
303
|
+
{
|
304
|
+
lzw_result res;
|
305
|
+
uint32_t code_new;
|
306
|
+
uint32_t code_out;
|
307
|
+
uint8_t last_value;
|
308
|
+
uint8_t *stack_pos = ctx->stack_base;
|
309
|
+
uint32_t clear_code = ctx->clear_code;
|
310
|
+
uint32_t current_entry = ctx->current_entry;
|
311
|
+
struct lzw_dictionary_entry * const table = ctx->table;
|
312
|
+
|
313
|
+
/* Get a new code from the input */
|
314
|
+
res = lzw__next_code(&ctx->input, ctx->current_code_size, &code_new);
|
315
|
+
if (res != LZW_OK) {
|
316
|
+
return res;
|
317
|
+
}
|
318
|
+
|
319
|
+
/* Handle the new code */
|
320
|
+
if (code_new == clear_code) {
|
321
|
+
/* Got Clear code */
|
322
|
+
return lzw__clear_codes(ctx, stack_pos_out);
|
323
|
+
|
324
|
+
} else if (code_new == ctx->eoi_code) {
|
325
|
+
/* Got End of Information code */
|
326
|
+
return LZW_EOI_CODE;
|
327
|
+
|
328
|
+
} else if (code_new > current_entry) {
|
329
|
+
/* Code is invalid */
|
330
|
+
return LZW_BAD_CODE;
|
331
|
+
|
332
|
+
} else if (code_new < current_entry) {
|
333
|
+
/* Code is in table */
|
334
|
+
code_out = code_new;
|
335
|
+
last_value = table[code_new].first_value;
|
336
|
+
} else {
|
337
|
+
/* Code not in table */
|
338
|
+
*stack_pos++ = ctx->previous_code_first;
|
339
|
+
code_out = ctx->previous_code;
|
340
|
+
last_value = ctx->previous_code_first;
|
341
|
+
}
|
342
|
+
|
343
|
+
/* Add to the dictionary, only if there's space */
|
344
|
+
if (current_entry < (1 << LZW_CODE_MAX)) {
|
345
|
+
struct lzw_dictionary_entry *entry = table + current_entry;
|
346
|
+
entry->last_value = last_value;
|
347
|
+
entry->first_value = ctx->previous_code_first;
|
348
|
+
entry->previous_entry = ctx->previous_code;
|
349
|
+
ctx->current_entry++;
|
350
|
+
}
|
351
|
+
|
352
|
+
/* Ensure code size is increased, if needed. */
|
353
|
+
if (current_entry == ctx->current_code_size_max) {
|
354
|
+
if (ctx->current_code_size < LZW_CODE_MAX) {
|
355
|
+
ctx->current_code_size++;
|
356
|
+
ctx->current_code_size_max =
|
357
|
+
(1 << ctx->current_code_size) - 1;
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
/* Store details of this code as "previous code" to the context. */
|
362
|
+
ctx->previous_code_first = table[code_new].first_value;
|
363
|
+
ctx->previous_code = code_new;
|
364
|
+
|
365
|
+
/* Put rest of data for this code on output stack.
|
366
|
+
* Note, in the case of "code not in table", the last entry of the
|
367
|
+
* current code has already been placed on the stack above. */
|
368
|
+
while (code_out > clear_code) {
|
369
|
+
struct lzw_dictionary_entry *entry = table + code_out;
|
370
|
+
*stack_pos++ = entry->last_value;
|
371
|
+
code_out = entry->previous_entry;
|
372
|
+
}
|
373
|
+
*stack_pos++ = table[code_out].last_value;
|
374
|
+
|
375
|
+
*stack_pos_out = stack_pos;
|
376
|
+
return LZW_OK;
|
377
|
+
}
|
data/ext/LiteRGSS/lzw.h
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
/*
|
2
|
+
* This file is part of NetSurf's LibNSGIF, http://www.netsurf-browser.org/
|
3
|
+
* Licensed under the MIT License,
|
4
|
+
* http://www.opensource.org/licenses/mit-license.php
|
5
|
+
*
|
6
|
+
* Copyright 2017 Michael Drake <michael.drake@codethink.co.uk>
|
7
|
+
*/
|
8
|
+
|
9
|
+
#ifndef LZW_H_
|
10
|
+
#define LZW_H_
|
11
|
+
|
12
|
+
/**
|
13
|
+
* \file
|
14
|
+
* \brief LZW decompression (interface)
|
15
|
+
*
|
16
|
+
* Decoder for GIF LZW data.
|
17
|
+
*/
|
18
|
+
|
19
|
+
|
20
|
+
/** Maximum LZW code size in bits */
|
21
|
+
#define LZW_CODE_MAX 12
|
22
|
+
|
23
|
+
|
24
|
+
/* Declare lzw internal context structure */
|
25
|
+
struct lzw_ctx;
|
26
|
+
|
27
|
+
|
28
|
+
/** LZW decoding response codes */
|
29
|
+
typedef enum lzw_result {
|
30
|
+
LZW_OK, /**< Success */
|
31
|
+
LZW_OK_EOD, /**< Success; reached zero-length sub-block */
|
32
|
+
LZW_NO_MEM, /**< Error: Out of memory */
|
33
|
+
LZW_NO_DATA, /**< Error: Out of data */
|
34
|
+
LZW_EOI_CODE, /**< Error: End of Information code */
|
35
|
+
LZW_BAD_ICODE, /**< Error: Bad initial LZW code */
|
36
|
+
LZW_BAD_CODE, /**< Error: Bad LZW code */
|
37
|
+
} lzw_result;
|
38
|
+
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Create an LZW decompression context.
|
42
|
+
*
|
43
|
+
* \param[out] ctx Returns an LZW decompression context. Caller owned,
|
44
|
+
* free with lzw_context_destroy().
|
45
|
+
* \return LZW_OK on success, or appropriate error code otherwise.
|
46
|
+
*/
|
47
|
+
lzw_result lzw_context_create(
|
48
|
+
struct lzw_ctx **ctx);
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Destroy an LZW decompression context.
|
52
|
+
*
|
53
|
+
* \param[in] ctx The LZW decompression context to destroy.
|
54
|
+
*/
|
55
|
+
void lzw_context_destroy(
|
56
|
+
struct lzw_ctx *ctx);
|
57
|
+
|
58
|
+
/**
|
59
|
+
* Initialise an LZW decompression context for decoding.
|
60
|
+
*
|
61
|
+
* Caller owns neither `stack_base_out` or `stack_pos_out`.
|
62
|
+
*
|
63
|
+
* \param[in] ctx The LZW decompression context to initialise.
|
64
|
+
* \param[in] compressed_data The compressed data.
|
65
|
+
* \param[in] compressed_data_len Byte length of compressed data.
|
66
|
+
* \param[in] compressed_data_pos Start position in data. Must be position
|
67
|
+
* of a size byte at sub-block start.
|
68
|
+
* \param[in] code_size The initial LZW code size to use.
|
69
|
+
* \param[out] stack_base_out Returns base of decompressed data stack.
|
70
|
+
* \param[out] stack_pos_out Returns current stack position.
|
71
|
+
* There are `stack_pos_out - stack_base_out`
|
72
|
+
* current stack entries.
|
73
|
+
* \return LZW_OK on success, or appropriate error code otherwise.
|
74
|
+
*/
|
75
|
+
lzw_result lzw_decode_init(
|
76
|
+
struct lzw_ctx *ctx,
|
77
|
+
const uint8_t *compressed_data,
|
78
|
+
uint32_t compressed_data_len,
|
79
|
+
uint32_t compressed_data_pos,
|
80
|
+
uint8_t code_size,
|
81
|
+
const uint8_t ** const stack_base_out,
|
82
|
+
const uint8_t ** const stack_pos_out);
|
83
|
+
|
84
|
+
/**
|
85
|
+
* Fill the LZW stack with decompressed data
|
86
|
+
*
|
87
|
+
* Ensure anything on the stack is used before calling this, as anything
|
88
|
+
* on the stack before this call will be trampled.
|
89
|
+
*
|
90
|
+
* Caller does not own `stack_pos_out`.
|
91
|
+
*
|
92
|
+
* \param[in] ctx LZW reading context, updated.
|
93
|
+
* \param[out] stack_pos_out Returns current stack position.
|
94
|
+
* Use with `stack_base_out` value from previous
|
95
|
+
* lzw_decode_init() call.
|
96
|
+
* There are `stack_pos_out - stack_base_out`
|
97
|
+
* current stack entries.
|
98
|
+
* \return LZW_OK on success, or appropriate error code otherwise.
|
99
|
+
*/
|
100
|
+
lzw_result lzw_decode(
|
101
|
+
struct lzw_ctx *ctx,
|
102
|
+
const uint8_t ** const stack_pos_out);
|
103
|
+
|
104
|
+
|
105
|
+
#endif
|