|
1 /* |
|
2 LodePNG version 20080927 |
|
3 |
|
4 Copyright (c) 2005-2008 Lode Vandevenne |
|
5 |
|
6 This software is provided 'as-is', without any express or implied |
|
7 warranty. In no event will the authors be held liable for any damages |
|
8 arising from the use of this software. |
|
9 |
|
10 Permission is granted to anyone to use this software for any purpose, |
|
11 including commercial applications, and to alter it and redistribute it |
|
12 freely, subject to the following restrictions: |
|
13 |
|
14 1. The origin of this software must not be misrepresented; you must not |
|
15 claim that you wrote the original software. If you use this software |
|
16 in a product, an acknowledgment in the product documentation would be |
|
17 appreciated but is not required. |
|
18 |
|
19 2. Altered source versions must be plainly marked as such, and must not be |
|
20 misrepresented as being the original software. |
|
21 |
|
22 3. This notice may not be removed or altered from any source |
|
23 distribution. |
|
24 */ |
|
25 |
|
26 /* |
|
27 The manual and changelog can be found in the header file "lodepng.h" |
|
28 You are free to name this file lodepng.cpp or lodepng.c depending on your usage. |
|
29 */ |
|
30 |
|
31 #include "lodepng.h" |
|
32 |
|
33 #define VERSION_STRING "20080927" |
|
34 |
|
35 /* ////////////////////////////////////////////////////////////////////////// */ |
|
36 /* / Tools For C / */ |
|
37 /* ////////////////////////////////////////////////////////////////////////// */ |
|
38 |
|
39 /* |
|
40 About these tools (vector, uivector, ucvector and string): |
|
41 -LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. |
|
42 -The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. |
|
43 -They're not used in the interface, only internally in this file, so all their functions are made static. |
|
44 */ |
|
45 |
|
46 #ifdef LODEPNG_COMPILE_ZLIB |
|
47 #ifdef LODEPNG_COMPILE_ENCODER |
|
48 |
|
49 typedef struct vector /*this one is used only by the deflate compressor*/ |
|
50 { |
|
51 void* data; |
|
52 size_t size; /*in groups of bytes depending on type*/ |
|
53 size_t allocsize; /*in bytes*/ |
|
54 unsigned typesize; /*sizeof the type you store in data*/ |
|
55 } vector; |
|
56 |
|
57 static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ |
|
58 { |
|
59 if(size * p->typesize > p->allocsize) |
|
60 { |
|
61 size_t newsize = size * p->typesize * 2; |
|
62 void* data = realloc(p->data, newsize); |
|
63 if(data) |
|
64 { |
|
65 p->allocsize = newsize; |
|
66 p->data = data; |
|
67 p->size = size; |
|
68 } |
|
69 else return 0; |
|
70 } |
|
71 else p->size = size; |
|
72 return 1; |
|
73 } |
|
74 |
|
75 static unsigned vector_resized(vector* p, size_t size, void dtor(void*)) /*resize and use destructor on elements if it gets smaller*/ |
|
76 { |
|
77 size_t i; |
|
78 if(size < p->size) for(i = size; i < p->size; i++) dtor(&((char*)(p->data))[i * p->typesize]); |
|
79 return vector_resize(p, size); |
|
80 } |
|
81 |
|
82 static void vector_cleanup(void* p) |
|
83 { |
|
84 ((vector*)p)->size = ((vector*)p)->allocsize = 0; |
|
85 free(((vector*)p)->data); |
|
86 ((vector*)p)->data = NULL; |
|
87 } |
|
88 |
|
89 static void vector_cleanupd(vector* p, void dtor(void*)) /*clear and use destructor on elements*/ |
|
90 { |
|
91 vector_resized(p, 0, dtor); |
|
92 vector_cleanup(p); |
|
93 } |
|
94 |
|
95 static void vector_init(vector* p, unsigned typesize) |
|
96 { |
|
97 p->data = NULL; |
|
98 p->size = p->allocsize = 0; |
|
99 p->typesize = typesize; |
|
100 } |
|
101 |
|
102 static void vector_swap(vector* p, vector* q) /*they're supposed to have the same typesize*/ |
|
103 { |
|
104 size_t tmp; |
|
105 void* tmpp; |
|
106 tmp = p->size; p->size = q->size; q->size = tmp; |
|
107 tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp; |
|
108 tmpp = p->data; p->data = q->data; q->data = tmpp; |
|
109 } |
|
110 |
|
111 static void* vector_get(vector* p, size_t index) |
|
112 { |
|
113 return &((char*)p->data)[index * p->typesize]; |
|
114 } |
|
115 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
116 #endif /*LODEPNG_COMPILE_ZLIB*/ |
|
117 |
|
118 /* /////////////////////////////////////////////////////////////////////////// */ |
|
119 |
|
120 #ifdef LODEPNG_COMPILE_ZLIB |
|
121 typedef struct uivector |
|
122 { |
|
123 unsigned* data; |
|
124 size_t size; /*size in number of unsigned longs*/ |
|
125 size_t allocsize; /*allocated size in bytes*/ |
|
126 } uivector; |
|
127 |
|
128 static void uivector_cleanup(void* p) |
|
129 { |
|
130 ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; |
|
131 free(((uivector*)p)->data); |
|
132 ((uivector*)p)->data = NULL; |
|
133 } |
|
134 |
|
135 static unsigned uivector_resize(uivector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ |
|
136 { |
|
137 if(size * sizeof(unsigned) > p->allocsize) |
|
138 { |
|
139 size_t newsize = size * sizeof(unsigned) * 2; |
|
140 void* data = realloc(p->data, newsize); |
|
141 if(data) |
|
142 { |
|
143 p->allocsize = newsize; |
|
144 p->data = (unsigned*)data; |
|
145 p->size = size; |
|
146 } |
|
147 else return 0; |
|
148 } |
|
149 else p->size = size; |
|
150 return 1; |
|
151 } |
|
152 |
|
153 static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) /*resize and give all new elements the value*/ |
|
154 { |
|
155 size_t oldsize = p->size, i; |
|
156 if(!uivector_resize(p, size)) return 0; |
|
157 for(i = oldsize; i < size; i++) p->data[i] = value; |
|
158 return 1; |
|
159 } |
|
160 |
|
161 static void uivector_init(uivector* p) |
|
162 { |
|
163 p->data = NULL; |
|
164 p->size = p->allocsize = 0; |
|
165 } |
|
166 |
|
167 #ifdef LODEPNG_COMPILE_ENCODER |
|
168 static unsigned uivector_push_back(uivector* p, unsigned c) /*returns 1 if success, 0 if failure ==> nothing done*/ |
|
169 { |
|
170 if(!uivector_resize(p, p->size + 1)) return 0; |
|
171 p->data[p->size - 1] = c; |
|
172 return 1; |
|
173 } |
|
174 |
|
175 static unsigned uivector_copy(uivector* p, const uivector* q) /*copy q to p, returns 1 if success, 0 if failure ==> nothing done*/ |
|
176 { |
|
177 size_t i; |
|
178 if(!uivector_resize(p, q->size)) return 0; |
|
179 for(i = 0; i < q->size; i++) p->data[i] = q->data[i]; |
|
180 return 1; |
|
181 } |
|
182 |
|
183 static void uivector_swap(uivector* p, uivector* q) |
|
184 { |
|
185 size_t tmp; |
|
186 unsigned* tmpp; |
|
187 tmp = p->size; p->size = q->size; q->size = tmp; |
|
188 tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp; |
|
189 tmpp = p->data; p->data = q->data; q->data = tmpp; |
|
190 } |
|
191 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
192 #endif /*LODEPNG_COMPILE_ZLIB*/ |
|
193 |
|
194 /* /////////////////////////////////////////////////////////////////////////// */ |
|
195 |
|
196 typedef struct ucvector |
|
197 { |
|
198 unsigned char* data; |
|
199 size_t size; /*used size*/ |
|
200 size_t allocsize; /*allocated size*/ |
|
201 } ucvector; |
|
202 |
|
203 static void ucvector_cleanup(void* p) |
|
204 { |
|
205 ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; |
|
206 free(((ucvector*)p)->data); |
|
207 ((ucvector*)p)->data = NULL; |
|
208 } |
|
209 |
|
210 static unsigned ucvector_resize(ucvector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ |
|
211 { |
|
212 if(size * sizeof(unsigned) > p->allocsize) |
|
213 { |
|
214 size_t newsize = size * sizeof(unsigned) * 2; |
|
215 void* data = realloc(p->data, newsize); |
|
216 if(data) |
|
217 { |
|
218 p->allocsize = newsize; |
|
219 p->data = (unsigned char*)data; |
|
220 p->size = size; |
|
221 } |
|
222 else return 0; /*error: not enough memory*/ |
|
223 } |
|
224 else p->size = size; |
|
225 return 1; |
|
226 } |
|
227 |
|
228 #ifdef LODEPNG_COMPILE_DECODER |
|
229 #ifdef LODEPNG_COMPILE_PNG |
|
230 static unsigned ucvector_resizev(ucvector* p, size_t size, unsigned char value) /*resize and give all new elements the value*/ |
|
231 { |
|
232 size_t oldsize = p->size, i; |
|
233 if(!ucvector_resize(p, size)) return 0; |
|
234 for(i = oldsize; i < size; i++) p->data[i] = value; |
|
235 return 1; |
|
236 } |
|
237 #endif /*LODEPNG_COMPILE_PNG*/ |
|
238 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
239 |
|
240 static void ucvector_init(ucvector* p) |
|
241 { |
|
242 p->data = NULL; |
|
243 p->size = p->allocsize = 0; |
|
244 } |
|
245 |
|
246 #ifdef LODEPNG_COMPILE_ZLIB |
|
247 /*you can both convert from vector to buffer&size and vica versa*/ |
|
248 static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) |
|
249 { |
|
250 p->data = buffer; |
|
251 p->allocsize = p->size = size; |
|
252 } |
|
253 #endif /*LODEPNG_COMPILE_ZLIB*/ |
|
254 |
|
255 static unsigned ucvector_push_back(ucvector* p, unsigned char c) /*returns 1 if success, 0 if failure ==> nothing done*/ |
|
256 { |
|
257 if(!ucvector_resize(p, p->size + 1)) return 0; |
|
258 p->data[p->size - 1] = c; |
|
259 return 1; |
|
260 } |
|
261 |
|
262 /* /////////////////////////////////////////////////////////////////////////// */ |
|
263 |
|
264 #ifdef LODEPNG_COMPILE_PNG |
|
265 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
266 static unsigned string_resize(char** out, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ |
|
267 { |
|
268 char* data = (char*)realloc(*out, size + 1); |
|
269 if(data) |
|
270 { |
|
271 data[size] = 0; /*null termination char*/ |
|
272 *out = data; |
|
273 } |
|
274 return data != 0; |
|
275 } |
|
276 |
|
277 static void string_init(char** out) /*init a {char*, size_t} pair for use as string*/ |
|
278 { |
|
279 *out = NULL; |
|
280 string_resize(out, 0); |
|
281 } |
|
282 |
|
283 static void string_cleanup(char** out) /*free the above pair again*/ |
|
284 { |
|
285 free(*out); |
|
286 *out = NULL; |
|
287 } |
|
288 |
|
289 static void string_set(char** out, const char* in) |
|
290 { |
|
291 size_t insize = strlen(in), i = 0; |
|
292 if(string_resize(out, insize)) for(i = 0; i < insize; i++) (*out)[i] = in[i]; |
|
293 } |
|
294 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
295 #endif /*LODEPNG_COMPILE_PNG*/ |
|
296 |
|
297 #ifdef LODEPNG_COMPILE_ZLIB |
|
298 |
|
299 /* ////////////////////////////////////////////////////////////////////////// */ |
|
300 /* / Reading and writing single bits and bytes from/to stream for Deflate / */ |
|
301 /* ////////////////////////////////////////////////////////////////////////// */ |
|
302 |
|
303 #ifdef LODEPNG_COMPILE_ENCODER |
|
304 static void addBitToStream(size_t* bitpointer, ucvector* bitstream, unsigned char bit) |
|
305 { |
|
306 if((*bitpointer) % 8 == 0) ucvector_push_back(bitstream, 0); /*add a new byte at the end*/ |
|
307 (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7)); /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ |
|
308 (*bitpointer)++; |
|
309 } |
|
310 |
|
311 static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) |
|
312 { |
|
313 size_t i; |
|
314 for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); |
|
315 } |
|
316 |
|
317 static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) |
|
318 { |
|
319 size_t i; |
|
320 for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); |
|
321 } |
|
322 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
323 |
|
324 #ifdef LODEPNG_COMPILE_DECODER |
|
325 static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) |
|
326 { |
|
327 unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> ((*bitpointer) & 0x7)) & 1); |
|
328 (*bitpointer)++; |
|
329 return result; |
|
330 } |
|
331 |
|
332 static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) |
|
333 { |
|
334 unsigned result = 0, i; |
|
335 for(i = 0; i < nbits; i++) result += ((unsigned)readBitFromStream(bitpointer, bitstream)) << i; |
|
336 return result; |
|
337 } |
|
338 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
339 |
|
340 /* ////////////////////////////////////////////////////////////////////////// */ |
|
341 /* / Deflate - Huffman / */ |
|
342 /* ////////////////////////////////////////////////////////////////////////// */ |
|
343 |
|
344 #define FIRST_LENGTH_CODE_INDEX 257 |
|
345 #define LAST_LENGTH_CODE_INDEX 285 |
|
346 #define NUM_DEFLATE_CODE_SYMBOLS 288 /*256 literals, the end code, some length codes, and 2 unused codes*/ |
|
347 #define NUM_DISTANCE_SYMBOLS 32 /*the distance codes have their own symbols, 30 used, 2 unused*/ |
|
348 #define NUM_CODE_LENGTH_CODES 19 /*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ |
|
349 |
|
350 static const unsigned LENGTHBASE[29] /*the base lengths represented by codes 257-285*/ |
|
351 = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; |
|
352 static const unsigned LENGTHEXTRA[29] /*the extra bits used by codes 257-285 (added to base length)*/ |
|
353 = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; |
|
354 static const unsigned DISTANCEBASE[30] /*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ |
|
355 = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; |
|
356 static const unsigned DISTANCEEXTRA[30] /*the extra bits of backwards distances (added to base)*/ |
|
357 = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; |
|
358 static const unsigned CLCL[NUM_CODE_LENGTH_CODES] /*the order in which "code length alphabet code lengths" are stored, out of this the huffman tree of the dynamic huffman tree lengths is generated*/ |
|
359 = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; |
|
360 |
|
361 /* /////////////////////////////////////////////////////////////////////////// */ |
|
362 |
|
363 #ifdef LODEPNG_COMPILE_ENCODER |
|
364 /*terminology used for the package-merge algorithm and the coin collector's problem*/ |
|
365 typedef struct Coin /*a coin can be multiple coins (when they're merged)*/ |
|
366 { |
|
367 uivector symbols; |
|
368 float weight; /*the sum of all weights in this coin*/ |
|
369 } Coin; |
|
370 |
|
371 static void Coin_init(Coin* c) |
|
372 { |
|
373 uivector_init(&c->symbols); |
|
374 } |
|
375 |
|
376 static void Coin_cleanup(void* c) /*void* so that this dtor can be given as function pointer to the vector resize function*/ |
|
377 { |
|
378 uivector_cleanup(&((Coin*)c)->symbols); |
|
379 } |
|
380 |
|
381 static void Coin_copy(Coin* c1, const Coin* c2) |
|
382 { |
|
383 c1->weight = c2->weight; |
|
384 uivector_copy(&c1->symbols, &c2->symbols); |
|
385 } |
|
386 |
|
387 static void addCoins(Coin* c1, const Coin* c2) |
|
388 { |
|
389 unsigned i; |
|
390 for(i = 0; i < c2->symbols.size; i++) uivector_push_back(&c1->symbols, c2->symbols.data[i]); |
|
391 c1->weight += c2->weight; |
|
392 } |
|
393 |
|
394 static void Coin_sort(Coin* data, size_t amount) /*combsort*/ |
|
395 { |
|
396 size_t gap = amount; |
|
397 unsigned char swapped = 0; |
|
398 while(gap > 1 || swapped) |
|
399 { |
|
400 size_t i; |
|
401 gap = (gap * 10) / 13; /*shrink factor 1.3*/ |
|
402 if(gap == 9 || gap == 10) gap = 11; /*combsort11*/ |
|
403 if(gap < 1) gap = 1; |
|
404 swapped = 0; |
|
405 for(i = 0; i < amount - gap; i++) |
|
406 { |
|
407 size_t j = i + gap; |
|
408 if(data[j].weight < data[i].weight) |
|
409 { |
|
410 float temp = data[j].weight; data[j].weight = data[i].weight; data[i].weight = temp; |
|
411 uivector_swap(&data[i].symbols, &data[j].symbols); |
|
412 swapped = 1; |
|
413 } |
|
414 } |
|
415 } |
|
416 } |
|
417 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
418 |
|
419 typedef struct HuffmanTree |
|
420 { |
|
421 uivector tree2d; |
|
422 uivector tree1d; |
|
423 uivector lengths; /*the lengths of the codes of the 1d-tree*/ |
|
424 unsigned maxbitlen; /*maximum number of bits a single code can get*/ |
|
425 unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ |
|
426 } HuffmanTree; |
|
427 |
|
428 /*function used for debug purposes*/ |
|
429 /*#include <iostream> |
|
430 static void HuffmanTree_draw(HuffmanTree* tree) |
|
431 { |
|
432 std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; |
|
433 for(size_t i = 0; i < tree->tree1d.size; i++) |
|
434 { |
|
435 if(tree->lengths.data[i]) |
|
436 std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; |
|
437 } |
|
438 std::cout << std::endl; |
|
439 }*/ |
|
440 |
|
441 static void HuffmanTree_init(HuffmanTree* tree) |
|
442 { |
|
443 uivector_init(&tree->tree2d); |
|
444 uivector_init(&tree->tree1d); |
|
445 uivector_init(&tree->lengths); |
|
446 } |
|
447 |
|
448 static void HuffmanTree_cleanup(HuffmanTree* tree) |
|
449 { |
|
450 uivector_cleanup(&tree->tree2d); |
|
451 uivector_cleanup(&tree->tree1d); |
|
452 uivector_cleanup(&tree->lengths); |
|
453 } |
|
454 |
|
455 /*the tree representation used by the decoder. return value is error*/ |
|
456 static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) |
|
457 { |
|
458 unsigned nodefilled = 0; /*up to which node it is filled*/ |
|
459 unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ |
|
460 unsigned n, i; |
|
461 |
|
462 if(!uivector_resize(&tree->tree2d, tree->numcodes * 2)) return 9901; /*if failed return not enough memory error*/ |
|
463 /*convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means uninited, a value >= numcodes is an address to another bit, a value < numcodes is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as many columns as codes - 1 |
|
464 a good huffmann tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. Here, the internal nodes are stored (what their 0 and 1 option point to). There is only memory for such good tree currently, if there are more nodes (due to too long length codes), error 55 will happen*/ |
|
465 for(n = 0; n < tree->numcodes * 2; n++) tree->tree2d.data[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ |
|
466 |
|
467 for(n = 0; n < tree->numcodes; n++) /*the codes*/ |
|
468 for(i = 0; i < tree->lengths.data[n]; i++) /*the bits for this code*/ |
|
469 { |
|
470 unsigned char bit = (unsigned char)((tree->tree1d.data[n] >> (tree->lengths.data[n] - i - 1)) & 1); |
|
471 if(treepos > tree->numcodes - 2) return 55; /*error 55: oversubscribed; see description in header*/ |
|
472 if(tree->tree2d.data[2 * treepos + bit] == 32767) /*not yet filled in*/ |
|
473 { |
|
474 if(i + 1 == tree->lengths.data[n]) /*last bit*/ |
|
475 { |
|
476 tree->tree2d.data[2 * treepos + bit] = n; /*put the current code in it*/ |
|
477 treepos = 0; |
|
478 } |
|
479 else /*put address of the next step in here, first that address has to be found of course (it's just nodefilled + 1)...*/ |
|
480 { |
|
481 nodefilled++; |
|
482 tree->tree2d.data[2 * treepos + bit] = nodefilled + tree->numcodes; /*addresses encoded with numcodes added to it*/ |
|
483 treepos = nodefilled; |
|
484 } |
|
485 } |
|
486 else treepos = tree->tree2d.data[2 * treepos + bit] - tree->numcodes; |
|
487 } |
|
488 for(n = 0; n < tree->numcodes * 2; n++) if(tree->tree2d.data[n] == 32767) tree->tree2d.data[n] = 0; /*remove possible remaining 32767's*/ |
|
489 |
|
490 return 0; |
|
491 } |
|
492 |
|
493 static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) /*given that numcodes, lengths and maxbitlen are already filled in correctly. return value is error.*/ |
|
494 { |
|
495 uivector blcount; |
|
496 uivector nextcode; |
|
497 unsigned bits, n, error = 0; |
|
498 |
|
499 uivector_init(&blcount); |
|
500 uivector_init(&nextcode); |
|
501 if(!uivector_resize(&tree->tree1d, tree->numcodes) |
|
502 || !uivector_resizev(&blcount, tree->maxbitlen + 1, 0) |
|
503 || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) |
|
504 error = 9902; |
|
505 |
|
506 if(!error) |
|
507 { |
|
508 /*step 1: count number of instances of each code length*/ |
|
509 for(bits = 0; bits < tree->numcodes; bits++) blcount.data[tree->lengths.data[bits]]++; |
|
510 /*step 2: generate the nextcode values*/ |
|
511 for(bits = 1; bits <= tree->maxbitlen; bits++) nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; |
|
512 /*step 3: generate all the codes*/ |
|
513 for(n = 0; n < tree->numcodes; n++) if(tree->lengths.data[n] != 0) tree->tree1d.data[n] = nextcode.data[tree->lengths.data[n]]++; |
|
514 } |
|
515 |
|
516 uivector_cleanup(&blcount); |
|
517 uivector_cleanup(&nextcode); |
|
518 |
|
519 if(!error) return HuffmanTree_make2DTree(tree); |
|
520 else return error; |
|
521 } |
|
522 |
|
523 /*given the code lengths (as stored in the PNG file), generate the tree as defined by Deflate. maxbitlen is the maximum bits that a code in the tree can have. return value is error.*/ |
|
524 static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, size_t numcodes, unsigned maxbitlen) |
|
525 { |
|
526 unsigned i; |
|
527 if(!uivector_resize(&tree->lengths, numcodes)) return 9903; |
|
528 for(i = 0; i < numcodes; i++) tree->lengths.data[i] = bitlen[i]; |
|
529 tree->numcodes = (unsigned)numcodes; /*number of symbols*/ |
|
530 tree->maxbitlen = maxbitlen; |
|
531 return HuffmanTree_makeFromLengths2(tree); |
|
532 } |
|
533 |
|
534 #ifdef LODEPNG_COMPILE_ENCODER |
|
535 static unsigned HuffmanTree_fillInCoins(vector* coins, const unsigned* frequencies, unsigned numcodes, size_t sum) |
|
536 { |
|
537 unsigned i; |
|
538 for(i = 0; i < numcodes; i++) |
|
539 { |
|
540 Coin* coin; |
|
541 if(frequencies[i] == 0) continue; /*it's important to exclude symbols that aren't present*/ |
|
542 if(!vector_resize(coins, coins->size + 1)) { vector_cleanup(coins); return 9904; } |
|
543 coin = (Coin*)(vector_get(coins, coins->size - 1)); |
|
544 Coin_init(coin); |
|
545 coin->weight = frequencies[i] / (float)sum; |
|
546 uivector_push_back(&coin->symbols, i); |
|
547 } |
|
548 if(coins->size) Coin_sort((Coin*)coins->data, coins->size); |
|
549 return 0; |
|
550 } |
|
551 |
|
552 static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, size_t numcodes, unsigned maxbitlen) |
|
553 { |
|
554 unsigned i, j; |
|
555 size_t sum = 0, numpresent = 0; |
|
556 unsigned error = 0; |
|
557 |
|
558 vector prev_row; /*type Coin, the previous row of coins*/ |
|
559 vector coins; /*type Coin, the coins of the currently calculated row*/ |
|
560 |
|
561 tree->maxbitlen = maxbitlen; |
|
562 |
|
563 for(i = 0; i < numcodes; i++) |
|
564 { |
|
565 if(frequencies[i] > 0) |
|
566 { |
|
567 numpresent++; |
|
568 sum += frequencies[i]; |
|
569 } |
|
570 } |
|
571 |
|
572 if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ |
|
573 tree->numcodes = (unsigned)numcodes; /*number of symbols*/ |
|
574 uivector_resize(&tree->lengths, 0); |
|
575 if(!uivector_resizev(&tree->lengths, tree->numcodes, 0)) return 9905; |
|
576 |
|
577 if(numpresent == 0) /*there are no symbols at all, in that case add one symbol of value 0 to the tree (see RFC 1951 section 3.2.7) */ |
|
578 { |
|
579 tree->lengths.data[0] = 1; |
|
580 return HuffmanTree_makeFromLengths2(tree); |
|
581 } |
|
582 else if(numpresent == 1) /*the package merge algorithm gives wrong results if there's only one symbol (theoretically 0 bits would then suffice, but we need a proper symbol for zlib)*/ |
|
583 { |
|
584 for(i = 0; i < numcodes; i++) if(frequencies[i]) tree->lengths.data[i] = 1; |
|
585 return HuffmanTree_makeFromLengths2(tree); |
|
586 } |
|
587 |
|
588 vector_init(&coins, sizeof(Coin)); |
|
589 vector_init(&prev_row, sizeof(Coin)); |
|
590 |
|
591 /*Package-Merge algorithm represented by coin collector's problem |
|
592 For every symbol, maxbitlen coins will be created*/ |
|
593 |
|
594 /*first row, lowest denominator*/ |
|
595 error = HuffmanTree_fillInCoins(&coins, frequencies, tree->numcodes, sum); |
|
596 if(!error) |
|
597 { |
|
598 for(j = 1; j <= maxbitlen && !error; j++) /*each of the remaining rows*/ |
|
599 { |
|
600 vector_swap(&coins, &prev_row); /*swap instead of copying*/ |
|
601 if(!vector_resized(&coins, 0, Coin_cleanup)) { error = 9906; break; } |
|
602 |
|
603 for(i = 0; i + 1 < prev_row.size; i += 2) |
|
604 { |
|
605 if(!vector_resize(&coins, coins.size + 1)) { error = 9907; break; } |
|
606 Coin_init((Coin*)vector_get(&coins, coins.size - 1)); |
|
607 Coin_copy((Coin*)vector_get(&coins, coins.size - 1), (Coin*)vector_get(&prev_row, i)); |
|
608 addCoins((Coin*)vector_get(&coins, coins.size - 1), (Coin*)vector_get(&prev_row, i + 1)); /*merge the coins into packages*/ |
|
609 } |
|
610 if(j < maxbitlen) |
|
611 { |
|
612 error = HuffmanTree_fillInCoins(&coins, frequencies, tree->numcodes, sum); |
|
613 } |
|
614 } |
|
615 } |
|
616 |
|
617 if(!error) |
|
618 { |
|
619 /*keep the coins with lowest weight, so that they add up to the amount of symbols - 1*/ |
|
620 vector_resized(&coins, numpresent - 1, Coin_cleanup); |
|
621 |
|
622 /*calculate the lenghts of each symbol, as the amount of times a coin of each symbol is used*/ |
|
623 for(i = 0; i < coins.size; i++) |
|
624 { |
|
625 Coin* coin = (Coin*)vector_get(&coins, i); |
|
626 for(j = 0; j < coin->symbols.size; j++) tree->lengths.data[coin->symbols.data[j]]++; |
|
627 } |
|
628 |
|
629 error = HuffmanTree_makeFromLengths2(tree); |
|
630 } |
|
631 |
|
632 vector_cleanupd(&coins, Coin_cleanup); |
|
633 vector_cleanupd(&prev_row, Coin_cleanup); |
|
634 |
|
635 return error; |
|
636 } |
|
637 |
|
638 static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) { return tree->tree1d.data[index]; } |
|
639 static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) { return tree->lengths.data[index]; } |
|
640 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
641 |
|
642 /*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ |
|
643 static unsigned generateFixedTree(HuffmanTree* tree) |
|
644 { |
|
645 unsigned i, error = 0; |
|
646 uivector bitlen; |
|
647 uivector_init(&bitlen); |
|
648 if(!uivector_resize(&bitlen, NUM_DEFLATE_CODE_SYMBOLS)) error = 9909; |
|
649 |
|
650 if(!error) |
|
651 { |
|
652 /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ |
|
653 for(i = 0; i <= 143; i++) bitlen.data[i] = 8; |
|
654 for(i = 144; i <= 255; i++) bitlen.data[i] = 9; |
|
655 for(i = 256; i <= 279; i++) bitlen.data[i] = 7; |
|
656 for(i = 280; i <= 287; i++) bitlen.data[i] = 8; |
|
657 |
|
658 error = HuffmanTree_makeFromLengths(tree, bitlen.data, NUM_DEFLATE_CODE_SYMBOLS, 15); |
|
659 } |
|
660 |
|
661 uivector_cleanup(&bitlen); |
|
662 return error; |
|
663 } |
|
664 |
|
665 static unsigned generateDistanceTree(HuffmanTree* tree) |
|
666 { |
|
667 unsigned i, error = 0; |
|
668 uivector bitlen; |
|
669 uivector_init(&bitlen); |
|
670 if(!uivector_resize(&bitlen, NUM_DISTANCE_SYMBOLS)) error = 9910; |
|
671 |
|
672 /*there are 32 distance codes, but 30-31 are unused*/ |
|
673 if(!error) |
|
674 { |
|
675 for(i = 0; i < NUM_DISTANCE_SYMBOLS; i++) bitlen.data[i] = 5; |
|
676 error = HuffmanTree_makeFromLengths(tree, bitlen.data, NUM_DISTANCE_SYMBOLS, 15); |
|
677 } |
|
678 uivector_cleanup(&bitlen); |
|
679 return error; |
|
680 } |
|
681 |
|
682 #ifdef LODEPNG_COMPILE_DECODER |
|
683 /*Decodes a symbol from the tree |
|
684 if decoded is true, then result contains the symbol, otherwise it contains something unspecified (because the symbol isn't fully decoded yet) |
|
685 bit is the bit that was just read from the stream |
|
686 you have to decode a full symbol (let the decode function return true) before you can try to decode another one, otherwise the state isn't reset |
|
687 return value is error.*/ |
|
688 static unsigned HuffmanTree_decode(const HuffmanTree* tree, unsigned* decoded, unsigned* result, unsigned* treepos, unsigned char bit) |
|
689 { |
|
690 if((*treepos) >= tree->numcodes) return 11; /*error: it appeared outside the codetree*/ |
|
691 |
|
692 (*result) = tree->tree2d.data[2 * (*treepos) + bit]; |
|
693 (*decoded) = ((*result) < tree->numcodes); |
|
694 |
|
695 if(*decoded) (*treepos) = 0; |
|
696 else (*treepos) = (*result) - tree->numcodes; |
|
697 |
|
698 return 0; |
|
699 } |
|
700 |
|
701 static unsigned huffmanDecodeSymbol(unsigned int* error, const unsigned char* in, size_t* bp, const HuffmanTree* codetree, size_t inlength) |
|
702 { |
|
703 unsigned treepos = 0, decoded, ct; |
|
704 for(;;) |
|
705 { |
|
706 unsigned char bit; |
|
707 if(((*bp) & 0x07) == 0 && ((*bp) >> 3) > inlength) { *error = 10; return 0; } /*error: end of input memory reached without endcode*/ |
|
708 bit = readBitFromStream(bp, in); |
|
709 *error = HuffmanTree_decode(codetree, &decoded, &ct, &treepos, bit); |
|
710 if(*error) return 0; /*stop, an error happened*/ |
|
711 if(decoded) return ct; |
|
712 } |
|
713 } |
|
714 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
715 |
|
716 #ifdef LODEPNG_COMPILE_DECODER |
|
717 |
|
718 /* ////////////////////////////////////////////////////////////////////////// */ |
|
719 /* / Inflator / */ |
|
720 /* ////////////////////////////////////////////////////////////////////////// */ |
|
721 |
|
722 /*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ |
|
723 static void getTreeInflateFixed(HuffmanTree* tree, HuffmanTree* treeD) |
|
724 { |
|
725 /*error checking not done, this is fixed stuff, it works, it doesn't depend on the image*/ |
|
726 generateFixedTree(tree); |
|
727 generateDistanceTree(treeD); |
|
728 } |
|
729 |
|
730 /*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ |
|
731 static unsigned getTreeInflateDynamic(HuffmanTree* codetree, HuffmanTree* codetreeD, HuffmanTree* codelengthcodetree, |
|
732 const unsigned char* in, size_t* bp, size_t inlength) |
|
733 { |
|
734 /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ |
|
735 /*C-code note: use no "return" between ctor and dtor of an uivector!*/ |
|
736 unsigned error = 0; |
|
737 unsigned n, HLIT, HDIST, HCLEN, i; |
|
738 uivector bitlen; |
|
739 uivector bitlenD; |
|
740 uivector codelengthcode; |
|
741 |
|
742 if((*bp) >> 3 >= inlength - 2) { return 49; } /*the bit pointer is or will go past the memory*/ |
|
743 |
|
744 HLIT = readBitsFromStream(bp, in, 5) + 257; /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ |
|
745 HDIST = readBitsFromStream(bp, in, 5) + 1; /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ |
|
746 HCLEN = readBitsFromStream(bp, in, 4) + 4; /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ |
|
747 |
|
748 /*read the code length codes out of 3 * (amount of code length codes) bits*/ |
|
749 uivector_init(&codelengthcode); |
|
750 if(!uivector_resize(&codelengthcode, NUM_CODE_LENGTH_CODES)) error = 9911; |
|
751 |
|
752 if(!error) |
|
753 { |
|
754 for(i = 0; i < NUM_CODE_LENGTH_CODES; i++) |
|
755 { |
|
756 if(i < HCLEN) codelengthcode.data[CLCL[i]] = readBitsFromStream(bp, in, 3); |
|
757 else codelengthcode.data[CLCL[i]] = 0; /*if not, it must stay 0*/ |
|
758 } |
|
759 |
|
760 error = HuffmanTree_makeFromLengths(codelengthcodetree, codelengthcode.data, codelengthcode.size, 7); |
|
761 } |
|
762 |
|
763 uivector_cleanup(&codelengthcode); |
|
764 if(error) return error; |
|
765 |
|
766 /*now we can use this tree to read the lengths for the tree that this function will return*/ |
|
767 uivector_init(&bitlen); |
|
768 uivector_resizev(&bitlen, NUM_DEFLATE_CODE_SYMBOLS, 0); |
|
769 uivector_init(&bitlenD); |
|
770 uivector_resizev(&bitlenD, NUM_DISTANCE_SYMBOLS, 0); |
|
771 i = 0; |
|
772 if(!bitlen.data || !bitlenD.data) error = 9912; |
|
773 else while(i < HLIT + HDIST) /*i is the current symbol we're reading in the part that contains the code lengths of lit/len codes and dist codes*/ |
|
774 { |
|
775 unsigned code = huffmanDecodeSymbol(&error, in, bp, codelengthcodetree, inlength); |
|
776 if(error) break; |
|
777 |
|
778 if(code <= 15) /*a length code*/ |
|
779 { |
|
780 if(i < HLIT) bitlen.data[i] = code; |
|
781 else bitlenD.data[i - HLIT] = code; |
|
782 i++; |
|
783 } |
|
784 else if(code == 16) /*repeat previous*/ |
|
785 { |
|
786 unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ |
|
787 unsigned value; /*set value to the previous code*/ |
|
788 |
|
789 if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/ |
|
790 |
|
791 replength += readBitsFromStream(bp, in, 2); |
|
792 |
|
793 if((i - 1) < HLIT) value = bitlen.data[i - 1]; |
|
794 else value = bitlenD.data[i - HLIT - 1]; |
|
795 /*repeat this value in the next lengths*/ |
|
796 for(n = 0; n < replength; n++) |
|
797 { |
|
798 if(i >= HLIT + HDIST) { error = 13; break; } /*error: i is larger than the amount of codes*/ |
|
799 if(i < HLIT) bitlen.data[i] = value; |
|
800 else bitlenD.data[i - HLIT] = value; |
|
801 i++; |
|
802 } |
|
803 } |
|
804 else if(code == 17) /*repeat "0" 3-10 times*/ |
|
805 { |
|
806 unsigned replength = 3; /*read in the bits that indicate repeat length*/ |
|
807 if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/ |
|
808 |
|
809 replength += readBitsFromStream(bp, in, 3); |
|
810 |
|
811 /*repeat this value in the next lengths*/ |
|
812 for(n = 0; n < replength; n++) |
|
813 { |
|
814 if(i >= HLIT + HDIST) { error = 14; break; } /*error: i is larger than the amount of codes*/ |
|
815 if(i < HLIT) bitlen.data[i] = 0; |
|
816 else bitlenD.data[i - HLIT] = 0; |
|
817 i++; |
|
818 } |
|
819 } |
|
820 else if(code == 18) /*repeat "0" 11-138 times*/ |
|
821 { |
|
822 unsigned replength = 11; /*read in the bits that indicate repeat length*/ |
|
823 if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/ |
|
824 replength += readBitsFromStream(bp, in, 7); |
|
825 |
|
826 /*repeat this value in the next lengths*/ |
|
827 for(n = 0; n < replength; n++) |
|
828 { |
|
829 if(i >= HLIT + HDIST) { error = 15; break; } /*error: i is larger than the amount of codes*/ |
|
830 if(i < HLIT) bitlen.data[i] = 0; |
|
831 else bitlenD.data[i - HLIT] = 0; |
|
832 i++; |
|
833 } |
|
834 } |
|
835 else { error = 16; break; } /*error: somehow an unexisting code appeared. This can never happen.*/ |
|
836 } |
|
837 |
|
838 if(!error && bitlen.data[256] == 0) { error = 64; } /*the length of the end code 256 must be larger than 0*/ |
|
839 |
|
840 /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ |
|
841 if(!error) error = HuffmanTree_makeFromLengths(codetree, &bitlen.data[0], bitlen.size, 15); |
|
842 if(!error) error = HuffmanTree_makeFromLengths(codetreeD, &bitlenD.data[0], bitlenD.size, 15); |
|
843 |
|
844 uivector_cleanup(&bitlen); |
|
845 uivector_cleanup(&bitlenD); |
|
846 |
|
847 return error; |
|
848 } |
|
849 |
|
850 /*inflate a block with dynamic of fixed Huffman tree*/ |
|
851 static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength, unsigned btype) |
|
852 { |
|
853 unsigned endreached = 0, error = 0; |
|
854 HuffmanTree codetree; /*287, the code tree for Huffman codes*/ |
|
855 HuffmanTree codetreeD; /*31, the code tree for distance codes*/ |
|
856 |
|
857 HuffmanTree_init(&codetree); |
|
858 HuffmanTree_init(&codetreeD); |
|
859 |
|
860 if(btype == 1) getTreeInflateFixed(&codetree, &codetreeD); |
|
861 else if(btype == 2) |
|
862 { |
|
863 HuffmanTree codelengthcodetree; /*18, the code tree for code length codes*/ |
|
864 HuffmanTree_init(&codelengthcodetree); |
|
865 error = getTreeInflateDynamic(&codetree, &codetreeD, &codelengthcodetree, in, bp, inlength); |
|
866 HuffmanTree_cleanup(&codelengthcodetree); |
|
867 } |
|
868 |
|
869 while(!endreached && !error) |
|
870 { |
|
871 unsigned code = huffmanDecodeSymbol(&error, in, bp, &codetree, inlength); |
|
872 if(error) break; /*some error happened in the above function*/ |
|
873 if(code == 256) endreached = 1; /*end code*/ |
|
874 else if(code <= 255) /*literal symbol*/ |
|
875 { |
|
876 if((*pos) >= out->size) ucvector_resize(out, ((*pos) + 1) * 2); /*reserve more room at once*/ |
|
877 if((*pos) >= out->size) { error = 9913; break; } /*not enough memory*/ |
|
878 out->data[(*pos)] = (unsigned char)(code); |
|
879 (*pos)++; |
|
880 } |
|
881 else if(code >= FIRST_LENGTH_CODE_INDEX && code <= LAST_LENGTH_CODE_INDEX) /*length code*/ |
|
882 { |
|
883 /*part 1: get length base*/ |
|
884 size_t length = LENGTHBASE[code - FIRST_LENGTH_CODE_INDEX]; |
|
885 unsigned codeD, distance, numextrabitsD; |
|
886 size_t start, forward, backward, numextrabits; |
|
887 |
|
888 /*part 2: get extra bits and add the value of that to length*/ |
|
889 numextrabits = LENGTHEXTRA[code - FIRST_LENGTH_CODE_INDEX]; |
|
890 if(((*bp) >> 3) >= inlength) { error = 51; break; } /*error, bit pointer will jump past memory*/ |
|
891 length += readBitsFromStream(bp, in, numextrabits); |
|
892 |
|
893 /*part 3: get distance code*/ |
|
894 codeD = huffmanDecodeSymbol(&error, in, bp, &codetreeD, inlength); |
|
895 if(error) break; |
|
896 if(codeD > 29) { error = 18; break; } /*error: invalid distance code (30-31 are never used)*/ |
|
897 distance = DISTANCEBASE[codeD]; |
|
898 |
|
899 /*part 4: get extra bits from distance*/ |
|
900 numextrabitsD = DISTANCEEXTRA[codeD]; |
|
901 if(((*bp) >> 3) >= inlength) { error = 51; break; } /*error, bit pointer will jump past memory*/ |
|
902 distance += readBitsFromStream(bp, in, numextrabitsD); |
|
903 |
|
904 /*part 5: fill in all the out[n] values based on the length and dist*/ |
|
905 start = (*pos); |
|
906 backward = start - distance; |
|
907 if((*pos) + length >= out->size) ucvector_resize(out, ((*pos) + length) * 2); /*reserve more room at once*/ |
|
908 if((*pos) + length >= out->size) { error = 9914; break; } /*not enough memory*/ |
|
909 |
|
910 for(forward = 0; forward < length; forward++) |
|
911 { |
|
912 out->data[(*pos)] = out->data[backward]; |
|
913 (*pos)++; |
|
914 backward++; |
|
915 if(backward >= start) backward = start - distance; |
|
916 } |
|
917 } |
|
918 } |
|
919 |
|
920 HuffmanTree_cleanup(&codetree); |
|
921 HuffmanTree_cleanup(&codetreeD); |
|
922 |
|
923 return error; |
|
924 } |
|
925 |
|
926 static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) |
|
927 { |
|
928 /*go to first boundary of byte*/ |
|
929 size_t p; |
|
930 unsigned LEN, NLEN, n, error = 0; |
|
931 while(((*bp) & 0x7) != 0) (*bp)++; |
|
932 p = (*bp) / 8; /*byte position*/ |
|
933 |
|
934 /*read LEN (2 bytes) and NLEN (2 bytes)*/ |
|
935 if(p >= inlength - 4) return 52; /*error, bit pointer will jump past memory*/ |
|
936 LEN = in[p] + 256 * in[p + 1]; p += 2; |
|
937 NLEN = in[p] + 256 * in[p + 1]; p += 2; |
|
938 |
|
939 /*check if 16-bit NLEN is really the one's complement of LEN*/ |
|
940 if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/ |
|
941 |
|
942 if((*pos) + LEN >= out->size) { if(!ucvector_resize(out, (*pos) + LEN)) return 9915; } |
|
943 |
|
944 /*read the literal data: LEN bytes are now stored in the out buffer*/ |
|
945 if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/ |
|
946 for(n = 0; n < LEN; n++) out->data[(*pos)++] = in[p++]; |
|
947 |
|
948 (*bp) = p * 8; |
|
949 |
|
950 return error; |
|
951 } |
|
952 |
|
953 /*inflate the deflated data (cfr. deflate spec); return value is the error*/ |
|
954 unsigned LodeFlate_inflate(ucvector* out, const unsigned char* in, size_t insize, size_t inpos) |
|
955 { |
|
956 size_t bp = 0; /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/ |
|
957 unsigned BFINAL = 0; |
|
958 size_t pos = 0; /*byte position in the out buffer*/ |
|
959 |
|
960 unsigned error = 0; |
|
961 |
|
962 while(!BFINAL) |
|
963 { |
|
964 unsigned BTYPE; |
|
965 if((bp >> 3) >= insize) return 52; /*error, bit pointer will jump past memory*/ |
|
966 BFINAL = readBitFromStream(&bp, &in[inpos]); |
|
967 BTYPE = 1 * readBitFromStream(&bp, &in[inpos]); BTYPE += 2 * readBitFromStream(&bp, &in[inpos]); |
|
968 |
|
969 if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ |
|
970 else if(BTYPE == 0) error = inflateNoCompression(out, &in[inpos], &bp, &pos, insize); /*no compression*/ |
|
971 else error = inflateHuffmanBlock(out, &in[inpos], &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/ |
|
972 if(error) return error; |
|
973 } |
|
974 |
|
975 if(!ucvector_resize(out, pos)) error = 9916; /*Only now we know the true size of out, resize it to that*/ |
|
976 |
|
977 return error; |
|
978 } |
|
979 |
|
980 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
981 |
|
982 #ifdef LODEPNG_COMPILE_ENCODER |
|
983 |
|
984 /* ////////////////////////////////////////////////////////////////////////// */ |
|
985 /* / Deflator / */ |
|
986 /* ////////////////////////////////////////////////////////////////////////// */ |
|
987 |
|
988 static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; |
|
989 |
|
990 /*bitlen is the size in bits of the code*/ |
|
991 static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) |
|
992 { |
|
993 addBitsToStreamReversed(bp, compressed, code, bitlen); |
|
994 } |
|
995 |
|
996 /*search the index in the array, that has the largest value smaller than or equal to the given value, given array must be sorted (if no value is smaller, it returns the size of the given array)*/ |
|
997 static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) |
|
998 { |
|
999 /*linear search implementation*/ |
|
1000 /*for(size_t i = 1; i < array_size; i++) if(array[i] > value) return i - 1; |
|
1001 return array_size - 1;*/ |
|
1002 |
|
1003 /*binary search implementation (not that much faster) (precondition: array_size > 0)*/ |
|
1004 size_t left = 1; |
|
1005 size_t right = array_size - 1; |
|
1006 while(left <= right) |
|
1007 { |
|
1008 size_t mid = (left + right) / 2; |
|
1009 if(array[mid] <= value) left = mid + 1; /*the value to find is more to the right*/ |
|
1010 else if(array[mid - 1] > value) right = mid - 1; /*the value to find is more to the left*/ |
|
1011 else return mid - 1; |
|
1012 } |
|
1013 return array_size - 1; |
|
1014 } |
|
1015 |
|
1016 static void addLengthDistance(uivector* values, size_t length, size_t distance) |
|
1017 { |
|
1018 /*values in encoded vector are those used by deflate: |
|
1019 0-255: literal bytes |
|
1020 256: end |
|
1021 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) |
|
1022 286-287: invalid*/ |
|
1023 |
|
1024 unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); |
|
1025 unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); |
|
1026 unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); |
|
1027 unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); |
|
1028 |
|
1029 uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX); |
|
1030 uivector_push_back(values, extra_length); |
|
1031 uivector_push_back(values, dist_code); |
|
1032 uivector_push_back(values, extra_distance); |
|
1033 } |
|
1034 |
|
1035 #if 0 |
|
1036 /*the "brute force" version of the encodeLZ7 algorithm, not used anymore, kept here for reference*/ |
|
1037 static void encodeLZ77_brute(uivector* out, const unsigned char* in, size_t size, unsigned windowSize) |
|
1038 { |
|
1039 size_t pos; |
|
1040 /*using pointer instead of vector for input makes it faster when NOT using optimization when compiling; no influence if optimization is used*/ |
|
1041 for(pos = 0; pos < size; pos++) |
|
1042 { |
|
1043 size_t length = 0, offset = 0; /*the length and offset found for the current position*/ |
|
1044 size_t max_offset = pos < windowSize ? pos : windowSize; /*how far back to test*/ |
|
1045 size_t current_offset; |
|
1046 |
|
1047 /**search for the longest string**/ |
|
1048 for(current_offset = 1; current_offset < max_offset; current_offset++) /*search backwards through all possible distances (=offsets)*/ |
|
1049 { |
|
1050 size_t backpos = pos - current_offset; |
|
1051 if(in[backpos] == in[pos]) |
|
1052 { |
|
1053 /*test the next characters*/ |
|
1054 size_t current_length = 1; |
|
1055 size_t backtest = backpos + 1; |
|
1056 size_t foretest = pos + 1; |
|
1057 while(foretest < size && in[backtest] == in[foretest] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) /*maximum supporte length by deflate is max length*/ |
|
1058 { |
|
1059 if(backpos >= pos) backpos -= current_offset; /*continue as if we work on the decoded bytes after pos by jumping back before pos*/ |
|
1060 current_length++; |
|
1061 backtest++; |
|
1062 foretest++; |
|
1063 } |
|
1064 if(current_length > length) |
|
1065 { |
|
1066 length = current_length; /*the longest length*/ |
|
1067 offset = current_offset; /*the offset that is related to this longest length*/ |
|
1068 if(current_length == MAX_SUPPORTED_DEFLATE_LENGTH) break; /*you can jump out of this for loop once a length of max length is found (gives significant speed gain)*/ |
|
1069 } |
|
1070 } |
|
1071 } |
|
1072 |
|
1073 /**encode it as length/distance pair or literal value**/ |
|
1074 if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ |
|
1075 { |
|
1076 uivector_push_back(out, in[pos]); |
|
1077 } |
|
1078 else |
|
1079 { |
|
1080 addLengthDistance(out, length, offset); |
|
1081 pos += (length - 1); |
|
1082 } |
|
1083 } /*end of the loop through each character of input*/ |
|
1084 } |
|
1085 #endif |
|
1086 |
|
1087 static const unsigned HASH_NUM_VALUES = 65536; |
|
1088 static const unsigned HASH_NUM_CHARACTERS = 6; |
|
1089 static const unsigned HASH_SHIFT = 2; |
|
1090 /* |
|
1091 Good and fast values: HASH_NUM_VALUES=65536, HASH_NUM_CHARACTERS=6, HASH_SHIFT=2 |
|
1092 making HASH_NUM_CHARACTERS larger (like 8), makes the file size larger but is a bit faster |
|
1093 making HASH_NUM_CHARACTERS smaller (like 3), makes the file size smaller but is slower |
|
1094 */ |
|
1095 |
|
1096 static unsigned getHash(const unsigned char* data, size_t size, size_t pos) |
|
1097 { |
|
1098 unsigned result = 0; |
|
1099 size_t amount, i; |
|
1100 if(pos >= size) return 0; |
|
1101 amount = HASH_NUM_CHARACTERS; if(pos + amount >= size) amount = size - pos; |
|
1102 for(i = 0; i < amount; i++) result ^= (data[pos + i] << (i * HASH_SHIFT)); |
|
1103 return result % HASH_NUM_VALUES; |
|
1104 } |
|
1105 |
|
1106 /*LZ77-encode the data using a hash table technique to let it encode faster. Return value is error code*/ |
|
1107 static unsigned encodeLZ77(uivector* out, const unsigned char* in, size_t size, unsigned windowSize) |
|
1108 { |
|
1109 /**generate hash table**/ |
|
1110 vector table; /*HASH_NUM_VALUES uivectors; this represents what would be an std::vector<std::vector<unsigned> > in C++*/ |
|
1111 uivector tablepos1, tablepos2; |
|
1112 unsigned pos, i, error = 0; |
|
1113 |
|
1114 vector_init(&table, sizeof(uivector)); |
|
1115 if(!vector_resize(&table, HASH_NUM_VALUES)) return 9917; |
|
1116 for(i = 0; i < HASH_NUM_VALUES; i++) |
|
1117 { |
|
1118 uivector* v = (uivector*)vector_get(&table, i); |
|
1119 uivector_init(v); |
|
1120 } |
|
1121 |
|
1122 /*remember start and end positions in the tables to searching in*/ |
|
1123 uivector_init(&tablepos1); |
|
1124 uivector_init(&tablepos2); |
|
1125 if(!uivector_resizev(&tablepos1, HASH_NUM_VALUES, 0)) error = 9918; |
|
1126 if(!uivector_resizev(&tablepos2, HASH_NUM_VALUES, 0)) error = 9919; |
|
1127 |
|
1128 if(!error) |
|
1129 { |
|
1130 for(pos = 0; pos < size; pos++) |
|
1131 { |
|
1132 unsigned length = 0, offset = 0; /*the length and offset found for the current position*/ |
|
1133 unsigned max_offset = pos < windowSize ? pos : windowSize; /*how far back to test*/ |
|
1134 unsigned tablepos; |
|
1135 |
|
1136 /*/search for the longest string*/ |
|
1137 /*first find out where in the table to start (the first value that is in the range from "pos - max_offset" to "pos")*/ |
|
1138 unsigned hash = getHash(in, size, pos); |
|
1139 if(!uivector_push_back((uivector*)vector_get(&table, hash), pos)) { error = 9920; break; } |
|
1140 |
|
1141 while(((uivector*)vector_get(&table, hash))->data[tablepos1.data[hash]] < pos - max_offset) tablepos1.data[hash]++; /*it now points to the first value in the table for which the index is larger than or equal to pos - max_offset*/ |
|
1142 while(((uivector*)vector_get(&table, hash))->data[tablepos2.data[hash]] < pos) tablepos2.data[hash]++; /*it now points to the first value in the table for which the index is larger than or equal to pos*/ |
|
1143 |
|
1144 for(tablepos = tablepos2.data[hash] - 1; tablepos >= tablepos1.data[hash] && tablepos < tablepos2.data[hash]; tablepos--) |
|
1145 { |
|
1146 unsigned backpos = ((uivector*)vector_get(&table, hash))->data[tablepos]; |
|
1147 unsigned current_offset = pos - backpos; |
|
1148 |
|
1149 /*test the next characters*/ |
|
1150 unsigned current_length = 0; |
|
1151 unsigned backtest = backpos; |
|
1152 unsigned foretest = pos; |
|
1153 while(foretest < size && in[backtest] == in[foretest] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) /*maximum supporte length by deflate is max length*/ |
|
1154 { |
|
1155 if(backpos >= pos) backpos -= current_offset; /*continue as if we work on the decoded bytes after pos by jumping back before pos*/ |
|
1156 current_length++; |
|
1157 backtest++; |
|
1158 foretest++; |
|
1159 } |
|
1160 if(current_length > length) |
|
1161 { |
|
1162 length = current_length; /*the longest length*/ |
|
1163 offset = current_offset; /*the offset that is related to this longest length*/ |
|
1164 if(current_length == MAX_SUPPORTED_DEFLATE_LENGTH) break; /*you can jump out of this for loop once a length of max length is found (gives significant speed gain)*/ |
|
1165 } |
|
1166 } |
|
1167 |
|
1168 /**encode it as length/distance pair or literal value**/ |
|
1169 if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ |
|
1170 { |
|
1171 if(!uivector_push_back(out, in[pos])) { error = 9921; break; } |
|
1172 } |
|
1173 else |
|
1174 { |
|
1175 unsigned j; |
|
1176 addLengthDistance(out, length, offset); |
|
1177 for(j = 0; j < length - 1; j++) |
|
1178 { |
|
1179 pos++; |
|
1180 if(!uivector_push_back((uivector*)vector_get(&table, getHash(in, size, pos)), pos)) { error = 9922; break; } |
|
1181 } |
|
1182 } |
|
1183 } /*end of the loop through each character of input*/ |
|
1184 } /*end of "if(!error)"*/ |
|
1185 |
|
1186 /*cleanup*/ |
|
1187 for(i = 0; i < table.size; i++) |
|
1188 { |
|
1189 uivector* v = (uivector*)vector_get(&table, i); |
|
1190 uivector_cleanup(v); |
|
1191 } |
|
1192 vector_cleanup(&table); |
|
1193 uivector_cleanup(&tablepos1); |
|
1194 uivector_cleanup(&tablepos2); |
|
1195 return error; |
|
1196 } |
|
1197 |
|
1198 /* /////////////////////////////////////////////////////////////////////////// */ |
|
1199 |
|
1200 static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) |
|
1201 { |
|
1202 /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ |
|
1203 |
|
1204 size_t i, j, numdeflateblocks = datasize / 65536 + 1; |
|
1205 unsigned datapos = 0; |
|
1206 for(i = 0; i < numdeflateblocks; i++) |
|
1207 { |
|
1208 unsigned BFINAL, BTYPE, LEN, NLEN; |
|
1209 unsigned char firstbyte; |
|
1210 |
|
1211 BFINAL = (i == numdeflateblocks - 1); |
|
1212 BTYPE = 0; |
|
1213 |
|
1214 firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); |
|
1215 ucvector_push_back(out, firstbyte); |
|
1216 |
|
1217 LEN = 65535; |
|
1218 if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; |
|
1219 NLEN = 65535 - LEN; |
|
1220 |
|
1221 ucvector_push_back(out, (unsigned char)(LEN % 256)); |
|
1222 ucvector_push_back(out, (unsigned char)(LEN / 256)); |
|
1223 ucvector_push_back(out, (unsigned char)(NLEN % 256)); |
|
1224 ucvector_push_back(out, (unsigned char)(NLEN / 256)); |
|
1225 |
|
1226 /*Decompressed data*/ |
|
1227 for(j = 0; j < 65535 && datapos < datasize; j++) |
|
1228 { |
|
1229 ucvector_push_back(out, data[datapos++]); |
|
1230 } |
|
1231 } |
|
1232 |
|
1233 return 0; |
|
1234 } |
|
1235 |
|
1236 /*write the encoded data, using lit/len as well as distance codes*/ |
|
1237 static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded, const HuffmanTree* codes, const HuffmanTree* codesD) |
|
1238 { |
|
1239 size_t i = 0; |
|
1240 for(i = 0; i < lz77_encoded->size; i++) |
|
1241 { |
|
1242 unsigned val = lz77_encoded->data[i]; |
|
1243 addHuffmanSymbol(bp, out, HuffmanTree_getCode(codes, val), HuffmanTree_getLength(codes, val)); |
|
1244 if(val > 256) /*for a length code, 3 more things have to be added*/ |
|
1245 { |
|
1246 unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; |
|
1247 unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; |
|
1248 unsigned length_extra_bits = lz77_encoded->data[++i]; |
|
1249 |
|
1250 unsigned distance_code = lz77_encoded->data[++i]; |
|
1251 |
|
1252 unsigned distance_index = distance_code; |
|
1253 unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; |
|
1254 unsigned distance_extra_bits = lz77_encoded->data[++i]; |
|
1255 |
|
1256 addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits); |
|
1257 addHuffmanSymbol(bp, out, HuffmanTree_getCode(codesD, distance_code), HuffmanTree_getLength(codesD, distance_code)); |
|
1258 addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits); |
|
1259 } |
|
1260 } |
|
1261 } |
|
1262 |
|
1263 static unsigned deflateDynamic(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) |
|
1264 { |
|
1265 /* |
|
1266 after the BFINAL and BTYPE, the dynamic block consists out of the following: |
|
1267 - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN |
|
1268 - (HCLEN+4)*3 bits code lengths of code length alphabet |
|
1269 - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length alphabet, + possible repetition codes 16, 17, 18) |
|
1270 - HDIST + 1 code lengths of distance alphabet (encoded using the code length alphabet, + possible repetition codes 16, 17, 18) |
|
1271 - compressed data |
|
1272 - 256 (end code) |
|
1273 */ |
|
1274 |
|
1275 unsigned error = 0; |
|
1276 |
|
1277 uivector lz77_encoded; |
|
1278 HuffmanTree codes; /*tree for literal values and length codes*/ |
|
1279 HuffmanTree codesD; /*tree for distance codes*/ |
|
1280 HuffmanTree codelengthcodes; |
|
1281 uivector frequencies; |
|
1282 uivector frequenciesD; |
|
1283 uivector amounts; /*the amounts in the "normal" order*/ |
|
1284 uivector lldl; |
|
1285 uivector lldll; /*lit/len & dist code lenghts*/ |
|
1286 uivector clcls; |
|
1287 |
|
1288 unsigned BFINAL = 1; /*make only one block... the first and final one*/ |
|
1289 size_t numcodes, numcodesD, i, bp = 0; /*the bit pointer*/ |
|
1290 unsigned HLIT, HDIST, HCLEN; |
|
1291 |
|
1292 uivector_init(&lz77_encoded); |
|
1293 HuffmanTree_init(&codes); |
|
1294 HuffmanTree_init(&codesD); |
|
1295 HuffmanTree_init(&codelengthcodes); |
|
1296 uivector_init(&frequencies); |
|
1297 uivector_init(&frequenciesD); |
|
1298 uivector_init(&amounts); |
|
1299 uivector_init(&lldl); |
|
1300 uivector_init(&lldll); |
|
1301 uivector_init(&clcls); |
|
1302 |
|
1303 while(!error) /*the goto-avoiding while construct: break out to go to the cleanup phase, a break at the end makes sure the while is never repeated*/ |
|
1304 { |
|
1305 if(settings->useLZ77) |
|
1306 { |
|
1307 error = encodeLZ77(&lz77_encoded, data, datasize, settings->windowSize); /*LZ77 encoded*/ |
|
1308 if(error) break; |
|
1309 } |
|
1310 else |
|
1311 { |
|
1312 if(!uivector_resize(&lz77_encoded, datasize)) { error = 9923; break; } |
|
1313 for(i = 0; i < datasize; i++) lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/ |
|
1314 } |
|
1315 |
|
1316 if(!uivector_resizev(&frequencies, 286, 0)) { error = 9924; break; } |
|
1317 if(!uivector_resizev(&frequenciesD, 30, 0)) { error = 9925; break; } |
|
1318 for(i = 0; i < lz77_encoded.size; i++) |
|
1319 { |
|
1320 unsigned symbol = lz77_encoded.data[i]; |
|
1321 frequencies.data[symbol]++; |
|
1322 if(symbol > 256) |
|
1323 { |
|
1324 unsigned dist = lz77_encoded.data[i + 2]; |
|
1325 frequenciesD.data[dist]++; |
|
1326 i += 3; |
|
1327 } |
|
1328 } |
|
1329 frequencies.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ |
|
1330 |
|
1331 error = HuffmanTree_makeFromFrequencies(&codes, frequencies.data, frequencies.size, 15); |
|
1332 if(error) break; |
|
1333 error = HuffmanTree_makeFromFrequencies(&codesD, frequenciesD.data, frequenciesD.size, 15); |
|
1334 if(error) break; |
|
1335 |
|
1336 addBitToStream(&bp, out, BFINAL); |
|
1337 addBitToStream(&bp, out, 0); /*first bit of BTYPE "dynamic"*/ |
|
1338 addBitToStream(&bp, out, 1); /*second bit of BTYPE "dynamic"*/ |
|
1339 |
|
1340 numcodes = codes.numcodes; if(numcodes > 286) numcodes = 286; |
|
1341 numcodesD = codesD.numcodes; if(numcodesD > 30) numcodesD = 30; |
|
1342 for(i = 0; i < numcodes; i++) uivector_push_back(&lldll, HuffmanTree_getLength(&codes, (unsigned)i)); |
|
1343 for(i = 0; i < numcodesD; i++) uivector_push_back(&lldll, HuffmanTree_getLength(&codesD, (unsigned)i)); |
|
1344 |
|
1345 /*make lldl smaller by using repeat codes 16 (copy length 3-6 times), 17 (3-10 zeroes), 18 (11-138 zeroes)*/ |
|
1346 for(i = 0; i < (unsigned)lldll.size; i++) |
|
1347 { |
|
1348 unsigned j = 0; |
|
1349 while(i + j + 1 < (unsigned)lldll.size && lldll.data[i + j + 1] == lldll.data[i]) j++; |
|
1350 |
|
1351 if(lldll.data[i] == 0 && j >= 2) |
|
1352 { |
|
1353 j++; /*include the first zero*/ |
|
1354 if(j <= 10) { uivector_push_back(&lldl, 17); uivector_push_back(&lldl, j - 3); } |
|
1355 else |
|
1356 { |
|
1357 if(j > 138) j = 138; |
|
1358 uivector_push_back(&lldl, 18); uivector_push_back(&lldl, j - 11); |
|
1359 } |
|
1360 i += (j - 1); |
|
1361 } |
|
1362 else if(j >= 3) |
|
1363 { |
|
1364 size_t k; |
|
1365 unsigned num = j / 6, rest = j % 6; |
|
1366 uivector_push_back(&lldl, lldll.data[i]); |
|
1367 for(k = 0; k < num; k++) { uivector_push_back(&lldl, 16); uivector_push_back(&lldl, 6 - 3); } |
|
1368 if(rest >= 3) { uivector_push_back(&lldl, 16); uivector_push_back(&lldl, rest - 3); } |
|
1369 else j -= rest; |
|
1370 i += j; |
|
1371 } |
|
1372 else uivector_push_back(&lldl, lldll.data[i]); |
|
1373 } |
|
1374 |
|
1375 /*generate huffmantree for the length codes of lit/len and dist codes*/ |
|
1376 if(!uivector_resizev(&amounts, 19, 0)) { error = 9926; break; } /*16 possible lengths (0-15) and 3 repeat codes (16, 17 and 18)*/ |
|
1377 for(i = 0; i < lldl.size; i++) |
|
1378 { |
|
1379 amounts.data[lldl.data[i]]++; |
|
1380 if(lldl.data[i] >= 16) i++; /*after a repeat code come the bits that specify the amount, those don't need to be in the amounts calculation*/ |
|
1381 } |
|
1382 |
|
1383 error = HuffmanTree_makeFromFrequencies(&codelengthcodes, amounts.data, amounts.size, 7); |
|
1384 if(error) break; |
|
1385 |
|
1386 if(!uivector_resize(&clcls, 19)) { error = 9927; break; } |
|
1387 for(i = 0; i < 19; i++) clcls.data[i] = HuffmanTree_getLength(&codelengthcodes, CLCL[i]); /*lenghts of code length tree is in the order as specified by deflate*/ |
|
1388 while(clcls.data[clcls.size - 1] == 0 && clcls.size > 4) |
|
1389 { |
|
1390 if(!uivector_resize(&clcls, clcls.size - 1)) { error = 9928; break; } /*remove zeros at the end, but minimum size must be 4*/ |
|
1391 } |
|
1392 if(error) break; |
|
1393 |
|
1394 /*write the HLIT, HDIST and HCLEN values*/ |
|
1395 HLIT = (unsigned)(numcodes - 257); |
|
1396 HDIST = (unsigned)(numcodesD - 1); |
|
1397 HCLEN = (unsigned)clcls.size - 4; |
|
1398 addBitsToStream(&bp, out, HLIT, 5); |
|
1399 addBitsToStream(&bp, out, HDIST, 5); |
|
1400 addBitsToStream(&bp, out, HCLEN, 4); |
|
1401 |
|
1402 /*write the code lenghts of the code length alphabet*/ |
|
1403 for(i = 0; i < HCLEN + 4; i++) addBitsToStream(&bp, out, clcls.data[i], 3); |
|
1404 |
|
1405 /*write the lenghts of the lit/len AND the dist alphabet*/ |
|
1406 for(i = 0; i < lldl.size; i++) |
|
1407 { |
|
1408 addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codelengthcodes, lldl.data[i]), HuffmanTree_getLength(&codelengthcodes, lldl.data[i])); |
|
1409 /*extra bits of repeat codes*/ |
|
1410 if(lldl.data[i] == 16) addBitsToStream(&bp, out, lldl.data[++i], 2); |
|
1411 else if(lldl.data[i] == 17) addBitsToStream(&bp, out, lldl.data[++i], 3); |
|
1412 else if(lldl.data[i] == 18) addBitsToStream(&bp, out, lldl.data[++i], 7); |
|
1413 } |
|
1414 |
|
1415 /*write the compressed data symbols*/ |
|
1416 writeLZ77data(&bp, out, &lz77_encoded, &codes, &codesD); |
|
1417 if(HuffmanTree_getLength(&codes, 256) == 0) { error = 64; break; } /*the length of the end code 256 must be larger than 0*/ |
|
1418 addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, 256), HuffmanTree_getLength(&codes, 256)); /*end code*/ |
|
1419 |
|
1420 break; /*end of error-while*/ |
|
1421 } |
|
1422 |
|
1423 /*cleanup*/ |
|
1424 uivector_cleanup(&lz77_encoded); |
|
1425 HuffmanTree_cleanup(&codes); |
|
1426 HuffmanTree_cleanup(&codesD); |
|
1427 HuffmanTree_cleanup(&codelengthcodes); |
|
1428 uivector_cleanup(&frequencies); |
|
1429 uivector_cleanup(&frequenciesD); |
|
1430 uivector_cleanup(&amounts); |
|
1431 uivector_cleanup(&lldl); |
|
1432 uivector_cleanup(&lldll); |
|
1433 uivector_cleanup(&clcls); |
|
1434 |
|
1435 return error; |
|
1436 } |
|
1437 |
|
1438 static unsigned deflateFixed(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) |
|
1439 { |
|
1440 HuffmanTree codes; /*tree for literal values and length codes*/ |
|
1441 HuffmanTree codesD; /*tree for distance codes*/ |
|
1442 |
|
1443 unsigned BFINAL = 1; /*make only one block... the first and final one*/ |
|
1444 unsigned error = 0; |
|
1445 size_t i, bp = 0; /*the bit pointer*/ |
|
1446 |
|
1447 HuffmanTree_init(&codes); |
|
1448 HuffmanTree_init(&codesD); |
|
1449 |
|
1450 generateFixedTree(&codes); |
|
1451 generateDistanceTree(&codesD); |
|
1452 |
|
1453 addBitToStream(&bp, out, BFINAL); |
|
1454 addBitToStream(&bp, out, 1); /*first bit of BTYPE*/ |
|
1455 addBitToStream(&bp, out, 0); /*second bit of BTYPE*/ |
|
1456 |
|
1457 if(settings->useLZ77) /*LZ77 encoded*/ |
|
1458 { |
|
1459 uivector lz77_encoded; |
|
1460 uivector_init(&lz77_encoded); |
|
1461 error = encodeLZ77(&lz77_encoded, data, datasize, settings->windowSize); |
|
1462 if(!error) writeLZ77data(&bp, out, &lz77_encoded, &codes, &codesD); |
|
1463 uivector_cleanup(&lz77_encoded); |
|
1464 } |
|
1465 else /*no LZ77, but still will be Huffman compressed*/ |
|
1466 { |
|
1467 for(i = 0; i < datasize; i++) addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, data[i]), HuffmanTree_getLength(&codes, data[i])); |
|
1468 } |
|
1469 if(!error) addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, 256), HuffmanTree_getLength(&codes, 256)); /*"end" code*/ |
|
1470 |
|
1471 /*cleanup*/ |
|
1472 HuffmanTree_cleanup(&codes); |
|
1473 HuffmanTree_cleanup(&codesD); |
|
1474 |
|
1475 return error; |
|
1476 } |
|
1477 |
|
1478 unsigned LodeFlate_deflate(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) |
|
1479 { |
|
1480 unsigned error = 0; |
|
1481 if(settings->btype == 0) error = deflateNoCompression(out, data, datasize); |
|
1482 else if(settings->btype == 1) error = deflateFixed(out, data, datasize, settings); |
|
1483 else if(settings->btype == 2) error = deflateDynamic(out, data, datasize, settings); |
|
1484 else error = 61; |
|
1485 return error; |
|
1486 } |
|
1487 |
|
1488 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
1489 |
|
1490 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1491 /* / Adler32 */ |
|
1492 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1493 |
|
1494 static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) |
|
1495 { |
|
1496 unsigned s1 = adler & 0xffff; |
|
1497 unsigned s2 = (adler >> 16) & 0xffff; |
|
1498 |
|
1499 while(len > 0) |
|
1500 { |
|
1501 /*at least 5550 sums can be done before the sums overflow, saving us from a lot of module divisions*/ |
|
1502 unsigned amount = len > 5550 ? 5550 : len; |
|
1503 len -= amount; |
|
1504 while(amount > 0) |
|
1505 { |
|
1506 s1 = (s1 + *data++); |
|
1507 s2 = (s2 + s1); |
|
1508 amount--; |
|
1509 } |
|
1510 s1 %= 65521; |
|
1511 s2 %= 65521; |
|
1512 } |
|
1513 |
|
1514 return (s2 << 16) | s1; |
|
1515 } |
|
1516 |
|
1517 /*Return the adler32 of the bytes data[0..len-1]*/ |
|
1518 static unsigned adler32(const unsigned char* data, unsigned len) |
|
1519 { |
|
1520 return update_adler32(1L, data, len); |
|
1521 } |
|
1522 |
|
1523 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1524 /* / Reading and writing single bits and bytes from/to stream for Zlib / */ |
|
1525 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1526 |
|
1527 #ifdef LODEPNG_COMPILE_ENCODER |
|
1528 void LodeZlib_add32bitInt(ucvector* buffer, unsigned value) |
|
1529 { |
|
1530 ucvector_push_back(buffer, (unsigned char)((value >> 24) & 0xff)); |
|
1531 ucvector_push_back(buffer, (unsigned char)((value >> 16) & 0xff)); |
|
1532 ucvector_push_back(buffer, (unsigned char)((value >> 8) & 0xff)); |
|
1533 ucvector_push_back(buffer, (unsigned char)((value ) & 0xff)); |
|
1534 } |
|
1535 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
1536 |
|
1537 unsigned LodeZlib_read32bitInt(const unsigned char* buffer) |
|
1538 { |
|
1539 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; |
|
1540 } |
|
1541 |
|
1542 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1543 /* / Zlib / */ |
|
1544 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1545 |
|
1546 #ifdef LODEPNG_COMPILE_DECODER |
|
1547 |
|
1548 unsigned LodeZlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DecompressSettings* settings) |
|
1549 { |
|
1550 unsigned error = 0; |
|
1551 unsigned CM, CINFO, FDICT; |
|
1552 ucvector outv; |
|
1553 |
|
1554 if(insize < 2) { error = 53; return error; } /*error, size of zlib data too small*/ |
|
1555 /*read information from zlib header*/ |
|
1556 if((in[0] * 256 + in[1]) % 31 != 0) { error = 24; return error; } /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ |
|
1557 |
|
1558 CM = in[0] & 15; |
|
1559 CINFO = (in[0] >> 4) & 15; |
|
1560 /*FCHECK = in[1] & 31; //FCHECK is already tested above*/ |
|
1561 FDICT = (in[1] >> 5) & 1; |
|
1562 /*FLEVEL = (in[1] >> 6) & 3; //not really important, all it does it to give a compiler warning about unused variable, we don't care what encoding setting the encoder used*/ |
|
1563 |
|
1564 if(CM != 8 || CINFO > 7) { error = 25; return error; } /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ |
|
1565 if(FDICT != 0) { error = 26; return error; } /*error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary."*/ |
|
1566 |
|
1567 ucvector_init_buffer(&outv, *out, *outsize); /*ucvector-controlled version of the output buffer, for dynamic array*/ |
|
1568 error = LodeFlate_inflate(&outv, in, insize, 2); |
|
1569 *out = outv.data; |
|
1570 *outsize = outv.size; |
|
1571 if(error) return error; |
|
1572 |
|
1573 if(!settings->ignoreAdler32) |
|
1574 { |
|
1575 unsigned ADLER32 = LodeZlib_read32bitInt(&in[insize - 4]); |
|
1576 unsigned checksum = adler32(outv.data, (unsigned)outv.size); |
|
1577 if(checksum != ADLER32) { error = 58; return error; } |
|
1578 } |
|
1579 |
|
1580 return error; |
|
1581 } |
|
1582 |
|
1583 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
1584 |
|
1585 #ifdef LODEPNG_COMPILE_ENCODER |
|
1586 |
|
1587 unsigned LodeZlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings) |
|
1588 { |
|
1589 /*initially, *out must be NULL and outsize 0, if you just give some random *out that's pointing to a non allocated buffer, this'll crash*/ |
|
1590 ucvector deflatedata, outv; |
|
1591 size_t i; |
|
1592 unsigned error; |
|
1593 |
|
1594 unsigned ADLER32; |
|
1595 /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ |
|
1596 unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ |
|
1597 unsigned FLEVEL = 0; |
|
1598 unsigned FDICT = 0; |
|
1599 unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; |
|
1600 unsigned FCHECK = 31 - CMFFLG % 31; |
|
1601 CMFFLG += FCHECK; |
|
1602 |
|
1603 ucvector_init_buffer(&outv, *out, *outsize); /*ucvector-controlled version of the output buffer, for dynamic array*/ |
|
1604 |
|
1605 ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256)); |
|
1606 ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256)); |
|
1607 |
|
1608 ucvector_init(&deflatedata); |
|
1609 error = LodeFlate_deflate(&deflatedata, in, insize, settings); |
|
1610 |
|
1611 if(!error) |
|
1612 { |
|
1613 ADLER32 = adler32(in, (unsigned)insize); |
|
1614 for(i = 0; i < deflatedata.size; i++) ucvector_push_back(&outv, deflatedata.data[i]); |
|
1615 ucvector_cleanup(&deflatedata); |
|
1616 LodeZlib_add32bitInt(&outv, ADLER32); |
|
1617 } |
|
1618 |
|
1619 *out = outv.data; |
|
1620 *outsize = outv.size; |
|
1621 |
|
1622 return error; |
|
1623 } |
|
1624 |
|
1625 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
1626 |
|
1627 #endif /*LODEPNG_COMPILE_ZLIB*/ |
|
1628 |
|
1629 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1630 |
|
1631 #ifdef LODEPNG_COMPILE_ENCODER |
|
1632 |
|
1633 void LodeZlib_DeflateSettings_init(LodeZlib_DeflateSettings* settings) |
|
1634 { |
|
1635 settings->btype = 2; /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ |
|
1636 settings->useLZ77 = 1; |
|
1637 settings->windowSize = 2048; /*this is a good tradeoff between speed and compression ratio*/ |
|
1638 } |
|
1639 |
|
1640 const LodeZlib_DeflateSettings LodeZlib_defaultDeflateSettings = {2, 1, 2048}; |
|
1641 |
|
1642 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
1643 |
|
1644 #ifdef LODEPNG_COMPILE_DECODER |
|
1645 |
|
1646 void LodeZlib_DecompressSettings_init(LodeZlib_DecompressSettings* settings) |
|
1647 { |
|
1648 settings->ignoreAdler32 = 0; |
|
1649 } |
|
1650 |
|
1651 const LodeZlib_DecompressSettings LodeZlib_defaultDecompressSettings = {0}; |
|
1652 |
|
1653 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
1654 |
|
1655 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1656 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1657 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1658 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1659 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1660 /* // End of Zlib related code, now comes the PNG related code that uses it// */ |
|
1661 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1662 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1663 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1664 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1665 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1666 |
|
1667 #ifdef LODEPNG_COMPILE_PNG |
|
1668 |
|
1669 /* |
|
1670 The two functions below (LodePNG_decompress and LodePNG_compress) directly call the |
|
1671 LodeZlib_decompress and LodeZlib_compress functions. The only purpose of the functions |
|
1672 below, is to provide the ability to let LodePNG use a different Zlib encoder by only |
|
1673 changing the two functions below, instead of changing it inside the vareous places |
|
1674 in the other LodePNG functions. |
|
1675 |
|
1676 *out must be NULL and *outsize must be 0 initially, and after the function is done, |
|
1677 *out must point to the decompressed data, *outsize must be the size of it, and must |
|
1678 be the size of the useful data in bytes, not the alloc size. |
|
1679 */ |
|
1680 |
|
1681 #ifdef LODEPNG_COMPILE_DECODER |
|
1682 static unsigned LodePNG_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DecompressSettings* settings) |
|
1683 { |
|
1684 return LodeZlib_decompress(out, outsize, in, insize, settings); |
|
1685 } |
|
1686 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
1687 #ifdef LODEPNG_COMPILE_ENCODER |
|
1688 static unsigned LodePNG_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings) |
|
1689 { |
|
1690 return LodeZlib_compress(out, outsize, in, insize, settings); |
|
1691 } |
|
1692 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
1693 |
|
1694 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1695 /* / CRC32 / */ |
|
1696 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1697 |
|
1698 static unsigned Crc32_crc_table_computed = 0; |
|
1699 static unsigned Crc32_crc_table[256]; |
|
1700 |
|
1701 /*Make the table for a fast CRC.*/ |
|
1702 static void Crc32_make_crc_table(void) |
|
1703 { |
|
1704 unsigned c, k, n; |
|
1705 for(n = 0; n < 256; n++) |
|
1706 { |
|
1707 c = n; |
|
1708 for(k = 0; k < 8; k++) |
|
1709 { |
|
1710 if(c & 1) c = 0xedb88320L ^ (c >> 1); |
|
1711 else c = c >> 1; |
|
1712 } |
|
1713 Crc32_crc_table[n] = c; |
|
1714 } |
|
1715 Crc32_crc_table_computed = 1; |
|
1716 } |
|
1717 |
|
1718 /*Update a running CRC with the bytes buf[0..len-1]--the CRC should be |
|
1719 initialized to all 1's, and the transmitted value is the 1's complement of the |
|
1720 final running CRC (see the crc() routine below).*/ |
|
1721 static unsigned Crc32_update_crc(const unsigned char* buf, unsigned crc, size_t len) |
|
1722 { |
|
1723 unsigned c = crc; |
|
1724 size_t n; |
|
1725 |
|
1726 if(!Crc32_crc_table_computed) Crc32_make_crc_table(); |
|
1727 for(n = 0; n < len; n++) |
|
1728 { |
|
1729 c = Crc32_crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); |
|
1730 } |
|
1731 return c; |
|
1732 } |
|
1733 |
|
1734 /*Return the CRC of the bytes buf[0..len-1].*/ |
|
1735 static unsigned Crc32_crc(const unsigned char* buf, size_t len) |
|
1736 { |
|
1737 return Crc32_update_crc(buf, 0xffffffffL, len) ^ 0xffffffffL; |
|
1738 } |
|
1739 |
|
1740 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1741 /* / Reading and writing single bits and bytes from/to stream for LodePNG / */ |
|
1742 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1743 |
|
1744 static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) |
|
1745 { |
|
1746 unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); |
|
1747 (*bitpointer)++; |
|
1748 return result; |
|
1749 } |
|
1750 |
|
1751 static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) |
|
1752 { |
|
1753 unsigned result = 0; |
|
1754 size_t i; |
|
1755 for(i = nbits - 1; i < nbits; i--) result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i; |
|
1756 return result; |
|
1757 } |
|
1758 |
|
1759 #ifdef LODEPNG_COMPILE_DECODER |
|
1760 static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) |
|
1761 { |
|
1762 /*the current bit in bitstream must be 0 for this to work*/ |
|
1763 if(bit) bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ |
|
1764 (*bitpointer)++; |
|
1765 } |
|
1766 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
1767 |
|
1768 static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) |
|
1769 { |
|
1770 /*the current bit in bitstream may be 0 or 1 for this to work*/ |
|
1771 if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7)))); |
|
1772 else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7))); |
|
1773 (*bitpointer)++; |
|
1774 } |
|
1775 |
|
1776 static unsigned LodePNG_read32bitInt(const unsigned char* buffer) |
|
1777 { |
|
1778 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; |
|
1779 } |
|
1780 |
|
1781 static void LodePNG_set32bitInt(unsigned char* buffer, unsigned value) /*buffer must have at least 4 allocated bytes available*/ |
|
1782 { |
|
1783 buffer[0] = (unsigned char)((value >> 24) & 0xff); |
|
1784 buffer[1] = (unsigned char)((value >> 16) & 0xff); |
|
1785 buffer[2] = (unsigned char)((value >> 8) & 0xff); |
|
1786 buffer[3] = (unsigned char)((value ) & 0xff); |
|
1787 } |
|
1788 |
|
1789 #ifdef LODEPNG_COMPILE_ENCODER |
|
1790 static void LodePNG_add32bitInt(ucvector* buffer, unsigned value) |
|
1791 { |
|
1792 ucvector_resize(buffer, buffer->size + 4); |
|
1793 LodePNG_set32bitInt(&buffer->data[buffer->size - 4], value); |
|
1794 } |
|
1795 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
1796 |
|
1797 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1798 /* / PNG chunks / */ |
|
1799 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1800 |
|
1801 unsigned LodePNG_chunk_length(const unsigned char* chunk) /*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/ |
|
1802 { |
|
1803 return LodePNG_read32bitInt(&chunk[0]); |
|
1804 } |
|
1805 |
|
1806 void LodePNG_chunk_type(char type[5], const unsigned char* chunk) /*puts the 4-byte type in null terminated string*/ |
|
1807 { |
|
1808 unsigned i; |
|
1809 for(i = 0; i < 4; i++) type[i] = chunk[4 + i]; |
|
1810 type[4] = 0; /*null termination char*/ |
|
1811 } |
|
1812 |
|
1813 unsigned char LodePNG_chunk_type_equals(const unsigned char* chunk, const char* type) /*check if the type is the given type*/ |
|
1814 { |
|
1815 if(strlen(type) != 4) return 0; |
|
1816 return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); |
|
1817 } |
|
1818 |
|
1819 /*properties of PNG chunks gotten from capitalization of chunk type name, as defined by the standard*/ |
|
1820 unsigned char LodePNG_chunk_critical(const unsigned char* chunk) /*0: ancillary chunk, 1: it's one of the critical chunk types*/ |
|
1821 { |
|
1822 return((chunk[4] & 32) == 0); |
|
1823 } |
|
1824 |
|
1825 unsigned char LodePNG_chunk_private(const unsigned char* chunk) /*0: public, 1: private*/ |
|
1826 { |
|
1827 return((chunk[6] & 32) != 0); |
|
1828 } |
|
1829 |
|
1830 unsigned char LodePNG_chunk_safetocopy(const unsigned char* chunk) /*0: the chunk is unsafe to copy, 1: the chunk is safe to copy*/ |
|
1831 { |
|
1832 return((chunk[7] & 32) != 0); |
|
1833 } |
|
1834 |
|
1835 unsigned char* LodePNG_chunk_data(unsigned char* chunk) /*get pointer to the data of the chunk*/ |
|
1836 { |
|
1837 return &chunk[8]; |
|
1838 } |
|
1839 |
|
1840 const unsigned char* LodePNG_chunk_data_const(const unsigned char* chunk) /*get pointer to the data of the chunk*/ |
|
1841 { |
|
1842 return &chunk[8]; |
|
1843 } |
|
1844 |
|
1845 unsigned LodePNG_chunk_check_crc(const unsigned char* chunk) /*returns 0 if the crc is correct, error code if it's incorrect*/ |
|
1846 { |
|
1847 unsigned length = LodePNG_chunk_length(chunk); |
|
1848 unsigned CRC = LodePNG_read32bitInt(&chunk[length + 8]); |
|
1849 unsigned checksum = Crc32_crc(&chunk[4], length + 4); /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ |
|
1850 if(CRC != checksum) return 1; |
|
1851 else return 0; |
|
1852 } |
|
1853 |
|
1854 void LodePNG_chunk_generate_crc(unsigned char* chunk) /*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ |
|
1855 { |
|
1856 unsigned length = LodePNG_chunk_length(chunk); |
|
1857 unsigned CRC = Crc32_crc(&chunk[4], length + 4); |
|
1858 LodePNG_set32bitInt(chunk + 8 + length, CRC); |
|
1859 } |
|
1860 |
|
1861 unsigned char* LodePNG_chunk_next(unsigned char* chunk) /*don't use on IEND chunk, as there is no next chunk then*/ |
|
1862 { |
|
1863 unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12; |
|
1864 return &chunk[total_chunk_length]; |
|
1865 } |
|
1866 |
|
1867 const unsigned char* LodePNG_chunk_next_const(const unsigned char* chunk) /*don't use on IEND chunk, as there is no next chunk then*/ |
|
1868 { |
|
1869 unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12; |
|
1870 return &chunk[total_chunk_length]; |
|
1871 } |
|
1872 |
|
1873 unsigned LodePNG_append_chunk(unsigned char** out, size_t* outlength, const unsigned char* chunk) /*appends chunk that was already created, to the data. Returns error code.*/ |
|
1874 { |
|
1875 unsigned i; |
|
1876 unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12; |
|
1877 unsigned char *chunk_start, *new_buffer; |
|
1878 size_t new_length = (*outlength) + total_chunk_length; |
|
1879 if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/ |
|
1880 |
|
1881 new_buffer = (unsigned char*)realloc(*out, new_length); |
|
1882 if(!new_buffer) return 9929; |
|
1883 (*out) = new_buffer; |
|
1884 (*outlength) = new_length; |
|
1885 chunk_start = &(*out)[new_length - total_chunk_length]; |
|
1886 |
|
1887 for(i = 0; i < total_chunk_length; i++) chunk_start[i] = chunk[i]; |
|
1888 |
|
1889 return 0; |
|
1890 } |
|
1891 |
|
1892 unsigned LodePNG_create_chunk(unsigned char** out, size_t* outlength, unsigned length, const char* type, const unsigned char* data) /*appends new chunk to out. Returns error code; may change memory address of out buffer*/ |
|
1893 { |
|
1894 unsigned i; |
|
1895 unsigned char *chunk, *new_buffer; |
|
1896 size_t new_length = (*outlength) + length + 12; |
|
1897 if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/ |
|
1898 new_buffer = (unsigned char*)realloc(*out, new_length); |
|
1899 if(!new_buffer) return 9930; |
|
1900 (*out) = new_buffer; |
|
1901 (*outlength) = new_length; |
|
1902 chunk = &(*out)[(*outlength) - length - 12]; |
|
1903 |
|
1904 /*1: length*/ |
|
1905 LodePNG_set32bitInt(chunk, (unsigned)length); |
|
1906 |
|
1907 /*2: chunk name (4 letters)*/ |
|
1908 chunk[4] = type[0]; |
|
1909 chunk[5] = type[1]; |
|
1910 chunk[6] = type[2]; |
|
1911 chunk[7] = type[3]; |
|
1912 |
|
1913 /*3: the data*/ |
|
1914 for(i = 0; i < length; i++) chunk[8 + i] = data[i]; |
|
1915 |
|
1916 /*4: CRC (of the chunkname characters and the data)*/ |
|
1917 LodePNG_chunk_generate_crc(chunk); |
|
1918 |
|
1919 return 0; |
|
1920 } |
|
1921 |
|
1922 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1923 /* / Color types and such / */ |
|
1924 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1925 |
|
1926 /*return type is a LodePNG error code*/ |
|
1927 static unsigned checkColorValidity(unsigned colorType, unsigned bd) /*bd = bitDepth*/ |
|
1928 { |
|
1929 switch(colorType) |
|
1930 { |
|
1931 case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/ |
|
1932 case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/ |
|
1933 case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/ |
|
1934 case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/ |
|
1935 case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/ |
|
1936 default: return 31; |
|
1937 } |
|
1938 return 0; /*allowed color type / bits combination*/ |
|
1939 } |
|
1940 |
|
1941 static unsigned getNumColorChannels(unsigned colorType) |
|
1942 { |
|
1943 switch(colorType) |
|
1944 { |
|
1945 case 0: return 1; /*grey*/ |
|
1946 case 2: return 3; /*RGB*/ |
|
1947 case 3: return 1; /*palette*/ |
|
1948 case 4: return 2; /*grey + alpha*/ |
|
1949 case 6: return 4; /*RGBA*/ |
|
1950 } |
|
1951 return 0; /*unexisting color type*/ |
|
1952 } |
|
1953 |
|
1954 static unsigned getBpp(unsigned colorType, unsigned bitDepth) |
|
1955 { |
|
1956 return getNumColorChannels(colorType) * bitDepth; /*bits per pixel is amount of channels * bits per channel*/ |
|
1957 } |
|
1958 |
|
1959 /* ////////////////////////////////////////////////////////////////////////// */ |
|
1960 |
|
1961 void LodePNG_InfoColor_init(LodePNG_InfoColor* info) |
|
1962 { |
|
1963 info->key_defined = 0; |
|
1964 info->key_r = info->key_g = info->key_b = 0; |
|
1965 info->colorType = 6; |
|
1966 info->bitDepth = 8; |
|
1967 info->palette = 0; |
|
1968 info->palettesize = 0; |
|
1969 } |
|
1970 |
|
1971 void LodePNG_InfoColor_cleanup(LodePNG_InfoColor* info) |
|
1972 { |
|
1973 LodePNG_InfoColor_clearPalette(info); |
|
1974 } |
|
1975 |
|
1976 void LodePNG_InfoColor_clearPalette(LodePNG_InfoColor* info) |
|
1977 { |
|
1978 if(info->palette) free(info->palette); |
|
1979 info->palettesize = 0; |
|
1980 } |
|
1981 |
|
1982 unsigned LodePNG_InfoColor_addPalette(LodePNG_InfoColor* info, unsigned char r, unsigned char g, unsigned char b, unsigned char a) |
|
1983 { |
|
1984 unsigned char* data; |
|
1985 /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with the max of 256 colors, it'll have the exact alloc size*/ |
|
1986 if(!(info->palettesize & (info->palettesize - 1))) /*if palettesize is 0 or a power of two*/ |
|
1987 { |
|
1988 /*allocated data must be at least 4* palettesize (for 4 color bytes)*/ |
|
1989 size_t alloc_size = info->palettesize == 0 ? 4 : info->palettesize * 4 * 2; |
|
1990 data = (unsigned char*)realloc(info->palette, alloc_size); |
|
1991 if(!data) return 9931; |
|
1992 else info->palette = data; |
|
1993 } |
|
1994 info->palette[4 * info->palettesize + 0] = r; |
|
1995 info->palette[4 * info->palettesize + 1] = g; |
|
1996 info->palette[4 * info->palettesize + 2] = b; |
|
1997 info->palette[4 * info->palettesize + 3] = a; |
|
1998 info->palettesize++; |
|
1999 return 0; |
|
2000 } |
|
2001 |
|
2002 unsigned LodePNG_InfoColor_getBpp(const LodePNG_InfoColor* info) { return getBpp(info->colorType, info->bitDepth); } /*calculate bits per pixel out of colorType and bitDepth*/ |
|
2003 unsigned LodePNG_InfoColor_getChannels(const LodePNG_InfoColor* info) { return getNumColorChannels(info->colorType); } |
|
2004 unsigned LodePNG_InfoColor_isGreyscaleType(const LodePNG_InfoColor* info) { return info->colorType == 0 || info->colorType == 4; } |
|
2005 unsigned LodePNG_InfoColor_isAlphaType(const LodePNG_InfoColor* info) { return (info->colorType & 4) != 0; } |
|
2006 |
|
2007 unsigned LodePNG_InfoColor_equal(const LodePNG_InfoColor* info1, const LodePNG_InfoColor* info2) |
|
2008 { |
|
2009 return info1->colorType == info2->colorType |
|
2010 && info1->bitDepth == info2->bitDepth; /*palette and color key not compared*/ |
|
2011 } |
|
2012 |
|
2013 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
2014 |
|
2015 void LodePNG_UnknownChunks_init(LodePNG_UnknownChunks* chunks) |
|
2016 { |
|
2017 unsigned i; |
|
2018 for(i = 0; i < 3; i++) chunks->data[i] = 0; |
|
2019 for(i = 0; i < 3; i++) chunks->datasize[i] = 0; |
|
2020 } |
|
2021 |
|
2022 void LodePNG_UnknownChunks_cleanup(LodePNG_UnknownChunks* chunks) |
|
2023 { |
|
2024 unsigned i; |
|
2025 for(i = 0; i < 3; i++) free(chunks->data[i]); |
|
2026 } |
|
2027 |
|
2028 unsigned LodePNG_UnknownChunks_copy(LodePNG_UnknownChunks* dest, const LodePNG_UnknownChunks* src) |
|
2029 { |
|
2030 unsigned i; |
|
2031 |
|
2032 LodePNG_UnknownChunks_cleanup(dest); |
|
2033 |
|
2034 for(i = 0; i < 3; i++) |
|
2035 { |
|
2036 size_t j; |
|
2037 dest->datasize[i] = src->datasize[i]; |
|
2038 dest->data[i] = (unsigned char*)malloc(src->datasize[i]); |
|
2039 if(!dest->data[i] && dest->datasize[i]) return 9932; |
|
2040 for(j = 0; j < src->datasize[i]; j++) dest->data[i][j] = src->data[i][j]; |
|
2041 } |
|
2042 |
|
2043 return 0; |
|
2044 } |
|
2045 |
|
2046 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
2047 |
|
2048 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
2049 |
|
2050 void LodePNG_Text_init(LodePNG_Text* text) |
|
2051 { |
|
2052 text->num = 0; |
|
2053 text->keys = NULL; |
|
2054 text->strings = NULL; |
|
2055 } |
|
2056 |
|
2057 void LodePNG_Text_cleanup(LodePNG_Text* text) |
|
2058 { |
|
2059 LodePNG_Text_clear(text); |
|
2060 } |
|
2061 |
|
2062 unsigned LodePNG_Text_copy(LodePNG_Text* dest, const LodePNG_Text* source) |
|
2063 { |
|
2064 size_t i = 0; |
|
2065 dest->keys = 0; |
|
2066 dest->strings = 0; |
|
2067 dest->num = 0; |
|
2068 for(i = 0; i < source->num; i++) |
|
2069 { |
|
2070 unsigned error = LodePNG_Text_add(dest, source->keys[i], source->strings[i]); |
|
2071 if(error) return error; |
|
2072 } |
|
2073 return 0; |
|
2074 } |
|
2075 |
|
2076 void LodePNG_Text_clear(LodePNG_Text* text) |
|
2077 { |
|
2078 size_t i; |
|
2079 for(i = 0; i < text->num; i++) |
|
2080 { |
|
2081 string_cleanup(&text->keys[i]); |
|
2082 string_cleanup(&text->strings[i]); |
|
2083 } |
|
2084 free(text->keys); |
|
2085 free(text->strings); |
|
2086 } |
|
2087 |
|
2088 unsigned LodePNG_Text_add(LodePNG_Text* text, const char* key, const char* str) |
|
2089 { |
|
2090 char** new_keys = (char**)(realloc(text->keys, sizeof(char*) * (text->num + 1))); |
|
2091 char** new_strings = (char**)(realloc(text->strings, sizeof(char*) * (text->num + 1))); |
|
2092 if(!new_keys || !new_strings) |
|
2093 { |
|
2094 free(new_keys); |
|
2095 free(new_strings); |
|
2096 return 9933; |
|
2097 } |
|
2098 |
|
2099 text->num++; |
|
2100 text->keys = new_keys; |
|
2101 text->strings = new_strings; |
|
2102 |
|
2103 string_init(&text->keys[text->num - 1]); |
|
2104 string_set(&text->keys[text->num - 1], key); |
|
2105 |
|
2106 string_init(&text->strings[text->num - 1]); |
|
2107 string_set(&text->strings[text->num - 1], str); |
|
2108 |
|
2109 return 0; |
|
2110 } |
|
2111 |
|
2112 /******************************************************************************/ |
|
2113 |
|
2114 void LodePNG_IText_init(LodePNG_IText* text) |
|
2115 { |
|
2116 text->num = 0; |
|
2117 text->keys = NULL; |
|
2118 text->langtags = NULL; |
|
2119 text->transkeys = NULL; |
|
2120 text->strings = NULL; |
|
2121 } |
|
2122 |
|
2123 void LodePNG_IText_cleanup(LodePNG_IText* text) |
|
2124 { |
|
2125 LodePNG_IText_clear(text); |
|
2126 } |
|
2127 |
|
2128 unsigned LodePNG_IText_copy(LodePNG_IText* dest, const LodePNG_IText* source) |
|
2129 { |
|
2130 size_t i = 0; |
|
2131 dest->keys = 0; |
|
2132 dest->langtags = 0; |
|
2133 dest->transkeys = 0; |
|
2134 dest->strings = 0; |
|
2135 dest->num = 0; |
|
2136 for(i = 0; i < source->num; i++) |
|
2137 { |
|
2138 unsigned error = LodePNG_IText_add(dest, source->keys[i], source->langtags[i], source->transkeys[i], source->strings[i]); |
|
2139 if(error) return error; |
|
2140 } |
|
2141 return 0; |
|
2142 } |
|
2143 |
|
2144 void LodePNG_IText_clear(LodePNG_IText* text) |
|
2145 { |
|
2146 size_t i; |
|
2147 for(i = 0; i < text->num; i++) |
|
2148 { |
|
2149 string_cleanup(&text->keys[i]); |
|
2150 string_cleanup(&text->langtags[i]); |
|
2151 string_cleanup(&text->transkeys[i]); |
|
2152 string_cleanup(&text->strings[i]); |
|
2153 } |
|
2154 free(text->keys); |
|
2155 free(text->langtags); |
|
2156 free(text->transkeys); |
|
2157 free(text->strings); |
|
2158 } |
|
2159 |
|
2160 unsigned LodePNG_IText_add(LodePNG_IText* text, const char* key, const char* langtag, const char* transkey, const char* str) |
|
2161 { |
|
2162 char** new_keys = (char**)(realloc(text->keys, sizeof(char*) * (text->num + 1))); |
|
2163 char** new_langtags = (char**)(realloc(text->langtags, sizeof(char*) * (text->num + 1))); |
|
2164 char** new_transkeys = (char**)(realloc(text->transkeys, sizeof(char*) * (text->num + 1))); |
|
2165 char** new_strings = (char**)(realloc(text->strings, sizeof(char*) * (text->num + 1))); |
|
2166 if(!new_keys || !new_langtags || !new_transkeys || !new_strings) |
|
2167 { |
|
2168 free(new_keys); |
|
2169 free(new_langtags); |
|
2170 free(new_transkeys); |
|
2171 free(new_strings); |
|
2172 return 9934; |
|
2173 } |
|
2174 |
|
2175 text->num++; |
|
2176 text->keys = new_keys; |
|
2177 text->langtags = new_langtags; |
|
2178 text->transkeys = new_transkeys; |
|
2179 text->strings = new_strings; |
|
2180 |
|
2181 string_init(&text->keys[text->num - 1]); |
|
2182 string_set(&text->keys[text->num - 1], key); |
|
2183 |
|
2184 string_init(&text->langtags[text->num - 1]); |
|
2185 string_set(&text->langtags[text->num - 1], langtag); |
|
2186 |
|
2187 string_init(&text->transkeys[text->num - 1]); |
|
2188 string_set(&text->transkeys[text->num - 1], transkey); |
|
2189 |
|
2190 string_init(&text->strings[text->num - 1]); |
|
2191 string_set(&text->strings[text->num - 1], str); |
|
2192 |
|
2193 return 0; |
|
2194 } |
|
2195 |
|
2196 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
2197 |
|
2198 void LodePNG_InfoPng_init(LodePNG_InfoPng* info) |
|
2199 { |
|
2200 info->width = info->height = 0; |
|
2201 LodePNG_InfoColor_init(&info->color); |
|
2202 info->interlaceMethod = 0; |
|
2203 info->compressionMethod = 0; |
|
2204 info->filterMethod = 0; |
|
2205 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
2206 info->background_defined = 0; |
|
2207 info->background_r = info->background_g = info->background_b = 0; |
|
2208 |
|
2209 LodePNG_Text_init(&info->text); |
|
2210 LodePNG_IText_init(&info->itext); |
|
2211 |
|
2212 info->time_defined = 0; |
|
2213 info->phys_defined = 0; |
|
2214 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
2215 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
2216 LodePNG_UnknownChunks_init(&info->unknown_chunks); |
|
2217 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
2218 } |
|
2219 |
|
2220 void LodePNG_InfoPng_cleanup(LodePNG_InfoPng* info) |
|
2221 { |
|
2222 LodePNG_InfoColor_cleanup(&info->color); |
|
2223 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
2224 LodePNG_Text_cleanup(&info->text); |
|
2225 LodePNG_IText_cleanup(&info->itext); |
|
2226 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
2227 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
2228 LodePNG_UnknownChunks_cleanup(&info->unknown_chunks); |
|
2229 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
2230 } |
|
2231 |
|
2232 unsigned LodePNG_InfoPng_copy(LodePNG_InfoPng* dest, const LodePNG_InfoPng* source) |
|
2233 { |
|
2234 unsigned error = 0; |
|
2235 LodePNG_InfoPng_cleanup(dest); |
|
2236 *dest = *source; |
|
2237 LodePNG_InfoColor_init(&dest->color); |
|
2238 error = LodePNG_InfoColor_copy(&dest->color, &source->color); if(error) return error; |
|
2239 |
|
2240 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
2241 error = LodePNG_Text_copy(&dest->text, &source->text); if(error) return error; |
|
2242 error = LodePNG_IText_copy(&dest->itext, &source->itext); if(error) return error; |
|
2243 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
2244 |
|
2245 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
2246 LodePNG_UnknownChunks_init(&dest->unknown_chunks); |
|
2247 error = LodePNG_UnknownChunks_copy(&dest->unknown_chunks, &source->unknown_chunks); if(error) return error; |
|
2248 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
2249 return error; |
|
2250 } |
|
2251 |
|
2252 void LodePNG_InfoPng_swap(LodePNG_InfoPng* a, LodePNG_InfoPng* b) |
|
2253 { |
|
2254 LodePNG_InfoPng temp = *a; |
|
2255 *a = *b; |
|
2256 *b = temp; |
|
2257 } |
|
2258 |
|
2259 unsigned LodePNG_InfoColor_copy(LodePNG_InfoColor* dest, const LodePNG_InfoColor* source) |
|
2260 { |
|
2261 size_t i; |
|
2262 LodePNG_InfoColor_cleanup(dest); |
|
2263 *dest = *source; |
|
2264 dest->palette = (unsigned char*)malloc(source->palettesize * 4); |
|
2265 if(!dest->palette && source->palettesize) return 9935; |
|
2266 for(i = 0; i < source->palettesize * 4; i++) dest->palette[i] = source->palette[i]; |
|
2267 return 0; |
|
2268 } |
|
2269 |
|
2270 void LodePNG_InfoRaw_init(LodePNG_InfoRaw* info) |
|
2271 { |
|
2272 LodePNG_InfoColor_init(&info->color); |
|
2273 } |
|
2274 |
|
2275 void LodePNG_InfoRaw_cleanup(LodePNG_InfoRaw* info) |
|
2276 { |
|
2277 LodePNG_InfoColor_cleanup(&info->color); |
|
2278 } |
|
2279 |
|
2280 unsigned LodePNG_InfoRaw_copy(LodePNG_InfoRaw* dest, const LodePNG_InfoRaw* source) |
|
2281 { |
|
2282 unsigned error = 0; |
|
2283 LodePNG_InfoRaw_cleanup(dest); |
|
2284 *dest = *source; |
|
2285 LodePNG_InfoColor_init(&dest->color); |
|
2286 error = LodePNG_InfoColor_copy(&dest->color, &source->color); if(error) return error; |
|
2287 return error; |
|
2288 } |
|
2289 |
|
2290 /* ////////////////////////////////////////////////////////////////////////// */ |
|
2291 |
|
2292 /* |
|
2293 converts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code |
|
2294 the out buffer must have (w * h * bpp + 7) / 8 bytes, where bpp is the bits per pixel of the output color type (LodePNG_InfoColor_getBpp) |
|
2295 for < 8 bpp images, there may _not_ be padding bits at the end of scanlines. |
|
2296 */ |
|
2297 unsigned LodePNG_convert(unsigned char* out, const unsigned char* in, LodePNG_InfoColor* infoOut, LodePNG_InfoColor* infoIn, unsigned w, unsigned h) |
|
2298 { |
|
2299 const size_t numpixels = w * h; /*amount of pixels*/ |
|
2300 const unsigned OUT_BYTES = LodePNG_InfoColor_getBpp(infoOut) / 8; /*bytes per pixel in the output image*/ |
|
2301 const unsigned OUT_ALPHA = LodePNG_InfoColor_isAlphaType(infoOut); /*use 8-bit alpha channel*/ |
|
2302 size_t i, c, bp = 0; /*bitpointer, used by less-than-8-bit color types*/ |
|
2303 |
|
2304 /*cases where in and out already have the same format*/ |
|
2305 if(LodePNG_InfoColor_equal(infoIn, infoOut)) |
|
2306 { |
|
2307 size_t i, size = (w * h * LodePNG_InfoColor_getBpp(infoIn) + 7) / 8; |
|
2308 for(i = 0; i < size; i++) out[i] = in[i]; |
|
2309 return 0; |
|
2310 } |
|
2311 |
|
2312 if((infoOut->colorType == 2 || infoOut->colorType == 6) && infoOut->bitDepth == 8) |
|
2313 { |
|
2314 if(infoIn->bitDepth == 8) |
|
2315 { |
|
2316 switch(infoIn->colorType) |
|
2317 { |
|
2318 case 0: /*greyscale color*/ |
|
2319 for(i = 0; i < numpixels; i++) |
|
2320 { |
|
2321 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2322 out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[i]; |
|
2323 if(OUT_ALPHA && infoIn->key_defined && in[i] == infoIn->key_r) out[OUT_BYTES * i + 3] = 0; |
|
2324 } |
|
2325 break; |
|
2326 case 2: /*RGB color*/ |
|
2327 for(i = 0; i < numpixels; i++) |
|
2328 { |
|
2329 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2330 for(c = 0; c < 3; c++) out[OUT_BYTES * i + c] = in[3 * i + c]; |
|
2331 if(OUT_ALPHA && infoIn->key_defined == 1 && in[3 * i + 0] == infoIn->key_r && in[3 * i + 1] == infoIn->key_g && in[3 * i + 2] == infoIn->key_b) out[OUT_BYTES * i + 3] = 0; |
|
2332 } |
|
2333 break; |
|
2334 case 3: /*indexed color (palette)*/ |
|
2335 for(i = 0; i < numpixels; i++) |
|
2336 { |
|
2337 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2338 if(in[i] >= infoIn->palettesize) return 46; |
|
2339 for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = infoIn->palette[4 * in[i] + c]; /*get rgb colors from the palette*/ |
|
2340 } |
|
2341 break; |
|
2342 case 4: /*greyscale with alpha*/ |
|
2343 for(i = 0; i < numpixels; i++) |
|
2344 { |
|
2345 out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[2 * i + 0]; |
|
2346 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = in[2 * i + 1]; |
|
2347 } |
|
2348 break; |
|
2349 case 6: /*RGB with alpha*/ |
|
2350 for(i = 0; i < numpixels; i++) |
|
2351 { |
|
2352 for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = in[4 * i + c]; |
|
2353 } |
|
2354 break; |
|
2355 default: break; |
|
2356 } |
|
2357 } |
|
2358 else if(infoIn->bitDepth == 16) |
|
2359 { |
|
2360 switch(infoIn->colorType) |
|
2361 { |
|
2362 case 0: /*greyscale color*/ |
|
2363 for(i = 0; i < numpixels; i++) |
|
2364 { |
|
2365 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2366 out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[2 * i]; |
|
2367 if(OUT_ALPHA && infoIn->key_defined && 256U * in[i] + in[i + 1] == infoIn->key_r) out[OUT_BYTES * i + 3] = 0; |
|
2368 } |
|
2369 break; |
|
2370 case 2: /*RGB color*/ |
|
2371 for(i = 0; i < numpixels; i++) |
|
2372 { |
|
2373 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2374 for(c = 0; c < 3; c++) out[OUT_BYTES * i + c] = in[6 * i + 2 * c]; |
|
2375 if(OUT_ALPHA && infoIn->key_defined && 256U * in[6 * i + 0] + in[6 * i + 1] == infoIn->key_r && 256U * in[6 * i + 2] + in[6 * i + 3] == infoIn->key_g && 256U * in[6 * i + 4] + in[6 * i + 5] == infoIn->key_b) out[OUT_BYTES * i + 3] = 0; |
|
2376 } |
|
2377 break; |
|
2378 case 4: /*greyscale with alpha*/ |
|
2379 for(i = 0; i < numpixels; i++) |
|
2380 { |
|
2381 out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[4 * i]; /*most significant byte*/ |
|
2382 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = in[4 * i + 2]; |
|
2383 } |
|
2384 break; |
|
2385 case 6: /*RGB with alpha*/ |
|
2386 for(i = 0; i < numpixels; i++) |
|
2387 { |
|
2388 for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = in[8 * i + 2 * c]; |
|
2389 } |
|
2390 break; |
|
2391 default: break; |
|
2392 } |
|
2393 } |
|
2394 else /*infoIn->bitDepth is less than 8 bit per channel*/ |
|
2395 { |
|
2396 switch(infoIn->colorType) |
|
2397 { |
|
2398 case 0: /*greyscale color*/ |
|
2399 for(i = 0; i < numpixels; i++) |
|
2400 { |
|
2401 unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); |
|
2402 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2403 if(OUT_ALPHA && infoIn->key_defined && value && ((1U << infoIn->bitDepth) - 1U) == infoIn->key_r && ((1U << infoIn->bitDepth) - 1U)) out[OUT_BYTES * i + 3] = 0; |
|
2404 value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/ |
|
2405 out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = (unsigned char)(value); |
|
2406 } |
|
2407 break; |
|
2408 case 3: /*indexed color (palette)*/ |
|
2409 for(i = 0; i < numpixels; i++) |
|
2410 { |
|
2411 unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); |
|
2412 if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; |
|
2413 if(value >= infoIn->palettesize) return 47; |
|
2414 for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = infoIn->palette[4 * value + c]; /*get rgb colors from the palette*/ |
|
2415 } |
|
2416 break; |
|
2417 default: break; |
|
2418 } |
|
2419 } |
|
2420 } |
|
2421 else if(LodePNG_InfoColor_isGreyscaleType(infoOut) && infoOut->bitDepth == 8) /*conversion from greyscale to greyscale*/ |
|
2422 { |
|
2423 if(!LodePNG_InfoColor_isGreyscaleType(infoIn)) return 62; |
|
2424 if(infoIn->bitDepth == 8) |
|
2425 { |
|
2426 switch(infoIn->colorType) |
|
2427 { |
|
2428 case 0: /*greyscale color*/ |
|
2429 for(i = 0; i < numpixels; i++) |
|
2430 { |
|
2431 if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; |
|
2432 out[OUT_BYTES * i] = in[i]; |
|
2433 if(OUT_ALPHA && infoIn->key_defined && in[i] == infoIn->key_r) out[OUT_BYTES * i + 1] = 0; |
|
2434 } |
|
2435 break; |
|
2436 case 4: /*greyscale with alpha*/ |
|
2437 for(i = 0; i < numpixels; i++) |
|
2438 { |
|
2439 out[OUT_BYTES * i + 0] = in[2 * i + 0]; |
|
2440 if(OUT_ALPHA) out[OUT_BYTES * i + 1] = in[2 * i + 1]; |
|
2441 } |
|
2442 break; |
|
2443 default: return 31; |
|
2444 } |
|
2445 } |
|
2446 else if(infoIn->bitDepth == 16) |
|
2447 { |
|
2448 switch(infoIn->colorType) |
|
2449 { |
|
2450 case 0: /*greyscale color*/ |
|
2451 for(i = 0; i < numpixels; i++) |
|
2452 { |
|
2453 if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; |
|
2454 out[OUT_BYTES * i] = in[2 * i]; |
|
2455 if(OUT_ALPHA && infoIn->key_defined && 256U * in[i] + in[i + 1] == infoIn->key_r) out[OUT_BYTES * i + 1] = 0; |
|
2456 } |
|
2457 break; |
|
2458 case 4: /*greyscale with alpha*/ |
|
2459 for(i = 0; i < numpixels; i++) |
|
2460 { |
|
2461 out[OUT_BYTES * i] = in[4 * i]; /*most significant byte*/ |
|
2462 if(OUT_ALPHA) out[OUT_BYTES * i + 1] = in[4 * i + 2]; /*most significant byte*/ |
|
2463 } |
|
2464 break; |
|
2465 default: return 31; |
|
2466 } |
|
2467 } |
|
2468 else /*infoIn->bitDepth is less than 8 bit per channel*/ |
|
2469 { |
|
2470 if(infoIn->colorType != 0) return 31; /*colorType 0 is the only greyscale type with < 8 bits per channel*/ |
|
2471 for(i = 0; i < numpixels; i++) |
|
2472 { |
|
2473 unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); |
|
2474 if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; |
|
2475 if(OUT_ALPHA && infoIn->key_defined && value && ((1U << infoIn->bitDepth) - 1U) == infoIn->key_r && ((1U << infoIn->bitDepth) - 1U)) out[OUT_BYTES * i + 1] = 0; |
|
2476 value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/ |
|
2477 out[OUT_BYTES * i] = (unsigned char)(value); |
|
2478 } |
|
2479 } |
|
2480 } |
|
2481 else return 59; |
|
2482 |
|
2483 return 0; |
|
2484 } |
|
2485 |
|
2486 /*Paeth predicter, used by PNG filter type 4*/ |
|
2487 static int paethPredictor(int a, int b, int c) |
|
2488 { |
|
2489 int p = a + b - c; |
|
2490 int pa = p > a ? p - a : a - p; |
|
2491 int pb = p > b ? p - b : b - p; |
|
2492 int pc = p > c ? p - c : c - p; |
|
2493 |
|
2494 if(pa <= pb && pa <= pc) return a; |
|
2495 else if(pb <= pc) return b; |
|
2496 else return c; |
|
2497 } |
|
2498 |
|
2499 /*shared values used by multiple Adam7 related functions*/ |
|
2500 |
|
2501 static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ |
|
2502 static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ |
|
2503 static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ |
|
2504 static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ |
|
2505 |
|
2506 static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) |
|
2507 { |
|
2508 /*the passstart values have 8 values: the 8th one actually indicates the byte after the end of the 7th (= last) pass*/ |
|
2509 unsigned i; |
|
2510 |
|
2511 /*calculate width and height in pixels of each pass*/ |
|
2512 for(i = 0; i < 7; i++) |
|
2513 { |
|
2514 passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; |
|
2515 passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; |
|
2516 if(passw[i] == 0) passh[i] = 0; |
|
2517 if(passh[i] == 0) passw[i] = 0; |
|
2518 } |
|
2519 |
|
2520 filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; |
|
2521 for(i = 0; i < 7; i++) |
|
2522 { |
|
2523 filter_passstart[i + 1] = filter_passstart[i] + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ |
|
2524 padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); /*bits padded if needed to fill full byte at end of each scanline*/ |
|
2525 passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; /*only padded at end of reduced image*/ |
|
2526 } |
|
2527 } |
|
2528 |
|
2529 #ifdef LODEPNG_COMPILE_DECODER |
|
2530 |
|
2531 /* ////////////////////////////////////////////////////////////////////////// */ |
|
2532 /* / PNG Decoder / */ |
|
2533 /* ////////////////////////////////////////////////////////////////////////// */ |
|
2534 |
|
2535 /*read the information from the header and store it in the LodePNG_Info. return value is error*/ |
|
2536 void LodePNG_inspect(LodePNG_Decoder* decoder, const unsigned char* in, size_t inlength) |
|
2537 { |
|
2538 if(inlength == 0 || in == 0) { decoder->error = 48; return; } /*the given data is empty*/ |
|
2539 if(inlength < 29) { decoder->error = 27; return; } /*error: the data length is smaller than the length of the header*/ |
|
2540 |
|
2541 /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ |
|
2542 LodePNG_InfoPng_cleanup(&decoder->infoPng); |
|
2543 LodePNG_InfoPng_init(&decoder->infoPng); |
|
2544 decoder->error = 0; |
|
2545 |
|
2546 if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { decoder->error = 28; return; } /*error: the first 8 bytes are not the correct PNG signature*/ |
|
2547 if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { decoder->error = 29; return; } /*error: it doesn't start with a IHDR chunk!*/ |
|
2548 |
|
2549 /*read the values given in the header*/ |
|
2550 decoder->infoPng.width = LodePNG_read32bitInt(&in[16]); |
|
2551 decoder->infoPng.height = LodePNG_read32bitInt(&in[20]); |
|
2552 decoder->infoPng.color.bitDepth = in[24]; |
|
2553 decoder->infoPng.color.colorType = in[25]; |
|
2554 decoder->infoPng.compressionMethod = in[26]; |
|
2555 decoder->infoPng.filterMethod = in[27]; |
|
2556 decoder->infoPng.interlaceMethod = in[28]; |
|
2557 |
|
2558 if(!decoder->settings.ignoreCrc) |
|
2559 { |
|
2560 unsigned CRC = LodePNG_read32bitInt(&in[29]); |
|
2561 unsigned checksum = Crc32_crc(&in[12], 17); |
|
2562 if(CRC != checksum) { decoder->error = 57; return; } |
|
2563 } |
|
2564 |
|
2565 if(decoder->infoPng.compressionMethod != 0) { decoder->error = 32; return; } /*error: only compression method 0 is allowed in the specification*/ |
|
2566 if(decoder->infoPng.filterMethod != 0) { decoder->error = 33; return; } /*error: only filter method 0 is allowed in the specification*/ |
|
2567 if(decoder->infoPng.interlaceMethod > 1) { decoder->error = 34; return; } /*error: only interlace methods 0 and 1 exist in the specification*/ |
|
2568 |
|
2569 decoder->error = checkColorValidity(decoder->infoPng.color.colorType, decoder->infoPng.color.bitDepth); |
|
2570 } |
|
2571 |
|
2572 static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned char filterType, size_t length) |
|
2573 { |
|
2574 /* |
|
2575 For PNG filter method 0 |
|
2576 unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, the filter works byte per byte (bytewidth = 1) |
|
2577 precon is the previous unfiltered scanline, recon the result, scanline the current one |
|
2578 the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead |
|
2579 recon and scanline MAY be the same memory address! precon must be disjoint. |
|
2580 */ |
|
2581 |
|
2582 size_t i; |
|
2583 switch(filterType) |
|
2584 { |
|
2585 case 0: |
|
2586 for(i = 0; i < length; i++) recon[i] = scanline[i]; |
|
2587 break; |
|
2588 case 1: |
|
2589 for(i = 0; i < bytewidth; i++) recon[i] = scanline[i]; |
|
2590 for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth]; |
|
2591 break; |
|
2592 case 2: |
|
2593 if(precon) for(i = 0; i < length; i++) recon[i] = scanline[i] + precon[i]; |
|
2594 else for(i = 0; i < length; i++) recon[i] = scanline[i]; |
|
2595 break; |
|
2596 case 3: |
|
2597 if(precon) |
|
2598 { |
|
2599 for(i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2; |
|
2600 for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); |
|
2601 } |
|
2602 else |
|
2603 { |
|
2604 for(i = 0; i < bytewidth; i++) recon[i] = scanline[i]; |
|
2605 for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2; |
|
2606 } |
|
2607 break; |
|
2608 case 4: |
|
2609 if(precon) |
|
2610 { |
|
2611 for(i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(0, precon[i], 0)); |
|
2612 for(i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); |
|
2613 } |
|
2614 else |
|
2615 { |
|
2616 for(i = 0; i < bytewidth; i++) recon[i] = scanline[i]; |
|
2617 for(i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0)); |
|
2618 } |
|
2619 break; |
|
2620 default: return 36; /*error: unexisting filter type given*/ |
|
2621 } |
|
2622 return 0; |
|
2623 } |
|
2624 |
|
2625 static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) |
|
2626 { |
|
2627 /* |
|
2628 For PNG filter method 0 |
|
2629 this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 it's called 7 times) |
|
2630 out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline |
|
2631 w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel |
|
2632 in and out are allowed to be the same memory address! |
|
2633 */ |
|
2634 |
|
2635 unsigned y; |
|
2636 unsigned char* prevline = 0; |
|
2637 |
|
2638 size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ |
|
2639 size_t linebytes = (w * bpp + 7) / 8; |
|
2640 |
|
2641 for(y = 0; y < h; y++) |
|
2642 { |
|
2643 size_t outindex = linebytes * y; |
|
2644 size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ |
|
2645 unsigned char filterType = in[inindex]; |
|
2646 |
|
2647 unsigned error = unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes); |
|
2648 if(error) return error; |
|
2649 |
|
2650 prevline = &out[outindex]; |
|
2651 } |
|
2652 |
|
2653 return 0; |
|
2654 } |
|
2655 |
|
2656 static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) |
|
2657 { |
|
2658 /*Note: this function works on image buffers WITHOUT padding bits at end of scanlines with non-multiple-of-8 bit amounts, only between reduced images is padding |
|
2659 out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation (because that's likely a little bit faster)*/ |
|
2660 unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; |
|
2661 unsigned i; |
|
2662 |
|
2663 Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); |
|
2664 |
|
2665 if(bpp >= 8) |
|
2666 { |
|
2667 for(i = 0; i < 7; i++) |
|
2668 { |
|
2669 unsigned x, y, b; |
|
2670 size_t bytewidth = bpp / 8; |
|
2671 for(y = 0; y < passh[i]; y++) |
|
2672 for(x = 0; x < passw[i]; x++) |
|
2673 { |
|
2674 size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; |
|
2675 size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; |
|
2676 for(b = 0; b < bytewidth; b++) |
|
2677 { |
|
2678 out[pixeloutstart + b] = in[pixelinstart + b]; |
|
2679 } |
|
2680 } |
|
2681 } |
|
2682 } |
|
2683 else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ |
|
2684 { |
|
2685 for(i = 0; i < 7; i++) |
|
2686 { |
|
2687 unsigned x, y, b; |
|
2688 unsigned ilinebits = bpp * passw[i]; |
|
2689 unsigned olinebits = bpp * w; |
|
2690 size_t obp, ibp; /*bit pointers (for out and in buffer)*/ |
|
2691 for(y = 0; y < passh[i]; y++) |
|
2692 for(x = 0; x < passw[i]; x++) |
|
2693 { |
|
2694 ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); |
|
2695 obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; |
|
2696 for(b = 0; b < bpp; b++) |
|
2697 { |
|
2698 unsigned char bit = readBitFromReversedStream(&ibp, in); |
|
2699 setBitOfReversedStream0(&obp, out, bit); /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/ |
|
2700 } |
|
2701 } |
|
2702 } |
|
2703 } |
|
2704 } |
|
2705 |
|
2706 static void removePaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h) |
|
2707 { |
|
2708 /* |
|
2709 After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers for the Adam7 code, the color convert code and the output to the user. |
|
2710 in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits |
|
2711 also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 |
|
2712 only useful if (ilinebits - olinebits) is a value in the range 1..7 |
|
2713 */ |
|
2714 unsigned y; |
|
2715 size_t diff = ilinebits - olinebits; |
|
2716 size_t obp = 0, ibp = 0; /*bit pointers*/ |
|
2717 for(y = 0; y < h; y++) |
|
2718 { |
|
2719 size_t x; |
|
2720 for(x = 0; x < olinebits; x++) |
|
2721 { |
|
2722 unsigned char bit = readBitFromReversedStream(&ibp, in); |
|
2723 setBitOfReversedStream(&obp, out, bit); |
|
2724 } |
|
2725 ibp += diff; |
|
2726 } |
|
2727 } |
|
2728 |
|
2729 /*out must be buffer big enough to contain full image, and in must contain the full decompressed data from the IDAT chunks*/ |
|
2730 static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, const LodePNG_InfoPng* infoPng) /*return value is error*/ |
|
2731 { |
|
2732 /* |
|
2733 This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. Steps: |
|
2734 *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8) |
|
2735 *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace |
|
2736 NOTE: the in buffer will be overwritten with intermediate data! |
|
2737 */ |
|
2738 unsigned bpp = LodePNG_InfoColor_getBpp(&infoPng->color); |
|
2739 unsigned w = infoPng->width; |
|
2740 unsigned h = infoPng->height; |
|
2741 unsigned error = 0; |
|
2742 if(bpp == 0) return 31; /*error: invalid colortype*/ |
|
2743 |
|
2744 if(infoPng->interlaceMethod == 0) |
|
2745 { |
|
2746 if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) |
|
2747 { |
|
2748 error = unfilter(in, in, w, h, bpp); |
|
2749 if(error) return error; |
|
2750 removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h); |
|
2751 } |
|
2752 else error = unfilter(out, in, w, h, bpp); /*we can immediatly filter into the out buffer, no other steps needed*/ |
|
2753 } |
|
2754 else /*interlaceMethod is 1 (Adam7)*/ |
|
2755 { |
|
2756 unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; |
|
2757 unsigned i; |
|
2758 |
|
2759 Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); |
|
2760 |
|
2761 for(i = 0; i < 7; i++) |
|
2762 { |
|
2763 error = unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp); |
|
2764 if(error) return error; |
|
2765 if(bpp < 8) /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, move bytes instead of bits or move not at all*/ |
|
2766 { |
|
2767 /*remove padding bits in scanlines; after this there still may be padding bits between the different reduced images: each reduced image still starts nicely at a byte*/ |
|
2768 removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, ((passw[i] * bpp + 7) / 8) * 8, passh[i]); |
|
2769 } |
|
2770 } |
|
2771 |
|
2772 Adam7_deinterlace(out, in, w, h, bpp); |
|
2773 } |
|
2774 |
|
2775 return error; |
|
2776 } |
|
2777 |
|
2778 /*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ |
|
2779 static void decodeGeneric(LodePNG_Decoder* decoder, unsigned char** out, size_t* outsize, const unsigned char* in, size_t size) |
|
2780 { |
|
2781 unsigned char IEND = 0; |
|
2782 const unsigned char* chunk; |
|
2783 size_t i; |
|
2784 ucvector idat; /*the data from idat chunks*/ |
|
2785 |
|
2786 /*for unknown chunk order*/ |
|
2787 unsigned unknown = 0; |
|
2788 unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ |
|
2789 |
|
2790 /*provide some proper output values if error will happen*/ |
|
2791 *out = 0; |
|
2792 *outsize = 0; |
|
2793 |
|
2794 if(size == 0 || in == 0) { decoder->error = 48; return; } /*the given data is empty*/ |
|
2795 |
|
2796 LodePNG_inspect(decoder, in, size); /*reads header and resets other parameters in decoder->infoPng*/ |
|
2797 if(decoder->error) return; |
|
2798 |
|
2799 ucvector_init(&idat); |
|
2800 |
|
2801 chunk = &in[33]; /*first byte of the first chunk after the header*/ |
|
2802 |
|
2803 while(!IEND) /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer*/ |
|
2804 { |
|
2805 unsigned chunkLength; |
|
2806 const unsigned char* data; /*the data in the chunk*/ |
|
2807 |
|
2808 if((size_t)((chunk - in) + 12) > size || chunk < in) { decoder->error = 30; break; } /*error: size of the in buffer too small to contain next chunk*/ |
|
2809 chunkLength = LodePNG_chunk_length(chunk); /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ |
|
2810 if(chunkLength > 2147483647) { decoder->error = 63; break; } |
|
2811 if((size_t)((chunk - in) + chunkLength + 12) > size || (chunk + chunkLength + 12) < in) { decoder->error = 35; break; } /*error: size of the in buffer too small to contain next chunk*/ |
|
2812 data = LodePNG_chunk_data_const(chunk); |
|
2813 |
|
2814 /*IDAT chunk, containing compressed image data*/ |
|
2815 if(LodePNG_chunk_type_equals(chunk, "IDAT")) |
|
2816 { |
|
2817 size_t oldsize = idat.size; |
|
2818 if(!ucvector_resize(&idat, oldsize + chunkLength)) { decoder->error = 9936; break; } |
|
2819 for(i = 0; i < chunkLength; i++) idat.data[oldsize + i] = data[i]; |
|
2820 critical_pos = 3; |
|
2821 } |
|
2822 /*IEND chunk*/ |
|
2823 else if(LodePNG_chunk_type_equals(chunk, "IEND")) |
|
2824 { |
|
2825 IEND = 1; |
|
2826 } |
|
2827 /*palette chunk (PLTE)*/ |
|
2828 else if(LodePNG_chunk_type_equals(chunk, "PLTE")) |
|
2829 { |
|
2830 unsigned pos = 0; |
|
2831 if(decoder->infoPng.color.palette) free(decoder->infoPng.color.palette); |
|
2832 decoder->infoPng.color.palettesize = chunkLength / 3; |
|
2833 decoder->infoPng.color.palette = (unsigned char*)malloc(4 * decoder->infoPng.color.palettesize); |
|
2834 if(!decoder->infoPng.color.palette && decoder->infoPng.color.palettesize) { decoder->error = 9937; break; } |
|
2835 if(!decoder->infoPng.color.palette) decoder->infoPng.color.palettesize = 0; /*malloc failed...*/ |
|
2836 if(decoder->infoPng.color.palettesize > 256) { decoder->error = 38; break; } /*error: palette too big*/ |
|
2837 for(i = 0; i < decoder->infoPng.color.palettesize; i++) |
|
2838 { |
|
2839 decoder->infoPng.color.palette[4 * i + 0] = data[pos++]; /*R*/ |
|
2840 decoder->infoPng.color.palette[4 * i + 1] = data[pos++]; /*G*/ |
|
2841 decoder->infoPng.color.palette[4 * i + 2] = data[pos++]; /*B*/ |
|
2842 decoder->infoPng.color.palette[4 * i + 3] = 255; /*alpha*/ |
|
2843 } |
|
2844 critical_pos = 2; |
|
2845 } |
|
2846 /*palette transparency chunk (tRNS)*/ |
|
2847 else if(LodePNG_chunk_type_equals(chunk, "tRNS")) |
|
2848 { |
|
2849 if(decoder->infoPng.color.colorType == 3) |
|
2850 { |
|
2851 if(chunkLength > decoder->infoPng.color.palettesize) { decoder->error = 39; break; } /*error: more alpha values given than there are palette entries*/ |
|
2852 for(i = 0; i < chunkLength; i++) decoder->infoPng.color.palette[4 * i + 3] = data[i]; |
|
2853 } |
|
2854 else if(decoder->infoPng.color.colorType == 0) |
|
2855 { |
|
2856 if(chunkLength != 2) { decoder->error = 40; break; } /*error: this chunk must be 2 bytes for greyscale image*/ |
|
2857 decoder->infoPng.color.key_defined = 1; |
|
2858 decoder->infoPng.color.key_r = decoder->infoPng.color.key_g = decoder->infoPng.color.key_b = 256 * data[0] + data[1]; |
|
2859 } |
|
2860 else if(decoder->infoPng.color.colorType == 2) |
|
2861 { |
|
2862 if(chunkLength != 6) { decoder->error = 41; break; } /*error: this chunk must be 6 bytes for RGB image*/ |
|
2863 decoder->infoPng.color.key_defined = 1; |
|
2864 decoder->infoPng.color.key_r = 256 * data[0] + data[1]; |
|
2865 decoder->infoPng.color.key_g = 256 * data[2] + data[3]; |
|
2866 decoder->infoPng.color.key_b = 256 * data[4] + data[5]; |
|
2867 } |
|
2868 else { decoder->error = 42; break; } /*error: tRNS chunk not allowed for other color models*/ |
|
2869 } |
|
2870 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
2871 /*background color chunk (bKGD)*/ |
|
2872 else if(LodePNG_chunk_type_equals(chunk, "bKGD")) |
|
2873 { |
|
2874 if(decoder->infoPng.color.colorType == 3) |
|
2875 { |
|
2876 if(chunkLength != 1) { decoder->error = 43; break; } /*error: this chunk must be 1 byte for indexed color image*/ |
|
2877 decoder->infoPng.background_defined = 1; |
|
2878 decoder->infoPng.background_r = decoder->infoPng.background_g = decoder->infoPng.background_g = data[0]; |
|
2879 } |
|
2880 else if(decoder->infoPng.color.colorType == 0 || decoder->infoPng.color.colorType == 4) |
|
2881 { |
|
2882 if(chunkLength != 2) { decoder->error = 44; break; } /*error: this chunk must be 2 bytes for greyscale image*/ |
|
2883 decoder->infoPng.background_defined = 1; |
|
2884 decoder->infoPng.background_r = decoder->infoPng.background_g = decoder->infoPng.background_b = 256 * data[0] + data[1]; |
|
2885 } |
|
2886 else if(decoder->infoPng.color.colorType == 2 || decoder->infoPng.color.colorType == 6) |
|
2887 { |
|
2888 if(chunkLength != 6) { decoder->error = 45; break; } /*error: this chunk must be 6 bytes for greyscale image*/ |
|
2889 decoder->infoPng.background_defined = 1; |
|
2890 decoder->infoPng.background_r = 256 * data[0] + data[1]; |
|
2891 decoder->infoPng.background_g = 256 * data[2] + data[3]; |
|
2892 decoder->infoPng.background_b = 256 * data[4] + data[5]; |
|
2893 } |
|
2894 } |
|
2895 /*text chunk (tEXt)*/ |
|
2896 else if(LodePNG_chunk_type_equals(chunk, "tEXt")) |
|
2897 { |
|
2898 if(decoder->settings.readTextChunks) |
|
2899 { |
|
2900 char *key = 0, *str = 0; |
|
2901 |
|
2902 while(!decoder->error) /*not really a while loop, only used to break on error*/ |
|
2903 { |
|
2904 unsigned length, string2_begin; |
|
2905 |
|
2906 for(length = 0; length < chunkLength && data[length] != 0; length++) ; |
|
2907 if(length + 1 >= chunkLength) { decoder->error = 75; break; } |
|
2908 key = (char*)malloc(length + 1); |
|
2909 if(!key) { decoder->error = 9938; break; } |
|
2910 key[length] = 0; |
|
2911 for(i = 0; i < length; i++) key[i] = data[i]; |
|
2912 |
|
2913 string2_begin = length + 1; |
|
2914 if(string2_begin > chunkLength) { decoder->error = 75; break; } |
|
2915 length = chunkLength - string2_begin; |
|
2916 str = (char*)malloc(length + 1); |
|
2917 if(!str) { decoder->error = 9939; break; } |
|
2918 str[length] = 0; |
|
2919 for(i = 0; i < length; i++) str[i] = data[string2_begin + i]; |
|
2920 |
|
2921 decoder->error = LodePNG_Text_add(&decoder->infoPng.text, key, str); |
|
2922 |
|
2923 break; |
|
2924 } |
|
2925 |
|
2926 free(key); |
|
2927 free(str); |
|
2928 } |
|
2929 } |
|
2930 /*compressed text chunk (zTXt)*/ |
|
2931 else if(LodePNG_chunk_type_equals(chunk, "zTXt")) |
|
2932 { |
|
2933 if(decoder->settings.readTextChunks) |
|
2934 { |
|
2935 unsigned length, string2_begin; |
|
2936 char *key = 0; |
|
2937 ucvector decoded; |
|
2938 |
|
2939 ucvector_init(&decoded); |
|
2940 |
|
2941 while(!decoder->error) /*not really a while loop, only used to break on error*/ |
|
2942 { |
|
2943 for(length = 0; length < chunkLength && data[length] != 0; length++) ; |
|
2944 if(length + 2 >= chunkLength) { decoder->error = 75; break; } |
|
2945 key = (char*)malloc(length + 1); |
|
2946 if(!key) { decoder->error = 9940; break; } |
|
2947 key[length] = 0; |
|
2948 for(i = 0; i < length; i++) key[i] = data[i]; |
|
2949 |
|
2950 if(data[length + 1] != 0) { decoder->error = 72; break; } /*the 0 byte indicating compression must be 0*/ |
|
2951 |
|
2952 string2_begin = length + 2; |
|
2953 if(string2_begin > chunkLength) { decoder->error = 75; break; } |
|
2954 length = chunkLength - string2_begin; |
|
2955 decoder->error = LodePNG_decompress(&decoded.data, &decoded.size, (unsigned char*)(&data[string2_begin]), length, &decoder->settings.zlibsettings); |
|
2956 if(decoder->error) break; |
|
2957 ucvector_push_back(&decoded, 0); |
|
2958 |
|
2959 decoder->error = LodePNG_Text_add(&decoder->infoPng.text, key, (char*)decoded.data); |
|
2960 |
|
2961 break; |
|
2962 } |
|
2963 |
|
2964 free(key); |
|
2965 ucvector_cleanup(&decoded); |
|
2966 if(decoder->error) break; |
|
2967 } |
|
2968 } |
|
2969 /*international text chunk (iTXt)*/ |
|
2970 else if(LodePNG_chunk_type_equals(chunk, "iTXt")) |
|
2971 { |
|
2972 if(decoder->settings.readTextChunks) |
|
2973 { |
|
2974 unsigned length, begin, compressed; |
|
2975 char *key = 0, *langtag = 0, *transkey = 0; |
|
2976 ucvector decoded; |
|
2977 ucvector_init(&decoded); |
|
2978 |
|
2979 while(!decoder->error) /*not really a while loop, only used to break on error*/ |
|
2980 { |
|
2981 if(chunkLength < 5) { decoder->error = 76; break; } |
|
2982 for(length = 0; length < chunkLength && data[length] != 0; length++) ; |
|
2983 if(length + 2 >= chunkLength) { decoder->error = 75; break; } |
|
2984 key = (char*)malloc(length + 1); |
|
2985 if(!key) { decoder->error = 9941; break; } |
|
2986 key[length] = 0; |
|
2987 for(i = 0; i < length; i++) key[i] = data[i]; |
|
2988 |
|
2989 compressed = data[length + 1]; |
|
2990 if(data[length + 2] != 0) { decoder->error = 72; break; } /*the 0 byte indicating compression must be 0*/ |
|
2991 |
|
2992 begin = length + 3; |
|
2993 length = 0; |
|
2994 for(i = begin; i < chunkLength && data[i] != 0; i++) length++; |
|
2995 if(begin + length + 1 >= chunkLength) { decoder->error = 75; break; } |
|
2996 langtag = (char*)malloc(length + 1); |
|
2997 if(!langtag) { decoder->error = 9942; break; } |
|
2998 langtag[length] = 0; |
|
2999 for(i = 0; i < length; i++) langtag[i] = data[begin + i]; |
|
3000 |
|
3001 begin += length + 1; |
|
3002 length = 0; |
|
3003 for(i = begin; i < chunkLength && data[i] != 0; i++) length++; |
|
3004 if(begin + length + 1 >= chunkLength) { decoder->error = 75; break; } |
|
3005 transkey = (char*)malloc(length + 1); |
|
3006 if(!transkey) { decoder->error = 9943; break; } |
|
3007 transkey[length] = 0; |
|
3008 for(i = 0; i < length; i++) transkey[i] = data[begin + i]; |
|
3009 |
|
3010 begin += length + 1; |
|
3011 if(begin > chunkLength) { decoder->error = 75; break; } |
|
3012 length = chunkLength - begin; |
|
3013 |
|
3014 if(compressed) |
|
3015 { |
|
3016 decoder->error = LodePNG_decompress(&decoded.data, &decoded.size, (unsigned char*)(&data[begin]), length, &decoder->settings.zlibsettings); |
|
3017 if(decoder->error) break; |
|
3018 ucvector_push_back(&decoded, 0); |
|
3019 } |
|
3020 else |
|
3021 { |
|
3022 if(!ucvector_resize(&decoded, length + 1)) { decoder->error = 9944; break; } |
|
3023 decoded.data[length] = 0; |
|
3024 for(i = 0; i < length; i++) decoded.data[i] = data[begin + i]; |
|
3025 } |
|
3026 |
|
3027 decoder->error = LodePNG_IText_add(&decoder->infoPng.itext, key, langtag, transkey, (char*)decoded.data); |
|
3028 |
|
3029 break; |
|
3030 } |
|
3031 |
|
3032 free(key); |
|
3033 free(langtag); |
|
3034 free(transkey); |
|
3035 ucvector_cleanup(&decoded); |
|
3036 if(decoder->error) break; |
|
3037 } |
|
3038 } |
|
3039 else if(LodePNG_chunk_type_equals(chunk, "tIME")) |
|
3040 { |
|
3041 if(chunkLength != 7) { decoder->error = 73; break; } |
|
3042 decoder->infoPng.time_defined = 1; |
|
3043 decoder->infoPng.time.year = 256 * data[0] + data[+ 1]; |
|
3044 decoder->infoPng.time.month = data[2]; |
|
3045 decoder->infoPng.time.day = data[3]; |
|
3046 decoder->infoPng.time.hour = data[4]; |
|
3047 decoder->infoPng.time.minute = data[5]; |
|
3048 decoder->infoPng.time.second = data[6]; |
|
3049 } |
|
3050 else if(LodePNG_chunk_type_equals(chunk, "pHYs")) |
|
3051 { |
|
3052 if(chunkLength != 9) { decoder->error = 74; break; } |
|
3053 decoder->infoPng.phys_defined = 1; |
|
3054 decoder->infoPng.phys_x = 16777216 * data[0] + 65536 * data[1] + 256 * data[2] + data[3]; |
|
3055 decoder->infoPng.phys_y = 16777216 * data[4] + 65536 * data[5] + 256 * data[6] + data[7]; |
|
3056 decoder->infoPng.phys_unit = data[8]; |
|
3057 } |
|
3058 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
3059 else /*it's not an implemented chunk type, so ignore it: skip over the data*/ |
|
3060 { |
|
3061 if(LodePNG_chunk_critical(chunk)) { decoder->error = 69; break; } /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ |
|
3062 unknown = 1; |
|
3063 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
3064 if(decoder->settings.rememberUnknownChunks) |
|
3065 { |
|
3066 LodePNG_UnknownChunks* unknown = &decoder->infoPng.unknown_chunks; |
|
3067 decoder->error = LodePNG_append_chunk(&unknown->data[critical_pos - 1], &unknown->datasize[critical_pos - 1], chunk); |
|
3068 if(decoder->error) break; |
|
3069 } |
|
3070 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
3071 } |
|
3072 |
|
3073 if(!decoder->settings.ignoreCrc && !unknown) /*check CRC if wanted, only on known chunk types*/ |
|
3074 { |
|
3075 if(LodePNG_chunk_check_crc(chunk)) { decoder->error = 57; break; } |
|
3076 } |
|
3077 |
|
3078 if(!IEND) chunk = LodePNG_chunk_next_const(chunk); |
|
3079 } |
|
3080 |
|
3081 if(!decoder->error) |
|
3082 { |
|
3083 ucvector scanlines; |
|
3084 ucvector_init(&scanlines); |
|
3085 if(!ucvector_resize(&scanlines, ((decoder->infoPng.width * (decoder->infoPng.height * LodePNG_InfoColor_getBpp(&decoder->infoPng.color) + 7)) / 8) + decoder->infoPng.height)) decoder->error = 9945; /*maximum final image length is already reserved in the vector's length - this is not really necessary*/ |
|
3086 if(!decoder->error) decoder->error = LodePNG_decompress(&scanlines.data, &scanlines.size, idat.data, idat.size, &decoder->settings.zlibsettings); /*decompress with the Zlib decompressor*/ |
|
3087 |
|
3088 if(!decoder->error) |
|
3089 { |
|
3090 ucvector outv; |
|
3091 ucvector_init(&outv); |
|
3092 if(!ucvector_resizev(&outv, (decoder->infoPng.height * decoder->infoPng.width * LodePNG_InfoColor_getBpp(&decoder->infoPng.color) + 7) / 8, 0)) decoder->error = 9946; |
|
3093 if(!decoder->error) decoder->error = postProcessScanlines(outv.data, scanlines.data, &decoder->infoPng); |
|
3094 *out = outv.data; |
|
3095 *outsize = outv.size; |
|
3096 } |
|
3097 ucvector_cleanup(&scanlines); |
|
3098 } |
|
3099 |
|
3100 ucvector_cleanup(&idat); |
|
3101 } |
|
3102 |
|
3103 void LodePNG_decode(LodePNG_Decoder* decoder, unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize) |
|
3104 { |
|
3105 *out = 0; |
|
3106 *outsize = 0; |
|
3107 decodeGeneric(decoder, out, outsize, in, insize); |
|
3108 if(decoder->error) return; |
|
3109 if(!decoder->settings.color_convert || LodePNG_InfoColor_equal(&decoder->infoRaw.color, &decoder->infoPng.color)) |
|
3110 { |
|
3111 /*same color type, no copying or converting of data needed*/ |
|
3112 /*store the infoPng color settings on the infoRaw so that the infoRaw still reflects what colorType |
|
3113 the raw image has to the end user*/ |
|
3114 if(!decoder->settings.color_convert) |
|
3115 { |
|
3116 decoder->error = LodePNG_InfoColor_copy(&decoder->infoRaw.color, &decoder->infoPng.color); |
|
3117 if(decoder->error) return; |
|
3118 } |
|
3119 } |
|
3120 else |
|
3121 { |
|
3122 /*color conversion needed; sort of copy of the data*/ |
|
3123 unsigned char* data = *out; |
|
3124 |
|
3125 /*TODO: check if this works according to the statement in the documentation: "The converter can convert from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/ |
|
3126 if(!(decoder->infoRaw.color.colorType == 2 || decoder->infoRaw.color.colorType == 6) && !(decoder->infoRaw.color.bitDepth == 8)) { decoder->error = 56; return; } |
|
3127 |
|
3128 *outsize = (decoder->infoPng.width * decoder->infoPng.height * LodePNG_InfoColor_getBpp(&decoder->infoRaw.color) + 7) / 8; |
|
3129 *out = (unsigned char*)malloc(*outsize); |
|
3130 if(!(*out)) |
|
3131 { |
|
3132 decoder->error = 9947; |
|
3133 *outsize = 0; |
|
3134 } |
|
3135 else decoder->error = LodePNG_convert(*out, data, &decoder->infoRaw.color, &decoder->infoPng.color, decoder->infoPng.width, decoder->infoPng.height); |
|
3136 free(data); |
|
3137 } |
|
3138 } |
|
3139 |
|
3140 unsigned LodePNG_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) |
|
3141 { |
|
3142 unsigned error; |
|
3143 size_t dummy_size; |
|
3144 LodePNG_Decoder decoder; |
|
3145 LodePNG_Decoder_init(&decoder); |
|
3146 LodePNG_decode(&decoder, out, &dummy_size, in, insize); |
|
3147 error = decoder.error; |
|
3148 *w = decoder.infoPng.width; |
|
3149 *h = decoder.infoPng.height; |
|
3150 LodePNG_Decoder_cleanup(&decoder); |
|
3151 return error; |
|
3152 } |
|
3153 |
|
3154 #ifdef LODEPNG_COMPILE_DISK |
|
3155 unsigned LodePNG_decode32f(unsigned char** out, unsigned* w, unsigned* h, const char* filename) |
|
3156 { |
|
3157 unsigned char* buffer; |
|
3158 size_t buffersize; |
|
3159 unsigned error; |
|
3160 error = LodePNG_loadFile(&buffer, &buffersize, filename); |
|
3161 if(!error) error = LodePNG_decode32(out, w, h, buffer, buffersize); |
|
3162 free(buffer); |
|
3163 return error; |
|
3164 } |
|
3165 #endif /*LODEPNG_COMPILE_DISK*/ |
|
3166 |
|
3167 void LodePNG_DecodeSettings_init(LodePNG_DecodeSettings* settings) |
|
3168 { |
|
3169 settings->color_convert = 1; |
|
3170 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
3171 settings->readTextChunks = 1; |
|
3172 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
3173 settings->ignoreCrc = 0; |
|
3174 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
3175 settings->rememberUnknownChunks = 0; |
|
3176 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
3177 LodeZlib_DecompressSettings_init(&settings->zlibsettings); |
|
3178 } |
|
3179 |
|
3180 void LodePNG_Decoder_init(LodePNG_Decoder* decoder) |
|
3181 { |
|
3182 LodePNG_DecodeSettings_init(&decoder->settings); |
|
3183 LodePNG_InfoRaw_init(&decoder->infoRaw); |
|
3184 LodePNG_InfoPng_init(&decoder->infoPng); |
|
3185 decoder->error = 1; |
|
3186 } |
|
3187 |
|
3188 void LodePNG_Decoder_cleanup(LodePNG_Decoder* decoder) |
|
3189 { |
|
3190 LodePNG_InfoRaw_cleanup(&decoder->infoRaw); |
|
3191 LodePNG_InfoPng_cleanup(&decoder->infoPng); |
|
3192 } |
|
3193 |
|
3194 void LodePNG_Decoder_copy(LodePNG_Decoder* dest, const LodePNG_Decoder* source) |
|
3195 { |
|
3196 LodePNG_Decoder_cleanup(dest); |
|
3197 *dest = *source; |
|
3198 LodePNG_InfoRaw_init(&dest->infoRaw); |
|
3199 LodePNG_InfoPng_init(&dest->infoPng); |
|
3200 dest->error = LodePNG_InfoRaw_copy(&dest->infoRaw, &source->infoRaw); if(dest->error) return; |
|
3201 dest->error = LodePNG_InfoPng_copy(&dest->infoPng, &source->infoPng); if(dest->error) return; |
|
3202 } |
|
3203 |
|
3204 #endif /*LODEPNG_COMPILE_DECODER*/ |
|
3205 |
|
3206 #ifdef LODEPNG_COMPILE_ENCODER |
|
3207 |
|
3208 /* ////////////////////////////////////////////////////////////////////////// */ |
|
3209 /* / PNG Encoder / */ |
|
3210 /* ////////////////////////////////////////////////////////////////////////// */ |
|
3211 |
|
3212 /*chunkName must be string of 4 characters*/ |
|
3213 static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) |
|
3214 { |
|
3215 unsigned error = LodePNG_create_chunk(&out->data, &out->size, (unsigned)length, chunkName, data); |
|
3216 if(error) return error; |
|
3217 out->allocsize = out->size; /*fix the allocsize again*/ |
|
3218 return 0; |
|
3219 } |
|
3220 |
|
3221 static void writeSignature(ucvector* out) |
|
3222 { |
|
3223 /*8 bytes PNG signature*/ |
|
3224 ucvector_push_back(out, 137); |
|
3225 ucvector_push_back(out, 80); |
|
3226 ucvector_push_back(out, 78); |
|
3227 ucvector_push_back(out, 71); |
|
3228 ucvector_push_back(out, 13); |
|
3229 ucvector_push_back(out, 10); |
|
3230 ucvector_push_back(out, 26); |
|
3231 ucvector_push_back(out, 10); |
|
3232 } |
|
3233 |
|
3234 static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, unsigned bitDepth, unsigned colorType, unsigned interlaceMethod) |
|
3235 { |
|
3236 unsigned error = 0; |
|
3237 ucvector header; |
|
3238 ucvector_init(&header); |
|
3239 |
|
3240 LodePNG_add32bitInt(&header, w); /*width*/ |
|
3241 LodePNG_add32bitInt(&header, h); /*height*/ |
|
3242 ucvector_push_back(&header, (unsigned char)bitDepth); /*bit depth*/ |
|
3243 ucvector_push_back(&header, (unsigned char)colorType); /*color type*/ |
|
3244 ucvector_push_back(&header, 0); /*compression method*/ |
|
3245 ucvector_push_back(&header, 0); /*filter method*/ |
|
3246 ucvector_push_back(&header, interlaceMethod); /*interlace method*/ |
|
3247 |
|
3248 error = addChunk(out, "IHDR", header.data, header.size); |
|
3249 ucvector_cleanup(&header); |
|
3250 |
|
3251 return error; |
|
3252 } |
|
3253 |
|
3254 static unsigned addChunk_PLTE(ucvector* out, const LodePNG_InfoColor* info) |
|
3255 { |
|
3256 unsigned error = 0; |
|
3257 size_t i; |
|
3258 ucvector PLTE; |
|
3259 ucvector_init(&PLTE); |
|
3260 for(i = 0; i < info->palettesize * 4; i++) if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]); /*add all channels except alpha channel*/ |
|
3261 error = addChunk(out, "PLTE", PLTE.data, PLTE.size); |
|
3262 ucvector_cleanup(&PLTE); |
|
3263 |
|
3264 return error; |
|
3265 } |
|
3266 |
|
3267 static unsigned addChunk_tRNS(ucvector* out, const LodePNG_InfoColor* info) |
|
3268 { |
|
3269 unsigned error = 0; |
|
3270 size_t i; |
|
3271 ucvector tRNS; |
|
3272 ucvector_init(&tRNS); |
|
3273 if(info->colorType == 3) |
|
3274 { |
|
3275 for(i = 0; i < info->palettesize; i++) ucvector_push_back(&tRNS, info->palette[4 * i + 3]); /*add only alpha channel*/ |
|
3276 } |
|
3277 else if(info->colorType == 0) |
|
3278 { |
|
3279 if(info->key_defined) |
|
3280 { |
|
3281 ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); |
|
3282 ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); |
|
3283 } |
|
3284 } |
|
3285 else if(info->colorType == 2) |
|
3286 { |
|
3287 if(info->key_defined) |
|
3288 { |
|
3289 ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); |
|
3290 ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); |
|
3291 ucvector_push_back(&tRNS, (unsigned char)(info->key_g / 256)); |
|
3292 ucvector_push_back(&tRNS, (unsigned char)(info->key_g % 256)); |
|
3293 ucvector_push_back(&tRNS, (unsigned char)(info->key_b / 256)); |
|
3294 ucvector_push_back(&tRNS, (unsigned char)(info->key_b % 256)); |
|
3295 } |
|
3296 } |
|
3297 |
|
3298 error = addChunk(out, "tRNS", tRNS.data, tRNS.size); |
|
3299 ucvector_cleanup(&tRNS); |
|
3300 |
|
3301 return error; |
|
3302 } |
|
3303 |
|
3304 static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, LodeZlib_DeflateSettings* zlibsettings) |
|
3305 { |
|
3306 ucvector zlibdata; |
|
3307 unsigned error = 0; |
|
3308 |
|
3309 /*compress with the Zlib compressor*/ |
|
3310 ucvector_init(&zlibdata); |
|
3311 error = LodePNG_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings); |
|
3312 if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size); |
|
3313 ucvector_cleanup(&zlibdata); |
|
3314 |
|
3315 return error; |
|
3316 } |
|
3317 |
|
3318 static unsigned addChunk_IEND(ucvector* out) |
|
3319 { |
|
3320 unsigned error = 0; |
|
3321 error = addChunk(out, "IEND", 0, 0); |
|
3322 return error; |
|
3323 } |
|
3324 |
|
3325 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
3326 |
|
3327 static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) /*add text chunk*/ |
|
3328 { |
|
3329 unsigned error = 0; |
|
3330 size_t i; |
|
3331 ucvector text; |
|
3332 ucvector_init(&text); |
|
3333 for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&text, (unsigned char)keyword[i]); |
|
3334 ucvector_push_back(&text, 0); |
|
3335 for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&text, (unsigned char)textstring[i]); |
|
3336 error = addChunk(out, "tEXt", text.data, text.size); |
|
3337 ucvector_cleanup(&text); |
|
3338 |
|
3339 return error; |
|
3340 } |
|
3341 |
|
3342 static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, LodeZlib_DeflateSettings* zlibsettings) |
|
3343 { |
|
3344 unsigned error = 0; |
|
3345 ucvector data, compressed; |
|
3346 size_t i, textsize = strlen(textstring); |
|
3347 |
|
3348 ucvector_init(&data); |
|
3349 ucvector_init(&compressed); |
|
3350 for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&data, (unsigned char)keyword[i]); |
|
3351 ucvector_push_back(&data, 0); /* 0 termination char*/ |
|
3352 ucvector_push_back(&data, 0); /*compression method: 0*/ |
|
3353 |
|
3354 error = LodePNG_compress(&compressed.data, &compressed.size, (unsigned char*)textstring, textsize, zlibsettings); |
|
3355 if(!error) |
|
3356 { |
|
3357 for(i = 0; i < compressed.size; i++) ucvector_push_back(&data, compressed.data[i]); |
|
3358 error = addChunk(out, "zTXt", data.data, data.size); |
|
3359 } |
|
3360 |
|
3361 ucvector_cleanup(&compressed); |
|
3362 ucvector_cleanup(&data); |
|
3363 return error; |
|
3364 } |
|
3365 |
|
3366 static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag, const char* transkey, const char* textstring, LodeZlib_DeflateSettings* zlibsettings) |
|
3367 { |
|
3368 unsigned error = 0; |
|
3369 ucvector data, compressed_data; |
|
3370 size_t i, textsize = strlen(textstring); |
|
3371 |
|
3372 ucvector_init(&data); |
|
3373 |
|
3374 for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&data, (unsigned char)keyword[i]); |
|
3375 ucvector_push_back(&data, 0); /*null termination char*/ |
|
3376 ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/ |
|
3377 ucvector_push_back(&data, 0); /*compression method*/ |
|
3378 for(i = 0; langtag[i] != 0; i++) ucvector_push_back(&data, (unsigned char)langtag[i]); |
|
3379 ucvector_push_back(&data, 0); /*null termination char*/ |
|
3380 for(i = 0; transkey[i] != 0; i++) ucvector_push_back(&data, (unsigned char)transkey[i]); |
|
3381 ucvector_push_back(&data, 0); /*null termination char*/ |
|
3382 |
|
3383 if(compressed) |
|
3384 { |
|
3385 ucvector_init(&compressed_data); |
|
3386 error = LodePNG_compress(&compressed_data.data, &compressed_data.size, (unsigned char*)textstring, textsize, zlibsettings); |
|
3387 if(!error) |
|
3388 { |
|
3389 for(i = 0; i < compressed_data.size; i++) ucvector_push_back(&data, compressed_data.data[i]); |
|
3390 for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&data, (unsigned char)textstring[i]); |
|
3391 } |
|
3392 } |
|
3393 else /*not compressed*/ |
|
3394 { |
|
3395 for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&data, (unsigned char)textstring[i]); |
|
3396 } |
|
3397 |
|
3398 if(!error) error = addChunk(out, "iTXt", data.data, data.size); |
|
3399 ucvector_cleanup(&data); |
|
3400 return error; |
|
3401 } |
|
3402 |
|
3403 static unsigned addChunk_bKGD(ucvector* out, const LodePNG_InfoPng* info) |
|
3404 { |
|
3405 unsigned error = 0; |
|
3406 ucvector bKGD; |
|
3407 ucvector_init(&bKGD); |
|
3408 if(info->color.colorType == 0 || info->color.colorType == 4) |
|
3409 { |
|
3410 ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); |
|
3411 ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); |
|
3412 } |
|
3413 else if(info->color.colorType == 2 || info->color.colorType == 6) |
|
3414 { |
|
3415 ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); |
|
3416 ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); |
|
3417 ucvector_push_back(&bKGD, (unsigned char)(info->background_g / 256)); |
|
3418 ucvector_push_back(&bKGD, (unsigned char)(info->background_g % 256)); |
|
3419 ucvector_push_back(&bKGD, (unsigned char)(info->background_b / 256)); |
|
3420 ucvector_push_back(&bKGD, (unsigned char)(info->background_b % 256)); |
|
3421 } |
|
3422 else if(info->color.colorType == 3) |
|
3423 { |
|
3424 ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); /*palette index*/ |
|
3425 } |
|
3426 |
|
3427 error = addChunk(out, "bKGD", bKGD.data, bKGD.size); |
|
3428 ucvector_cleanup(&bKGD); |
|
3429 |
|
3430 return error; |
|
3431 } |
|
3432 |
|
3433 static unsigned addChunk_tIME(ucvector* out, const LodePNG_Time* time) |
|
3434 { |
|
3435 unsigned error = 0; |
|
3436 unsigned char* data = (unsigned char*)malloc(7); |
|
3437 if(!data) return 9948; |
|
3438 data[0] = (unsigned char)(time->year / 256); |
|
3439 data[1] = (unsigned char)(time->year % 256); |
|
3440 data[2] = time->month; |
|
3441 data[3] = time->day; |
|
3442 data[4] = time->hour; |
|
3443 data[5] = time->minute; |
|
3444 data[6] = time->second; |
|
3445 error = addChunk(out, "tIME", data, 7); |
|
3446 free(data); |
|
3447 return error; |
|
3448 } |
|
3449 |
|
3450 static unsigned addChunk_pHYs(ucvector* out, const LodePNG_InfoPng* info) |
|
3451 { |
|
3452 unsigned error = 0; |
|
3453 ucvector data; |
|
3454 ucvector_init(&data); |
|
3455 |
|
3456 LodePNG_add32bitInt(&data, info->phys_x); |
|
3457 LodePNG_add32bitInt(&data, info->phys_y); |
|
3458 ucvector_push_back(&data, info->phys_unit); |
|
3459 |
|
3460 error = addChunk(out, "pHYs", data.data, data.size); |
|
3461 ucvector_cleanup(&data); |
|
3462 |
|
3463 return error; |
|
3464 } |
|
3465 |
|
3466 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
3467 |
|
3468 static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, size_t length, size_t bytewidth, unsigned char filterType) |
|
3469 { |
|
3470 size_t i; |
|
3471 switch(filterType) |
|
3472 { |
|
3473 case 0: |
|
3474 if(prevline) for(i = 0; i < length; i++) out[i] = scanline[i]; |
|
3475 else for(i = 0; i < length; i++) out[i] = scanline[i]; |
|
3476 break; |
|
3477 case 1: |
|
3478 if(prevline) |
|
3479 { |
|
3480 for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; |
|
3481 for(i = bytewidth; i < length ; i++) out[i] = scanline[i] - scanline[i - bytewidth]; |
|
3482 } |
|
3483 else |
|
3484 { |
|
3485 for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; |
|
3486 for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth]; |
|
3487 } |
|
3488 break; |
|
3489 case 2: |
|
3490 if(prevline) for(i = 0; i < length; i++) out[i] = scanline[i] - prevline[i]; |
|
3491 else for(i = 0; i < length; i++) out[i] = scanline[i]; |
|
3492 break; |
|
3493 case 3: |
|
3494 if(prevline) |
|
3495 { |
|
3496 for(i = 0; i < bytewidth; i++) out[i] = scanline[i] - prevline[i] / 2; |
|
3497 for(i = bytewidth; i < length; i++) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) / 2); |
|
3498 } |
|
3499 else |
|
3500 { |
|
3501 for(i = 0; i < length; i++) out[i] = scanline[i]; |
|
3502 for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth] / 2; |
|
3503 } |
|
3504 break; |
|
3505 case 4: |
|
3506 if(prevline) |
|
3507 { |
|
3508 for(i = 0; i < bytewidth; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(0, prevline[i], 0)); |
|
3509 for(i = bytewidth; i < length; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); |
|
3510 } |
|
3511 else |
|
3512 { |
|
3513 for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; |
|
3514 for(i = bytewidth; i < length; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(scanline[i - bytewidth], 0, 0)); |
|
3515 } |
|
3516 break; |
|
3517 default: return; /*unexisting filter type given*/ |
|
3518 } |
|
3519 } |
|
3520 |
|
3521 static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, const LodePNG_InfoColor* info) |
|
3522 { |
|
3523 /* |
|
3524 For PNG filter method 0 |
|
3525 out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are the scanlines with 1 extra byte per scanline |
|
3526 |
|
3527 There is a nice heuristic described here: http://www.cs.toronto.edu/~cosmin/pngtech/optipng.html. It says: |
|
3528 * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. use fixed filtering, with the filter None). |
|
3529 * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply all five filters and select the filter that produces the smallest sum of absolute values per row. |
|
3530 |
|
3531 Here the above method is used mostly. Note though that it appears to be better to use the adaptive filtering on the plasma 8-bit palette example, but that image isn't the best reference for palette images in general. |
|
3532 */ |
|
3533 |
|
3534 unsigned bpp = LodePNG_InfoColor_getBpp(info); |
|
3535 size_t linebytes = (w * bpp + 7) / 8; /*the width of a scanline in bytes, not including the filter type*/ |
|
3536 size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ |
|
3537 const unsigned char* prevline = 0; |
|
3538 unsigned x, y; |
|
3539 unsigned heuristic; |
|
3540 unsigned error = 0; |
|
3541 |
|
3542 if(bpp == 0) return 31; /*invalid color type*/ |
|
3543 |
|
3544 /*choose heuristic as described above*/ |
|
3545 if(info->colorType == 3 || info->bitDepth < 8) heuristic = 0; |
|
3546 else heuristic = 1; |
|
3547 |
|
3548 if(heuristic == 0) /*None filtertype for everything*/ |
|
3549 { |
|
3550 for(y = 0; y < h; y++) |
|
3551 { |
|
3552 size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ |
|
3553 size_t inindex = linebytes * y; |
|
3554 const unsigned TYPE = 0; |
|
3555 out[outindex] = TYPE; /*filter type byte*/ |
|
3556 filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, TYPE); |
|
3557 prevline = &in[inindex]; |
|
3558 } |
|
3559 } |
|
3560 else if(heuristic == 1) /*adaptive filtering*/ |
|
3561 { |
|
3562 size_t sum[5]; |
|
3563 ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ |
|
3564 size_t smallest = 0; |
|
3565 unsigned type, bestType = 0; |
|
3566 |
|
3567 for(type = 0; type < 5; type++) ucvector_init(&attempt[type]); |
|
3568 for(type = 0; type < 5; type++) |
|
3569 { |
|
3570 if(!ucvector_resize(&attempt[type], linebytes)) { error = 9949; break; } |
|
3571 } |
|
3572 |
|
3573 if(!error) |
|
3574 { |
|
3575 for(y = 0; y < h; y++) |
|
3576 { |
|
3577 /*try the 5 filter types*/ |
|
3578 for(type = 0; type < 5; type++) |
|
3579 { |
|
3580 filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); |
|
3581 |
|
3582 /*calculate the sum of the result*/ |
|
3583 sum[type] = 0; |
|
3584 for(x = 0; x < attempt[type].size; x+=3) sum[type] += attempt[type].data[x]; /*note that not all pixels are checked to speed this up while still having probably the best choice*/ |
|
3585 |
|
3586 /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ |
|
3587 if(type == 0 || sum[type] < smallest) |
|
3588 { |
|
3589 bestType = type; |
|
3590 smallest = sum[type]; |
|
3591 } |
|
3592 } |
|
3593 |
|
3594 prevline = &in[y * linebytes]; |
|
3595 |
|
3596 /*now fill the out values*/ |
|
3597 out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ |
|
3598 for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; |
|
3599 } |
|
3600 } |
|
3601 |
|
3602 for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]); |
|
3603 } |
|
3604 #if 0 /*deflate the scanline with a fixed tree after every filter attempt to see which one deflates best. This is slow, and _does not work as expected_: the heuristic gives smaller result!*/ |
|
3605 else if(heuristic == 2) /*adaptive filtering by using deflate*/ |
|
3606 { |
|
3607 size_t size[5]; |
|
3608 ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ |
|
3609 size_t smallest; |
|
3610 unsigned type = 0, bestType = 0; |
|
3611 unsigned char* dummy; |
|
3612 LodeZlib_DeflateSettings deflatesettings = LodeZlib_defaultDeflateSettings; |
|
3613 deflatesettings.btype = 1; /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, to simulate the true case where the tree is the same for the whole image*/ |
|
3614 for(type = 0; type < 5; type++) { ucvector_init(&attempt[type]); ucvector_resize(&attempt[type], linebytes); } |
|
3615 for(y = 0; y < h; y++) /*try the 5 filter types*/ |
|
3616 { |
|
3617 for(type = 0; type < 5; type++) |
|
3618 { |
|
3619 filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); |
|
3620 size[type] = 0; dummy = 0; |
|
3621 LodePNG_compress(&dummy, &size[type], attempt[type].data, attempt[type].size, &deflatesettings); |
|
3622 free(dummy); |
|
3623 /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ |
|
3624 if(type == 0 || size[type] < smallest) { bestType = type; smallest = size[type]; } |
|
3625 } |
|
3626 prevline = &in[y * linebytes]; |
|
3627 out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ |
|
3628 for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; |
|
3629 } |
|
3630 for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]); |
|
3631 } |
|
3632 #endif |
|
3633 |
|
3634 return error; |
|
3635 } |
|
3636 |
|
3637 static void addPaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h) |
|
3638 { |
|
3639 /*The opposite of the removePaddingBits function |
|
3640 olinebits must be >= ilinebits*/ |
|
3641 unsigned y; |
|
3642 size_t diff = olinebits - ilinebits; |
|
3643 size_t obp = 0, ibp = 0; /*bit pointers*/ |
|
3644 for(y = 0; y < h; y++) |
|
3645 { |
|
3646 size_t x; |
|
3647 for(x = 0; x < ilinebits; x++) |
|
3648 { |
|
3649 unsigned char bit = readBitFromReversedStream(&ibp, in); |
|
3650 setBitOfReversedStream(&obp, out, bit); |
|
3651 } |
|
3652 /*obp += diff; --> no, fill in some value in the padding bits too, to avoid "Use of uninitialised value of size ###" warning from valgrind*/ |
|
3653 for(x = 0; x < diff; x++) setBitOfReversedStream(&obp, out, 0); |
|
3654 } |
|
3655 } |
|
3656 |
|
3657 static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) |
|
3658 { |
|
3659 /*Note: this function works on image buffers WITHOUT padding bits at end of scanlines with non-multiple-of-8 bit amounts, only between reduced images is padding*/ |
|
3660 unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; |
|
3661 unsigned i; |
|
3662 |
|
3663 Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); |
|
3664 |
|
3665 if(bpp >= 8) |
|
3666 { |
|
3667 for(i = 0; i < 7; i++) |
|
3668 { |
|
3669 unsigned x, y, b; |
|
3670 size_t bytewidth = bpp / 8; |
|
3671 for(y = 0; y < passh[i]; y++) |
|
3672 for(x = 0; x < passw[i]; x++) |
|
3673 { |
|
3674 size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; |
|
3675 size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; |
|
3676 for(b = 0; b < bytewidth; b++) |
|
3677 { |
|
3678 out[pixeloutstart + b] = in[pixelinstart + b]; |
|
3679 } |
|
3680 } |
|
3681 } |
|
3682 } |
|
3683 else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ |
|
3684 { |
|
3685 for(i = 0; i < 7; i++) |
|
3686 { |
|
3687 unsigned x, y, b; |
|
3688 unsigned ilinebits = bpp * passw[i]; |
|
3689 unsigned olinebits = bpp * w; |
|
3690 size_t obp, ibp; /*bit pointers (for out and in buffer)*/ |
|
3691 for(y = 0; y < passh[i]; y++) |
|
3692 for(x = 0; x < passw[i]; x++) |
|
3693 { |
|
3694 ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; |
|
3695 obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); |
|
3696 for(b = 0; b < bpp; b++) |
|
3697 { |
|
3698 unsigned char bit = readBitFromReversedStream(&ibp, in); |
|
3699 setBitOfReversedStream(&obp, out, bit); |
|
3700 } |
|
3701 } |
|
3702 } |
|
3703 } |
|
3704 } |
|
3705 |
|
3706 /*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image*/ |
|
3707 static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, const LodePNG_InfoPng* infoPng) /*return value is error*/ |
|
3708 { |
|
3709 /* |
|
3710 This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: |
|
3711 *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter |
|
3712 *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter |
|
3713 */ |
|
3714 unsigned bpp = LodePNG_InfoColor_getBpp(&infoPng->color); |
|
3715 unsigned w = infoPng->width; |
|
3716 unsigned h = infoPng->height; |
|
3717 unsigned error = 0; |
|
3718 |
|
3719 if(infoPng->interlaceMethod == 0) |
|
3720 { |
|
3721 *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/ |
|
3722 *out = (unsigned char*)malloc(*outsize); |
|
3723 if(!(*out) && (*outsize)) error = 9950; |
|
3724 |
|
3725 if(!error) |
|
3726 { |
|
3727 if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ |
|
3728 { |
|
3729 ucvector padded; |
|
3730 ucvector_init(&padded); |
|
3731 if(!ucvector_resize(&padded, h * ((w * bpp + 7) / 8))) error = 9951; |
|
3732 if(!error) |
|
3733 { |
|
3734 addPaddingBits(padded.data, in, ((w * bpp + 7) / 8) * 8, w * bpp, h); |
|
3735 error = filter(*out, padded.data, w, h, &infoPng->color); |
|
3736 } |
|
3737 ucvector_cleanup(&padded); |
|
3738 } |
|
3739 else error = filter(*out, in, w, h, &infoPng->color); /*we can immediatly filter into the out buffer, no other steps needed*/ |
|
3740 } |
|
3741 } |
|
3742 else /*interlaceMethod is 1 (Adam7)*/ |
|
3743 { |
|
3744 unsigned char* adam7 = (unsigned char*)malloc((h * w * bpp + 7) / 8); |
|
3745 if(!adam7 && ((h * w * bpp + 7) / 8)) error = 9952; /*malloc failed*/ |
|
3746 |
|
3747 while(!error) /*not a real while loop, used to break out to cleanup to avoid a goto*/ |
|
3748 { |
|
3749 unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; |
|
3750 unsigned i; |
|
3751 |
|
3752 Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); |
|
3753 |
|
3754 *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ |
|
3755 *out = (unsigned char*)malloc(*outsize); |
|
3756 if(!(*out) && (*outsize)) { error = 9953; break; } |
|
3757 |
|
3758 Adam7_interlace(adam7, in, w, h, bpp); |
|
3759 |
|
3760 for(i = 0; i < 7; i++) |
|
3761 { |
|
3762 if(bpp < 8) |
|
3763 { |
|
3764 ucvector padded; |
|
3765 ucvector_init(&padded); |
|
3766 if(!ucvector_resize(&padded, h * ((w * bpp + 7) / 8))) error = 9954; |
|
3767 if(!error) |
|
3768 { |
|
3769 addPaddingBits(&padded.data[padded_passstart[i]], &adam7[passstart[i]], ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]); |
|
3770 error = filter(&(*out)[filter_passstart[i]], &padded.data[padded_passstart[i]], passw[i], passh[i], &infoPng->color); |
|
3771 } |
|
3772 |
|
3773 ucvector_cleanup(&padded); |
|
3774 } |
|
3775 else |
|
3776 { |
|
3777 error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], passw[i], passh[i], &infoPng->color); |
|
3778 } |
|
3779 } |
|
3780 |
|
3781 break; |
|
3782 } |
|
3783 |
|
3784 free(adam7); |
|
3785 } |
|
3786 |
|
3787 return error; |
|
3788 } |
|
3789 |
|
3790 /*palette must have 4 * palettesize bytes allocated*/ |
|
3791 static unsigned isPaletteFullyOpaque(const unsigned char* palette, size_t palettesize) /*palette given in format RGBARGBARGBARGBA...*/ |
|
3792 { |
|
3793 size_t i; |
|
3794 for(i = 0; i < palettesize; i++) |
|
3795 { |
|
3796 if(palette[4 * i + 3] != 255) return 0; |
|
3797 } |
|
3798 return 1; |
|
3799 } |
|
3800 |
|
3801 /*this function checks if the input image given by the user has no transparent pixels*/ |
|
3802 static unsigned isFullyOpaque(const unsigned char* image, unsigned w, unsigned h, const LodePNG_InfoColor* info) |
|
3803 { |
|
3804 /*TODO: When the user specified a color key for the input image, then this function must also check for pixels that are the same as the color key and treat those as transparent.*/ |
|
3805 |
|
3806 unsigned i, numpixels = w * h; |
|
3807 if(info->colorType == 6) |
|
3808 { |
|
3809 if(info->bitDepth == 8) |
|
3810 { |
|
3811 for(i = 0; i < numpixels; i++) if(image[i * 4 + 3] != 255) return 0; |
|
3812 } |
|
3813 else |
|
3814 { |
|
3815 for(i = 0; i < numpixels; i++) if(image[i * 8 + 6] != 255 || image[i * 8 + 7] != 255) return 0; |
|
3816 } |
|
3817 return 1; /*no single pixel with alpha channel other than 255 found*/ |
|
3818 } |
|
3819 else if(info->colorType == 4) |
|
3820 { |
|
3821 if(info->bitDepth == 8) |
|
3822 { |
|
3823 for(i = 0; i < numpixels; i++) if(image[i * 2 + 1] != 255) return 0; |
|
3824 } |
|
3825 else |
|
3826 { |
|
3827 for(i = 0; i < numpixels; i++) if(image[i * 4 + 2] != 255 || image[i * 4 + 3] != 255) return 0; |
|
3828 } |
|
3829 return 1; /*no single pixel with alpha channel other than 255 found*/ |
|
3830 } |
|
3831 else if(info->colorType == 3) |
|
3832 { |
|
3833 /*when there's a palette, we could check every pixel for translucency, but much quicker is to just check the palette*/ |
|
3834 return(isPaletteFullyOpaque(info->palette, info->palettesize)); |
|
3835 } |
|
3836 |
|
3837 return 0; /*color type that isn't supported by this function yet, so assume there is transparency to be safe*/ |
|
3838 } |
|
3839 |
|
3840 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
3841 static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) |
|
3842 { |
|
3843 unsigned char* inchunk = data; |
|
3844 while((size_t)(inchunk - data) < datasize) |
|
3845 { |
|
3846 unsigned error = LodePNG_append_chunk(&out->data, &out->size, inchunk); |
|
3847 if(error) return error; /*error: not enough memory*/ |
|
3848 out->allocsize = out->size; /*fix the allocsize again*/ |
|
3849 inchunk = LodePNG_chunk_next(inchunk); |
|
3850 } |
|
3851 return 0; |
|
3852 } |
|
3853 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
3854 |
|
3855 void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) |
|
3856 { |
|
3857 LodePNG_InfoPng info; |
|
3858 ucvector outv; |
|
3859 unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ |
|
3860 size_t datasize = 0; |
|
3861 |
|
3862 /*provide some proper output values if error will happen*/ |
|
3863 *out = 0; |
|
3864 *outsize = 0; |
|
3865 encoder->error = 0; |
|
3866 |
|
3867 info = encoder->infoPng; /*UNSAFE copy to avoid having to cleanup! but we will only change primitive parameters, and not invoke the cleanup function nor touch the palette's buffer so we use it safely*/ |
|
3868 info.width = w; |
|
3869 info.height = h; |
|
3870 |
|
3871 if(encoder->settings.autoLeaveOutAlphaChannel && isFullyOpaque(image, w, h, &encoder->infoRaw.color)) |
|
3872 { |
|
3873 /*go to a color type without alpha channel*/ |
|
3874 if(info.color.colorType == 6) info.color.colorType = 2; |
|
3875 else if(info.color.colorType == 4) info.color.colorType = 0; |
|
3876 } |
|
3877 |
|
3878 if(encoder->settings.zlibsettings.windowSize > 32768) { encoder->error = 60; return; } /*error: windowsize larger than allowed*/ |
|
3879 if(encoder->settings.zlibsettings.btype > 2) { encoder->error = 61; return; } /*error: unexisting btype*/ |
|
3880 if(encoder->infoPng.interlaceMethod > 1) { encoder->error = 71; return; } /*error: unexisting interlace mode*/ |
|
3881 if((encoder->error = checkColorValidity(info.color.colorType, info.color.bitDepth))) return; /*error: unexisting color type given*/ |
|
3882 if((encoder->error = checkColorValidity(encoder->infoRaw.color.colorType, encoder->infoRaw.color.bitDepth))) return; /*error: unexisting color type given*/ |
|
3883 |
|
3884 if(!LodePNG_InfoColor_equal(&encoder->infoRaw.color, &info.color)) |
|
3885 { |
|
3886 unsigned char* converted; |
|
3887 size_t size = (w * h * LodePNG_InfoColor_getBpp(&info.color) + 7) / 8; |
|
3888 |
|
3889 if((info.color.colorType != 6 && info.color.colorType != 2) || (info.color.bitDepth != 8)) { encoder->error = 59; return; } /*for the output image, only these types are supported*/ |
|
3890 converted = (unsigned char*)malloc(size); |
|
3891 if(!converted && size) encoder->error = 9955; /*error: malloc failed*/ |
|
3892 if(!encoder->error) encoder->error = LodePNG_convert(converted, image, &info.color, &encoder->infoRaw.color, w, h); |
|
3893 if(!encoder->error) preProcessScanlines(&data, &datasize, converted, &info);/*filter(data.data, converted.data, w, h, LodePNG_InfoColor_getBpp(&info.color));*/ |
|
3894 free(converted); |
|
3895 } |
|
3896 else preProcessScanlines(&data, &datasize, image, &info);/*filter(data.data, image, w, h, LodePNG_InfoColor_getBpp(&info.color));*/ |
|
3897 |
|
3898 ucvector_init(&outv); |
|
3899 while(!encoder->error) /*not really a while loop, this is only used to break out if an error happens to avoid goto's to do the ucvector cleanup*/ |
|
3900 { |
|
3901 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
3902 size_t i; |
|
3903 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
3904 /*write signature and chunks*/ |
|
3905 writeSignature(&outv); |
|
3906 /*IHDR*/ |
|
3907 addChunk_IHDR(&outv, w, h, info.color.bitDepth, info.color.colorType, info.interlaceMethod); |
|
3908 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
3909 /*unknown chunks between IHDR and PLTE*/ |
|
3910 if(info.unknown_chunks.data[0]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[0], info.unknown_chunks.datasize[0]); if(encoder->error) break; } |
|
3911 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
3912 /*PLTE*/ |
|
3913 if(info.color.colorType == 3) |
|
3914 { |
|
3915 if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; } |
|
3916 addChunk_PLTE(&outv, &info.color); |
|
3917 } |
|
3918 if(encoder->settings.force_palette && (info.color.colorType == 2 || info.color.colorType == 6)) |
|
3919 { |
|
3920 if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; } |
|
3921 addChunk_PLTE(&outv, &info.color); |
|
3922 } |
|
3923 /*tRNS*/ |
|
3924 if(info.color.colorType == 3 && !isPaletteFullyOpaque(info.color.palette, info.color.palettesize)) addChunk_tRNS(&outv, &info.color); |
|
3925 if((info.color.colorType == 0 || info.color.colorType == 2) && info.color.key_defined) addChunk_tRNS(&outv, &info.color); |
|
3926 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
3927 /*bKGD (must come between PLTE and the IDAt chunks*/ |
|
3928 if(info.background_defined) addChunk_bKGD(&outv, &info); |
|
3929 /*pHYs (must come before the IDAT chunks)*/ |
|
3930 if(info.phys_defined) addChunk_pHYs(&outv, &info); |
|
3931 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
3932 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
3933 /*unknown chunks between PLTE and IDAT*/ |
|
3934 if(info.unknown_chunks.data[1]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[1], info.unknown_chunks.datasize[1]); if(encoder->error) break; } |
|
3935 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
3936 /*IDAT (multiple IDAT chunks must be consecutive)*/ |
|
3937 encoder->error = addChunk_IDAT(&outv, data, datasize, &encoder->settings.zlibsettings); |
|
3938 if(encoder->error) break; |
|
3939 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
3940 /*tIME*/ |
|
3941 if(info.time_defined) addChunk_tIME(&outv, &info.time); |
|
3942 /*tEXt and/or zTXt*/ |
|
3943 for(i = 0; i < info.text.num; i++) |
|
3944 { |
|
3945 if(strlen(info.text.keys[i]) > 79) { encoder->error = 66; break; } |
|
3946 if(strlen(info.text.keys[i]) < 1) { encoder->error = 67; break; } |
|
3947 if(encoder->settings.text_compression) |
|
3948 addChunk_zTXt(&outv, info.text.keys[i], info.text.strings[i], &encoder->settings.zlibsettings); |
|
3949 else |
|
3950 addChunk_tEXt(&outv, info.text.keys[i], info.text.strings[i]); |
|
3951 } |
|
3952 /*LodePNG version id in text chunk*/ |
|
3953 if(encoder->settings.add_id) |
|
3954 { |
|
3955 unsigned alread_added_id_text = 0; |
|
3956 for(i = 0; i < info.text.num; i++) |
|
3957 if(!strcmp(info.text.keys[i], "LodePNG")) { alread_added_id_text = 1; break; } |
|
3958 if(alread_added_id_text == 0) |
|
3959 addChunk_tEXt(&outv, "LodePNG", VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ |
|
3960 } |
|
3961 /*iTXt*/ |
|
3962 for(i = 0; i < info.itext.num; i++) |
|
3963 { |
|
3964 if(strlen(info.itext.keys[i]) > 79) { encoder->error = 66; break; } |
|
3965 if(strlen(info.itext.keys[i]) < 1) { encoder->error = 67; break; } |
|
3966 addChunk_iTXt(&outv, encoder->settings.text_compression, |
|
3967 info.itext.keys[i], info.itext.langtags[i], info.itext.transkeys[i], info.itext.strings[i], |
|
3968 &encoder->settings.zlibsettings); |
|
3969 } |
|
3970 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
3971 #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS |
|
3972 /*unknown chunks between IDAT and IEND*/ |
|
3973 if(info.unknown_chunks.data[2]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[2], info.unknown_chunks.datasize[2]); if(encoder->error) break; } |
|
3974 #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ |
|
3975 /*IEND*/ |
|
3976 addChunk_IEND(&outv); |
|
3977 |
|
3978 break; /*this isn't really a while loop; no error happened so break out now!*/ |
|
3979 } |
|
3980 |
|
3981 free(data); |
|
3982 /*instead of cleaning the vector up, give it to the output*/ |
|
3983 *out = outv.data; |
|
3984 *outsize = outv.size; |
|
3985 } |
|
3986 |
|
3987 unsigned LodePNG_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) |
|
3988 { |
|
3989 unsigned error; |
|
3990 LodePNG_Encoder encoder; |
|
3991 LodePNG_Encoder_init(&encoder); |
|
3992 LodePNG_encode(&encoder, out, outsize, image, w, h); |
|
3993 error = encoder.error; |
|
3994 LodePNG_Encoder_cleanup(&encoder); |
|
3995 return error; |
|
3996 } |
|
3997 |
|
3998 #ifdef LODEPNG_COMPILE_DISK |
|
3999 unsigned LodePNG_encode32f(const char* filename, const unsigned char* image, unsigned w, unsigned h) |
|
4000 { |
|
4001 unsigned char* buffer; |
|
4002 size_t buffersize; |
|
4003 unsigned error = LodePNG_encode32(&buffer, &buffersize, image, w, h); |
|
4004 LodePNG_saveFile(buffer, buffersize, filename); |
|
4005 free(buffer); |
|
4006 return error; |
|
4007 } |
|
4008 #endif /*LODEPNG_COMPILE_DISK*/ |
|
4009 |
|
4010 void LodePNG_EncodeSettings_init(LodePNG_EncodeSettings* settings) |
|
4011 { |
|
4012 LodeZlib_DeflateSettings_init(&settings->zlibsettings); |
|
4013 settings->autoLeaveOutAlphaChannel = 1; |
|
4014 settings->force_palette = 0; |
|
4015 #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS |
|
4016 settings->add_id = 1; |
|
4017 settings->text_compression = 0; |
|
4018 #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ |
|
4019 } |
|
4020 |
|
4021 void LodePNG_Encoder_init(LodePNG_Encoder* encoder) |
|
4022 { |
|
4023 LodePNG_EncodeSettings_init(&encoder->settings); |
|
4024 LodePNG_InfoPng_init(&encoder->infoPng); |
|
4025 LodePNG_InfoRaw_init(&encoder->infoRaw); |
|
4026 encoder->error = 1; |
|
4027 } |
|
4028 |
|
4029 void LodePNG_Encoder_cleanup(LodePNG_Encoder* encoder) |
|
4030 { |
|
4031 LodePNG_InfoPng_cleanup(&encoder->infoPng); |
|
4032 LodePNG_InfoRaw_cleanup(&encoder->infoRaw); |
|
4033 } |
|
4034 |
|
4035 void LodePNG_Encoder_copy(LodePNG_Encoder* dest, const LodePNG_Encoder* source) |
|
4036 { |
|
4037 LodePNG_Encoder_cleanup(dest); |
|
4038 *dest = *source; |
|
4039 LodePNG_InfoPng_init(&dest->infoPng); |
|
4040 LodePNG_InfoRaw_init(&dest->infoRaw); |
|
4041 dest->error = LodePNG_InfoPng_copy(&dest->infoPng, &source->infoPng); if(dest->error) return; |
|
4042 dest->error = LodePNG_InfoRaw_copy(&dest->infoRaw, &source->infoRaw); if(dest->error) return; |
|
4043 } |
|
4044 |
|
4045 #endif /*LODEPNG_COMPILE_ENCODER*/ |
|
4046 |
|
4047 #endif /*LODEPNG_COMPILE_PNG*/ |
|
4048 |
|
4049 /* ////////////////////////////////////////////////////////////////////////// */ |
|
4050 /* / File IO / */ |
|
4051 /* ////////////////////////////////////////////////////////////////////////// */ |
|
4052 |
|
4053 #ifdef LODEPNG_COMPILE_DISK |
|
4054 |
|
4055 unsigned LodePNG_loadFile(unsigned char** out, size_t* outsize, const char* filename) /*designed for loading files from hard disk in a dynamically allocated buffer*/ |
|
4056 { |
|
4057 FILE* file; |
|
4058 long size; |
|
4059 |
|
4060 /*provide some proper output values if error will happen*/ |
|
4061 *out = 0; |
|
4062 *outsize = 0; |
|
4063 |
|
4064 file = fopen(filename, "rb"); |
|
4065 if(!file) return 78; |
|
4066 |
|
4067 /*get filesize:*/ |
|
4068 fseek(file , 0 , SEEK_END); |
|
4069 size = ftell(file); |
|
4070 rewind(file); |
|
4071 |
|
4072 /*read contents of the file into the vector*/ |
|
4073 *outsize = 0; |
|
4074 *out = (unsigned char*)malloc((size_t)size); |
|
4075 if(size && (*out)) (*outsize) = fread(*out, 1, (size_t)size, file); |
|
4076 |
|
4077 fclose(file); |
|
4078 if(!(*out) && size) return 80; /*the above malloc failed*/ |
|
4079 return 0; |
|
4080 } |
|
4081 |
|
4082 /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ |
|
4083 unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename) |
|
4084 { |
|
4085 FILE* file; |
|
4086 file = fopen(filename, "wb" ); |
|
4087 if(!file) return 79; |
|
4088 fwrite((char*)buffer , 1 , buffersize, file); |
|
4089 fclose(file); |
|
4090 return 0; |
|
4091 } |
|
4092 |
|
4093 #endif /*LODEPNG_COMPILE_DISK*/ |
|
4094 |