Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch_Modules/i386/boot2/picopng.c

1// picoPNG version 20080503 (cleaned up and ported to c by kaitek)
2// Copyright (c) 2005-2008 Lode Vandevenne
3//
4// This software is provided 'as-is', without any express or implied
5// warranty. In no event will the authors be held liable for any damages
6// arising from the use of this software.
7//
8// Permission is granted to anyone to use this software for any purpose,
9// including commercial applications, and to alter it and redistribute it
10// freely, subject to the following restrictions:
11//
12// 1. The origin of this software must not be misrepresented; you must not
13// claim that you wrote the original software. If you use this software
14// in a product, an acknowledgment in the product documentation would be
15// appreciated but is not required.
16// 2. Altered source versions must be plainly marked as such, and must not be
17// misrepresented as being the original software.
18// 3. This notice may not be removed or altered from any source distribution.
19
20#include <sys/types.h>
21#include "libsa.h"
22#include "picopng.h"
23
24/*************************************************************************************************/
25
26typedef struct png_alloc_node {
27struct png_alloc_node *prev, *next;
28void *addr;
29size_t size;
30} png_alloc_node_t;
31
32png_alloc_node_t *png_alloc_head = NULL;
33png_alloc_node_t *png_alloc_tail = NULL;
34
35png_alloc_node_t *png_alloc_find_node(void *addr)
36{
37png_alloc_node_t *node;
38for (node = png_alloc_head; node; node = node->next)
39if (node->addr == addr)
40break;
41return node;
42}
43
44void png_alloc_add_node(void *addr, size_t size)
45{
46png_alloc_node_t *node;
47if (png_alloc_find_node(addr))
48return;
49node = malloc(sizeof (png_alloc_node_t));
50node->addr = addr;
51node->size = size;
52node->prev = png_alloc_tail;
53node->next = NULL;
54png_alloc_tail = node;
55if (node->prev)
56node->prev->next = node;
57if (!png_alloc_head)
58png_alloc_head = node;
59}
60
61void png_alloc_remove_node(png_alloc_node_t *node)
62{
63if (!node)
64{
65return;
66}
67if (node->prev)
68{
69node->prev->next = node->next;
70}
71if (node->next)
72{
73node->next->prev = node->prev;
74}
75if (node == png_alloc_head)
76{
77png_alloc_head = node->next;
78}
79if (node == png_alloc_tail)
80{
81png_alloc_tail = node->prev;
82}
83node->prev = node->next = node->addr = NULL;
84free(node);
85}
86
87void *png_alloc_malloc(size_t size)
88{
89void *addr = malloc(size);
90png_alloc_add_node(addr, size);
91return addr;
92}
93
94void *png_alloc_realloc(void *addr, size_t size)
95{
96void *new_addr = NULL;
97if (!addr)
98{
99return png_alloc_malloc(size);
100}
101
102png_alloc_node_t *old_node;
103old_node = png_alloc_find_node(addr);
104
105if (old_node)
106{
107new_addr = realloc(addr, size);
108if (new_addr && (new_addr != addr))
109{
110png_alloc_remove_node(old_node);
111png_alloc_add_node(new_addr, size);
112}
113}
114
115return new_addr;
116}
117
118void png_alloc_free(void *addr)
119{
120 if (!addr) return;
121
122png_alloc_node_t *node = png_alloc_find_node(addr);
123if (node)
124png_alloc_remove_node(node);
125
126free(addr);
127}
128
129void png_alloc_free_all()
130{
131while (png_alloc_tail) {
132void *addr = png_alloc_tail->addr;
133png_alloc_remove_node(png_alloc_tail);
134free(addr);
135}
136}
137
138/*************************************************************************************************/
139
140__unused void vector32_cleanup(vector32_t *p)
141{
142p->size = p->allocsize = 0;
143if (p->data)
144png_alloc_free(p->data);
145p->data = NULL;
146}
147
148uint32_t vector32_resize(vector32_t *p, size_t size)
149{// returns 1 if success, 0 if failure ==> nothing done
150if (size * sizeof (uint32_t) > p->allocsize)
151{
152size_t newsize = size * sizeof (uint32_t) * 2;
153void *data = png_alloc_realloc(p->data, newsize);
154if (data)
155{
156p->allocsize = newsize;
157p->data = (uint32_t *) data;
158p->size = size;
159} else
160return 0;
161}
162else
163p->size = size;
164return 1;
165}
166
167uint32_t vector32_resizev(vector32_t *p, size_t size, uint32_t value)
168{// resize and give all new elements the value
169size_t oldsize = p->size, i;
170if (!vector32_resize(p, size))
171return 0;
172for (i = oldsize; i < size; i++)
173p->data[i] = value;
174return 1;
175}
176
177void vector32_init(vector32_t *p)
178{
179p->data = NULL;
180p->size = p->allocsize = 0;
181}
182
183vector32_t *vector32_new(size_t size, uint32_t value)
184{
185vector32_t *p = png_alloc_malloc(sizeof (vector32_t));
186if (!p)
187{
188return NULL;
189}
190vector32_init(p);
191if (size && !vector32_resizev(p, size, value))
192{
193vector32_cleanup(p);
194png_alloc_free(p);
195return NULL;
196}
197return p;
198}
199
200/*************************************************************************************************/
201
202__unused void vector8_cleanup(vector8_t *p)
203{
204p->size = p->allocsize = 0;
205if (p->data)
206png_alloc_free(p->data);
207p->data = NULL;
208}
209
210uint32_t vector8_resize(vector8_t *p, size_t size)
211{// returns 1 if success, 0 if failure ==> nothing done
212// xxx: the use of sizeof uint32_t here seems like a bug (this descends from the lodepng vector
213// compatibility functions which do the same). without this there is corruption in certain cases,
214// so this was probably done to cover up allocation bug(s) in the original picopng code!
215if (size * sizeof (uint32_t) > p->allocsize)
216{
217size_t newsize = size * sizeof (uint32_t) * 2;
218void *data = png_alloc_realloc(p->data, newsize);
219if (data)
220{
221p->allocsize = newsize;
222p->data = (uint8_t *) data;
223p->size = size;
224} else
225return 0; // error: not enough memory
226} else
227p->size = size;
228return 1;
229}
230
231uint32_t vector8_resizev(vector8_t *p, size_t size, uint8_t value)
232{// resize and give all new elements the value
233size_t oldsize = p->size, i;
234if (!vector8_resize(p, size))
235return 0;
236for (i = oldsize; i < size; i++)
237p->data[i] = value;
238return 1;
239}
240
241void vector8_init(vector8_t *p)
242{
243p->data = NULL;
244p->size = p->allocsize = 0;
245}
246
247vector8_t *vector8_new(size_t size, uint8_t value)
248{
249vector8_t *p = png_alloc_malloc(sizeof (vector8_t));
250if(!p)
251{
252return NULL;
253}
254vector8_init(p);
255if (size && !vector8_resizev(p, size, value))
256{
257vector8_cleanup(p);
258png_alloc_free(p);
259return NULL;
260}
261return p;
262}
263
264vector8_t *vector8_copy(vector8_t *p)
265{
266vector8_t *q = vector8_new(p->size, 0);
267uint32_t n;
268if (!q)
269{
270 return NULL;
271}
272for (n = 0; n < q->size; n++)
273q->data[n] = p->data[n];
274return q;
275}
276
277/*************************************************************************************************/
278
279const uint32_t LENBASE[29] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
28059, 67, 83, 99, 115, 131, 163, 195, 227, 258 };
281const uint32_t LENEXTRA[29] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
2824, 5, 5, 5, 5, 0 };
283const uint32_t DISTBASE[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
284513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
285const uint32_t DISTEXTRA[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
28610, 10, 11, 11, 12, 12, 13, 13 };
287// code length code lengths
288const uint32_t CLCL[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
289
290/*************************************************************************************************/
291
292typedef struct {
293// 2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all
294// nodes and leaves of the tree.
295vector32_t *tree2d;
296} HuffmanTree;
297
298HuffmanTree *HuffmanTree_new()
299{
300HuffmanTree *tree = png_alloc_malloc(sizeof (HuffmanTree));
301if (!tree)
302{
303return NULL;
304}
305tree->tree2d = NULL;
306return tree;
307}
308
309int HuffmanTree_makeFromLengths(HuffmanTree *tree, const vector32_t *bitlen, uint32_t maxbitlen)
310{// make tree given the lengths
311uint32_t bits, n, i;
312uint32_t numcodes = (uint32_t) bitlen->size, treepos = 0, nodefilled = 0;
313vector32_t *tree1d, *blcount, *nextcode;
314tree1d = vector32_new(numcodes, 0);
315blcount = vector32_new(maxbitlen + 1, 0);
316nextcode = vector32_new(maxbitlen + 1, 0);
317if (!tree1d || !blcount || !nextcode || !nextcode->data)
318{
319goto error;
320}
321for (bits = 0; bits < numcodes; bits++)
322blcount->data[bitlen->data[bits]]++; // count number of instances of each code length
323for (bits = 1; bits <= maxbitlen; bits++)
324nextcode->data[bits] = (nextcode->data[bits - 1] + blcount->data[bits - 1]) << 1;
325for (n = 0; n < numcodes; n++)
326if (bitlen->data[n] != 0)
327tree1d->data[n] = nextcode->data[bitlen->data[n]]++; // generate all the codes
328// 0x7fff here means the tree2d isn't filled there yet
329vector32_t *tree2d = vector32_new(numcodes * 2, 0x7fff);
330tree->tree2d = tree2d;
331for (n = 0; n < numcodes; n++) // the codes
332for (i = 0; i < bitlen->data[n]; i++)
333{ // the bits for this code
334uint32_t bit = (tree1d->data[n] >> (bitlen->data[n] - i - 1)) & 1;
335if (treepos > numcodes - 2)
336return 55;
337if (tree2d->data[2 * treepos + bit] == 0x7fff) // not yet filled in
338{
339if (i + 1 == bitlen->data[n]) // last bit
340{
341tree2d->data[2 * treepos + bit] = n;
342treepos = 0;
343}
344else // addresses are encoded as values > numcodes
345{
346tree2d->data[2 * treepos + bit] = ++nodefilled + numcodes;
347treepos = nodefilled;
348}
349} else // subtract numcodes from address to get address value
350treepos = tree2d->data[2 * treepos + bit] - numcodes;
351}
352return 0;
353error:
354if (tree1d)
355{
356vector32_cleanup(tree1d);
357png_alloc_free(tree1d);
358}
359if (blcount)
360{
361vector32_cleanup(blcount);
362png_alloc_free(blcount);
363}
364if (nextcode)
365{
366vector32_cleanup(nextcode);
367png_alloc_free(nextcode);
368}
369return 1;
370}
371
372int HuffmanTree_decode(const HuffmanTree *tree, bool *decoded, uint32_t *result, size_t *treepos,
373uint32_t bit)
374{// Decodes a symbol from the tree
375const vector32_t *tree2d = tree->tree2d;
376uint32_t numcodes = (uint32_t) tree2d->size / 2;
377if (*treepos >= numcodes)
378return 11; // error: you appeared outside the codetree
379*result = tree2d->data[2 * (*treepos) + bit];
380*decoded = (*result < numcodes);
381*treepos = *decoded ? 0 : *result - numcodes;
382return 0;
383}
384
385/*************************************************************************************************/
386
387int Inflator_error;
388
389uint32_t Zlib_readBitFromStream(size_t *bitp, const uint8_t *bits)
390{
391uint32_t result = (bits[*bitp >> 3] >> (*bitp & 0x7)) & 1;
392(*bitp)++;
393return result;
394}
395
396uint32_t Zlib_readBitsFromStream(size_t *bitp, const uint8_t *bits, size_t nbits)
397{
398uint32_t i, result = 0;
399for (i = 0; i < nbits; i++)
400result += (Zlib_readBitFromStream(bitp, bits)) << i;
401return result;
402}
403
404void Inflator_generateFixedTrees(HuffmanTree *tree, HuffmanTree *treeD)
405{// get the tree of a deflated block with fixed tree
406size_t i;
407vector32_t *bitlen, *bitlenD;
408bitlen = vector32_new(288, 8);
409bitlenD = vector32_new(32, 5);
410for (i = 144; i <= 255; i++)
411bitlen->data[i] = 9;
412for (i = 256; i <= 279; i++)
413bitlen->data[i] = 7;
414HuffmanTree_makeFromLengths(tree, bitlen, 15);
415HuffmanTree_makeFromLengths(treeD, bitlenD, 15);
416}
417
418uint32_t Inflator_huffmanDecodeSymbol(const uint8_t *in, size_t *bp, const HuffmanTree *codetree,
419size_t inlength)
420{// decode a single symbol from given list of bits with given code tree. returns the symbol
421bool decoded = false;
422uint32_t ct = 0;
423size_t treepos = 0;
424for (;;) {
425if ((*bp & 0x07) == 0 && (*bp >> 3) > inlength) {
426Inflator_error = 10; // error: end reached without endcode
427return 0;
428}
429Inflator_error = HuffmanTree_decode(codetree, &decoded, &ct, &treepos,
430Zlib_readBitFromStream(bp, in));
431if (Inflator_error)
432return 0; // stop, an error happened
433if (decoded)
434return ct;
435}
436}
437
438void Inflator_getTreeInflateDynamic(HuffmanTree *tree, HuffmanTree *treeD, const uint8_t *in,
439size_t *bp, size_t inlength)
440{// get the tree of a deflated block with dynamic tree, the tree itself is also Huffman
441// compressed with a known tree
442size_t i, n;
443size_t HLIT;
444size_t HDIST;
445size_t HCLEN;
446size_t replength;
447vector32_t *codelengthcode;
448HuffmanTree *codelengthcodetree = HuffmanTree_new(); // the code tree for code length codes
449vector32_t *bitlen, *bitlenD;
450bitlen = vector32_new(288, 0);
451bitlenD = vector32_new(32, 0);
452if (*bp >> 3 >= inlength - 2)
453{
454Inflator_error = 49; // the bit pointer is or will go past the memory
455return;
456}
457HLIT = Zlib_readBitsFromStream(bp, in, 5) + 257;// number of literal/length codes + 257
458HDIST = Zlib_readBitsFromStream(bp, in, 5) + 1;// number of dist codes + 1
459HCLEN = Zlib_readBitsFromStream(bp, in, 4) + 4;// number of code length codes + 4
460// lengths of tree to decode the lengths of the dynamic tree
461codelengthcode = vector32_new(19, 0);
462for (i = 0; i < 19; i++)
463codelengthcode->data[CLCL[i]] = (i < HCLEN) ? Zlib_readBitsFromStream(bp, in, 3) : 0;
464Inflator_error = HuffmanTree_makeFromLengths(codelengthcodetree, codelengthcode, 7);
465if (Inflator_error)
466return;
467for (i = 0; i < HLIT + HDIST; )
468{
469uint32_t code = Inflator_huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength);
470if (Inflator_error)
471{
472return;
473}
474if (code <= 15) // a length code
475{
476if (i < HLIT)
477{
478bitlen->data[i++] = code;
479}
480else
481{
482bitlenD->data[i++ - HLIT] = code;
483}
484} else if (code == 16)
485{ // repeat previous
486uint32_t value; // set value to the previous code
487if (*bp >> 3 >= inlength)
488{
489Inflator_error = 50; // error, bit pointer jumps past memory
490return;
491}
492replength = 3 + Zlib_readBitsFromStream(bp, in, 2);
493
494if ((i - 1) < HLIT)
495value = bitlen->data[i - 1];
496else
497value = bitlenD->data[i - HLIT - 1];
498for (n = 0; n < replength; n++)
499{ // repeat this value in the next lengths
500if (i >= HLIT + HDIST)
501{
502Inflator_error = 13; // error: i is larger than the amount of codes
503return;
504}
505if (i < HLIT)
506bitlen->data[i++] = value;
507else
508bitlenD->data[i++ - HLIT] = value;
509}
510}
511else if (code == 17)
512{ // repeat "0" 3-10 times
513if (*bp >> 3 >= inlength)
514{
515Inflator_error = 50; // error, bit pointer jumps past memory
516return;
517}
518replength = 3 + Zlib_readBitsFromStream(bp, in, 3);
519for (n = 0; n < replength; n++)
520{ // repeat this value in the next lengths
521if (i >= HLIT + HDIST) {
522Inflator_error = 14; // error: i is larger than the amount of codes
523return;
524}
525if (i < HLIT)
526{
527bitlen->data[i++] = 0;
528}
529else
530{
531bitlenD->data[i++ - HLIT] = 0;
532}
533}
534}
535else if (code == 18)
536{ // repeat "0" 11-138 times
537if (*bp >> 3 >= inlength)
538{
539Inflator_error = 50; // error, bit pointer jumps past memory
540return;
541}
542replength = 11 + Zlib_readBitsFromStream(bp, in, 7);
543for (n = 0; n < replength; n++)
544{ // repeat this value in the next lengths
545if (i >= HLIT + HDIST)
546{
547Inflator_error = 15; // error: i is larger than the amount of codes
548return;
549}
550if (i < HLIT)
551{
552bitlen->data[i++] = 0;
553}
554else
555{
556bitlenD->data[i++ - HLIT] = 0;
557}
558}
559}
560else
561{
562Inflator_error = 16; // error: an nonexitent code appeared. This can never happen.
563return;
564}
565}
566if (bitlen->data[256] == 0)
567{
568Inflator_error = 64; // the length of the end code 256 must be larger than 0
569return;
570}
571// now we've finally got HLIT and HDIST, so generate the code trees, and the function is done
572Inflator_error = HuffmanTree_makeFromLengths(tree, bitlen, 15);
573if (Inflator_error)
574return;
575Inflator_error = HuffmanTree_makeFromLengths(treeD, bitlenD, 15);
576if (Inflator_error)
577return;
578}
579
580void Inflator_inflateHuffmanBlock(vector8_t *out, const uint8_t *in, size_t *bp, size_t *pos,
581size_t inlength, uint32_t btype)
582{
583HuffmanTree *codetree, *codetreeD; // the code tree for Huffman codes, dist codes
584codetree = HuffmanTree_new();
585codetreeD = HuffmanTree_new();
586if (btype == 1)
587Inflator_generateFixedTrees(codetree, codetreeD);
588else if (btype == 2)
589{
590Inflator_getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength);
591if (Inflator_error)
592return;
593}
594for (;;)
595{
596uint32_t code = Inflator_huffmanDecodeSymbol(in, bp, codetree, inlength);
597if (Inflator_error)
598return;
599if (code == 256) // end code
600{
601return;
602}
603else if (code <= 255) { // literal symbol
604if (*pos >= out->size)
605{
606vector8_resize(out, (*pos + 1) * 2); // reserve more room
607}
608out->data[(*pos)++] = (uint8_t) code;
609} else if (code >= 257 && code <= 285)
610{ // length code
611size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
612if ((*bp >> 3) >= inlength)
613{
614Inflator_error = 51; // error, bit pointer will jump past memory
615return;
616}
617length += Zlib_readBitsFromStream(bp, in, numextrabits);
618uint32_t codeD = Inflator_huffmanDecodeSymbol(in, bp, codetreeD, inlength);
619if (Inflator_error)
620return;
621if (codeD > 29) {
622Inflator_error = 18; // error: invalid dist code (30-31 are never used)
623return;
624}
625uint32_t dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
626if ((*bp >> 3) >= inlength) {
627Inflator_error = 51; // error, bit pointer will jump past memory
628return;
629}
630dist += Zlib_readBitsFromStream(bp, in, numextrabitsD);
631size_t start = *pos, back = start - dist; // backwards
632if (*pos + length >= out->size)
633vector8_resize(out, (*pos + length) * 2); // reserve more room
634size_t i;
635for (i = 0; i < length; i++) {
636out->data[(*pos)++] = out->data[back++];
637if (back >= start)
638back = start - dist;
639}
640}
641}
642}
643
644void Inflator_inflateNoCompression(vector8_t *out, const uint8_t *in, size_t *bp, size_t *pos,
645size_t inlength)
646{
647while ((*bp & 0x7) != 0)
648(*bp)++; // go to first boundary of byte
649size_t p = *bp / 8;
650if (p >= inlength - 4) {
651Inflator_error = 52; // error, bit pointer will jump past memory
652return;
653}
654uint32_t LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3];
655p += 4;
656if (LEN + NLEN != 65535) {
657Inflator_error = 21; // error: NLEN is not one's complement of LEN
658return;
659}
660if (*pos + LEN >= out->size)
661vector8_resize(out, *pos + LEN);
662if (p + LEN > inlength) {
663Inflator_error = 23; // error: reading outside of in buffer
664return;
665}
666uint32_t n;
667for (n = 0; n < LEN; n++)
668out->data[(*pos)++] = in[p++]; // read LEN bytes of literal data
669*bp = p * 8;
670}
671
672void Inflator_inflate(vector8_t *out, const vector8_t *in, size_t inpos)
673{
674size_t bp = 0, pos = 0; // bit pointer and byte pointer
675Inflator_error = 0;
676uint32_t BFINAL = 0;
677while (!BFINAL && !Inflator_error) {
678if (bp >> 3 >= in->size) {
679Inflator_error = 52; // error, bit pointer will jump past memory
680return;
681}
682BFINAL = Zlib_readBitFromStream(&bp, &in->data[inpos]);
683uint32_t BTYPE = Zlib_readBitFromStream(&bp, &in->data[inpos]);
684BTYPE += 2 * Zlib_readBitFromStream(&bp, &in->data[inpos]);
685if (BTYPE == 3) {
686Inflator_error = 20; // error: invalid BTYPE
687return;
688}
689else if (BTYPE == 0)
690Inflator_inflateNoCompression(out, &in->data[inpos], &bp, &pos, in->size);
691else
692Inflator_inflateHuffmanBlock(out, &in->data[inpos], &bp, &pos, in->size, BTYPE);
693}
694if (!Inflator_error)
695vector8_resize(out, pos); // Only now we know the true size of out, resize it to that
696}
697
698/*************************************************************************************************/
699
700int Zlib_decompress(vector8_t *out, const vector8_t *in) // returns error value
701{
702if (in->size < 2)
703return 53; // error, size of zlib data too small
704if ((in->data[0] * 256 + in->data[1]) % 31 != 0)
705// error: 256 * in->data[0] + in->data[1] must be a multiple of 31, the FCHECK value is
706// supposed to be made that way
707return 24;
708uint32_t CM = in->data[0] & 15, CINFO = (in->data[0] >> 4) & 15, FDICT = (in->data[1] >> 5) & 1;
709if (CM != 8 || CINFO > 7){
710// error: only compression method 8: inflate with sliding window of 32k is supported by
711// the PNG spec
712
713return 25;
714}
715if (FDICT != 0){
716// error: the specification of PNG says about the zlib stream: "The additional flags shall
717// not specify a preset dictionary."
718return 26;
719}
720Inflator_inflate(out, in, 2);
721return Inflator_error; // note: adler32 checksum was skipped and ignored
722}
723
724/*************************************************************************************************/
725
726#define PNG_SIGNATURE0x0a1a0a0d474e5089ull
727
728#define CHUNK_IHDR0x52444849
729#define CHUNK_IDAT0x54414449
730#define CHUNK_IEND0x444e4549
731#define CHUNK_PLTE0x45544c50
732#define CHUNK_tRNS0x534e5274
733
734int PNG_error;
735
736uint32_t PNG_readBitFromReversedStream(size_t *bitp, const uint8_t *bits)
737{
738uint32_t result = (bits[*bitp >> 3] >> (7 - (*bitp & 0x7))) & 1;
739(*bitp)++;
740return result;
741}
742
743uint32_t PNG_readBitsFromReversedStream(size_t *bitp, const uint8_t *bits, uint32_t nbits)
744{
745uint32_t i, result = 0;
746for (i = nbits - 1; i < nbits; i--)
747result += ((PNG_readBitFromReversedStream(bitp, bits)) << i);
748return result;
749}
750
751void PNG_setBitOfReversedStream(size_t *bitp, uint8_t *bits, uint32_t bit)
752{
753bits[*bitp >> 3] |= (bit << (7 - (*bitp & 0x7)));
754(*bitp)++;
755}
756
757uint32_t PNG_read32bitInt(const uint8_t *buffer)
758{
759return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
760}
761
762int PNG_checkColorValidity(uint32_t colorType, uint32_t bd) // return type is a LodePNG error code
763{
764if ((colorType == 2 || colorType == 4 || colorType == 6)) {
765if (!(bd == 8 || bd == 16))
766return 37;
767else
768return 0;
769} else if (colorType == 0) {
770if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16))
771return 37;
772else
773return 0;
774} else if (colorType == 3) {
775if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8))
776return 37;
777else
778return 0;
779} else
780return 31; // nonexistent color type
781}
782
783uint32_t PNG_getBpp(const PNG_info_t *info)
784{
785uint32_t bitDepth, colorType;
786bitDepth = info->bitDepth;
787colorType = info->colorType;
788if (colorType == 2)
789{
790return (3 * bitDepth);
791}
792else if (colorType >= 4)
793{
794return (colorType - 2) * bitDepth;
795}
796else
797{
798return bitDepth;
799}
800}
801
802void PNG_readPngHeader(PNG_info_t *info, const uint8_t *in, size_t inlength)
803{// read the information from the header and store it in the Info
804if (inlength < 29) {
805PNG_error = 27; // error: the data length is smaller than the length of the header
806return;
807}
808if (*(uint64_t *) in != PNG_SIGNATURE) {
809PNG_error = 28; // no PNG signature
810return;
811}
812if (*(uint32_t *) &in[12] != CHUNK_IHDR) {
813PNG_error = 29; // error: it doesn't start with a IHDR chunk!
814return;
815}
816info->width = PNG_read32bitInt(&in[16]);
817info->height = PNG_read32bitInt(&in[20]);
818info->bitDepth = in[24];
819info->colorType = in[25];
820info->compressionMethod = in[26];
821if (in[26] != 0) {
822PNG_error = 32; // error: only compression method 0 is allowed in the specification
823return;
824}
825info->filterMethod = in[27];
826if (in[27] != 0) {
827PNG_error = 33; // error: only filter method 0 is allowed in the specification
828return;
829}
830info->interlaceMethod = in[28];
831if (in[28] > 1) {
832PNG_error = 34; // error: only interlace methods 0 and 1 exist in the specification
833return;
834}
835PNG_error = PNG_checkColorValidity(info->colorType, info->bitDepth);
836}
837
838int PNG_paethPredictor(int a, int b, int c) // Paeth predicter, used by PNG filter type 4
839{
840int p, pa, pb, pc;
841p = a + b - c;
842pa = p > a ? (p - a) : (a - p);
843pb = p > b ? (p - b) : (b - p);
844pc = p > c ? (p - c) : (c - p);
845return (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c);
846}
847
848void PNG_unFilterScanline(uint8_t *recon, const uint8_t *scanline, const uint8_t *precon,
849size_t bytewidth, uint32_t filterType, size_t length)
850{
851size_t i;
852switch (filterType) {
853case 0:
854for (i = 0; i < length; i++)
855recon[i] = scanline[i];
856break;
857case 1:
858for (i = 0; i < bytewidth; i++)
859recon[i] = scanline[i];
860for (i = bytewidth; i < length; i++)
861recon[i] = scanline[i] + recon[i - bytewidth];
862break;
863case 2:
864if (precon)
865for (i = 0; i < length; i++)
866recon[i] = scanline[i] + precon[i];
867else
868for (i = 0; i < length; i++)
869recon[i] = scanline[i];
870break;
871case 3:
872if (precon) {
873for (i = 0; i < bytewidth; i++)
874recon[i] = scanline[i] + precon[i] / 2;
875for (i = bytewidth; i < length; i++)
876recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
877} else {
878for (i = 0; i < bytewidth; i++)
879recon[i] = scanline[i];
880for (i = bytewidth; i < length; i++)
881recon[i] = scanline[i] + recon[i - bytewidth] / 2;
882}
883break;
884case 4:
885if (precon) {
886for (i = 0; i < bytewidth; i++)
887recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(0, precon[i], 0));
888for (i = bytewidth; i < length; i++)
889recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(recon[i - bytewidth],
890precon[i], precon[i - bytewidth]));
891} else {
892for (i = 0; i < bytewidth; i++)
893recon[i] = scanline[i];
894for (i = bytewidth; i < length; i++)
895recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(recon[i - bytewidth], 0, 0));
896}
897break;
898default:
899PNG_error = 36; // error: nonexistent filter type given
900return;
901}
902}
903
904void PNG_adam7Pass(uint8_t *out, uint8_t *linen, uint8_t *lineo, const uint8_t *in, uint32_t w,
905size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh,
906uint32_t bpp)
907{// filter and reposition the pixels into the output when the image is Adam7 interlaced. This
908// function can only do it after the full image is already decoded. The out buffer must have
909// the correct allocated memory size already.
910if (passw == 0)
911return;
912size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
913uint32_t y;
914for (y = 0; y < passh; y++) {
915size_t i, b;
916uint8_t filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo;
917PNG_unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType,
918(w * bpp + 7) / 8);
919if (PNG_error)
920return;
921if (bpp >= 8)
922for (i = 0; i < passw; i++)
923for (b = 0; b < bytewidth; b++) // b = current byte of this pixel
924out[bytewidth * w * (passtop + spacey * y) + bytewidth *
925(passleft + spacex * i) + b] = linen[bytewidth * i + b];
926else
927for (i = 0; i < passw; i++)
928{
929size_t obp, bp;
930obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i);
931bp = i * bpp;
932for (b = 0; b < bpp; b++)
933PNG_setBitOfReversedStream(&obp, out, PNG_readBitFromReversedStream(&bp, linen));
934}
935uint8_t *temp = linen;
936linen = lineo;
937lineo = temp; // swap the two buffer pointers "line old" and "line new"
938}
939}
940
941int PNG_convert(const PNG_info_t *info, vector8_t *out, const uint8_t *in)
942{// converts from any color type to 32-bit. return value = LodePNG error code
943size_t i, c;
944uint32_t bitDepth, colorType;
945bitDepth = info->bitDepth;
946colorType = info->colorType;
947size_t numpixels = info->width * info->height, bp = 0;
948vector8_resize(out, numpixels * 4);
949uint8_t *out_data = out->size ? out->data : 0;
950if (bitDepth == 8 && colorType == 0) // greyscale
951for (i = 0; i < numpixels; i++)
952{
953out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[i];
954out_data[4 * i + 3] = (info->key_defined && (in[i] == info->key_r)) ? 0 : 255;
955}
956else if (bitDepth == 8 && colorType == 2) // RGB color
957for (i = 0; i < numpixels; i++)
958{
959for (c = 0; c < 3; c++)
960out_data[4 * i + c] = in[3 * i + c];
961out_data[4 * i + 3] = (info->key_defined && (in[3 * i + 0] == info->key_r) &&
962(in[3 * i + 1] == info->key_g) && (in[3 * i + 2] == info->key_b)) ? 0 : 255;
963}
964else if (bitDepth == 8 && colorType == 3) // indexed color (palette)
965for (i = 0; i < numpixels; i++)
966{
967if (4U * in[i] >= info->palette->size)
968return 46;
969for (c = 0; c < 4; c++) // get rgb colors from the palette
970out_data[4 * i + c] = info->palette->data[4 * in[i] + c];
971}
972else if (bitDepth == 8 && colorType == 4) // greyscale with alpha
973for (i = 0; i < numpixels; i++) {
974out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[2 * i + 0];
975out_data[4 * i + 3] = in[2 * i + 1];
976}
977else if (bitDepth == 8 && colorType == 6)
978for (i = 0; i < numpixels; i++)
979for (c = 0; c < 4; c++)
980out_data[4 * i + c] = in[4 * i + c]; // RGB with alpha
981else if (bitDepth == 16 && colorType == 0) // greyscale
982for (i = 0; i < numpixels; i++) {
983out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[2 * i];
984out_data[4 * i + 3] = (info->key_defined && (256U * in[i] + in[i + 1] == info->key_r))
985? 0 : 255;
986}
987else if (bitDepth == 16 && colorType == 2) // RGB color
988for (i = 0; i < numpixels; i++) {
989for (c = 0; c < 3; c++)
990out_data[4 * i + c] = in[6 * i + 2 * c];
991out_data[4 * i + 3] = (info->key_defined &&
992(256U * in[6 * i + 0] + in[6 * i + 1] == info->key_r) &&
993(256U * in[6 * i + 2] + in[6 * i + 3] == info->key_g) &&
994(256U * in[6 * i + 4] + in[6 * i + 5] == info->key_b)) ? 0 : 255;
995}
996else if (bitDepth == 16 && colorType == 4) // greyscale with alpha
997for (i = 0; i < numpixels; i++) {
998out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[4 * i]; // msb
999out_data[4 * i + 3] = in[4 * i + 2];
1000}
1001else if (bitDepth == 16 && colorType == 6)
1002for (i = 0; i < numpixels; i++)
1003for (c = 0; c < 4; c++)
1004out_data[4 * i + c] = in[8 * i + 2 * c]; // RGB with alpha
1005else if (bitDepth < 8 && colorType == 0) // greyscale
1006for (i = 0; i < numpixels; i++) {
1007uint32_t value = (PNG_readBitsFromReversedStream(&bp, in, bitDepth) * 255) /
1008((1 << bitDepth) - 1); // scale value from 0 to 255
1009out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = (uint8_t) value;
1010out_data[4 * i + 3] = (info->key_defined && value &&
1011(((1U << bitDepth) - 1U) == info->key_r) && ((1U << bitDepth) - 1U)) ? 0 : 255;
1012}
1013else if (bitDepth < 8 && colorType == 3) // palette
1014for (i = 0; i < numpixels; i++)
1015{
1016uint32_t value = PNG_readBitsFromReversedStream(&bp, in, bitDepth);
1017if (4 * value >= info->palette->size)
1018return 47;
1019for (c = 0; c < 4; c++) // get rgb colors from the palette
1020out_data[4 * i + c] = info->palette->data[4 * value + c];
1021}
1022return 0;
1023}
1024
1025PNG_info_t *PNG_info_new()
1026{
1027PNG_info_t *info = png_alloc_malloc(sizeof (PNG_info_t));
1028if (!info)
1029{
1030return NULL;
1031}
1032uint32_t i;
1033for (i = 0; i < sizeof (PNG_info_t); i++)
1034((uint8_t *) info)[i] = 0;
1035info->palette = vector8_new(0, 0);
1036info->image = vector8_new(0, 0);
1037return info;
1038}
1039
1040PNG_info_t *PNG_decode(const uint8_t *in, uint32_t size)
1041{
1042PNG_info_t *info;
1043PNG_error = 0;
1044if (size == 0 || in == 0) {
1045PNG_error = 48; // the given data is empty
1046return NULL;
1047}
1048info = PNG_info_new();
1049PNG_readPngHeader(info, in, size);
1050if (PNG_error)
1051return NULL;
1052size_t pos = 33; // first byte of the first chunk after the header
1053vector8_t *idat = NULL; // the data from idat chunks
1054bool IEND = false, known_type = true;
1055info->key_defined = false;
1056// loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is
1057// put at the start of the in buffer
1058while (!IEND) {
1059size_t i, j;
1060if (pos + 8 >= size) {
1061PNG_error = 30; // error: size of the in buffer too small to contain next chunk
1062return NULL;
1063}
1064size_t chunkLength = PNG_read32bitInt(&in[pos]);
1065pos += 4;
1066if (chunkLength > 0x7fffffff) {
1067PNG_error = 63;
1068return NULL;
1069}
1070if (pos + chunkLength >= size) {
1071PNG_error = 35; // error: size of the in buffer too small to contain next chunk
1072return NULL;
1073}
1074uint32_t chunkType = *(uint32_t *) &in[pos];
1075if (chunkType == CHUNK_IDAT) { // IDAT: compressed image data chunk
1076size_t offset = 0;
1077if (idat) {
1078offset = idat->size;
1079vector8_resize(idat, offset + chunkLength);
1080} else
1081idat = vector8_new(chunkLength, 0);
1082
1083if (!idat)
1084{
1085PNG_error = 1;
1086return NULL;
1087}
1088for (i = 0; i < chunkLength; i++)
1089idat->data[offset + i] = in[pos + 4 + i];
1090pos += (4 + chunkLength);
1091} else if (chunkType == CHUNK_IEND) { // IEND
1092pos += 4;
1093IEND = true;
1094} else if (chunkType == CHUNK_PLTE) { // PLTE: palette chunk
1095pos += 4; // go after the 4 letters
1096vector8_resize(info->palette, 4 * (chunkLength / 3));
1097if (info->palette->size > (4 * 256)) {
1098PNG_error = 38; // error: palette too big
1099return NULL;
1100}
1101for (i = 0; i < info->palette->size; i += 4) {
1102for (j = 0; j < 3; j++)
1103info->palette->data[i + j] = in[pos++]; // RGB
1104info->palette->data[i + 3] = 255; // alpha
1105}
1106} else if (chunkType == CHUNK_tRNS) { // tRNS: palette transparency chunk
1107pos += 4; // go after the 4 letters
1108if (info->colorType == 3) {
1109if (4 * chunkLength > info->palette->size) {
1110PNG_error = 39; // error: more alpha values given than there are palette entries
1111return NULL;
1112}
1113for (i = 0; i < chunkLength; i++)
1114info->palette->data[4 * i + 3] = in[pos++];
1115} else if (info->colorType == 0) {
1116if (chunkLength != 2) {
1117PNG_error = 40; // error: this chunk must be 2 bytes for greyscale image
1118return NULL;
1119}
1120info->key_defined = true;
1121info->key_r = info->key_g = info->key_b = 256 * in[pos] + in[pos + 1];
1122pos += 2;
1123} else if (info->colorType == 2) {
1124if (chunkLength != 6) {
1125PNG_error = 41; // error: this chunk must be 6 bytes for RGB image
1126return NULL;
1127}
1128info->key_defined = true;
1129info->key_r = 256 * in[pos] + in[pos + 1];
1130pos += 2;
1131info->key_g = 256 * in[pos] + in[pos + 1];
1132pos += 2;
1133info->key_b = 256 * in[pos] + in[pos + 1];
1134pos += 2;
1135} else {
1136PNG_error = 42; // error: tRNS chunk not allowed for other color models
1137return NULL;
1138}
1139} else { // it's not an implemented chunk type, so ignore it: skip over the data
1140if (!(in[pos + 0] & 32)) {
1141// error: unknown critical chunk (5th bit of first byte of chunk type is 0)
1142PNG_error = 69;
1143return NULL;
1144}
1145pos += (chunkLength + 4); // skip 4 letters and uninterpreted data of unimplemented chunk
1146known_type = false;
1147}
1148pos += 4; // step over CRC (which is ignored)
1149}
1150uint32_t bpp = PNG_getBpp(info);
1151vector8_t *scanlines; // now the out buffer will be filled
1152scanlines = vector8_new(((info->width * (info->height * bpp + 7)) / 8) + info->height, 0);
1153if (!scanlines)
1154{
1155PNG_error = 1;
1156return NULL;
1157}
1158PNG_error = Zlib_decompress(scanlines, idat);
1159if (PNG_error)
1160return NULL; // stop if the zlib decompressor returned an error
1161size_t bytewidth = (bpp + 7) / 8, outlength = (info->height * info->width * bpp + 7) / 8;
1162vector8_resize(info->image, outlength); // time to fill the out buffer
1163uint8_t *out_data = outlength ? info->image->data : 0;
1164if (info->interlaceMethod == 0) { // no interlace, just filter
1165size_t y, obp, bp;
1166size_t linestart, linelength;
1167linestart = 0;
1168// length in bytes of a scanline, excluding the filtertype byte
1169linelength = (info->width * bpp + 7) / 8;
1170if (bpp >= 8) // byte per byte
1171for (y = 0; y < info->height; y++) {
1172uint32_t filterType = scanlines->data[linestart];
1173const uint8_t *prevline;
1174prevline = (y == 0) ? 0 : &out_data[(y - 1) * info->width * bytewidth];
1175PNG_unFilterScanline(&out_data[linestart - y], &scanlines->data[linestart + 1],
1176prevline, bytewidth, filterType, linelength);
1177if (PNG_error)
1178return NULL;
1179linestart += (1 + linelength); // go to start of next scanline
1180} else { // less than 8 bits per pixel, so fill it up bit per bit
1181vector8_t *templine; // only used if bpp < 8
1182templine = vector8_new((info->width * bpp + 7) >> 3, 0);
1183for (y = 0, obp = 0; y < info->height; y++) {
1184uint32_t filterType = scanlines->data[linestart];
1185const uint8_t *prevline;
1186prevline = (y == 0) ? 0 : &out_data[(y - 1) * info->width * bytewidth];
1187PNG_unFilterScanline(templine->data, &scanlines->data[linestart + 1], prevline,
1188bytewidth, filterType, linelength);
1189if (PNG_error)
1190return NULL;
1191for (bp = 0; bp < info->width * bpp;)
1192PNG_setBitOfReversedStream(&obp, out_data, PNG_readBitFromReversedStream(&bp,
1193templine->data));
1194linestart += (1 + linelength); // go to start of next scanline
1195}
1196}
1197} else { // interlaceMethod is 1 (Adam7)
1198int i;
1199size_t passw[7] = {
1200(info->width + 7) / 8, (info->width + 3) / 8, (info->width + 3) / 4,
1201(info->width + 1) / 4, (info->width + 1) / 2, (info->width + 0) / 2,
1202(info->width + 0) / 1
1203};
1204size_t passh[7] = {
1205(info->height + 7) / 8, (info->height + 7) / 8, (info->height + 3) / 8,
1206(info->height + 3) / 4, (info->height + 1) / 4, (info->height + 1) / 2,
1207(info->height + 0) / 2
1208};
1209size_t passstart[7] = { 0 };
1210size_t pattern[28] = { 0, 4, 0, 2, 0, 1, 0, 0, 0, 4, 0, 2, 0, 1, 8, 8, 4, 4, 2, 2, 1, 8, 8,
12118, 4, 4, 2, 2 }; // values for the adam7 passes
1212for (i = 0; i < 6; i++)
1213passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
1214vector8_t *scanlineo, *scanlinen; // "old" and "new" scanline
1215scanlineo = vector8_new((info->width * bpp + 7) / 8, 0);
1216scanlinen = vector8_new((info->width * bpp + 7) / 8, 0);
1217for (i = 0; i < 7; i++)
1218PNG_adam7Pass(out_data, scanlinen->data, scanlineo->data, &scanlines->data[passstart[i]],
1219info->width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21],
1220passw[i], passh[i], bpp);
1221}
1222if (info->colorType != 6 || info->bitDepth != 8) { // conversion needed
1223vector8_t *copy = vector8_copy(info->image); // xxx: is this copy necessary?
1224if (!copy)
1225{
1226return NULL;
1227}
1228PNG_error = PNG_convert(info, info->image, copy->data);
1229if (PNG_error)
1230{
1231return NULL;
1232 }
1233}
1234return info;
1235}
1236
1237/*************************************************************************************************/
1238
1239#ifdef TEST
1240
1241#include <stdio.h>
1242#include <sys/stat.h>
1243
1244int main(int argc, char **argv)
1245{
1246char *fname = (argc > 1) ? argv[1] : "test.png";
1247PNG_info_t *info;
1248struct stat statbuf;
1249uint32_t insize, outsize;
1250FILE *infp, *outfp;
1251uint8_t *inbuf;
1252uint32_t n;
1253
1254if (stat(fname, &statbuf) != 0) {
1255perror("stat");
1256return 1;
1257} else if (!statbuf.st_size) {
1258printf("file empty\n");
1259return 1;
1260}
1261insize = (uint32_t) statbuf.st_size;
1262inbuf = malloc(insize);
1263infp = fopen(fname, "rb");
1264if (!infp) {
1265perror("fopen");
1266return 1;
1267} else if (fread(inbuf, 1, insize, infp) != insize) {
1268perror("fread");
1269return 1;
1270}
1271fclose(infp);
1272
1273printf("input file: %s (size: %d)\n", fname, insize);
1274
1275info = PNG_decode(inbuf, insize);
1276free(inbuf);
1277printf("PNG_error: %d\n", PNG_error);
1278if (PNG_error != 0)
1279return 1;
1280
1281printf("width: %d, height: %d\nfirst 16 bytes: ", info->width, info->height);
1282for (n = 0; n < 16; n++)
1283printf("%02x ", info->image->data[n]);
1284printf("\n");
1285
1286outsize = info->width * info->height * 4;
1287printf("image size: %d\n", outsize);
1288if (outsize != info->image->size) {
1289printf("error: image size doesn't match dimensions\n");
1290return 1;
1291}
1292outfp = fopen("out.bin", "wb");
1293if (!outfp) {
1294perror("fopen");
1295return 1;
1296} else if (fwrite(info->image->data, 1, outsize, outfp) != outsize) {
1297perror("fwrite");
1298return 1;
1299}
1300fclose(outfp);
1301
1302#ifdef ALLOC_DEBUG
1303png_alloc_node_t *node;
1304for (node = png_alloc_head, n = 1; node; node = node->next, n++)
1305printf("node %d (%p) addr = %p, size = %ld\n", n, node, node->addr, node->size);
1306#endif
1307png_alloc_free_all(); // also frees info and image data from PNG_decode
1308
1309return 0;
1310}
1311
1312#endif
1313

Archive Download this file

Revision: 2238