1*e47783fdSXin Li /*
2*e47783fdSXin Li LodePNG version 20201017
3*e47783fdSXin Li
4*e47783fdSXin Li Copyright (c) 2005-2020 Lode Vandevenne
5*e47783fdSXin Li
6*e47783fdSXin Li This software is provided 'as-is', without any express or implied
7*e47783fdSXin Li warranty. In no event will the authors be held liable for any damages
8*e47783fdSXin Li arising from the use of this software.
9*e47783fdSXin Li
10*e47783fdSXin Li Permission is granted to anyone to use this software for any purpose,
11*e47783fdSXin Li including commercial applications, and to alter it and redistribute it
12*e47783fdSXin Li freely, subject to the following restrictions:
13*e47783fdSXin Li
14*e47783fdSXin Li 1. The origin of this software must not be misrepresented; you must not
15*e47783fdSXin Li claim that you wrote the original software. If you use this software
16*e47783fdSXin Li in a product, an acknowledgment in the product documentation would be
17*e47783fdSXin Li appreciated but is not required.
18*e47783fdSXin Li
19*e47783fdSXin Li 2. Altered source versions must be plainly marked as such, and must not be
20*e47783fdSXin Li misrepresented as being the original software.
21*e47783fdSXin Li
22*e47783fdSXin Li 3. This notice may not be removed or altered from any source
23*e47783fdSXin Li distribution.
24*e47783fdSXin Li */
25*e47783fdSXin Li
26*e47783fdSXin Li /*
27*e47783fdSXin Li The manual and changelog are in the header file "lodepng.h"
28*e47783fdSXin Li Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.
29*e47783fdSXin Li */
30*e47783fdSXin Li
31*e47783fdSXin Li #include "lodepng.h"
32*e47783fdSXin Li
33*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
34*e47783fdSXin Li #include <limits.h> /* LONG_MAX */
35*e47783fdSXin Li #include <stdio.h> /* file handling */
36*e47783fdSXin Li #endif /* LODEPNG_COMPILE_DISK */
37*e47783fdSXin Li
38*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ALLOCATORS
39*e47783fdSXin Li #include <stdlib.h> /* allocations */
40*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ALLOCATORS */
41*e47783fdSXin Li
42*e47783fdSXin Li #if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
43*e47783fdSXin Li #pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/
44*e47783fdSXin Li #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
45*e47783fdSXin Li #endif /*_MSC_VER */
46*e47783fdSXin Li
47*e47783fdSXin Li const char* LODEPNG_VERSION_STRING = "20201017";
48*e47783fdSXin Li
49*e47783fdSXin Li /*
50*e47783fdSXin Li This source file is built up in the following large parts. The code sections
51*e47783fdSXin Li with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way.
52*e47783fdSXin Li -Tools for C and common code for PNG and Zlib
53*e47783fdSXin Li -C Code for Zlib (huffman, deflate, ...)
54*e47783fdSXin Li -C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)
55*e47783fdSXin Li -The C++ wrapper around all of the above
56*e47783fdSXin Li */
57*e47783fdSXin Li
58*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
59*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
60*e47783fdSXin Li /* // Tools for C, and common code for PNG and Zlib. // */
61*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
62*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
63*e47783fdSXin Li
64*e47783fdSXin Li /*The malloc, realloc and free functions defined here with "lodepng_" in front
65*e47783fdSXin Li of the name, so that you can easily change them to others related to your
66*e47783fdSXin Li platform if needed. Everything else in the code calls these. Pass
67*e47783fdSXin Li -DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out
68*e47783fdSXin Li #define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and
69*e47783fdSXin Li define them in your own project's source files without needing to change
70*e47783fdSXin Li lodepng source code. Don't forget to remove "static" if you copypaste them
71*e47783fdSXin Li from here.*/
72*e47783fdSXin Li
73*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ALLOCATORS
lodepng_malloc(size_t size)74*e47783fdSXin Li static void* lodepng_malloc(size_t size) {
75*e47783fdSXin Li #ifdef LODEPNG_MAX_ALLOC
76*e47783fdSXin Li if(size > LODEPNG_MAX_ALLOC) return 0;
77*e47783fdSXin Li #endif
78*e47783fdSXin Li return malloc(size);
79*e47783fdSXin Li }
80*e47783fdSXin Li
81*e47783fdSXin Li /* NOTE: when realloc returns NULL, it leaves the original memory untouched */
lodepng_realloc(void * ptr,size_t new_size)82*e47783fdSXin Li static void* lodepng_realloc(void* ptr, size_t new_size) {
83*e47783fdSXin Li #ifdef LODEPNG_MAX_ALLOC
84*e47783fdSXin Li if(new_size > LODEPNG_MAX_ALLOC) return 0;
85*e47783fdSXin Li #endif
86*e47783fdSXin Li return realloc(ptr, new_size);
87*e47783fdSXin Li }
88*e47783fdSXin Li
lodepng_free(void * ptr)89*e47783fdSXin Li static void lodepng_free(void* ptr) {
90*e47783fdSXin Li free(ptr);
91*e47783fdSXin Li }
92*e47783fdSXin Li #else /*LODEPNG_COMPILE_ALLOCATORS*/
93*e47783fdSXin Li /* TODO: support giving additional void* payload to the custom allocators */
94*e47783fdSXin Li void* lodepng_malloc(size_t size);
95*e47783fdSXin Li void* lodepng_realloc(void* ptr, size_t new_size);
96*e47783fdSXin Li void lodepng_free(void* ptr);
97*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ALLOCATORS*/
98*e47783fdSXin Li
99*e47783fdSXin Li /* convince the compiler to inline a function, for use when this measurably improves performance */
100*e47783fdSXin Li /* inline is not available in C90, but use it when supported by the compiler */
101*e47783fdSXin Li #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L))
102*e47783fdSXin Li #define LODEPNG_INLINE inline
103*e47783fdSXin Li #else
104*e47783fdSXin Li #define LODEPNG_INLINE /* not available */
105*e47783fdSXin Li #endif
106*e47783fdSXin Li
107*e47783fdSXin Li /* restrict is not available in C90, but use it when supported by the compiler */
108*e47783fdSXin Li #if (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) ||\
109*e47783fdSXin Li (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \
110*e47783fdSXin Li (defined(__WATCOMC__) && (__WATCOMC__ >= 1250) && !defined(__cplusplus))
111*e47783fdSXin Li #define LODEPNG_RESTRICT __restrict
112*e47783fdSXin Li #else
113*e47783fdSXin Li #define LODEPNG_RESTRICT /* not available */
114*e47783fdSXin Li #endif
115*e47783fdSXin Li
116*e47783fdSXin Li /* Replacements for C library functions such as memcpy and strlen, to support platforms
117*e47783fdSXin Li where a full C library is not available. The compiler can recognize them and compile
118*e47783fdSXin Li to something as fast. */
119*e47783fdSXin Li
lodepng_memcpy(void * LODEPNG_RESTRICT dst,const void * LODEPNG_RESTRICT src,size_t size)120*e47783fdSXin Li static void lodepng_memcpy(void* LODEPNG_RESTRICT dst,
121*e47783fdSXin Li const void* LODEPNG_RESTRICT src, size_t size) {
122*e47783fdSXin Li size_t i;
123*e47783fdSXin Li for(i = 0; i < size; i++) ((char*)dst)[i] = ((const char*)src)[i];
124*e47783fdSXin Li }
125*e47783fdSXin Li
lodepng_memset(void * LODEPNG_RESTRICT dst,int value,size_t num)126*e47783fdSXin Li static void lodepng_memset(void* LODEPNG_RESTRICT dst,
127*e47783fdSXin Li int value, size_t num) {
128*e47783fdSXin Li size_t i;
129*e47783fdSXin Li for(i = 0; i < num; i++) ((char*)dst)[i] = (char)value;
130*e47783fdSXin Li }
131*e47783fdSXin Li
132*e47783fdSXin Li /* does not check memory out of bounds, do not use on untrusted data */
lodepng_strlen(const char * a)133*e47783fdSXin Li static size_t lodepng_strlen(const char* a) {
134*e47783fdSXin Li const char* orig = a;
135*e47783fdSXin Li /* avoid warning about unused function in case of disabled COMPILE... macros */
136*e47783fdSXin Li (void)(&lodepng_strlen);
137*e47783fdSXin Li while(*a) a++;
138*e47783fdSXin Li return (size_t)(a - orig);
139*e47783fdSXin Li }
140*e47783fdSXin Li
141*e47783fdSXin Li #define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b))
142*e47783fdSXin Li #define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b))
143*e47783fdSXin Li #define LODEPNG_ABS(x) ((x) < 0 ? -(x) : (x))
144*e47783fdSXin Li
145*e47783fdSXin Li #if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)
146*e47783fdSXin Li /* Safely check if adding two integers will overflow (no undefined
147*e47783fdSXin Li behavior, compiler removing the code, etc...) and output result. */
lodepng_addofl(size_t a,size_t b,size_t * result)148*e47783fdSXin Li static int lodepng_addofl(size_t a, size_t b, size_t* result) {
149*e47783fdSXin Li *result = a + b; /* Unsigned addition is well defined and safe in C90 */
150*e47783fdSXin Li return *result < a;
151*e47783fdSXin Li }
152*e47783fdSXin Li #endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/
153*e47783fdSXin Li
154*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
155*e47783fdSXin Li /* Safely check if multiplying two integers will overflow (no undefined
156*e47783fdSXin Li behavior, compiler removing the code, etc...) and output result. */
lodepng_mulofl(size_t a,size_t b,size_t * result)157*e47783fdSXin Li static int lodepng_mulofl(size_t a, size_t b, size_t* result) {
158*e47783fdSXin Li *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */
159*e47783fdSXin Li return (a != 0 && *result / a != b);
160*e47783fdSXin Li }
161*e47783fdSXin Li
162*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ZLIB
163*e47783fdSXin Li /* Safely check if a + b > c, even if overflow could happen. */
lodepng_gtofl(size_t a,size_t b,size_t c)164*e47783fdSXin Li static int lodepng_gtofl(size_t a, size_t b, size_t c) {
165*e47783fdSXin Li size_t d;
166*e47783fdSXin Li if(lodepng_addofl(a, b, &d)) return 1;
167*e47783fdSXin Li return d > c;
168*e47783fdSXin Li }
169*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ZLIB*/
170*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
171*e47783fdSXin Li
172*e47783fdSXin Li
173*e47783fdSXin Li /*
174*e47783fdSXin Li Often in case of an error a value is assigned to a variable and then it breaks
175*e47783fdSXin Li out of a loop (to go to the cleanup phase of a function). This macro does that.
176*e47783fdSXin Li It makes the error handling code shorter and more readable.
177*e47783fdSXin Li
178*e47783fdSXin Li Example: if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83);
179*e47783fdSXin Li */
180*e47783fdSXin Li #define CERROR_BREAK(errorvar, code){\
181*e47783fdSXin Li errorvar = code;\
182*e47783fdSXin Li break;\
183*e47783fdSXin Li }
184*e47783fdSXin Li
185*e47783fdSXin Li /*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/
186*e47783fdSXin Li #define ERROR_BREAK(code) CERROR_BREAK(error, code)
187*e47783fdSXin Li
188*e47783fdSXin Li /*Set error var to the error code, and return it.*/
189*e47783fdSXin Li #define CERROR_RETURN_ERROR(errorvar, code){\
190*e47783fdSXin Li errorvar = code;\
191*e47783fdSXin Li return code;\
192*e47783fdSXin Li }
193*e47783fdSXin Li
194*e47783fdSXin Li /*Try the code, if it returns error, also return the error.*/
195*e47783fdSXin Li #define CERROR_TRY_RETURN(call){\
196*e47783fdSXin Li unsigned error = call;\
197*e47783fdSXin Li if(error) return error;\
198*e47783fdSXin Li }
199*e47783fdSXin Li
200*e47783fdSXin Li /*Set error var to the error code, and return from the void function.*/
201*e47783fdSXin Li #define CERROR_RETURN(errorvar, code){\
202*e47783fdSXin Li errorvar = code;\
203*e47783fdSXin Li return;\
204*e47783fdSXin Li }
205*e47783fdSXin Li
206*e47783fdSXin Li /*
207*e47783fdSXin Li About uivector, ucvector and string:
208*e47783fdSXin Li -All of them wrap dynamic arrays or text strings in a similar way.
209*e47783fdSXin Li -LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.
210*e47783fdSXin Li -The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.
211*e47783fdSXin Li -They're not used in the interface, only internally in this file as static functions.
212*e47783fdSXin Li -As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.
213*e47783fdSXin Li */
214*e47783fdSXin Li
215*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ZLIB
216*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
217*e47783fdSXin Li /*dynamic vector of unsigned ints*/
218*e47783fdSXin Li typedef struct uivector {
219*e47783fdSXin Li unsigned* data;
220*e47783fdSXin Li size_t size; /*size in number of unsigned longs*/
221*e47783fdSXin Li size_t allocsize; /*allocated size in bytes*/
222*e47783fdSXin Li } uivector;
223*e47783fdSXin Li
uivector_cleanup(void * p)224*e47783fdSXin Li static void uivector_cleanup(void* p) {
225*e47783fdSXin Li ((uivector*)p)->size = ((uivector*)p)->allocsize = 0;
226*e47783fdSXin Li lodepng_free(((uivector*)p)->data);
227*e47783fdSXin Li ((uivector*)p)->data = NULL;
228*e47783fdSXin Li }
229*e47783fdSXin Li
230*e47783fdSXin Li /*returns 1 if success, 0 if failure ==> nothing done*/
uivector_resize(uivector * p,size_t size)231*e47783fdSXin Li static unsigned uivector_resize(uivector* p, size_t size) {
232*e47783fdSXin Li size_t allocsize = size * sizeof(unsigned);
233*e47783fdSXin Li if(allocsize > p->allocsize) {
234*e47783fdSXin Li size_t newsize = allocsize + (p->allocsize >> 1u);
235*e47783fdSXin Li void* data = lodepng_realloc(p->data, newsize);
236*e47783fdSXin Li if(data) {
237*e47783fdSXin Li p->allocsize = newsize;
238*e47783fdSXin Li p->data = (unsigned*)data;
239*e47783fdSXin Li }
240*e47783fdSXin Li else return 0; /*error: not enough memory*/
241*e47783fdSXin Li }
242*e47783fdSXin Li p->size = size;
243*e47783fdSXin Li return 1; /*success*/
244*e47783fdSXin Li }
245*e47783fdSXin Li
uivector_init(uivector * p)246*e47783fdSXin Li static void uivector_init(uivector* p) {
247*e47783fdSXin Li p->data = NULL;
248*e47783fdSXin Li p->size = p->allocsize = 0;
249*e47783fdSXin Li }
250*e47783fdSXin Li
251*e47783fdSXin Li /*returns 1 if success, 0 if failure ==> nothing done*/
uivector_push_back(uivector * p,unsigned c)252*e47783fdSXin Li static unsigned uivector_push_back(uivector* p, unsigned c) {
253*e47783fdSXin Li if(!uivector_resize(p, p->size + 1)) return 0;
254*e47783fdSXin Li p->data[p->size - 1] = c;
255*e47783fdSXin Li return 1;
256*e47783fdSXin Li }
257*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
258*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ZLIB*/
259*e47783fdSXin Li
260*e47783fdSXin Li /* /////////////////////////////////////////////////////////////////////////// */
261*e47783fdSXin Li
262*e47783fdSXin Li /*dynamic vector of unsigned chars*/
263*e47783fdSXin Li typedef struct ucvector {
264*e47783fdSXin Li unsigned char* data;
265*e47783fdSXin Li size_t size; /*used size*/
266*e47783fdSXin Li size_t allocsize; /*allocated size*/
267*e47783fdSXin Li } ucvector;
268*e47783fdSXin Li
269*e47783fdSXin Li /*returns 1 if success, 0 if failure ==> nothing done*/
ucvector_resize(ucvector * p,size_t size)270*e47783fdSXin Li static unsigned ucvector_resize(ucvector* p, size_t size) {
271*e47783fdSXin Li if(size > p->allocsize) {
272*e47783fdSXin Li size_t newsize = size + (p->allocsize >> 1u);
273*e47783fdSXin Li void* data = lodepng_realloc(p->data, newsize);
274*e47783fdSXin Li if(data) {
275*e47783fdSXin Li p->allocsize = newsize;
276*e47783fdSXin Li p->data = (unsigned char*)data;
277*e47783fdSXin Li }
278*e47783fdSXin Li else return 0; /*error: not enough memory*/
279*e47783fdSXin Li }
280*e47783fdSXin Li p->size = size;
281*e47783fdSXin Li return 1; /*success*/
282*e47783fdSXin Li }
283*e47783fdSXin Li
ucvector_init(unsigned char * buffer,size_t size)284*e47783fdSXin Li static ucvector ucvector_init(unsigned char* buffer, size_t size) {
285*e47783fdSXin Li ucvector v;
286*e47783fdSXin Li v.data = buffer;
287*e47783fdSXin Li v.allocsize = v.size = size;
288*e47783fdSXin Li return v;
289*e47783fdSXin Li }
290*e47783fdSXin Li
291*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
292*e47783fdSXin Li
293*e47783fdSXin Li #ifdef LODEPNG_COMPILE_PNG
294*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
295*e47783fdSXin Li
296*e47783fdSXin Li /*free string pointer and set it to NULL*/
string_cleanup(char ** out)297*e47783fdSXin Li static void string_cleanup(char** out) {
298*e47783fdSXin Li lodepng_free(*out);
299*e47783fdSXin Li *out = NULL;
300*e47783fdSXin Li }
301*e47783fdSXin Li
302*e47783fdSXin Li /*also appends null termination character*/
alloc_string_sized(const char * in,size_t insize)303*e47783fdSXin Li static char* alloc_string_sized(const char* in, size_t insize) {
304*e47783fdSXin Li char* out = (char*)lodepng_malloc(insize + 1);
305*e47783fdSXin Li if(out) {
306*e47783fdSXin Li lodepng_memcpy(out, in, insize);
307*e47783fdSXin Li out[insize] = 0;
308*e47783fdSXin Li }
309*e47783fdSXin Li return out;
310*e47783fdSXin Li }
311*e47783fdSXin Li
312*e47783fdSXin Li /* dynamically allocates a new string with a copy of the null terminated input text */
alloc_string(const char * in)313*e47783fdSXin Li static char* alloc_string(const char* in) {
314*e47783fdSXin Li return alloc_string_sized(in, lodepng_strlen(in));
315*e47783fdSXin Li }
316*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
317*e47783fdSXin Li #endif /*LODEPNG_COMPILE_PNG*/
318*e47783fdSXin Li
319*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
320*e47783fdSXin Li
321*e47783fdSXin Li #if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)
lodepng_read32bitInt(const unsigned char * buffer)322*e47783fdSXin Li static unsigned lodepng_read32bitInt(const unsigned char* buffer) {
323*e47783fdSXin Li return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) |
324*e47783fdSXin Li ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]);
325*e47783fdSXin Li }
326*e47783fdSXin Li #endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/
327*e47783fdSXin Li
328*e47783fdSXin Li #if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)
329*e47783fdSXin Li /*buffer must have at least 4 allocated bytes available*/
lodepng_set32bitInt(unsigned char * buffer,unsigned value)330*e47783fdSXin Li static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) {
331*e47783fdSXin Li buffer[0] = (unsigned char)((value >> 24) & 0xff);
332*e47783fdSXin Li buffer[1] = (unsigned char)((value >> 16) & 0xff);
333*e47783fdSXin Li buffer[2] = (unsigned char)((value >> 8) & 0xff);
334*e47783fdSXin Li buffer[3] = (unsigned char)((value ) & 0xff);
335*e47783fdSXin Li }
336*e47783fdSXin Li #endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
337*e47783fdSXin Li
338*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
339*e47783fdSXin Li /* / File IO / */
340*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
341*e47783fdSXin Li
342*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
343*e47783fdSXin Li
344*e47783fdSXin Li /* returns negative value on error. This should be pure C compatible, so no fstat. */
lodepng_filesize(const char * filename)345*e47783fdSXin Li static long lodepng_filesize(const char* filename) {
346*e47783fdSXin Li FILE* file;
347*e47783fdSXin Li long size;
348*e47783fdSXin Li file = fopen(filename, "rb");
349*e47783fdSXin Li if(!file) return -1;
350*e47783fdSXin Li
351*e47783fdSXin Li if(fseek(file, 0, SEEK_END) != 0) {
352*e47783fdSXin Li fclose(file);
353*e47783fdSXin Li return -1;
354*e47783fdSXin Li }
355*e47783fdSXin Li
356*e47783fdSXin Li size = ftell(file);
357*e47783fdSXin Li /* It may give LONG_MAX as directory size, this is invalid for us. */
358*e47783fdSXin Li if(size == LONG_MAX) size = -1;
359*e47783fdSXin Li
360*e47783fdSXin Li fclose(file);
361*e47783fdSXin Li return size;
362*e47783fdSXin Li }
363*e47783fdSXin Li
364*e47783fdSXin Li /* load file into buffer that already has the correct allocated size. Returns error code.*/
lodepng_buffer_file(unsigned char * out,size_t size,const char * filename)365*e47783fdSXin Li static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) {
366*e47783fdSXin Li FILE* file;
367*e47783fdSXin Li size_t readsize;
368*e47783fdSXin Li file = fopen(filename, "rb");
369*e47783fdSXin Li if(!file) return 78;
370*e47783fdSXin Li
371*e47783fdSXin Li readsize = fread(out, 1, size, file);
372*e47783fdSXin Li fclose(file);
373*e47783fdSXin Li
374*e47783fdSXin Li if(readsize != size) return 78;
375*e47783fdSXin Li return 0;
376*e47783fdSXin Li }
377*e47783fdSXin Li
lodepng_load_file(unsigned char ** out,size_t * outsize,const char * filename)378*e47783fdSXin Li unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) {
379*e47783fdSXin Li long size = lodepng_filesize(filename);
380*e47783fdSXin Li if(size < 0) return 78;
381*e47783fdSXin Li *outsize = (size_t)size;
382*e47783fdSXin Li
383*e47783fdSXin Li *out = (unsigned char*)lodepng_malloc((size_t)size);
384*e47783fdSXin Li if(!(*out) && size > 0) return 83; /*the above malloc failed*/
385*e47783fdSXin Li
386*e47783fdSXin Li return lodepng_buffer_file(*out, (size_t)size, filename);
387*e47783fdSXin Li }
388*e47783fdSXin Li
389*e47783fdSXin Li /*write given buffer to the file, overwriting the file, it doesn't append to it.*/
lodepng_save_file(const unsigned char * buffer,size_t buffersize,const char * filename)390*e47783fdSXin Li unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) {
391*e47783fdSXin Li FILE* file;
392*e47783fdSXin Li file = fopen(filename, "wb" );
393*e47783fdSXin Li if(!file) return 79;
394*e47783fdSXin Li fwrite(buffer, 1, buffersize, file);
395*e47783fdSXin Li fclose(file);
396*e47783fdSXin Li return 0;
397*e47783fdSXin Li }
398*e47783fdSXin Li
399*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DISK*/
400*e47783fdSXin Li
401*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
402*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
403*e47783fdSXin Li /* // End of common code and tools. Begin of Zlib related code. // */
404*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
405*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
406*e47783fdSXin Li
407*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ZLIB
408*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
409*e47783fdSXin Li
410*e47783fdSXin Li typedef struct {
411*e47783fdSXin Li ucvector* data;
412*e47783fdSXin Li unsigned char bp; /*ok to overflow, indicates bit pos inside byte*/
413*e47783fdSXin Li } LodePNGBitWriter;
414*e47783fdSXin Li
LodePNGBitWriter_init(LodePNGBitWriter * writer,ucvector * data)415*e47783fdSXin Li static void LodePNGBitWriter_init(LodePNGBitWriter* writer, ucvector* data) {
416*e47783fdSXin Li writer->data = data;
417*e47783fdSXin Li writer->bp = 0;
418*e47783fdSXin Li }
419*e47783fdSXin Li
420*e47783fdSXin Li /*TODO: this ignores potential out of memory errors*/
421*e47783fdSXin Li #define WRITEBIT(writer, bit){\
422*e47783fdSXin Li /* append new byte */\
423*e47783fdSXin Li if(((writer->bp) & 7u) == 0) {\
424*e47783fdSXin Li if(!ucvector_resize(writer->data, writer->data->size + 1)) return;\
425*e47783fdSXin Li writer->data->data[writer->data->size - 1] = 0;\
426*e47783fdSXin Li }\
427*e47783fdSXin Li (writer->data->data[writer->data->size - 1]) |= (bit << ((writer->bp) & 7u));\
428*e47783fdSXin Li ++writer->bp;\
429*e47783fdSXin Li }
430*e47783fdSXin Li
431*e47783fdSXin Li /* LSB of value is written first, and LSB of bytes is used first */
writeBits(LodePNGBitWriter * writer,unsigned value,size_t nbits)432*e47783fdSXin Li static void writeBits(LodePNGBitWriter* writer, unsigned value, size_t nbits) {
433*e47783fdSXin Li if(nbits == 1) { /* compiler should statically compile this case if nbits == 1 */
434*e47783fdSXin Li WRITEBIT(writer, value);
435*e47783fdSXin Li } else {
436*e47783fdSXin Li /* TODO: increase output size only once here rather than in each WRITEBIT */
437*e47783fdSXin Li size_t i;
438*e47783fdSXin Li for(i = 0; i != nbits; ++i) {
439*e47783fdSXin Li WRITEBIT(writer, (unsigned char)((value >> i) & 1));
440*e47783fdSXin Li }
441*e47783fdSXin Li }
442*e47783fdSXin Li }
443*e47783fdSXin Li
444*e47783fdSXin Li /* This one is to use for adding huffman symbol, the value bits are written MSB first */
writeBitsReversed(LodePNGBitWriter * writer,unsigned value,size_t nbits)445*e47783fdSXin Li static void writeBitsReversed(LodePNGBitWriter* writer, unsigned value, size_t nbits) {
446*e47783fdSXin Li size_t i;
447*e47783fdSXin Li for(i = 0; i != nbits; ++i) {
448*e47783fdSXin Li /* TODO: increase output size only once here rather than in each WRITEBIT */
449*e47783fdSXin Li WRITEBIT(writer, (unsigned char)((value >> (nbits - 1u - i)) & 1u));
450*e47783fdSXin Li }
451*e47783fdSXin Li }
452*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
453*e47783fdSXin Li
454*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
455*e47783fdSXin Li
456*e47783fdSXin Li typedef struct {
457*e47783fdSXin Li const unsigned char* data;
458*e47783fdSXin Li size_t size; /*size of data in bytes*/
459*e47783fdSXin Li size_t bitsize; /*size of data in bits, end of valid bp values, should be 8*size*/
460*e47783fdSXin Li size_t bp;
461*e47783fdSXin Li unsigned buffer; /*buffer for reading bits. NOTE: 'unsigned' must support at least 32 bits*/
462*e47783fdSXin Li } LodePNGBitReader;
463*e47783fdSXin Li
464*e47783fdSXin Li /* data size argument is in bytes. Returns error if size too large causing overflow */
LodePNGBitReader_init(LodePNGBitReader * reader,const unsigned char * data,size_t size)465*e47783fdSXin Li static unsigned LodePNGBitReader_init(LodePNGBitReader* reader, const unsigned char* data, size_t size) {
466*e47783fdSXin Li size_t temp;
467*e47783fdSXin Li reader->data = data;
468*e47783fdSXin Li reader->size = size;
469*e47783fdSXin Li /* size in bits, return error if overflow (if size_t is 32 bit this supports up to 500MB) */
470*e47783fdSXin Li if(lodepng_mulofl(size, 8u, &reader->bitsize)) return 105;
471*e47783fdSXin Li /*ensure incremented bp can be compared to bitsize without overflow even when it would be incremented 32 too much and
472*e47783fdSXin Li trying to ensure 32 more bits*/
473*e47783fdSXin Li if(lodepng_addofl(reader->bitsize, 64u, &temp)) return 105;
474*e47783fdSXin Li reader->bp = 0;
475*e47783fdSXin Li reader->buffer = 0;
476*e47783fdSXin Li return 0; /*ok*/
477*e47783fdSXin Li }
478*e47783fdSXin Li
479*e47783fdSXin Li /*
480*e47783fdSXin Li ensureBits functions:
481*e47783fdSXin Li Ensures the reader can at least read nbits bits in one or more readBits calls,
482*e47783fdSXin Li safely even if not enough bits are available.
483*e47783fdSXin Li Returns 1 if there are enough bits available, 0 if not.
484*e47783fdSXin Li */
485*e47783fdSXin Li
486*e47783fdSXin Li /*See ensureBits documentation above. This one ensures exactly 1 bit */
487*e47783fdSXin Li /*static unsigned ensureBits1(LodePNGBitReader* reader) {
488*e47783fdSXin Li if(reader->bp >= reader->bitsize) return 0;
489*e47783fdSXin Li reader->buffer = (unsigned)reader->data[reader->bp >> 3u] >> (reader->bp & 7u);
490*e47783fdSXin Li return 1;
491*e47783fdSXin Li }*/
492*e47783fdSXin Li
493*e47783fdSXin Li /*See ensureBits documentation above. This one ensures up to 9 bits */
ensureBits9(LodePNGBitReader * reader,size_t nbits)494*e47783fdSXin Li static unsigned ensureBits9(LodePNGBitReader* reader, size_t nbits) {
495*e47783fdSXin Li size_t start = reader->bp >> 3u;
496*e47783fdSXin Li size_t size = reader->size;
497*e47783fdSXin Li if(start + 1u < size) {
498*e47783fdSXin Li reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u);
499*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
500*e47783fdSXin Li return 1;
501*e47783fdSXin Li } else {
502*e47783fdSXin Li reader->buffer = 0;
503*e47783fdSXin Li if(start + 0u < size) reader->buffer |= reader->data[start + 0];
504*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
505*e47783fdSXin Li return reader->bp + nbits <= reader->bitsize;
506*e47783fdSXin Li }
507*e47783fdSXin Li }
508*e47783fdSXin Li
509*e47783fdSXin Li /*See ensureBits documentation above. This one ensures up to 17 bits */
ensureBits17(LodePNGBitReader * reader,size_t nbits)510*e47783fdSXin Li static unsigned ensureBits17(LodePNGBitReader* reader, size_t nbits) {
511*e47783fdSXin Li size_t start = reader->bp >> 3u;
512*e47783fdSXin Li size_t size = reader->size;
513*e47783fdSXin Li if(start + 2u < size) {
514*e47783fdSXin Li reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
515*e47783fdSXin Li ((unsigned)reader->data[start + 2] << 16u);
516*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
517*e47783fdSXin Li return 1;
518*e47783fdSXin Li } else {
519*e47783fdSXin Li reader->buffer = 0;
520*e47783fdSXin Li if(start + 0u < size) reader->buffer |= reader->data[start + 0];
521*e47783fdSXin Li if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
522*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
523*e47783fdSXin Li return reader->bp + nbits <= reader->bitsize;
524*e47783fdSXin Li }
525*e47783fdSXin Li }
526*e47783fdSXin Li
527*e47783fdSXin Li /*See ensureBits documentation above. This one ensures up to 25 bits */
ensureBits25(LodePNGBitReader * reader,size_t nbits)528*e47783fdSXin Li static LODEPNG_INLINE unsigned ensureBits25(LodePNGBitReader* reader, size_t nbits) {
529*e47783fdSXin Li size_t start = reader->bp >> 3u;
530*e47783fdSXin Li size_t size = reader->size;
531*e47783fdSXin Li if(start + 3u < size) {
532*e47783fdSXin Li reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
533*e47783fdSXin Li ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u);
534*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
535*e47783fdSXin Li return 1;
536*e47783fdSXin Li } else {
537*e47783fdSXin Li reader->buffer = 0;
538*e47783fdSXin Li if(start + 0u < size) reader->buffer |= reader->data[start + 0];
539*e47783fdSXin Li if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
540*e47783fdSXin Li if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u);
541*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
542*e47783fdSXin Li return reader->bp + nbits <= reader->bitsize;
543*e47783fdSXin Li }
544*e47783fdSXin Li }
545*e47783fdSXin Li
546*e47783fdSXin Li /*See ensureBits documentation above. This one ensures up to 32 bits */
ensureBits32(LodePNGBitReader * reader,size_t nbits)547*e47783fdSXin Li static LODEPNG_INLINE unsigned ensureBits32(LodePNGBitReader* reader, size_t nbits) {
548*e47783fdSXin Li size_t start = reader->bp >> 3u;
549*e47783fdSXin Li size_t size = reader->size;
550*e47783fdSXin Li if(start + 4u < size) {
551*e47783fdSXin Li reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
552*e47783fdSXin Li ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u);
553*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
554*e47783fdSXin Li reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u)));
555*e47783fdSXin Li return 1;
556*e47783fdSXin Li } else {
557*e47783fdSXin Li reader->buffer = 0;
558*e47783fdSXin Li if(start + 0u < size) reader->buffer |= reader->data[start + 0];
559*e47783fdSXin Li if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
560*e47783fdSXin Li if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u);
561*e47783fdSXin Li if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u);
562*e47783fdSXin Li reader->buffer >>= (reader->bp & 7u);
563*e47783fdSXin Li return reader->bp + nbits <= reader->bitsize;
564*e47783fdSXin Li }
565*e47783fdSXin Li }
566*e47783fdSXin Li
567*e47783fdSXin Li /* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */
peekBits(LodePNGBitReader * reader,size_t nbits)568*e47783fdSXin Li static unsigned peekBits(LodePNGBitReader* reader, size_t nbits) {
569*e47783fdSXin Li /* The shift allows nbits to be only up to 31. */
570*e47783fdSXin Li return reader->buffer & ((1u << nbits) - 1u);
571*e47783fdSXin Li }
572*e47783fdSXin Li
573*e47783fdSXin Li /* Must have enough bits available with ensureBits */
advanceBits(LodePNGBitReader * reader,size_t nbits)574*e47783fdSXin Li static void advanceBits(LodePNGBitReader* reader, size_t nbits) {
575*e47783fdSXin Li reader->buffer >>= nbits;
576*e47783fdSXin Li reader->bp += nbits;
577*e47783fdSXin Li }
578*e47783fdSXin Li
579*e47783fdSXin Li /* Must have enough bits available with ensureBits */
readBits(LodePNGBitReader * reader,size_t nbits)580*e47783fdSXin Li static unsigned readBits(LodePNGBitReader* reader, size_t nbits) {
581*e47783fdSXin Li unsigned result = peekBits(reader, nbits);
582*e47783fdSXin Li advanceBits(reader, nbits);
583*e47783fdSXin Li return result;
584*e47783fdSXin Li }
585*e47783fdSXin Li
586*e47783fdSXin Li /* Public for testing only. steps and result must have numsteps values. */
lode_png_test_bitreader(const unsigned char * data,size_t size,size_t numsteps,const size_t * steps,unsigned * result)587*e47783fdSXin Li unsigned lode_png_test_bitreader(const unsigned char* data, size_t size,
588*e47783fdSXin Li size_t numsteps, const size_t* steps, unsigned* result) {
589*e47783fdSXin Li size_t i;
590*e47783fdSXin Li LodePNGBitReader reader;
591*e47783fdSXin Li unsigned error = LodePNGBitReader_init(&reader, data, size);
592*e47783fdSXin Li if(error) return 0;
593*e47783fdSXin Li for(i = 0; i < numsteps; i++) {
594*e47783fdSXin Li size_t step = steps[i];
595*e47783fdSXin Li unsigned ok;
596*e47783fdSXin Li if(step > 25) ok = ensureBits32(&reader, step);
597*e47783fdSXin Li else if(step > 17) ok = ensureBits25(&reader, step);
598*e47783fdSXin Li else if(step > 9) ok = ensureBits17(&reader, step);
599*e47783fdSXin Li else ok = ensureBits9(&reader, step);
600*e47783fdSXin Li if(!ok) return 0;
601*e47783fdSXin Li result[i] = readBits(&reader, step);
602*e47783fdSXin Li }
603*e47783fdSXin Li return 1;
604*e47783fdSXin Li }
605*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
606*e47783fdSXin Li
reverseBits(unsigned bits,unsigned num)607*e47783fdSXin Li static unsigned reverseBits(unsigned bits, unsigned num) {
608*e47783fdSXin Li /*TODO: implement faster lookup table based version when needed*/
609*e47783fdSXin Li unsigned i, result = 0;
610*e47783fdSXin Li for(i = 0; i < num; i++) result |= ((bits >> (num - i - 1u)) & 1u) << i;
611*e47783fdSXin Li return result;
612*e47783fdSXin Li }
613*e47783fdSXin Li
614*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
615*e47783fdSXin Li /* / Deflate - Huffman / */
616*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
617*e47783fdSXin Li
618*e47783fdSXin Li #define FIRST_LENGTH_CODE_INDEX 257
619*e47783fdSXin Li #define LAST_LENGTH_CODE_INDEX 285
620*e47783fdSXin Li /*256 literals, the end code, some length codes, and 2 unused codes*/
621*e47783fdSXin Li #define NUM_DEFLATE_CODE_SYMBOLS 288
622*e47783fdSXin Li /*the distance codes have their own symbols, 30 used, 2 unused*/
623*e47783fdSXin Li #define NUM_DISTANCE_SYMBOLS 32
624*e47783fdSXin Li /*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/
625*e47783fdSXin Li #define NUM_CODE_LENGTH_CODES 19
626*e47783fdSXin Li
627*e47783fdSXin Li /*the base lengths represented by codes 257-285*/
628*e47783fdSXin Li static const unsigned LENGTHBASE[29]
629*e47783fdSXin Li = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
630*e47783fdSXin Li 67, 83, 99, 115, 131, 163, 195, 227, 258};
631*e47783fdSXin Li
632*e47783fdSXin Li /*the extra bits used by codes 257-285 (added to base length)*/
633*e47783fdSXin Li static const unsigned LENGTHEXTRA[29]
634*e47783fdSXin Li = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
635*e47783fdSXin Li 4, 4, 4, 4, 5, 5, 5, 5, 0};
636*e47783fdSXin Li
637*e47783fdSXin Li /*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/
638*e47783fdSXin Li static const unsigned DISTANCEBASE[30]
639*e47783fdSXin Li = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
640*e47783fdSXin Li 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
641*e47783fdSXin Li
642*e47783fdSXin Li /*the extra bits of backwards distances (added to base)*/
643*e47783fdSXin Li static const unsigned DISTANCEEXTRA[30]
644*e47783fdSXin Li = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
645*e47783fdSXin Li 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
646*e47783fdSXin Li
647*e47783fdSXin Li /*the order in which "code length alphabet code lengths" are stored as specified by deflate, out of this the huffman
648*e47783fdSXin Li tree of the dynamic huffman tree lengths is generated*/
649*e47783fdSXin Li static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES]
650*e47783fdSXin Li = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
651*e47783fdSXin Li
652*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
653*e47783fdSXin Li
654*e47783fdSXin Li /*
655*e47783fdSXin Li Huffman tree struct, containing multiple representations of the tree
656*e47783fdSXin Li */
657*e47783fdSXin Li typedef struct HuffmanTree {
658*e47783fdSXin Li unsigned* codes; /*the huffman codes (bit patterns representing the symbols)*/
659*e47783fdSXin Li unsigned* lengths; /*the lengths of the huffman codes*/
660*e47783fdSXin Li unsigned maxbitlen; /*maximum number of bits a single code can get*/
661*e47783fdSXin Li unsigned numcodes; /*number of symbols in the alphabet = number of codes*/
662*e47783fdSXin Li /* for reading only */
663*e47783fdSXin Li unsigned char* table_len; /*length of symbol from lookup table, or max length if secondary lookup needed*/
664*e47783fdSXin Li unsigned short* table_value; /*value of symbol from lookup table, or pointer to secondary table if needed*/
665*e47783fdSXin Li } HuffmanTree;
666*e47783fdSXin Li
HuffmanTree_init(HuffmanTree * tree)667*e47783fdSXin Li static void HuffmanTree_init(HuffmanTree* tree) {
668*e47783fdSXin Li tree->codes = 0;
669*e47783fdSXin Li tree->lengths = 0;
670*e47783fdSXin Li tree->table_len = 0;
671*e47783fdSXin Li tree->table_value = 0;
672*e47783fdSXin Li }
673*e47783fdSXin Li
HuffmanTree_cleanup(HuffmanTree * tree)674*e47783fdSXin Li static void HuffmanTree_cleanup(HuffmanTree* tree) {
675*e47783fdSXin Li lodepng_free(tree->codes);
676*e47783fdSXin Li lodepng_free(tree->lengths);
677*e47783fdSXin Li lodepng_free(tree->table_len);
678*e47783fdSXin Li lodepng_free(tree->table_value);
679*e47783fdSXin Li }
680*e47783fdSXin Li
681*e47783fdSXin Li /* amount of bits for first huffman table lookup (aka root bits), see HuffmanTree_makeTable and huffmanDecodeSymbol.*/
682*e47783fdSXin Li /* values 8u and 9u work the fastest */
683*e47783fdSXin Li #define FIRSTBITS 9u
684*e47783fdSXin Li
685*e47783fdSXin Li /* a symbol value too big to represent any valid symbol, to indicate reading disallowed huffman bits combination,
686*e47783fdSXin Li which is possible in case of only 0 or 1 present symbols. */
687*e47783fdSXin Li #define INVALIDSYMBOL 65535u
688*e47783fdSXin Li
689*e47783fdSXin Li /* make table for huffman decoding */
HuffmanTree_makeTable(HuffmanTree * tree)690*e47783fdSXin Li static unsigned HuffmanTree_makeTable(HuffmanTree* tree) {
691*e47783fdSXin Li static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/
692*e47783fdSXin Li static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u;
693*e47783fdSXin Li size_t i, numpresent, pointer, size; /*total table size*/
694*e47783fdSXin Li unsigned* maxlens = (unsigned*)lodepng_malloc(headsize * sizeof(unsigned));
695*e47783fdSXin Li if(!maxlens) return 83; /*alloc fail*/
696*e47783fdSXin Li
697*e47783fdSXin Li /* compute maxlens: max total bit length of symbols sharing prefix in the first table*/
698*e47783fdSXin Li lodepng_memset(maxlens, 0, headsize * sizeof(*maxlens));
699*e47783fdSXin Li for(i = 0; i < tree->numcodes; i++) {
700*e47783fdSXin Li unsigned symbol = tree->codes[i];
701*e47783fdSXin Li unsigned l = tree->lengths[i];
702*e47783fdSXin Li unsigned index;
703*e47783fdSXin Li if(l <= FIRSTBITS) continue; /*symbols that fit in first table don't increase secondary table size*/
704*e47783fdSXin Li /*get the FIRSTBITS MSBs, the MSBs of the symbol are encoded first. See later comment about the reversing*/
705*e47783fdSXin Li index = reverseBits(symbol >> (l - FIRSTBITS), FIRSTBITS);
706*e47783fdSXin Li maxlens[index] = LODEPNG_MAX(maxlens[index], l);
707*e47783fdSXin Li }
708*e47783fdSXin Li /* compute total table size: size of first table plus all secondary tables for symbols longer than FIRSTBITS */
709*e47783fdSXin Li size = headsize;
710*e47783fdSXin Li for(i = 0; i < headsize; ++i) {
711*e47783fdSXin Li unsigned l = maxlens[i];
712*e47783fdSXin Li if(l > FIRSTBITS) size += (1u << (l - FIRSTBITS));
713*e47783fdSXin Li }
714*e47783fdSXin Li tree->table_len = (unsigned char*)lodepng_malloc(size * sizeof(*tree->table_len));
715*e47783fdSXin Li tree->table_value = (unsigned short*)lodepng_malloc(size * sizeof(*tree->table_value));
716*e47783fdSXin Li if(!tree->table_len || !tree->table_value) {
717*e47783fdSXin Li lodepng_free(maxlens);
718*e47783fdSXin Li /* freeing tree->table values is done at a higher scope */
719*e47783fdSXin Li return 83; /*alloc fail*/
720*e47783fdSXin Li }
721*e47783fdSXin Li /*initialize with an invalid length to indicate unused entries*/
722*e47783fdSXin Li for(i = 0; i < size; ++i) tree->table_len[i] = 16;
723*e47783fdSXin Li
724*e47783fdSXin Li /*fill in the first table for long symbols: max prefix size and pointer to secondary tables*/
725*e47783fdSXin Li pointer = headsize;
726*e47783fdSXin Li for(i = 0; i < headsize; ++i) {
727*e47783fdSXin Li unsigned l = maxlens[i];
728*e47783fdSXin Li if(l <= FIRSTBITS) continue;
729*e47783fdSXin Li tree->table_len[i] = l;
730*e47783fdSXin Li tree->table_value[i] = pointer;
731*e47783fdSXin Li pointer += (1u << (l - FIRSTBITS));
732*e47783fdSXin Li }
733*e47783fdSXin Li lodepng_free(maxlens);
734*e47783fdSXin Li
735*e47783fdSXin Li /*fill in the first table for short symbols, or secondary table for long symbols*/
736*e47783fdSXin Li numpresent = 0;
737*e47783fdSXin Li for(i = 0; i < tree->numcodes; ++i) {
738*e47783fdSXin Li unsigned l = tree->lengths[i];
739*e47783fdSXin Li unsigned symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/
740*e47783fdSXin Li /*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/
741*e47783fdSXin Li unsigned reverse = reverseBits(symbol, l);
742*e47783fdSXin Li if(l == 0) continue;
743*e47783fdSXin Li numpresent++;
744*e47783fdSXin Li
745*e47783fdSXin Li if(l <= FIRSTBITS) {
746*e47783fdSXin Li /*short symbol, fully in first table, replicated num times if l < FIRSTBITS*/
747*e47783fdSXin Li unsigned num = 1u << (FIRSTBITS - l);
748*e47783fdSXin Li unsigned j;
749*e47783fdSXin Li for(j = 0; j < num; ++j) {
750*e47783fdSXin Li /*bit reader will read the l bits of symbol first, the remaining FIRSTBITS - l bits go to the MSB's*/
751*e47783fdSXin Li unsigned index = reverse | (j << l);
752*e47783fdSXin Li if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/
753*e47783fdSXin Li tree->table_len[index] = l;
754*e47783fdSXin Li tree->table_value[index] = i;
755*e47783fdSXin Li }
756*e47783fdSXin Li } else {
757*e47783fdSXin Li /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/
758*e47783fdSXin Li /*the FIRSTBITS MSBs of the symbol are the first table index*/
759*e47783fdSXin Li unsigned index = reverse & mask;
760*e47783fdSXin Li unsigned maxlen = tree->table_len[index];
761*e47783fdSXin Li /*log2 of secondary table length, should be >= l - FIRSTBITS*/
762*e47783fdSXin Li unsigned tablelen = maxlen - FIRSTBITS;
763*e47783fdSXin Li unsigned start = tree->table_value[index]; /*starting index in secondary table*/
764*e47783fdSXin Li unsigned num = 1u << (tablelen - (l - FIRSTBITS)); /*amount of entries of this symbol in secondary table*/
765*e47783fdSXin Li unsigned j;
766*e47783fdSXin Li if(maxlen < l) return 55; /*invalid tree: long symbol shares prefix with short symbol*/
767*e47783fdSXin Li for(j = 0; j < num; ++j) {
768*e47783fdSXin Li unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */
769*e47783fdSXin Li unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS)));
770*e47783fdSXin Li tree->table_len[index2] = l;
771*e47783fdSXin Li tree->table_value[index2] = i;
772*e47783fdSXin Li }
773*e47783fdSXin Li }
774*e47783fdSXin Li }
775*e47783fdSXin Li
776*e47783fdSXin Li if(numpresent < 2) {
777*e47783fdSXin Li /* In case of exactly 1 symbol, in theory the huffman symbol needs 0 bits,
778*e47783fdSXin Li but deflate uses 1 bit instead. In case of 0 symbols, no symbols can
779*e47783fdSXin Li appear at all, but such huffman tree could still exist (e.g. if distance
780*e47783fdSXin Li codes are never used). In both cases, not all symbols of the table will be
781*e47783fdSXin Li filled in. Fill them in with an invalid symbol value so returning them from
782*e47783fdSXin Li huffmanDecodeSymbol will cause error. */
783*e47783fdSXin Li for(i = 0; i < size; ++i) {
784*e47783fdSXin Li if(tree->table_len[i] == 16) {
785*e47783fdSXin Li /* As length, use a value smaller than FIRSTBITS for the head table,
786*e47783fdSXin Li and a value larger than FIRSTBITS for the secondary table, to ensure
787*e47783fdSXin Li valid behavior for advanceBits when reading this symbol. */
788*e47783fdSXin Li tree->table_len[i] = (i < headsize) ? 1 : (FIRSTBITS + 1);
789*e47783fdSXin Li tree->table_value[i] = INVALIDSYMBOL;
790*e47783fdSXin Li }
791*e47783fdSXin Li }
792*e47783fdSXin Li } else {
793*e47783fdSXin Li /* A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes.
794*e47783fdSXin Li If that is not the case (due to too long length codes), the table will not
795*e47783fdSXin Li have been fully used, and this is an error (not all bit combinations can be
796*e47783fdSXin Li decoded): an oversubscribed huffman tree, indicated by error 55. */
797*e47783fdSXin Li for(i = 0; i < size; ++i) {
798*e47783fdSXin Li if(tree->table_len[i] == 16) return 55;
799*e47783fdSXin Li }
800*e47783fdSXin Li }
801*e47783fdSXin Li
802*e47783fdSXin Li return 0;
803*e47783fdSXin Li }
804*e47783fdSXin Li
805*e47783fdSXin Li /*
806*e47783fdSXin Li Second step for the ...makeFromLengths and ...makeFromFrequencies functions.
807*e47783fdSXin Li numcodes, lengths and maxbitlen must already be filled in correctly. return
808*e47783fdSXin Li value is error.
809*e47783fdSXin Li */
HuffmanTree_makeFromLengths2(HuffmanTree * tree)810*e47783fdSXin Li static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) {
811*e47783fdSXin Li unsigned* blcount;
812*e47783fdSXin Li unsigned* nextcode;
813*e47783fdSXin Li unsigned error = 0;
814*e47783fdSXin Li unsigned bits, n;
815*e47783fdSXin Li
816*e47783fdSXin Li tree->codes = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned));
817*e47783fdSXin Li blcount = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned));
818*e47783fdSXin Li nextcode = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned));
819*e47783fdSXin Li if(!tree->codes || !blcount || !nextcode) error = 83; /*alloc fail*/
820*e47783fdSXin Li
821*e47783fdSXin Li if(!error) {
822*e47783fdSXin Li for(n = 0; n != tree->maxbitlen + 1; n++) blcount[n] = nextcode[n] = 0;
823*e47783fdSXin Li /*step 1: count number of instances of each code length*/
824*e47783fdSXin Li for(bits = 0; bits != tree->numcodes; ++bits) ++blcount[tree->lengths[bits]];
825*e47783fdSXin Li /*step 2: generate the nextcode values*/
826*e47783fdSXin Li for(bits = 1; bits <= tree->maxbitlen; ++bits) {
827*e47783fdSXin Li nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1u;
828*e47783fdSXin Li }
829*e47783fdSXin Li /*step 3: generate all the codes*/
830*e47783fdSXin Li for(n = 0; n != tree->numcodes; ++n) {
831*e47783fdSXin Li if(tree->lengths[n] != 0) {
832*e47783fdSXin Li tree->codes[n] = nextcode[tree->lengths[n]]++;
833*e47783fdSXin Li /*remove superfluous bits from the code*/
834*e47783fdSXin Li tree->codes[n] &= ((1u << tree->lengths[n]) - 1u);
835*e47783fdSXin Li }
836*e47783fdSXin Li }
837*e47783fdSXin Li }
838*e47783fdSXin Li
839*e47783fdSXin Li lodepng_free(blcount);
840*e47783fdSXin Li lodepng_free(nextcode);
841*e47783fdSXin Li
842*e47783fdSXin Li if(!error) error = HuffmanTree_makeTable(tree);
843*e47783fdSXin Li return error;
844*e47783fdSXin Li }
845*e47783fdSXin Li
846*e47783fdSXin Li /*
847*e47783fdSXin Li given the code lengths (as stored in the PNG file), generate the tree as defined
848*e47783fdSXin Li by Deflate. maxbitlen is the maximum bits that a code in the tree can have.
849*e47783fdSXin Li return value is error.
850*e47783fdSXin Li */
HuffmanTree_makeFromLengths(HuffmanTree * tree,const unsigned * bitlen,size_t numcodes,unsigned maxbitlen)851*e47783fdSXin Li static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen,
852*e47783fdSXin Li size_t numcodes, unsigned maxbitlen) {
853*e47783fdSXin Li unsigned i;
854*e47783fdSXin Li tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));
855*e47783fdSXin Li if(!tree->lengths) return 83; /*alloc fail*/
856*e47783fdSXin Li for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i];
857*e47783fdSXin Li tree->numcodes = (unsigned)numcodes; /*number of symbols*/
858*e47783fdSXin Li tree->maxbitlen = maxbitlen;
859*e47783fdSXin Li return HuffmanTree_makeFromLengths2(tree);
860*e47783fdSXin Li }
861*e47783fdSXin Li
862*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
863*e47783fdSXin Li
864*e47783fdSXin Li /*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding",
865*e47783fdSXin Li Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/
866*e47783fdSXin Li
867*e47783fdSXin Li /*chain node for boundary package merge*/
868*e47783fdSXin Li typedef struct BPMNode {
869*e47783fdSXin Li int weight; /*the sum of all weights in this chain*/
870*e47783fdSXin Li unsigned index; /*index of this leaf node (called "count" in the paper)*/
871*e47783fdSXin Li struct BPMNode* tail; /*the next nodes in this chain (null if last)*/
872*e47783fdSXin Li int in_use;
873*e47783fdSXin Li } BPMNode;
874*e47783fdSXin Li
875*e47783fdSXin Li /*lists of chains*/
876*e47783fdSXin Li typedef struct BPMLists {
877*e47783fdSXin Li /*memory pool*/
878*e47783fdSXin Li unsigned memsize;
879*e47783fdSXin Li BPMNode* memory;
880*e47783fdSXin Li unsigned numfree;
881*e47783fdSXin Li unsigned nextfree;
882*e47783fdSXin Li BPMNode** freelist;
883*e47783fdSXin Li /*two heads of lookahead chains per list*/
884*e47783fdSXin Li unsigned listsize;
885*e47783fdSXin Li BPMNode** chains0;
886*e47783fdSXin Li BPMNode** chains1;
887*e47783fdSXin Li } BPMLists;
888*e47783fdSXin Li
889*e47783fdSXin Li /*creates a new chain node with the given parameters, from the memory in the lists */
bpmnode_create(BPMLists * lists,int weight,unsigned index,BPMNode * tail)890*e47783fdSXin Li static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) {
891*e47783fdSXin Li unsigned i;
892*e47783fdSXin Li BPMNode* result;
893*e47783fdSXin Li
894*e47783fdSXin Li /*memory full, so garbage collect*/
895*e47783fdSXin Li if(lists->nextfree >= lists->numfree) {
896*e47783fdSXin Li /*mark only those that are in use*/
897*e47783fdSXin Li for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0;
898*e47783fdSXin Li for(i = 0; i != lists->listsize; ++i) {
899*e47783fdSXin Li BPMNode* node;
900*e47783fdSXin Li for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1;
901*e47783fdSXin Li for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1;
902*e47783fdSXin Li }
903*e47783fdSXin Li /*collect those that are free*/
904*e47783fdSXin Li lists->numfree = 0;
905*e47783fdSXin Li for(i = 0; i != lists->memsize; ++i) {
906*e47783fdSXin Li if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i];
907*e47783fdSXin Li }
908*e47783fdSXin Li lists->nextfree = 0;
909*e47783fdSXin Li }
910*e47783fdSXin Li
911*e47783fdSXin Li result = lists->freelist[lists->nextfree++];
912*e47783fdSXin Li result->weight = weight;
913*e47783fdSXin Li result->index = index;
914*e47783fdSXin Li result->tail = tail;
915*e47783fdSXin Li return result;
916*e47783fdSXin Li }
917*e47783fdSXin Li
918*e47783fdSXin Li /*sort the leaves with stable mergesort*/
bpmnode_sort(BPMNode * leaves,size_t num)919*e47783fdSXin Li static void bpmnode_sort(BPMNode* leaves, size_t num) {
920*e47783fdSXin Li BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num);
921*e47783fdSXin Li size_t width, counter = 0;
922*e47783fdSXin Li for(width = 1; width < num; width *= 2) {
923*e47783fdSXin Li BPMNode* a = (counter & 1) ? mem : leaves;
924*e47783fdSXin Li BPMNode* b = (counter & 1) ? leaves : mem;
925*e47783fdSXin Li size_t p;
926*e47783fdSXin Li for(p = 0; p < num; p += 2 * width) {
927*e47783fdSXin Li size_t q = (p + width > num) ? num : (p + width);
928*e47783fdSXin Li size_t r = (p + 2 * width > num) ? num : (p + 2 * width);
929*e47783fdSXin Li size_t i = p, j = q, k;
930*e47783fdSXin Li for(k = p; k < r; k++) {
931*e47783fdSXin Li if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++];
932*e47783fdSXin Li else b[k] = a[j++];
933*e47783fdSXin Li }
934*e47783fdSXin Li }
935*e47783fdSXin Li counter++;
936*e47783fdSXin Li }
937*e47783fdSXin Li if(counter & 1) lodepng_memcpy(leaves, mem, sizeof(*leaves) * num);
938*e47783fdSXin Li lodepng_free(mem);
939*e47783fdSXin Li }
940*e47783fdSXin Li
941*e47783fdSXin Li /*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/
boundaryPM(BPMLists * lists,BPMNode * leaves,size_t numpresent,int c,int num)942*e47783fdSXin Li static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) {
943*e47783fdSXin Li unsigned lastindex = lists->chains1[c]->index;
944*e47783fdSXin Li
945*e47783fdSXin Li if(c == 0) {
946*e47783fdSXin Li if(lastindex >= numpresent) return;
947*e47783fdSXin Li lists->chains0[c] = lists->chains1[c];
948*e47783fdSXin Li lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0);
949*e47783fdSXin Li } else {
950*e47783fdSXin Li /*sum of the weights of the head nodes of the previous lookahead chains.*/
951*e47783fdSXin Li int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight;
952*e47783fdSXin Li lists->chains0[c] = lists->chains1[c];
953*e47783fdSXin Li if(lastindex < numpresent && sum > leaves[lastindex].weight) {
954*e47783fdSXin Li lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail);
955*e47783fdSXin Li return;
956*e47783fdSXin Li }
957*e47783fdSXin Li lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]);
958*e47783fdSXin Li /*in the end we are only interested in the chain of the last list, so no
959*e47783fdSXin Li need to recurse if we're at the last one (this gives measurable speedup)*/
960*e47783fdSXin Li if(num + 1 < (int)(2 * numpresent - 2)) {
961*e47783fdSXin Li boundaryPM(lists, leaves, numpresent, c - 1, num);
962*e47783fdSXin Li boundaryPM(lists, leaves, numpresent, c - 1, num);
963*e47783fdSXin Li }
964*e47783fdSXin Li }
965*e47783fdSXin Li }
966*e47783fdSXin Li
lodepng_huffman_code_lengths(unsigned * lengths,const unsigned * frequencies,size_t numcodes,unsigned maxbitlen)967*e47783fdSXin Li unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
968*e47783fdSXin Li size_t numcodes, unsigned maxbitlen) {
969*e47783fdSXin Li unsigned error = 0;
970*e47783fdSXin Li unsigned i;
971*e47783fdSXin Li size_t numpresent = 0; /*number of symbols with non-zero frequency*/
972*e47783fdSXin Li BPMNode* leaves; /*the symbols, only those with > 0 frequency*/
973*e47783fdSXin Li
974*e47783fdSXin Li if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/
975*e47783fdSXin Li if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/
976*e47783fdSXin Li
977*e47783fdSXin Li leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves));
978*e47783fdSXin Li if(!leaves) return 83; /*alloc fail*/
979*e47783fdSXin Li
980*e47783fdSXin Li for(i = 0; i != numcodes; ++i) {
981*e47783fdSXin Li if(frequencies[i] > 0) {
982*e47783fdSXin Li leaves[numpresent].weight = (int)frequencies[i];
983*e47783fdSXin Li leaves[numpresent].index = i;
984*e47783fdSXin Li ++numpresent;
985*e47783fdSXin Li }
986*e47783fdSXin Li }
987*e47783fdSXin Li
988*e47783fdSXin Li lodepng_memset(lengths, 0, numcodes * sizeof(*lengths));
989*e47783fdSXin Li
990*e47783fdSXin Li /*ensure at least two present symbols. There should be at least one symbol
991*e47783fdSXin Li according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To
992*e47783fdSXin Li make these work as well ensure there are at least two symbols. The
993*e47783fdSXin Li Package-Merge code below also doesn't work correctly if there's only one
994*e47783fdSXin Li symbol, it'd give it the theoretical 0 bits but in practice zlib wants 1 bit*/
995*e47783fdSXin Li if(numpresent == 0) {
996*e47783fdSXin Li lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/
997*e47783fdSXin Li } else if(numpresent == 1) {
998*e47783fdSXin Li lengths[leaves[0].index] = 1;
999*e47783fdSXin Li lengths[leaves[0].index == 0 ? 1 : 0] = 1;
1000*e47783fdSXin Li } else {
1001*e47783fdSXin Li BPMLists lists;
1002*e47783fdSXin Li BPMNode* node;
1003*e47783fdSXin Li
1004*e47783fdSXin Li bpmnode_sort(leaves, numpresent);
1005*e47783fdSXin Li
1006*e47783fdSXin Li lists.listsize = maxbitlen;
1007*e47783fdSXin Li lists.memsize = 2 * maxbitlen * (maxbitlen + 1);
1008*e47783fdSXin Li lists.nextfree = 0;
1009*e47783fdSXin Li lists.numfree = lists.memsize;
1010*e47783fdSXin Li lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory));
1011*e47783fdSXin Li lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*));
1012*e47783fdSXin Li lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
1013*e47783fdSXin Li lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
1014*e47783fdSXin Li if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/
1015*e47783fdSXin Li
1016*e47783fdSXin Li if(!error) {
1017*e47783fdSXin Li for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i];
1018*e47783fdSXin Li
1019*e47783fdSXin Li bpmnode_create(&lists, leaves[0].weight, 1, 0);
1020*e47783fdSXin Li bpmnode_create(&lists, leaves[1].weight, 2, 0);
1021*e47783fdSXin Li
1022*e47783fdSXin Li for(i = 0; i != lists.listsize; ++i) {
1023*e47783fdSXin Li lists.chains0[i] = &lists.memory[0];
1024*e47783fdSXin Li lists.chains1[i] = &lists.memory[1];
1025*e47783fdSXin Li }
1026*e47783fdSXin Li
1027*e47783fdSXin Li /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/
1028*e47783fdSXin Li for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);
1029*e47783fdSXin Li
1030*e47783fdSXin Li for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) {
1031*e47783fdSXin Li for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index];
1032*e47783fdSXin Li }
1033*e47783fdSXin Li }
1034*e47783fdSXin Li
1035*e47783fdSXin Li lodepng_free(lists.memory);
1036*e47783fdSXin Li lodepng_free(lists.freelist);
1037*e47783fdSXin Li lodepng_free(lists.chains0);
1038*e47783fdSXin Li lodepng_free(lists.chains1);
1039*e47783fdSXin Li }
1040*e47783fdSXin Li
1041*e47783fdSXin Li lodepng_free(leaves);
1042*e47783fdSXin Li return error;
1043*e47783fdSXin Li }
1044*e47783fdSXin Li
1045*e47783fdSXin Li /*Create the Huffman tree given the symbol frequencies*/
HuffmanTree_makeFromFrequencies(HuffmanTree * tree,const unsigned * frequencies,size_t mincodes,size_t numcodes,unsigned maxbitlen)1046*e47783fdSXin Li static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,
1047*e47783fdSXin Li size_t mincodes, size_t numcodes, unsigned maxbitlen) {
1048*e47783fdSXin Li unsigned error = 0;
1049*e47783fdSXin Li while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/
1050*e47783fdSXin Li tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));
1051*e47783fdSXin Li if(!tree->lengths) return 83; /*alloc fail*/
1052*e47783fdSXin Li tree->maxbitlen = maxbitlen;
1053*e47783fdSXin Li tree->numcodes = (unsigned)numcodes; /*number of symbols*/
1054*e47783fdSXin Li
1055*e47783fdSXin Li error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen);
1056*e47783fdSXin Li if(!error) error = HuffmanTree_makeFromLengths2(tree);
1057*e47783fdSXin Li return error;
1058*e47783fdSXin Li }
1059*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
1060*e47783fdSXin Li
1061*e47783fdSXin Li /*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/
generateFixedLitLenTree(HuffmanTree * tree)1062*e47783fdSXin Li static unsigned generateFixedLitLenTree(HuffmanTree* tree) {
1063*e47783fdSXin Li unsigned i, error = 0;
1064*e47783fdSXin Li unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
1065*e47783fdSXin Li if(!bitlen) return 83; /*alloc fail*/
1066*e47783fdSXin Li
1067*e47783fdSXin Li /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/
1068*e47783fdSXin Li for(i = 0; i <= 143; ++i) bitlen[i] = 8;
1069*e47783fdSXin Li for(i = 144; i <= 255; ++i) bitlen[i] = 9;
1070*e47783fdSXin Li for(i = 256; i <= 279; ++i) bitlen[i] = 7;
1071*e47783fdSXin Li for(i = 280; i <= 287; ++i) bitlen[i] = 8;
1072*e47783fdSXin Li
1073*e47783fdSXin Li error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15);
1074*e47783fdSXin Li
1075*e47783fdSXin Li lodepng_free(bitlen);
1076*e47783fdSXin Li return error;
1077*e47783fdSXin Li }
1078*e47783fdSXin Li
1079*e47783fdSXin Li /*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/
generateFixedDistanceTree(HuffmanTree * tree)1080*e47783fdSXin Li static unsigned generateFixedDistanceTree(HuffmanTree* tree) {
1081*e47783fdSXin Li unsigned i, error = 0;
1082*e47783fdSXin Li unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
1083*e47783fdSXin Li if(!bitlen) return 83; /*alloc fail*/
1084*e47783fdSXin Li
1085*e47783fdSXin Li /*there are 32 distance codes, but 30-31 are unused*/
1086*e47783fdSXin Li for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5;
1087*e47783fdSXin Li error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15);
1088*e47783fdSXin Li
1089*e47783fdSXin Li lodepng_free(bitlen);
1090*e47783fdSXin Li return error;
1091*e47783fdSXin Li }
1092*e47783fdSXin Li
1093*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
1094*e47783fdSXin Li
1095*e47783fdSXin Li /*
1096*e47783fdSXin Li returns the code. The bit reader must already have been ensured at least 15 bits
1097*e47783fdSXin Li */
huffmanDecodeSymbol(LodePNGBitReader * reader,const HuffmanTree * codetree)1098*e47783fdSXin Li static unsigned huffmanDecodeSymbol(LodePNGBitReader* reader, const HuffmanTree* codetree) {
1099*e47783fdSXin Li unsigned short code = peekBits(reader, FIRSTBITS);
1100*e47783fdSXin Li unsigned short l = codetree->table_len[code];
1101*e47783fdSXin Li unsigned short value = codetree->table_value[code];
1102*e47783fdSXin Li if(l <= FIRSTBITS) {
1103*e47783fdSXin Li advanceBits(reader, l);
1104*e47783fdSXin Li return value;
1105*e47783fdSXin Li } else {
1106*e47783fdSXin Li unsigned index2;
1107*e47783fdSXin Li advanceBits(reader, FIRSTBITS);
1108*e47783fdSXin Li index2 = value + peekBits(reader, l - FIRSTBITS);
1109*e47783fdSXin Li advanceBits(reader, codetree->table_len[index2] - FIRSTBITS);
1110*e47783fdSXin Li return codetree->table_value[index2];
1111*e47783fdSXin Li }
1112*e47783fdSXin Li }
1113*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
1114*e47783fdSXin Li
1115*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
1116*e47783fdSXin Li
1117*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
1118*e47783fdSXin Li /* / Inflator (Decompressor) / */
1119*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
1120*e47783fdSXin Li
1121*e47783fdSXin Li /*get the tree of a deflated block with fixed tree, as specified in the deflate specification
1122*e47783fdSXin Li Returns error code.*/
getTreeInflateFixed(HuffmanTree * tree_ll,HuffmanTree * tree_d)1123*e47783fdSXin Li static unsigned getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) {
1124*e47783fdSXin Li unsigned error = generateFixedLitLenTree(tree_ll);
1125*e47783fdSXin Li if(error) return error;
1126*e47783fdSXin Li return generateFixedDistanceTree(tree_d);
1127*e47783fdSXin Li }
1128*e47783fdSXin Li
1129*e47783fdSXin Li /*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/
getTreeInflateDynamic(HuffmanTree * tree_ll,HuffmanTree * tree_d,LodePNGBitReader * reader)1130*e47783fdSXin Li static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
1131*e47783fdSXin Li LodePNGBitReader* reader) {
1132*e47783fdSXin Li /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/
1133*e47783fdSXin Li unsigned error = 0;
1134*e47783fdSXin Li unsigned n, HLIT, HDIST, HCLEN, i;
1135*e47783fdSXin Li
1136*e47783fdSXin Li /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/
1137*e47783fdSXin Li unsigned* bitlen_ll = 0; /*lit,len code lengths*/
1138*e47783fdSXin Li unsigned* bitlen_d = 0; /*dist code lengths*/
1139*e47783fdSXin Li /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/
1140*e47783fdSXin Li unsigned* bitlen_cl = 0;
1141*e47783fdSXin Li HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
1142*e47783fdSXin Li
1143*e47783fdSXin Li if(!ensureBits17(reader, 14)) return 49; /*error: the bit pointer is or will go past the memory*/
1144*e47783fdSXin Li
1145*e47783fdSXin Li /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
1146*e47783fdSXin Li HLIT = readBits(reader, 5) + 257;
1147*e47783fdSXin Li /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/
1148*e47783fdSXin Li HDIST = readBits(reader, 5) + 1;
1149*e47783fdSXin Li /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/
1150*e47783fdSXin Li HCLEN = readBits(reader, 4) + 4;
1151*e47783fdSXin Li
1152*e47783fdSXin Li bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));
1153*e47783fdSXin Li if(!bitlen_cl) return 83 /*alloc fail*/;
1154*e47783fdSXin Li
1155*e47783fdSXin Li HuffmanTree_init(&tree_cl);
1156*e47783fdSXin Li
1157*e47783fdSXin Li while(!error) {
1158*e47783fdSXin Li /*read the code length codes out of 3 * (amount of code length codes) bits*/
1159*e47783fdSXin Li if(lodepng_gtofl(reader->bp, HCLEN * 3, reader->bitsize)) {
1160*e47783fdSXin Li ERROR_BREAK(50); /*error: the bit pointer is or will go past the memory*/
1161*e47783fdSXin Li }
1162*e47783fdSXin Li for(i = 0; i != HCLEN; ++i) {
1163*e47783fdSXin Li ensureBits9(reader, 3); /*out of bounds already checked above */
1164*e47783fdSXin Li bitlen_cl[CLCL_ORDER[i]] = readBits(reader, 3);
1165*e47783fdSXin Li }
1166*e47783fdSXin Li for(i = HCLEN; i != NUM_CODE_LENGTH_CODES; ++i) {
1167*e47783fdSXin Li bitlen_cl[CLCL_ORDER[i]] = 0;
1168*e47783fdSXin Li }
1169*e47783fdSXin Li
1170*e47783fdSXin Li error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7);
1171*e47783fdSXin Li if(error) break;
1172*e47783fdSXin Li
1173*e47783fdSXin Li /*now we can use this tree to read the lengths for the tree that this function will return*/
1174*e47783fdSXin Li bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
1175*e47783fdSXin Li bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
1176*e47783fdSXin Li if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/);
1177*e47783fdSXin Li lodepng_memset(bitlen_ll, 0, NUM_DEFLATE_CODE_SYMBOLS * sizeof(*bitlen_ll));
1178*e47783fdSXin Li lodepng_memset(bitlen_d, 0, NUM_DISTANCE_SYMBOLS * sizeof(*bitlen_d));
1179*e47783fdSXin Li
1180*e47783fdSXin Li /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/
1181*e47783fdSXin Li i = 0;
1182*e47783fdSXin Li while(i < HLIT + HDIST) {
1183*e47783fdSXin Li unsigned code;
1184*e47783fdSXin Li ensureBits25(reader, 22); /* up to 15 bits for huffman code, up to 7 extra bits below*/
1185*e47783fdSXin Li code = huffmanDecodeSymbol(reader, &tree_cl);
1186*e47783fdSXin Li if(code <= 15) /*a length code*/ {
1187*e47783fdSXin Li if(i < HLIT) bitlen_ll[i] = code;
1188*e47783fdSXin Li else bitlen_d[i - HLIT] = code;
1189*e47783fdSXin Li ++i;
1190*e47783fdSXin Li } else if(code == 16) /*repeat previous*/ {
1191*e47783fdSXin Li unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/
1192*e47783fdSXin Li unsigned value; /*set value to the previous code*/
1193*e47783fdSXin Li
1194*e47783fdSXin Li if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/
1195*e47783fdSXin Li
1196*e47783fdSXin Li replength += readBits(reader, 2);
1197*e47783fdSXin Li
1198*e47783fdSXin Li if(i < HLIT + 1) value = bitlen_ll[i - 1];
1199*e47783fdSXin Li else value = bitlen_d[i - HLIT - 1];
1200*e47783fdSXin Li /*repeat this value in the next lengths*/
1201*e47783fdSXin Li for(n = 0; n < replength; ++n) {
1202*e47783fdSXin Li if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/
1203*e47783fdSXin Li if(i < HLIT) bitlen_ll[i] = value;
1204*e47783fdSXin Li else bitlen_d[i - HLIT] = value;
1205*e47783fdSXin Li ++i;
1206*e47783fdSXin Li }
1207*e47783fdSXin Li } else if(code == 17) /*repeat "0" 3-10 times*/ {
1208*e47783fdSXin Li unsigned replength = 3; /*read in the bits that indicate repeat length*/
1209*e47783fdSXin Li replength += readBits(reader, 3);
1210*e47783fdSXin Li
1211*e47783fdSXin Li /*repeat this value in the next lengths*/
1212*e47783fdSXin Li for(n = 0; n < replength; ++n) {
1213*e47783fdSXin Li if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/
1214*e47783fdSXin Li
1215*e47783fdSXin Li if(i < HLIT) bitlen_ll[i] = 0;
1216*e47783fdSXin Li else bitlen_d[i - HLIT] = 0;
1217*e47783fdSXin Li ++i;
1218*e47783fdSXin Li }
1219*e47783fdSXin Li } else if(code == 18) /*repeat "0" 11-138 times*/ {
1220*e47783fdSXin Li unsigned replength = 11; /*read in the bits that indicate repeat length*/
1221*e47783fdSXin Li replength += readBits(reader, 7);
1222*e47783fdSXin Li
1223*e47783fdSXin Li /*repeat this value in the next lengths*/
1224*e47783fdSXin Li for(n = 0; n < replength; ++n) {
1225*e47783fdSXin Li if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/
1226*e47783fdSXin Li
1227*e47783fdSXin Li if(i < HLIT) bitlen_ll[i] = 0;
1228*e47783fdSXin Li else bitlen_d[i - HLIT] = 0;
1229*e47783fdSXin Li ++i;
1230*e47783fdSXin Li }
1231*e47783fdSXin Li } else /*if(code == INVALIDSYMBOL)*/ {
1232*e47783fdSXin Li ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/
1233*e47783fdSXin Li }
1234*e47783fdSXin Li /*check if any of the ensureBits above went out of bounds*/
1235*e47783fdSXin Li if(reader->bp > reader->bitsize) {
1236*e47783fdSXin Li /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
1237*e47783fdSXin Li (10=no endcode, 11=wrong jump outside of tree)*/
1238*e47783fdSXin Li /* TODO: revise error codes 10,11,50: the above comment is no longer valid */
1239*e47783fdSXin Li ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
1240*e47783fdSXin Li }
1241*e47783fdSXin Li }
1242*e47783fdSXin Li if(error) break;
1243*e47783fdSXin Li
1244*e47783fdSXin Li if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/
1245*e47783fdSXin Li
1246*e47783fdSXin Li /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/
1247*e47783fdSXin Li error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15);
1248*e47783fdSXin Li if(error) break;
1249*e47783fdSXin Li error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15);
1250*e47783fdSXin Li
1251*e47783fdSXin Li break; /*end of error-while*/
1252*e47783fdSXin Li }
1253*e47783fdSXin Li
1254*e47783fdSXin Li lodepng_free(bitlen_cl);
1255*e47783fdSXin Li lodepng_free(bitlen_ll);
1256*e47783fdSXin Li lodepng_free(bitlen_d);
1257*e47783fdSXin Li HuffmanTree_cleanup(&tree_cl);
1258*e47783fdSXin Li
1259*e47783fdSXin Li return error;
1260*e47783fdSXin Li }
1261*e47783fdSXin Li
1262*e47783fdSXin Li /*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
inflateHuffmanBlock(ucvector * out,LodePNGBitReader * reader,unsigned btype,size_t max_output_size)1263*e47783fdSXin Li static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
1264*e47783fdSXin Li unsigned btype, size_t max_output_size) {
1265*e47783fdSXin Li unsigned error = 0;
1266*e47783fdSXin Li HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
1267*e47783fdSXin Li HuffmanTree tree_d; /*the huffman tree for distance codes*/
1268*e47783fdSXin Li
1269*e47783fdSXin Li HuffmanTree_init(&tree_ll);
1270*e47783fdSXin Li HuffmanTree_init(&tree_d);
1271*e47783fdSXin Li
1272*e47783fdSXin Li if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d);
1273*e47783fdSXin Li else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader);
1274*e47783fdSXin Li
1275*e47783fdSXin Li while(!error) /*decode all symbols until end reached, breaks at end code*/ {
1276*e47783fdSXin Li /*code_ll is literal, length or end code*/
1277*e47783fdSXin Li unsigned code_ll;
1278*e47783fdSXin Li ensureBits25(reader, 20); /* up to 15 for the huffman symbol, up to 5 for the length extra bits */
1279*e47783fdSXin Li code_ll = huffmanDecodeSymbol(reader, &tree_ll);
1280*e47783fdSXin Li if(code_ll <= 255) /*literal symbol*/ {
1281*e47783fdSXin Li if(!ucvector_resize(out, out->size + 1)) ERROR_BREAK(83 /*alloc fail*/);
1282*e47783fdSXin Li out->data[out->size - 1] = (unsigned char)code_ll;
1283*e47783fdSXin Li } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ {
1284*e47783fdSXin Li unsigned code_d, distance;
1285*e47783fdSXin Li unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
1286*e47783fdSXin Li size_t start, backward, length;
1287*e47783fdSXin Li
1288*e47783fdSXin Li /*part 1: get length base*/
1289*e47783fdSXin Li length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];
1290*e47783fdSXin Li
1291*e47783fdSXin Li /*part 2: get extra bits and add the value of that to length*/
1292*e47783fdSXin Li numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
1293*e47783fdSXin Li if(numextrabits_l != 0) {
1294*e47783fdSXin Li /* bits already ensured above */
1295*e47783fdSXin Li length += readBits(reader, numextrabits_l);
1296*e47783fdSXin Li }
1297*e47783fdSXin Li
1298*e47783fdSXin Li /*part 3: get distance code*/
1299*e47783fdSXin Li ensureBits32(reader, 28); /* up to 15 for the huffman symbol, up to 13 for the extra bits */
1300*e47783fdSXin Li code_d = huffmanDecodeSymbol(reader, &tree_d);
1301*e47783fdSXin Li if(code_d > 29) {
1302*e47783fdSXin Li if(code_d <= 31) {
1303*e47783fdSXin Li ERROR_BREAK(18); /*error: invalid distance code (30-31 are never used)*/
1304*e47783fdSXin Li } else /* if(code_d == INVALIDSYMBOL) */{
1305*e47783fdSXin Li ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/
1306*e47783fdSXin Li }
1307*e47783fdSXin Li }
1308*e47783fdSXin Li distance = DISTANCEBASE[code_d];
1309*e47783fdSXin Li
1310*e47783fdSXin Li /*part 4: get extra bits from distance*/
1311*e47783fdSXin Li numextrabits_d = DISTANCEEXTRA[code_d];
1312*e47783fdSXin Li if(numextrabits_d != 0) {
1313*e47783fdSXin Li /* bits already ensured above */
1314*e47783fdSXin Li distance += readBits(reader, numextrabits_d);
1315*e47783fdSXin Li }
1316*e47783fdSXin Li
1317*e47783fdSXin Li /*part 5: fill in all the out[n] values based on the length and dist*/
1318*e47783fdSXin Li start = out->size;
1319*e47783fdSXin Li if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
1320*e47783fdSXin Li backward = start - distance;
1321*e47783fdSXin Li
1322*e47783fdSXin Li if(!ucvector_resize(out, out->size + length)) ERROR_BREAK(83 /*alloc fail*/);
1323*e47783fdSXin Li if(distance < length) {
1324*e47783fdSXin Li size_t forward;
1325*e47783fdSXin Li lodepng_memcpy(out->data + start, out->data + backward, distance);
1326*e47783fdSXin Li start += distance;
1327*e47783fdSXin Li for(forward = distance; forward < length; ++forward) {
1328*e47783fdSXin Li out->data[start++] = out->data[backward++];
1329*e47783fdSXin Li }
1330*e47783fdSXin Li } else {
1331*e47783fdSXin Li lodepng_memcpy(out->data + start, out->data + backward, length);
1332*e47783fdSXin Li }
1333*e47783fdSXin Li } else if(code_ll == 256) {
1334*e47783fdSXin Li break; /*end code, break the loop*/
1335*e47783fdSXin Li } else /*if(code_ll == INVALIDSYMBOL)*/ {
1336*e47783fdSXin Li ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/
1337*e47783fdSXin Li }
1338*e47783fdSXin Li /*check if any of the ensureBits above went out of bounds*/
1339*e47783fdSXin Li if(reader->bp > reader->bitsize) {
1340*e47783fdSXin Li /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
1341*e47783fdSXin Li (10=no endcode, 11=wrong jump outside of tree)*/
1342*e47783fdSXin Li /* TODO: revise error codes 10,11,50: the above comment is no longer valid */
1343*e47783fdSXin Li ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
1344*e47783fdSXin Li }
1345*e47783fdSXin Li if(max_output_size && out->size > max_output_size) {
1346*e47783fdSXin Li ERROR_BREAK(109); /*error, larger than max size*/
1347*e47783fdSXin Li }
1348*e47783fdSXin Li }
1349*e47783fdSXin Li
1350*e47783fdSXin Li HuffmanTree_cleanup(&tree_ll);
1351*e47783fdSXin Li HuffmanTree_cleanup(&tree_d);
1352*e47783fdSXin Li
1353*e47783fdSXin Li return error;
1354*e47783fdSXin Li }
1355*e47783fdSXin Li
inflateNoCompression(ucvector * out,LodePNGBitReader * reader,const LodePNGDecompressSettings * settings)1356*e47783fdSXin Li static unsigned inflateNoCompression(ucvector* out, LodePNGBitReader* reader,
1357*e47783fdSXin Li const LodePNGDecompressSettings* settings) {
1358*e47783fdSXin Li size_t bytepos;
1359*e47783fdSXin Li size_t size = reader->size;
1360*e47783fdSXin Li unsigned LEN, NLEN, error = 0;
1361*e47783fdSXin Li
1362*e47783fdSXin Li /*go to first boundary of byte*/
1363*e47783fdSXin Li bytepos = (reader->bp + 7u) >> 3u;
1364*e47783fdSXin Li
1365*e47783fdSXin Li /*read LEN (2 bytes) and NLEN (2 bytes)*/
1366*e47783fdSXin Li if(bytepos + 4 >= size) return 52; /*error, bit pointer will jump past memory*/
1367*e47783fdSXin Li LEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2;
1368*e47783fdSXin Li NLEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2;
1369*e47783fdSXin Li
1370*e47783fdSXin Li /*check if 16-bit NLEN is really the one's complement of LEN*/
1371*e47783fdSXin Li if(!settings->ignore_nlen && LEN + NLEN != 65535) {
1372*e47783fdSXin Li return 21; /*error: NLEN is not one's complement of LEN*/
1373*e47783fdSXin Li }
1374*e47783fdSXin Li
1375*e47783fdSXin Li if(!ucvector_resize(out, out->size + LEN)) return 83; /*alloc fail*/
1376*e47783fdSXin Li
1377*e47783fdSXin Li /*read the literal data: LEN bytes are now stored in the out buffer*/
1378*e47783fdSXin Li if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/
1379*e47783fdSXin Li
1380*e47783fdSXin Li lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN);
1381*e47783fdSXin Li bytepos += LEN;
1382*e47783fdSXin Li
1383*e47783fdSXin Li reader->bp = bytepos << 3u;
1384*e47783fdSXin Li
1385*e47783fdSXin Li return error;
1386*e47783fdSXin Li }
1387*e47783fdSXin Li
lodepng_inflatev(ucvector * out,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)1388*e47783fdSXin Li static unsigned lodepng_inflatev(ucvector* out,
1389*e47783fdSXin Li const unsigned char* in, size_t insize,
1390*e47783fdSXin Li const LodePNGDecompressSettings* settings) {
1391*e47783fdSXin Li unsigned BFINAL = 0;
1392*e47783fdSXin Li LodePNGBitReader reader;
1393*e47783fdSXin Li unsigned error = LodePNGBitReader_init(&reader, in, insize);
1394*e47783fdSXin Li
1395*e47783fdSXin Li if(error) return error;
1396*e47783fdSXin Li
1397*e47783fdSXin Li while(!BFINAL) {
1398*e47783fdSXin Li unsigned BTYPE;
1399*e47783fdSXin Li if(!ensureBits9(&reader, 3)) return 52; /*error, bit pointer will jump past memory*/
1400*e47783fdSXin Li BFINAL = readBits(&reader, 1);
1401*e47783fdSXin Li BTYPE = readBits(&reader, 2);
1402*e47783fdSXin Li
1403*e47783fdSXin Li if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
1404*e47783fdSXin Li else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
1405*e47783fdSXin Li else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/
1406*e47783fdSXin Li if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109;
1407*e47783fdSXin Li if(error) break;
1408*e47783fdSXin Li }
1409*e47783fdSXin Li
1410*e47783fdSXin Li return error;
1411*e47783fdSXin Li }
1412*e47783fdSXin Li
lodepng_inflate(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)1413*e47783fdSXin Li unsigned lodepng_inflate(unsigned char** out, size_t* outsize,
1414*e47783fdSXin Li const unsigned char* in, size_t insize,
1415*e47783fdSXin Li const LodePNGDecompressSettings* settings) {
1416*e47783fdSXin Li ucvector v = ucvector_init(*out, *outsize);
1417*e47783fdSXin Li unsigned error = lodepng_inflatev(&v, in, insize, settings);
1418*e47783fdSXin Li *out = v.data;
1419*e47783fdSXin Li *outsize = v.size;
1420*e47783fdSXin Li return error;
1421*e47783fdSXin Li }
1422*e47783fdSXin Li
inflatev(ucvector * out,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)1423*e47783fdSXin Li static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize,
1424*e47783fdSXin Li const LodePNGDecompressSettings* settings) {
1425*e47783fdSXin Li if(settings->custom_inflate) {
1426*e47783fdSXin Li unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
1427*e47783fdSXin Li out->allocsize = out->size;
1428*e47783fdSXin Li if(error) {
1429*e47783fdSXin Li /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/
1430*e47783fdSXin Li error = 110;
1431*e47783fdSXin Li /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
1432*e47783fdSXin Li if(settings->max_output_size && out->size > settings->max_output_size) error = 109;
1433*e47783fdSXin Li }
1434*e47783fdSXin Li return error;
1435*e47783fdSXin Li } else {
1436*e47783fdSXin Li return lodepng_inflatev(out, in, insize, settings);
1437*e47783fdSXin Li }
1438*e47783fdSXin Li }
1439*e47783fdSXin Li
1440*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
1441*e47783fdSXin Li
1442*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
1443*e47783fdSXin Li
1444*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
1445*e47783fdSXin Li /* / Deflator (Compressor) / */
1446*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
1447*e47783fdSXin Li
1448*e47783fdSXin Li static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258;
1449*e47783fdSXin Li
1450*e47783fdSXin Li /*search the index in the array, that has the largest value smaller than or equal to the given value,
1451*e47783fdSXin Li given array must be sorted (if no value is smaller, it returns the size of the given array)*/
searchCodeIndex(const unsigned * array,size_t array_size,size_t value)1452*e47783fdSXin Li static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) {
1453*e47783fdSXin Li /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/
1454*e47783fdSXin Li size_t left = 1;
1455*e47783fdSXin Li size_t right = array_size - 1;
1456*e47783fdSXin Li
1457*e47783fdSXin Li while(left <= right) {
1458*e47783fdSXin Li size_t mid = (left + right) >> 1;
1459*e47783fdSXin Li if(array[mid] >= value) right = mid - 1;
1460*e47783fdSXin Li else left = mid + 1;
1461*e47783fdSXin Li }
1462*e47783fdSXin Li if(left >= array_size || array[left] > value) left--;
1463*e47783fdSXin Li return left;
1464*e47783fdSXin Li }
1465*e47783fdSXin Li
addLengthDistance(uivector * values,size_t length,size_t distance)1466*e47783fdSXin Li static void addLengthDistance(uivector* values, size_t length, size_t distance) {
1467*e47783fdSXin Li /*values in encoded vector are those used by deflate:
1468*e47783fdSXin Li 0-255: literal bytes
1469*e47783fdSXin Li 256: end
1470*e47783fdSXin Li 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits)
1471*e47783fdSXin Li 286-287: invalid*/
1472*e47783fdSXin Li
1473*e47783fdSXin Li unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length);
1474*e47783fdSXin Li unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]);
1475*e47783fdSXin Li unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance);
1476*e47783fdSXin Li unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]);
1477*e47783fdSXin Li
1478*e47783fdSXin Li size_t pos = values->size;
1479*e47783fdSXin Li /*TODO: return error when this fails (out of memory)*/
1480*e47783fdSXin Li unsigned ok = uivector_resize(values, values->size + 4);
1481*e47783fdSXin Li if(ok) {
1482*e47783fdSXin Li values->data[pos + 0] = length_code + FIRST_LENGTH_CODE_INDEX;
1483*e47783fdSXin Li values->data[pos + 1] = extra_length;
1484*e47783fdSXin Li values->data[pos + 2] = dist_code;
1485*e47783fdSXin Li values->data[pos + 3] = extra_distance;
1486*e47783fdSXin Li }
1487*e47783fdSXin Li }
1488*e47783fdSXin Li
1489*e47783fdSXin Li /*3 bytes of data get encoded into two bytes. The hash cannot use more than 3
1490*e47783fdSXin Li bytes as input because 3 is the minimum match length for deflate*/
1491*e47783fdSXin Li static const unsigned HASH_NUM_VALUES = 65536;
1492*e47783fdSXin Li static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/
1493*e47783fdSXin Li
1494*e47783fdSXin Li typedef struct Hash {
1495*e47783fdSXin Li int* head; /*hash value to head circular pos - can be outdated if went around window*/
1496*e47783fdSXin Li /*circular pos to prev circular pos*/
1497*e47783fdSXin Li unsigned short* chain;
1498*e47783fdSXin Li int* val; /*circular pos to hash value*/
1499*e47783fdSXin Li
1500*e47783fdSXin Li /*TODO: do this not only for zeros but for any repeated byte. However for PNG
1501*e47783fdSXin Li it's always going to be the zeros that dominate, so not important for PNG*/
1502*e47783fdSXin Li int* headz; /*similar to head, but for chainz*/
1503*e47783fdSXin Li unsigned short* chainz; /*those with same amount of zeros*/
1504*e47783fdSXin Li unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/
1505*e47783fdSXin Li } Hash;
1506*e47783fdSXin Li
hash_init(Hash * hash,unsigned windowsize)1507*e47783fdSXin Li static unsigned hash_init(Hash* hash, unsigned windowsize) {
1508*e47783fdSXin Li unsigned i;
1509*e47783fdSXin Li hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES);
1510*e47783fdSXin Li hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize);
1511*e47783fdSXin Li hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
1512*e47783fdSXin Li
1513*e47783fdSXin Li hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
1514*e47783fdSXin Li hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1));
1515*e47783fdSXin Li hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
1516*e47783fdSXin Li
1517*e47783fdSXin Li if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) {
1518*e47783fdSXin Li return 83; /*alloc fail*/
1519*e47783fdSXin Li }
1520*e47783fdSXin Li
1521*e47783fdSXin Li /*initialize hash table*/
1522*e47783fdSXin Li for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1;
1523*e47783fdSXin Li for(i = 0; i != windowsize; ++i) hash->val[i] = -1;
1524*e47783fdSXin Li for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/
1525*e47783fdSXin Li
1526*e47783fdSXin Li for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1;
1527*e47783fdSXin Li for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/
1528*e47783fdSXin Li
1529*e47783fdSXin Li return 0;
1530*e47783fdSXin Li }
1531*e47783fdSXin Li
hash_cleanup(Hash * hash)1532*e47783fdSXin Li static void hash_cleanup(Hash* hash) {
1533*e47783fdSXin Li lodepng_free(hash->head);
1534*e47783fdSXin Li lodepng_free(hash->val);
1535*e47783fdSXin Li lodepng_free(hash->chain);
1536*e47783fdSXin Li
1537*e47783fdSXin Li lodepng_free(hash->zeros);
1538*e47783fdSXin Li lodepng_free(hash->headz);
1539*e47783fdSXin Li lodepng_free(hash->chainz);
1540*e47783fdSXin Li }
1541*e47783fdSXin Li
1542*e47783fdSXin Li
1543*e47783fdSXin Li
getHash(const unsigned char * data,size_t size,size_t pos)1544*e47783fdSXin Li static unsigned getHash(const unsigned char* data, size_t size, size_t pos) {
1545*e47783fdSXin Li unsigned result = 0;
1546*e47783fdSXin Li if(pos + 2 < size) {
1547*e47783fdSXin Li /*A simple shift and xor hash is used. Since the data of PNGs is dominated
1548*e47783fdSXin Li by zeroes due to the filters, a better hash does not have a significant
1549*e47783fdSXin Li effect on speed in traversing the chain, and causes more time spend on
1550*e47783fdSXin Li calculating the hash.*/
1551*e47783fdSXin Li result ^= ((unsigned)data[pos + 0] << 0u);
1552*e47783fdSXin Li result ^= ((unsigned)data[pos + 1] << 4u);
1553*e47783fdSXin Li result ^= ((unsigned)data[pos + 2] << 8u);
1554*e47783fdSXin Li } else {
1555*e47783fdSXin Li size_t amount, i;
1556*e47783fdSXin Li if(pos >= size) return 0;
1557*e47783fdSXin Li amount = size - pos;
1558*e47783fdSXin Li for(i = 0; i != amount; ++i) result ^= ((unsigned)data[pos + i] << (i * 8u));
1559*e47783fdSXin Li }
1560*e47783fdSXin Li return result & HASH_BIT_MASK;
1561*e47783fdSXin Li }
1562*e47783fdSXin Li
countZeros(const unsigned char * data,size_t size,size_t pos)1563*e47783fdSXin Li static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) {
1564*e47783fdSXin Li const unsigned char* start = data + pos;
1565*e47783fdSXin Li const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH;
1566*e47783fdSXin Li if(end > data + size) end = data + size;
1567*e47783fdSXin Li data = start;
1568*e47783fdSXin Li while(data != end && *data == 0) ++data;
1569*e47783fdSXin Li /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/
1570*e47783fdSXin Li return (unsigned)(data - start);
1571*e47783fdSXin Li }
1572*e47783fdSXin Li
1573*e47783fdSXin Li /*wpos = pos & (windowsize - 1)*/
updateHashChain(Hash * hash,size_t wpos,unsigned hashval,unsigned short numzeros)1574*e47783fdSXin Li static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) {
1575*e47783fdSXin Li hash->val[wpos] = (int)hashval;
1576*e47783fdSXin Li if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];
1577*e47783fdSXin Li hash->head[hashval] = (int)wpos;
1578*e47783fdSXin Li
1579*e47783fdSXin Li hash->zeros[wpos] = numzeros;
1580*e47783fdSXin Li if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros];
1581*e47783fdSXin Li hash->headz[numzeros] = (int)wpos;
1582*e47783fdSXin Li }
1583*e47783fdSXin Li
1584*e47783fdSXin Li /*
1585*e47783fdSXin Li LZ77-encode the data. Return value is error code. The input are raw bytes, the output
1586*e47783fdSXin Li is in the form of unsigned integers with codes representing for example literal bytes, or
1587*e47783fdSXin Li length/distance pairs.
1588*e47783fdSXin Li It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a
1589*e47783fdSXin Li sliding window (of windowsize) is used, and all past bytes in that window can be used as
1590*e47783fdSXin Li the "dictionary". A brute force search through all possible distances would be slow, and
1591*e47783fdSXin Li this hash technique is one out of several ways to speed this up.
1592*e47783fdSXin Li */
encodeLZ77(uivector * out,Hash * hash,const unsigned char * in,size_t inpos,size_t insize,unsigned windowsize,unsigned minmatch,unsigned nicematch,unsigned lazymatching)1593*e47783fdSXin Li static unsigned encodeLZ77(uivector* out, Hash* hash,
1594*e47783fdSXin Li const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
1595*e47783fdSXin Li unsigned minmatch, unsigned nicematch, unsigned lazymatching) {
1596*e47783fdSXin Li size_t pos;
1597*e47783fdSXin Li unsigned i, error = 0;
1598*e47783fdSXin Li /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
1599*e47783fdSXin Li unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u;
1600*e47783fdSXin Li unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;
1601*e47783fdSXin Li
1602*e47783fdSXin Li unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
1603*e47783fdSXin Li unsigned numzeros = 0;
1604*e47783fdSXin Li
1605*e47783fdSXin Li unsigned offset; /*the offset represents the distance in LZ77 terminology*/
1606*e47783fdSXin Li unsigned length;
1607*e47783fdSXin Li unsigned lazy = 0;
1608*e47783fdSXin Li unsigned lazylength = 0, lazyoffset = 0;
1609*e47783fdSXin Li unsigned hashval;
1610*e47783fdSXin Li unsigned current_offset, current_length;
1611*e47783fdSXin Li unsigned prev_offset;
1612*e47783fdSXin Li const unsigned char *lastptr, *foreptr, *backptr;
1613*e47783fdSXin Li unsigned hashpos;
1614*e47783fdSXin Li
1615*e47783fdSXin Li if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
1616*e47783fdSXin Li if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/
1617*e47783fdSXin Li
1618*e47783fdSXin Li if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;
1619*e47783fdSXin Li
1620*e47783fdSXin Li for(pos = inpos; pos < insize; ++pos) {
1621*e47783fdSXin Li size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
1622*e47783fdSXin Li unsigned chainlength = 0;
1623*e47783fdSXin Li
1624*e47783fdSXin Li hashval = getHash(in, insize, pos);
1625*e47783fdSXin Li
1626*e47783fdSXin Li if(usezeros && hashval == 0) {
1627*e47783fdSXin Li if(numzeros == 0) numzeros = countZeros(in, insize, pos);
1628*e47783fdSXin Li else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
1629*e47783fdSXin Li } else {
1630*e47783fdSXin Li numzeros = 0;
1631*e47783fdSXin Li }
1632*e47783fdSXin Li
1633*e47783fdSXin Li updateHashChain(hash, wpos, hashval, numzeros);
1634*e47783fdSXin Li
1635*e47783fdSXin Li /*the length and offset found for the current position*/
1636*e47783fdSXin Li length = 0;
1637*e47783fdSXin Li offset = 0;
1638*e47783fdSXin Li
1639*e47783fdSXin Li hashpos = hash->chain[wpos];
1640*e47783fdSXin Li
1641*e47783fdSXin Li lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];
1642*e47783fdSXin Li
1643*e47783fdSXin Li /*search for the longest string*/
1644*e47783fdSXin Li prev_offset = 0;
1645*e47783fdSXin Li for(;;) {
1646*e47783fdSXin Li if(chainlength++ >= maxchainlength) break;
1647*e47783fdSXin Li current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize);
1648*e47783fdSXin Li
1649*e47783fdSXin Li if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/
1650*e47783fdSXin Li prev_offset = current_offset;
1651*e47783fdSXin Li if(current_offset > 0) {
1652*e47783fdSXin Li /*test the next characters*/
1653*e47783fdSXin Li foreptr = &in[pos];
1654*e47783fdSXin Li backptr = &in[pos - current_offset];
1655*e47783fdSXin Li
1656*e47783fdSXin Li /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/
1657*e47783fdSXin Li if(numzeros >= 3) {
1658*e47783fdSXin Li unsigned skip = hash->zeros[hashpos];
1659*e47783fdSXin Li if(skip > numzeros) skip = numzeros;
1660*e47783fdSXin Li backptr += skip;
1661*e47783fdSXin Li foreptr += skip;
1662*e47783fdSXin Li }
1663*e47783fdSXin Li
1664*e47783fdSXin Li while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ {
1665*e47783fdSXin Li ++backptr;
1666*e47783fdSXin Li ++foreptr;
1667*e47783fdSXin Li }
1668*e47783fdSXin Li current_length = (unsigned)(foreptr - &in[pos]);
1669*e47783fdSXin Li
1670*e47783fdSXin Li if(current_length > length) {
1671*e47783fdSXin Li length = current_length; /*the longest length*/
1672*e47783fdSXin Li offset = current_offset; /*the offset that is related to this longest length*/
1673*e47783fdSXin Li /*jump out once a length of max length is found (speed gain). This also jumps
1674*e47783fdSXin Li out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/
1675*e47783fdSXin Li if(current_length >= nicematch) break;
1676*e47783fdSXin Li }
1677*e47783fdSXin Li }
1678*e47783fdSXin Li
1679*e47783fdSXin Li if(hashpos == hash->chain[hashpos]) break;
1680*e47783fdSXin Li
1681*e47783fdSXin Li if(numzeros >= 3 && length > numzeros) {
1682*e47783fdSXin Li hashpos = hash->chainz[hashpos];
1683*e47783fdSXin Li if(hash->zeros[hashpos] != numzeros) break;
1684*e47783fdSXin Li } else {
1685*e47783fdSXin Li hashpos = hash->chain[hashpos];
1686*e47783fdSXin Li /*outdated hash value, happens if particular value was not encountered in whole last window*/
1687*e47783fdSXin Li if(hash->val[hashpos] != (int)hashval) break;
1688*e47783fdSXin Li }
1689*e47783fdSXin Li }
1690*e47783fdSXin Li
1691*e47783fdSXin Li if(lazymatching) {
1692*e47783fdSXin Li if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) {
1693*e47783fdSXin Li lazy = 1;
1694*e47783fdSXin Li lazylength = length;
1695*e47783fdSXin Li lazyoffset = offset;
1696*e47783fdSXin Li continue; /*try the next byte*/
1697*e47783fdSXin Li }
1698*e47783fdSXin Li if(lazy) {
1699*e47783fdSXin Li lazy = 0;
1700*e47783fdSXin Li if(pos == 0) ERROR_BREAK(81);
1701*e47783fdSXin Li if(length > lazylength + 1) {
1702*e47783fdSXin Li /*push the previous character as literal*/
1703*e47783fdSXin Li if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
1704*e47783fdSXin Li } else {
1705*e47783fdSXin Li length = lazylength;
1706*e47783fdSXin Li offset = lazyoffset;
1707*e47783fdSXin Li hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
1708*e47783fdSXin Li hash->headz[numzeros] = -1; /*idem*/
1709*e47783fdSXin Li --pos;
1710*e47783fdSXin Li }
1711*e47783fdSXin Li }
1712*e47783fdSXin Li }
1713*e47783fdSXin Li if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
1714*e47783fdSXin Li
1715*e47783fdSXin Li /*encode it as length/distance pair or literal value*/
1716*e47783fdSXin Li if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ {
1717*e47783fdSXin Li if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
1718*e47783fdSXin Li } else if(length < minmatch || (length == 3 && offset > 4096)) {
1719*e47783fdSXin Li /*compensate for the fact that longer offsets have more extra bits, a
1720*e47783fdSXin Li length of only 3 may be not worth it then*/
1721*e47783fdSXin Li if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
1722*e47783fdSXin Li } else {
1723*e47783fdSXin Li addLengthDistance(out, length, offset);
1724*e47783fdSXin Li for(i = 1; i < length; ++i) {
1725*e47783fdSXin Li ++pos;
1726*e47783fdSXin Li wpos = pos & (windowsize - 1);
1727*e47783fdSXin Li hashval = getHash(in, insize, pos);
1728*e47783fdSXin Li if(usezeros && hashval == 0) {
1729*e47783fdSXin Li if(numzeros == 0) numzeros = countZeros(in, insize, pos);
1730*e47783fdSXin Li else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
1731*e47783fdSXin Li } else {
1732*e47783fdSXin Li numzeros = 0;
1733*e47783fdSXin Li }
1734*e47783fdSXin Li updateHashChain(hash, wpos, hashval, numzeros);
1735*e47783fdSXin Li }
1736*e47783fdSXin Li }
1737*e47783fdSXin Li } /*end of the loop through each character of input*/
1738*e47783fdSXin Li
1739*e47783fdSXin Li return error;
1740*e47783fdSXin Li }
1741*e47783fdSXin Li
1742*e47783fdSXin Li /* /////////////////////////////////////////////////////////////////////////// */
1743*e47783fdSXin Li
deflateNoCompression(ucvector * out,const unsigned char * data,size_t datasize)1744*e47783fdSXin Li static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) {
1745*e47783fdSXin Li /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte,
1746*e47783fdSXin Li 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/
1747*e47783fdSXin Li
1748*e47783fdSXin Li size_t i, numdeflateblocks = (datasize + 65534u) / 65535u;
1749*e47783fdSXin Li unsigned datapos = 0;
1750*e47783fdSXin Li for(i = 0; i != numdeflateblocks; ++i) {
1751*e47783fdSXin Li unsigned BFINAL, BTYPE, LEN, NLEN;
1752*e47783fdSXin Li unsigned char firstbyte;
1753*e47783fdSXin Li size_t pos = out->size;
1754*e47783fdSXin Li
1755*e47783fdSXin Li BFINAL = (i == numdeflateblocks - 1);
1756*e47783fdSXin Li BTYPE = 0;
1757*e47783fdSXin Li
1758*e47783fdSXin Li LEN = 65535;
1759*e47783fdSXin Li if(datasize - datapos < 65535u) LEN = (unsigned)datasize - datapos;
1760*e47783fdSXin Li NLEN = 65535 - LEN;
1761*e47783fdSXin Li
1762*e47783fdSXin Li if(!ucvector_resize(out, out->size + LEN + 5)) return 83; /*alloc fail*/
1763*e47783fdSXin Li
1764*e47783fdSXin Li firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1u) << 1u) + ((BTYPE & 2u) << 1u));
1765*e47783fdSXin Li out->data[pos + 0] = firstbyte;
1766*e47783fdSXin Li out->data[pos + 1] = (unsigned char)(LEN & 255);
1767*e47783fdSXin Li out->data[pos + 2] = (unsigned char)(LEN >> 8u);
1768*e47783fdSXin Li out->data[pos + 3] = (unsigned char)(NLEN & 255);
1769*e47783fdSXin Li out->data[pos + 4] = (unsigned char)(NLEN >> 8u);
1770*e47783fdSXin Li lodepng_memcpy(out->data + pos + 5, data + datapos, LEN);
1771*e47783fdSXin Li datapos += LEN;
1772*e47783fdSXin Li }
1773*e47783fdSXin Li
1774*e47783fdSXin Li return 0;
1775*e47783fdSXin Li }
1776*e47783fdSXin Li
1777*e47783fdSXin Li /*
1778*e47783fdSXin Li write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees.
1779*e47783fdSXin Li tree_ll: the tree for lit and len codes.
1780*e47783fdSXin Li tree_d: the tree for distance codes.
1781*e47783fdSXin Li */
writeLZ77data(LodePNGBitWriter * writer,const uivector * lz77_encoded,const HuffmanTree * tree_ll,const HuffmanTree * tree_d)1782*e47783fdSXin Li static void writeLZ77data(LodePNGBitWriter* writer, const uivector* lz77_encoded,
1783*e47783fdSXin Li const HuffmanTree* tree_ll, const HuffmanTree* tree_d) {
1784*e47783fdSXin Li size_t i = 0;
1785*e47783fdSXin Li for(i = 0; i != lz77_encoded->size; ++i) {
1786*e47783fdSXin Li unsigned val = lz77_encoded->data[i];
1787*e47783fdSXin Li writeBitsReversed(writer, tree_ll->codes[val], tree_ll->lengths[val]);
1788*e47783fdSXin Li if(val > 256) /*for a length code, 3 more things have to be added*/ {
1789*e47783fdSXin Li unsigned length_index = val - FIRST_LENGTH_CODE_INDEX;
1790*e47783fdSXin Li unsigned n_length_extra_bits = LENGTHEXTRA[length_index];
1791*e47783fdSXin Li unsigned length_extra_bits = lz77_encoded->data[++i];
1792*e47783fdSXin Li
1793*e47783fdSXin Li unsigned distance_code = lz77_encoded->data[++i];
1794*e47783fdSXin Li
1795*e47783fdSXin Li unsigned distance_index = distance_code;
1796*e47783fdSXin Li unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index];
1797*e47783fdSXin Li unsigned distance_extra_bits = lz77_encoded->data[++i];
1798*e47783fdSXin Li
1799*e47783fdSXin Li writeBits(writer, length_extra_bits, n_length_extra_bits);
1800*e47783fdSXin Li writeBitsReversed(writer, tree_d->codes[distance_code], tree_d->lengths[distance_code]);
1801*e47783fdSXin Li writeBits(writer, distance_extra_bits, n_distance_extra_bits);
1802*e47783fdSXin Li }
1803*e47783fdSXin Li }
1804*e47783fdSXin Li }
1805*e47783fdSXin Li
1806*e47783fdSXin Li /*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/
deflateDynamic(LodePNGBitWriter * writer,Hash * hash,const unsigned char * data,size_t datapos,size_t dataend,const LodePNGCompressSettings * settings,unsigned final)1807*e47783fdSXin Li static unsigned deflateDynamic(LodePNGBitWriter* writer, Hash* hash,
1808*e47783fdSXin Li const unsigned char* data, size_t datapos, size_t dataend,
1809*e47783fdSXin Li const LodePNGCompressSettings* settings, unsigned final) {
1810*e47783fdSXin Li unsigned error = 0;
1811*e47783fdSXin Li
1812*e47783fdSXin Li /*
1813*e47783fdSXin Li A block is compressed as follows: The PNG data is lz77 encoded, resulting in
1814*e47783fdSXin Li literal bytes and length/distance pairs. This is then huffman compressed with
1815*e47783fdSXin Li two huffman trees. One huffman tree is used for the lit and len values ("ll"),
1816*e47783fdSXin Li another huffman tree is used for the dist values ("d"). These two trees are
1817*e47783fdSXin Li stored using their code lengths, and to compress even more these code lengths
1818*e47783fdSXin Li are also run-length encoded and huffman compressed. This gives a huffman tree
1819*e47783fdSXin Li of code lengths "cl". The code lengths used to describe this third tree are
1820*e47783fdSXin Li the code length code lengths ("clcl").
1821*e47783fdSXin Li */
1822*e47783fdSXin Li
1823*e47783fdSXin Li /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/
1824*e47783fdSXin Li uivector lz77_encoded;
1825*e47783fdSXin Li HuffmanTree tree_ll; /*tree for lit,len values*/
1826*e47783fdSXin Li HuffmanTree tree_d; /*tree for distance codes*/
1827*e47783fdSXin Li HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/
1828*e47783fdSXin Li unsigned* frequencies_ll = 0; /*frequency of lit,len codes*/
1829*e47783fdSXin Li unsigned* frequencies_d = 0; /*frequency of dist codes*/
1830*e47783fdSXin Li unsigned* frequencies_cl = 0; /*frequency of code length codes*/
1831*e47783fdSXin Li unsigned* bitlen_lld = 0; /*lit,len,dist code lengths (int bits), literally (without repeat codes).*/
1832*e47783fdSXin Li unsigned* bitlen_lld_e = 0; /*bitlen_lld encoded with repeat codes (this is a rudimentary run length compression)*/
1833*e47783fdSXin Li size_t datasize = dataend - datapos;
1834*e47783fdSXin Li
1835*e47783fdSXin Li /*
1836*e47783fdSXin Li If we could call "bitlen_cl" the the code length code lengths ("clcl"), that is the bit lengths of codes to represent
1837*e47783fdSXin Li tree_cl in CLCL_ORDER, then due to the huffman compression of huffman tree representations ("two levels"), there are
1838*e47783fdSXin Li some analogies:
1839*e47783fdSXin Li bitlen_lld is to tree_cl what data is to tree_ll and tree_d.
1840*e47783fdSXin Li bitlen_lld_e is to bitlen_lld what lz77_encoded is to data.
1841*e47783fdSXin Li bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded.
1842*e47783fdSXin Li */
1843*e47783fdSXin Li
1844*e47783fdSXin Li unsigned BFINAL = final;
1845*e47783fdSXin Li size_t i;
1846*e47783fdSXin Li size_t numcodes_ll, numcodes_d, numcodes_lld, numcodes_lld_e, numcodes_cl;
1847*e47783fdSXin Li unsigned HLIT, HDIST, HCLEN;
1848*e47783fdSXin Li
1849*e47783fdSXin Li uivector_init(&lz77_encoded);
1850*e47783fdSXin Li HuffmanTree_init(&tree_ll);
1851*e47783fdSXin Li HuffmanTree_init(&tree_d);
1852*e47783fdSXin Li HuffmanTree_init(&tree_cl);
1853*e47783fdSXin Li /* could fit on stack, but >1KB is on the larger side so allocate instead */
1854*e47783fdSXin Li frequencies_ll = (unsigned*)lodepng_malloc(286 * sizeof(*frequencies_ll));
1855*e47783fdSXin Li frequencies_d = (unsigned*)lodepng_malloc(30 * sizeof(*frequencies_d));
1856*e47783fdSXin Li frequencies_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl));
1857*e47783fdSXin Li
1858*e47783fdSXin Li if(!frequencies_ll || !frequencies_d || !frequencies_cl) error = 83; /*alloc fail*/
1859*e47783fdSXin Li
1860*e47783fdSXin Li /*This while loop never loops due to a break at the end, it is here to
1861*e47783fdSXin Li allow breaking out of it to the cleanup phase on error conditions.*/
1862*e47783fdSXin Li while(!error) {
1863*e47783fdSXin Li lodepng_memset(frequencies_ll, 0, 286 * sizeof(*frequencies_ll));
1864*e47783fdSXin Li lodepng_memset(frequencies_d, 0, 30 * sizeof(*frequencies_d));
1865*e47783fdSXin Li lodepng_memset(frequencies_cl, 0, NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl));
1866*e47783fdSXin Li
1867*e47783fdSXin Li if(settings->use_lz77) {
1868*e47783fdSXin Li error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
1869*e47783fdSXin Li settings->minmatch, settings->nicematch, settings->lazymatching);
1870*e47783fdSXin Li if(error) break;
1871*e47783fdSXin Li } else {
1872*e47783fdSXin Li if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/);
1873*e47783fdSXin Li for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/
1874*e47783fdSXin Li }
1875*e47783fdSXin Li
1876*e47783fdSXin Li /*Count the frequencies of lit, len and dist codes*/
1877*e47783fdSXin Li for(i = 0; i != lz77_encoded.size; ++i) {
1878*e47783fdSXin Li unsigned symbol = lz77_encoded.data[i];
1879*e47783fdSXin Li ++frequencies_ll[symbol];
1880*e47783fdSXin Li if(symbol > 256) {
1881*e47783fdSXin Li unsigned dist = lz77_encoded.data[i + 2];
1882*e47783fdSXin Li ++frequencies_d[dist];
1883*e47783fdSXin Li i += 3;
1884*e47783fdSXin Li }
1885*e47783fdSXin Li }
1886*e47783fdSXin Li frequencies_ll[256] = 1; /*there will be exactly 1 end code, at the end of the block*/
1887*e47783fdSXin Li
1888*e47783fdSXin Li /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/
1889*e47783fdSXin Li error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll, 257, 286, 15);
1890*e47783fdSXin Li if(error) break;
1891*e47783fdSXin Li /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/
1892*e47783fdSXin Li error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d, 2, 30, 15);
1893*e47783fdSXin Li if(error) break;
1894*e47783fdSXin Li
1895*e47783fdSXin Li numcodes_ll = LODEPNG_MIN(tree_ll.numcodes, 286);
1896*e47783fdSXin Li numcodes_d = LODEPNG_MIN(tree_d.numcodes, 30);
1897*e47783fdSXin Li /*store the code lengths of both generated trees in bitlen_lld*/
1898*e47783fdSXin Li numcodes_lld = numcodes_ll + numcodes_d;
1899*e47783fdSXin Li bitlen_lld = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld));
1900*e47783fdSXin Li /*numcodes_lld_e never needs more size than bitlen_lld*/
1901*e47783fdSXin Li bitlen_lld_e = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld_e));
1902*e47783fdSXin Li if(!bitlen_lld || !bitlen_lld_e) ERROR_BREAK(83); /*alloc fail*/
1903*e47783fdSXin Li numcodes_lld_e = 0;
1904*e47783fdSXin Li
1905*e47783fdSXin Li for(i = 0; i != numcodes_ll; ++i) bitlen_lld[i] = tree_ll.lengths[i];
1906*e47783fdSXin Li for(i = 0; i != numcodes_d; ++i) bitlen_lld[numcodes_ll + i] = tree_d.lengths[i];
1907*e47783fdSXin Li
1908*e47783fdSXin Li /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times),
1909*e47783fdSXin Li 17 (3-10 zeroes), 18 (11-138 zeroes)*/
1910*e47783fdSXin Li for(i = 0; i != numcodes_lld; ++i) {
1911*e47783fdSXin Li unsigned j = 0; /*amount of repetitions*/
1912*e47783fdSXin Li while(i + j + 1 < numcodes_lld && bitlen_lld[i + j + 1] == bitlen_lld[i]) ++j;
1913*e47783fdSXin Li
1914*e47783fdSXin Li if(bitlen_lld[i] == 0 && j >= 2) /*repeat code for zeroes*/ {
1915*e47783fdSXin Li ++j; /*include the first zero*/
1916*e47783fdSXin Li if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ {
1917*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = 17;
1918*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = j - 3;
1919*e47783fdSXin Li } else /*repeat code 18 supports max 138 zeroes*/ {
1920*e47783fdSXin Li if(j > 138) j = 138;
1921*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = 18;
1922*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = j - 11;
1923*e47783fdSXin Li }
1924*e47783fdSXin Li i += (j - 1);
1925*e47783fdSXin Li } else if(j >= 3) /*repeat code for value other than zero*/ {
1926*e47783fdSXin Li size_t k;
1927*e47783fdSXin Li unsigned num = j / 6u, rest = j % 6u;
1928*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i];
1929*e47783fdSXin Li for(k = 0; k < num; ++k) {
1930*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = 16;
1931*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = 6 - 3;
1932*e47783fdSXin Li }
1933*e47783fdSXin Li if(rest >= 3) {
1934*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = 16;
1935*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = rest - 3;
1936*e47783fdSXin Li }
1937*e47783fdSXin Li else j -= rest;
1938*e47783fdSXin Li i += j;
1939*e47783fdSXin Li } else /*too short to benefit from repeat code*/ {
1940*e47783fdSXin Li bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i];
1941*e47783fdSXin Li }
1942*e47783fdSXin Li }
1943*e47783fdSXin Li
1944*e47783fdSXin Li /*generate tree_cl, the huffmantree of huffmantrees*/
1945*e47783fdSXin Li for(i = 0; i != numcodes_lld_e; ++i) {
1946*e47783fdSXin Li ++frequencies_cl[bitlen_lld_e[i]];
1947*e47783fdSXin Li /*after a repeat code come the bits that specify the number of repetitions,
1948*e47783fdSXin Li those don't need to be in the frequencies_cl calculation*/
1949*e47783fdSXin Li if(bitlen_lld_e[i] >= 16) ++i;
1950*e47783fdSXin Li }
1951*e47783fdSXin Li
1952*e47783fdSXin Li error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl,
1953*e47783fdSXin Li NUM_CODE_LENGTH_CODES, NUM_CODE_LENGTH_CODES, 7);
1954*e47783fdSXin Li if(error) break;
1955*e47783fdSXin Li
1956*e47783fdSXin Li /*compute amount of code-length-code-lengths to output*/
1957*e47783fdSXin Li numcodes_cl = NUM_CODE_LENGTH_CODES;
1958*e47783fdSXin Li /*trim zeros at the end (using CLCL_ORDER), but minimum size must be 4 (see HCLEN below)*/
1959*e47783fdSXin Li while(numcodes_cl > 4u && tree_cl.lengths[CLCL_ORDER[numcodes_cl - 1u]] == 0) {
1960*e47783fdSXin Li numcodes_cl--;
1961*e47783fdSXin Li }
1962*e47783fdSXin Li
1963*e47783fdSXin Li /*
1964*e47783fdSXin Li Write everything into the output
1965*e47783fdSXin Li
1966*e47783fdSXin Li After the BFINAL and BTYPE, the dynamic block consists out of the following:
1967*e47783fdSXin Li - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN
1968*e47783fdSXin Li - (HCLEN+4)*3 bits code lengths of code length alphabet
1969*e47783fdSXin Li - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length
1970*e47783fdSXin Li alphabet, + possible repetition codes 16, 17, 18)
1971*e47783fdSXin Li - HDIST + 1 code lengths of distance alphabet (encoded using the code length
1972*e47783fdSXin Li alphabet, + possible repetition codes 16, 17, 18)
1973*e47783fdSXin Li - compressed data
1974*e47783fdSXin Li - 256 (end code)
1975*e47783fdSXin Li */
1976*e47783fdSXin Li
1977*e47783fdSXin Li /*Write block type*/
1978*e47783fdSXin Li writeBits(writer, BFINAL, 1);
1979*e47783fdSXin Li writeBits(writer, 0, 1); /*first bit of BTYPE "dynamic"*/
1980*e47783fdSXin Li writeBits(writer, 1, 1); /*second bit of BTYPE "dynamic"*/
1981*e47783fdSXin Li
1982*e47783fdSXin Li /*write the HLIT, HDIST and HCLEN values*/
1983*e47783fdSXin Li /*all three sizes take trimmed ending zeroes into account, done either by HuffmanTree_makeFromFrequencies
1984*e47783fdSXin Li or in the loop for numcodes_cl above, which saves space. */
1985*e47783fdSXin Li HLIT = (unsigned)(numcodes_ll - 257);
1986*e47783fdSXin Li HDIST = (unsigned)(numcodes_d - 1);
1987*e47783fdSXin Li HCLEN = (unsigned)(numcodes_cl - 4);
1988*e47783fdSXin Li writeBits(writer, HLIT, 5);
1989*e47783fdSXin Li writeBits(writer, HDIST, 5);
1990*e47783fdSXin Li writeBits(writer, HCLEN, 4);
1991*e47783fdSXin Li
1992*e47783fdSXin Li /*write the code lengths of the code length alphabet ("bitlen_cl")*/
1993*e47783fdSXin Li for(i = 0; i != numcodes_cl; ++i) writeBits(writer, tree_cl.lengths[CLCL_ORDER[i]], 3);
1994*e47783fdSXin Li
1995*e47783fdSXin Li /*write the lengths of the lit/len AND the dist alphabet*/
1996*e47783fdSXin Li for(i = 0; i != numcodes_lld_e; ++i) {
1997*e47783fdSXin Li writeBitsReversed(writer, tree_cl.codes[bitlen_lld_e[i]], tree_cl.lengths[bitlen_lld_e[i]]);
1998*e47783fdSXin Li /*extra bits of repeat codes*/
1999*e47783fdSXin Li if(bitlen_lld_e[i] == 16) writeBits(writer, bitlen_lld_e[++i], 2);
2000*e47783fdSXin Li else if(bitlen_lld_e[i] == 17) writeBits(writer, bitlen_lld_e[++i], 3);
2001*e47783fdSXin Li else if(bitlen_lld_e[i] == 18) writeBits(writer, bitlen_lld_e[++i], 7);
2002*e47783fdSXin Li }
2003*e47783fdSXin Li
2004*e47783fdSXin Li /*write the compressed data symbols*/
2005*e47783fdSXin Li writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d);
2006*e47783fdSXin Li /*error: the length of the end code 256 must be larger than 0*/
2007*e47783fdSXin Li if(tree_ll.lengths[256] == 0) ERROR_BREAK(64);
2008*e47783fdSXin Li
2009*e47783fdSXin Li /*write the end code*/
2010*e47783fdSXin Li writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]);
2011*e47783fdSXin Li
2012*e47783fdSXin Li break; /*end of error-while*/
2013*e47783fdSXin Li }
2014*e47783fdSXin Li
2015*e47783fdSXin Li /*cleanup*/
2016*e47783fdSXin Li uivector_cleanup(&lz77_encoded);
2017*e47783fdSXin Li HuffmanTree_cleanup(&tree_ll);
2018*e47783fdSXin Li HuffmanTree_cleanup(&tree_d);
2019*e47783fdSXin Li HuffmanTree_cleanup(&tree_cl);
2020*e47783fdSXin Li lodepng_free(frequencies_ll);
2021*e47783fdSXin Li lodepng_free(frequencies_d);
2022*e47783fdSXin Li lodepng_free(frequencies_cl);
2023*e47783fdSXin Li lodepng_free(bitlen_lld);
2024*e47783fdSXin Li lodepng_free(bitlen_lld_e);
2025*e47783fdSXin Li
2026*e47783fdSXin Li return error;
2027*e47783fdSXin Li }
2028*e47783fdSXin Li
deflateFixed(LodePNGBitWriter * writer,Hash * hash,const unsigned char * data,size_t datapos,size_t dataend,const LodePNGCompressSettings * settings,unsigned final)2029*e47783fdSXin Li static unsigned deflateFixed(LodePNGBitWriter* writer, Hash* hash,
2030*e47783fdSXin Li const unsigned char* data,
2031*e47783fdSXin Li size_t datapos, size_t dataend,
2032*e47783fdSXin Li const LodePNGCompressSettings* settings, unsigned final) {
2033*e47783fdSXin Li HuffmanTree tree_ll; /*tree for literal values and length codes*/
2034*e47783fdSXin Li HuffmanTree tree_d; /*tree for distance codes*/
2035*e47783fdSXin Li
2036*e47783fdSXin Li unsigned BFINAL = final;
2037*e47783fdSXin Li unsigned error = 0;
2038*e47783fdSXin Li size_t i;
2039*e47783fdSXin Li
2040*e47783fdSXin Li HuffmanTree_init(&tree_ll);
2041*e47783fdSXin Li HuffmanTree_init(&tree_d);
2042*e47783fdSXin Li
2043*e47783fdSXin Li error = generateFixedLitLenTree(&tree_ll);
2044*e47783fdSXin Li if(!error) error = generateFixedDistanceTree(&tree_d);
2045*e47783fdSXin Li
2046*e47783fdSXin Li if(!error) {
2047*e47783fdSXin Li writeBits(writer, BFINAL, 1);
2048*e47783fdSXin Li writeBits(writer, 1, 1); /*first bit of BTYPE*/
2049*e47783fdSXin Li writeBits(writer, 0, 1); /*second bit of BTYPE*/
2050*e47783fdSXin Li
2051*e47783fdSXin Li if(settings->use_lz77) /*LZ77 encoded*/ {
2052*e47783fdSXin Li uivector lz77_encoded;
2053*e47783fdSXin Li uivector_init(&lz77_encoded);
2054*e47783fdSXin Li error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
2055*e47783fdSXin Li settings->minmatch, settings->nicematch, settings->lazymatching);
2056*e47783fdSXin Li if(!error) writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d);
2057*e47783fdSXin Li uivector_cleanup(&lz77_encoded);
2058*e47783fdSXin Li } else /*no LZ77, but still will be Huffman compressed*/ {
2059*e47783fdSXin Li for(i = datapos; i < dataend; ++i) {
2060*e47783fdSXin Li writeBitsReversed(writer, tree_ll.codes[data[i]], tree_ll.lengths[data[i]]);
2061*e47783fdSXin Li }
2062*e47783fdSXin Li }
2063*e47783fdSXin Li /*add END code*/
2064*e47783fdSXin Li if(!error) writeBitsReversed(writer,tree_ll.codes[256], tree_ll.lengths[256]);
2065*e47783fdSXin Li }
2066*e47783fdSXin Li
2067*e47783fdSXin Li /*cleanup*/
2068*e47783fdSXin Li HuffmanTree_cleanup(&tree_ll);
2069*e47783fdSXin Li HuffmanTree_cleanup(&tree_d);
2070*e47783fdSXin Li
2071*e47783fdSXin Li return error;
2072*e47783fdSXin Li }
2073*e47783fdSXin Li
lodepng_deflatev(ucvector * out,const unsigned char * in,size_t insize,const LodePNGCompressSettings * settings)2074*e47783fdSXin Li static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize,
2075*e47783fdSXin Li const LodePNGCompressSettings* settings) {
2076*e47783fdSXin Li unsigned error = 0;
2077*e47783fdSXin Li size_t i, blocksize, numdeflateblocks;
2078*e47783fdSXin Li Hash hash;
2079*e47783fdSXin Li LodePNGBitWriter writer;
2080*e47783fdSXin Li
2081*e47783fdSXin Li LodePNGBitWriter_init(&writer, out);
2082*e47783fdSXin Li
2083*e47783fdSXin Li if(settings->btype > 2) return 61;
2084*e47783fdSXin Li else if(settings->btype == 0) return deflateNoCompression(out, in, insize);
2085*e47783fdSXin Li else if(settings->btype == 1) blocksize = insize;
2086*e47783fdSXin Li else /*if(settings->btype == 2)*/ {
2087*e47783fdSXin Li /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/
2088*e47783fdSXin Li blocksize = insize / 8u + 8;
2089*e47783fdSXin Li if(blocksize < 65536) blocksize = 65536;
2090*e47783fdSXin Li if(blocksize > 262144) blocksize = 262144;
2091*e47783fdSXin Li }
2092*e47783fdSXin Li
2093*e47783fdSXin Li numdeflateblocks = (insize + blocksize - 1) / blocksize;
2094*e47783fdSXin Li if(numdeflateblocks == 0) numdeflateblocks = 1;
2095*e47783fdSXin Li
2096*e47783fdSXin Li error = hash_init(&hash, settings->windowsize);
2097*e47783fdSXin Li
2098*e47783fdSXin Li if(!error) {
2099*e47783fdSXin Li for(i = 0; i != numdeflateblocks && !error; ++i) {
2100*e47783fdSXin Li unsigned final = (i == numdeflateblocks - 1);
2101*e47783fdSXin Li size_t start = i * blocksize;
2102*e47783fdSXin Li size_t end = start + blocksize;
2103*e47783fdSXin Li if(end > insize) end = insize;
2104*e47783fdSXin Li
2105*e47783fdSXin Li if(settings->btype == 1) error = deflateFixed(&writer, &hash, in, start, end, settings, final);
2106*e47783fdSXin Li else if(settings->btype == 2) error = deflateDynamic(&writer, &hash, in, start, end, settings, final);
2107*e47783fdSXin Li }
2108*e47783fdSXin Li }
2109*e47783fdSXin Li
2110*e47783fdSXin Li hash_cleanup(&hash);
2111*e47783fdSXin Li
2112*e47783fdSXin Li return error;
2113*e47783fdSXin Li }
2114*e47783fdSXin Li
lodepng_deflate(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGCompressSettings * settings)2115*e47783fdSXin Li unsigned lodepng_deflate(unsigned char** out, size_t* outsize,
2116*e47783fdSXin Li const unsigned char* in, size_t insize,
2117*e47783fdSXin Li const LodePNGCompressSettings* settings) {
2118*e47783fdSXin Li ucvector v = ucvector_init(*out, *outsize);
2119*e47783fdSXin Li unsigned error = lodepng_deflatev(&v, in, insize, settings);
2120*e47783fdSXin Li *out = v.data;
2121*e47783fdSXin Li *outsize = v.size;
2122*e47783fdSXin Li return error;
2123*e47783fdSXin Li }
2124*e47783fdSXin Li
deflate(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGCompressSettings * settings)2125*e47783fdSXin Li static unsigned deflate(unsigned char** out, size_t* outsize,
2126*e47783fdSXin Li const unsigned char* in, size_t insize,
2127*e47783fdSXin Li const LodePNGCompressSettings* settings) {
2128*e47783fdSXin Li if(settings->custom_deflate) {
2129*e47783fdSXin Li unsigned error = settings->custom_deflate(out, outsize, in, insize, settings);
2130*e47783fdSXin Li /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/
2131*e47783fdSXin Li return error ? 111 : 0;
2132*e47783fdSXin Li } else {
2133*e47783fdSXin Li return lodepng_deflate(out, outsize, in, insize, settings);
2134*e47783fdSXin Li }
2135*e47783fdSXin Li }
2136*e47783fdSXin Li
2137*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
2138*e47783fdSXin Li
2139*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2140*e47783fdSXin Li /* / Adler32 / */
2141*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2142*e47783fdSXin Li
update_adler32(unsigned adler,const unsigned char * data,unsigned len)2143*e47783fdSXin Li static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) {
2144*e47783fdSXin Li unsigned s1 = adler & 0xffffu;
2145*e47783fdSXin Li unsigned s2 = (adler >> 16u) & 0xffffu;
2146*e47783fdSXin Li
2147*e47783fdSXin Li while(len != 0u) {
2148*e47783fdSXin Li unsigned i;
2149*e47783fdSXin Li /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/
2150*e47783fdSXin Li unsigned amount = len > 5552u ? 5552u : len;
2151*e47783fdSXin Li len -= amount;
2152*e47783fdSXin Li for(i = 0; i != amount; ++i) {
2153*e47783fdSXin Li s1 += (*data++);
2154*e47783fdSXin Li s2 += s1;
2155*e47783fdSXin Li }
2156*e47783fdSXin Li s1 %= 65521u;
2157*e47783fdSXin Li s2 %= 65521u;
2158*e47783fdSXin Li }
2159*e47783fdSXin Li
2160*e47783fdSXin Li return (s2 << 16u) | s1;
2161*e47783fdSXin Li }
2162*e47783fdSXin Li
2163*e47783fdSXin Li /*Return the adler32 of the bytes data[0..len-1]*/
adler32(const unsigned char * data,unsigned len)2164*e47783fdSXin Li static unsigned adler32(const unsigned char* data, unsigned len) {
2165*e47783fdSXin Li return update_adler32(1u, data, len);
2166*e47783fdSXin Li }
2167*e47783fdSXin Li
2168*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2169*e47783fdSXin Li /* / Zlib / */
2170*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2171*e47783fdSXin Li
2172*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
2173*e47783fdSXin Li
lodepng_zlib_decompressv(ucvector * out,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)2174*e47783fdSXin Li static unsigned lodepng_zlib_decompressv(ucvector* out,
2175*e47783fdSXin Li const unsigned char* in, size_t insize,
2176*e47783fdSXin Li const LodePNGDecompressSettings* settings) {
2177*e47783fdSXin Li unsigned error = 0;
2178*e47783fdSXin Li unsigned CM, CINFO, FDICT;
2179*e47783fdSXin Li
2180*e47783fdSXin Li if(insize < 2) return 53; /*error, size of zlib data too small*/
2181*e47783fdSXin Li /*read information from zlib header*/
2182*e47783fdSXin Li if((in[0] * 256 + in[1]) % 31 != 0) {
2183*e47783fdSXin Li /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/
2184*e47783fdSXin Li return 24;
2185*e47783fdSXin Li }
2186*e47783fdSXin Li
2187*e47783fdSXin Li CM = in[0] & 15;
2188*e47783fdSXin Li CINFO = (in[0] >> 4) & 15;
2189*e47783fdSXin Li /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/
2190*e47783fdSXin Li FDICT = (in[1] >> 5) & 1;
2191*e47783fdSXin Li /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/
2192*e47783fdSXin Li
2193*e47783fdSXin Li if(CM != 8 || CINFO > 7) {
2194*e47783fdSXin Li /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/
2195*e47783fdSXin Li return 25;
2196*e47783fdSXin Li }
2197*e47783fdSXin Li if(FDICT != 0) {
2198*e47783fdSXin Li /*error: the specification of PNG says about the zlib stream:
2199*e47783fdSXin Li "The additional flags shall not specify a preset dictionary."*/
2200*e47783fdSXin Li return 26;
2201*e47783fdSXin Li }
2202*e47783fdSXin Li
2203*e47783fdSXin Li error = inflatev(out, in + 2, insize - 2, settings);
2204*e47783fdSXin Li if(error) return error;
2205*e47783fdSXin Li
2206*e47783fdSXin Li if(!settings->ignore_adler32) {
2207*e47783fdSXin Li unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]);
2208*e47783fdSXin Li unsigned checksum = adler32(out->data, (unsigned)(out->size));
2209*e47783fdSXin Li if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/
2210*e47783fdSXin Li }
2211*e47783fdSXin Li
2212*e47783fdSXin Li return 0; /*no error*/
2213*e47783fdSXin Li }
2214*e47783fdSXin Li
2215*e47783fdSXin Li
lodepng_zlib_decompress(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)2216*e47783fdSXin Li unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
2217*e47783fdSXin Li size_t insize, const LodePNGDecompressSettings* settings) {
2218*e47783fdSXin Li ucvector v = ucvector_init(*out, *outsize);
2219*e47783fdSXin Li unsigned error = lodepng_zlib_decompressv(&v, in, insize, settings);
2220*e47783fdSXin Li *out = v.data;
2221*e47783fdSXin Li *outsize = v.size;
2222*e47783fdSXin Li return error;
2223*e47783fdSXin Li }
2224*e47783fdSXin Li
2225*e47783fdSXin Li /*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
zlib_decompress(unsigned char ** out,size_t * outsize,size_t expected_size,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)2226*e47783fdSXin Li static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
2227*e47783fdSXin Li const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
2228*e47783fdSXin Li unsigned error;
2229*e47783fdSXin Li if(settings->custom_zlib) {
2230*e47783fdSXin Li error = settings->custom_zlib(out, outsize, in, insize, settings);
2231*e47783fdSXin Li if(error) {
2232*e47783fdSXin Li /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/
2233*e47783fdSXin Li error = 110;
2234*e47783fdSXin Li /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
2235*e47783fdSXin Li if(settings->max_output_size && *outsize > settings->max_output_size) error = 109;
2236*e47783fdSXin Li }
2237*e47783fdSXin Li } else {
2238*e47783fdSXin Li ucvector v = ucvector_init(*out, *outsize);
2239*e47783fdSXin Li if(expected_size) {
2240*e47783fdSXin Li /*reserve the memory to avoid intermediate reallocations*/
2241*e47783fdSXin Li ucvector_resize(&v, *outsize + expected_size);
2242*e47783fdSXin Li v.size = *outsize;
2243*e47783fdSXin Li }
2244*e47783fdSXin Li error = lodepng_zlib_decompressv(&v, in, insize, settings);
2245*e47783fdSXin Li *out = v.data;
2246*e47783fdSXin Li *outsize = v.size;
2247*e47783fdSXin Li }
2248*e47783fdSXin Li return error;
2249*e47783fdSXin Li }
2250*e47783fdSXin Li
2251*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
2252*e47783fdSXin Li
2253*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
2254*e47783fdSXin Li
lodepng_zlib_compress(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGCompressSettings * settings)2255*e47783fdSXin Li unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
2256*e47783fdSXin Li size_t insize, const LodePNGCompressSettings* settings) {
2257*e47783fdSXin Li size_t i;
2258*e47783fdSXin Li unsigned error;
2259*e47783fdSXin Li unsigned char* deflatedata = 0;
2260*e47783fdSXin Li size_t deflatesize = 0;
2261*e47783fdSXin Li
2262*e47783fdSXin Li error = deflate(&deflatedata, &deflatesize, in, insize, settings);
2263*e47783fdSXin Li
2264*e47783fdSXin Li *out = NULL;
2265*e47783fdSXin Li *outsize = 0;
2266*e47783fdSXin Li if(!error) {
2267*e47783fdSXin Li *outsize = deflatesize + 6;
2268*e47783fdSXin Li *out = (unsigned char*)lodepng_malloc(*outsize);
2269*e47783fdSXin Li if(!*out) error = 83; /*alloc fail*/
2270*e47783fdSXin Li }
2271*e47783fdSXin Li
2272*e47783fdSXin Li if(!error) {
2273*e47783fdSXin Li unsigned ADLER32 = adler32(in, (unsigned)insize);
2274*e47783fdSXin Li /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/
2275*e47783fdSXin Li unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/
2276*e47783fdSXin Li unsigned FLEVEL = 0;
2277*e47783fdSXin Li unsigned FDICT = 0;
2278*e47783fdSXin Li unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64;
2279*e47783fdSXin Li unsigned FCHECK = 31 - CMFFLG % 31;
2280*e47783fdSXin Li CMFFLG += FCHECK;
2281*e47783fdSXin Li
2282*e47783fdSXin Li (*out)[0] = (unsigned char)(CMFFLG >> 8);
2283*e47783fdSXin Li (*out)[1] = (unsigned char)(CMFFLG & 255);
2284*e47783fdSXin Li for(i = 0; i != deflatesize; ++i) (*out)[i + 2] = deflatedata[i];
2285*e47783fdSXin Li lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32);
2286*e47783fdSXin Li }
2287*e47783fdSXin Li
2288*e47783fdSXin Li lodepng_free(deflatedata);
2289*e47783fdSXin Li return error;
2290*e47783fdSXin Li }
2291*e47783fdSXin Li
2292*e47783fdSXin Li /* compress using the default or custom zlib function */
zlib_compress(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGCompressSettings * settings)2293*e47783fdSXin Li static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
2294*e47783fdSXin Li size_t insize, const LodePNGCompressSettings* settings) {
2295*e47783fdSXin Li if(settings->custom_zlib) {
2296*e47783fdSXin Li unsigned error = settings->custom_zlib(out, outsize, in, insize, settings);
2297*e47783fdSXin Li /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/
2298*e47783fdSXin Li return error ? 111 : 0;
2299*e47783fdSXin Li } else {
2300*e47783fdSXin Li return lodepng_zlib_compress(out, outsize, in, insize, settings);
2301*e47783fdSXin Li }
2302*e47783fdSXin Li }
2303*e47783fdSXin Li
2304*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
2305*e47783fdSXin Li
2306*e47783fdSXin Li #else /*no LODEPNG_COMPILE_ZLIB*/
2307*e47783fdSXin Li
2308*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
zlib_decompress(unsigned char ** out,size_t * outsize,size_t expected_size,const unsigned char * in,size_t insize,const LodePNGDecompressSettings * settings)2309*e47783fdSXin Li static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
2310*e47783fdSXin Li const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
2311*e47783fdSXin Li if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
2312*e47783fdSXin Li (void)expected_size;
2313*e47783fdSXin Li return settings->custom_zlib(out, outsize, in, insize, settings);
2314*e47783fdSXin Li }
2315*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
2316*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
zlib_compress(unsigned char ** out,size_t * outsize,const unsigned char * in,size_t insize,const LodePNGCompressSettings * settings)2317*e47783fdSXin Li static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
2318*e47783fdSXin Li size_t insize, const LodePNGCompressSettings* settings) {
2319*e47783fdSXin Li if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
2320*e47783fdSXin Li return settings->custom_zlib(out, outsize, in, insize, settings);
2321*e47783fdSXin Li }
2322*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
2323*e47783fdSXin Li
2324*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ZLIB*/
2325*e47783fdSXin Li
2326*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2327*e47783fdSXin Li
2328*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
2329*e47783fdSXin Li
2330*e47783fdSXin Li /*this is a good tradeoff between speed and compression ratio*/
2331*e47783fdSXin Li #define DEFAULT_WINDOWSIZE 2048
2332*e47783fdSXin Li
lodepng_compress_settings_init(LodePNGCompressSettings * settings)2333*e47783fdSXin Li void lodepng_compress_settings_init(LodePNGCompressSettings* settings) {
2334*e47783fdSXin Li /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/
2335*e47783fdSXin Li settings->btype = 2;
2336*e47783fdSXin Li settings->use_lz77 = 1;
2337*e47783fdSXin Li settings->windowsize = DEFAULT_WINDOWSIZE;
2338*e47783fdSXin Li settings->minmatch = 3;
2339*e47783fdSXin Li settings->nicematch = 128;
2340*e47783fdSXin Li settings->lazymatching = 1;
2341*e47783fdSXin Li
2342*e47783fdSXin Li settings->custom_zlib = 0;
2343*e47783fdSXin Li settings->custom_deflate = 0;
2344*e47783fdSXin Li settings->custom_context = 0;
2345*e47783fdSXin Li }
2346*e47783fdSXin Li
2347*e47783fdSXin Li const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0};
2348*e47783fdSXin Li
2349*e47783fdSXin Li
2350*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
2351*e47783fdSXin Li
2352*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
2353*e47783fdSXin Li
lodepng_decompress_settings_init(LodePNGDecompressSettings * settings)2354*e47783fdSXin Li void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
2355*e47783fdSXin Li settings->ignore_adler32 = 0;
2356*e47783fdSXin Li settings->ignore_nlen = 0;
2357*e47783fdSXin Li settings->max_output_size = 0;
2358*e47783fdSXin Li
2359*e47783fdSXin Li settings->custom_zlib = 0;
2360*e47783fdSXin Li settings->custom_inflate = 0;
2361*e47783fdSXin Li settings->custom_context = 0;
2362*e47783fdSXin Li }
2363*e47783fdSXin Li
2364*e47783fdSXin Li const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0};
2365*e47783fdSXin Li
2366*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
2367*e47783fdSXin Li
2368*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2369*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2370*e47783fdSXin Li /* // End of Zlib related code. Begin of PNG related code. // */
2371*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2372*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2373*e47783fdSXin Li
2374*e47783fdSXin Li #ifdef LODEPNG_COMPILE_PNG
2375*e47783fdSXin Li
2376*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2377*e47783fdSXin Li /* / CRC32 / */
2378*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2379*e47783fdSXin Li
2380*e47783fdSXin Li
2381*e47783fdSXin Li #ifndef LODEPNG_NO_COMPILE_CRC
2382*e47783fdSXin Li /* CRC polynomial: 0xedb88320 */
2383*e47783fdSXin Li static unsigned lodepng_crc32_table[256] = {
2384*e47783fdSXin Li 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u,
2385*e47783fdSXin Li 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u,
2386*e47783fdSXin Li 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u,
2387*e47783fdSXin Li 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u,
2388*e47783fdSXin Li 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
2389*e47783fdSXin Li 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u,
2390*e47783fdSXin Li 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u,
2391*e47783fdSXin Li 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u,
2392*e47783fdSXin Li 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u,
2393*e47783fdSXin Li 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u,
2394*e47783fdSXin Li 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u,
2395*e47783fdSXin Li 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u,
2396*e47783fdSXin Li 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,
2397*e47783fdSXin Li 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u,
2398*e47783fdSXin Li 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u,
2399*e47783fdSXin Li 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u,
2400*e47783fdSXin Li 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u,
2401*e47783fdSXin Li 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u,
2402*e47783fdSXin Li 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u,
2403*e47783fdSXin Li 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u,
2404*e47783fdSXin Li 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,
2405*e47783fdSXin Li 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u,
2406*e47783fdSXin Li 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u,
2407*e47783fdSXin Li 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u,
2408*e47783fdSXin Li 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u,
2409*e47783fdSXin Li 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u,
2410*e47783fdSXin Li 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u,
2411*e47783fdSXin Li 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u,
2412*e47783fdSXin Li 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,
2413*e47783fdSXin Li 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u,
2414*e47783fdSXin Li 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u,
2415*e47783fdSXin Li 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u
2416*e47783fdSXin Li };
2417*e47783fdSXin Li
2418*e47783fdSXin Li /*Return the CRC of the bytes buf[0..len-1].*/
lodepng_crc32(const unsigned char * data,size_t length)2419*e47783fdSXin Li unsigned lodepng_crc32(const unsigned char* data, size_t length) {
2420*e47783fdSXin Li unsigned r = 0xffffffffu;
2421*e47783fdSXin Li size_t i;
2422*e47783fdSXin Li for(i = 0; i < length; ++i) {
2423*e47783fdSXin Li r = lodepng_crc32_table[(r ^ data[i]) & 0xffu] ^ (r >> 8u);
2424*e47783fdSXin Li }
2425*e47783fdSXin Li return r ^ 0xffffffffu;
2426*e47783fdSXin Li }
2427*e47783fdSXin Li #else /* !LODEPNG_NO_COMPILE_CRC */
2428*e47783fdSXin Li unsigned lodepng_crc32(const unsigned char* data, size_t length);
2429*e47783fdSXin Li #endif /* !LODEPNG_NO_COMPILE_CRC */
2430*e47783fdSXin Li
2431*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2432*e47783fdSXin Li /* / Reading and writing PNG color channel bits / */
2433*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2434*e47783fdSXin Li
2435*e47783fdSXin Li /* The color channel bits of less-than-8-bit pixels are read with the MSB of bytes first,
2436*e47783fdSXin Li so LodePNGBitWriter and LodePNGBitReader can't be used for those. */
2437*e47783fdSXin Li
readBitFromReversedStream(size_t * bitpointer,const unsigned char * bitstream)2438*e47783fdSXin Li static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) {
2439*e47783fdSXin Li unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);
2440*e47783fdSXin Li ++(*bitpointer);
2441*e47783fdSXin Li return result;
2442*e47783fdSXin Li }
2443*e47783fdSXin Li
2444*e47783fdSXin Li /* TODO: make this faster */
readBitsFromReversedStream(size_t * bitpointer,const unsigned char * bitstream,size_t nbits)2445*e47783fdSXin Li static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) {
2446*e47783fdSXin Li unsigned result = 0;
2447*e47783fdSXin Li size_t i;
2448*e47783fdSXin Li for(i = 0 ; i < nbits; ++i) {
2449*e47783fdSXin Li result <<= 1u;
2450*e47783fdSXin Li result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream);
2451*e47783fdSXin Li }
2452*e47783fdSXin Li return result;
2453*e47783fdSXin Li }
2454*e47783fdSXin Li
setBitOfReversedStream(size_t * bitpointer,unsigned char * bitstream,unsigned char bit)2455*e47783fdSXin Li static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) {
2456*e47783fdSXin Li /*the current bit in bitstream may be 0 or 1 for this to work*/
2457*e47783fdSXin Li if(bit == 0) bitstream[(*bitpointer) >> 3u] &= (unsigned char)(~(1u << (7u - ((*bitpointer) & 7u))));
2458*e47783fdSXin Li else bitstream[(*bitpointer) >> 3u] |= (1u << (7u - ((*bitpointer) & 7u)));
2459*e47783fdSXin Li ++(*bitpointer);
2460*e47783fdSXin Li }
2461*e47783fdSXin Li
2462*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2463*e47783fdSXin Li /* / PNG chunks / */
2464*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2465*e47783fdSXin Li
lodepng_chunk_length(const unsigned char * chunk)2466*e47783fdSXin Li unsigned lodepng_chunk_length(const unsigned char* chunk) {
2467*e47783fdSXin Li return lodepng_read32bitInt(&chunk[0]);
2468*e47783fdSXin Li }
2469*e47783fdSXin Li
lodepng_chunk_type(char type[5],const unsigned char * chunk)2470*e47783fdSXin Li void lodepng_chunk_type(char type[5], const unsigned char* chunk) {
2471*e47783fdSXin Li unsigned i;
2472*e47783fdSXin Li for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i];
2473*e47783fdSXin Li type[4] = 0; /*null termination char*/
2474*e47783fdSXin Li }
2475*e47783fdSXin Li
lodepng_chunk_type_equals(const unsigned char * chunk,const char * type)2476*e47783fdSXin Li unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) {
2477*e47783fdSXin Li if(lodepng_strlen(type) != 4) return 0;
2478*e47783fdSXin Li return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);
2479*e47783fdSXin Li }
2480*e47783fdSXin Li
lodepng_chunk_ancillary(const unsigned char * chunk)2481*e47783fdSXin Li unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) {
2482*e47783fdSXin Li return((chunk[4] & 32) != 0);
2483*e47783fdSXin Li }
2484*e47783fdSXin Li
lodepng_chunk_private(const unsigned char * chunk)2485*e47783fdSXin Li unsigned char lodepng_chunk_private(const unsigned char* chunk) {
2486*e47783fdSXin Li return((chunk[6] & 32) != 0);
2487*e47783fdSXin Li }
2488*e47783fdSXin Li
lodepng_chunk_safetocopy(const unsigned char * chunk)2489*e47783fdSXin Li unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) {
2490*e47783fdSXin Li return((chunk[7] & 32) != 0);
2491*e47783fdSXin Li }
2492*e47783fdSXin Li
lodepng_chunk_data(unsigned char * chunk)2493*e47783fdSXin Li unsigned char* lodepng_chunk_data(unsigned char* chunk) {
2494*e47783fdSXin Li return &chunk[8];
2495*e47783fdSXin Li }
2496*e47783fdSXin Li
lodepng_chunk_data_const(const unsigned char * chunk)2497*e47783fdSXin Li const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) {
2498*e47783fdSXin Li return &chunk[8];
2499*e47783fdSXin Li }
2500*e47783fdSXin Li
lodepng_chunk_check_crc(const unsigned char * chunk)2501*e47783fdSXin Li unsigned lodepng_chunk_check_crc(const unsigned char* chunk) {
2502*e47783fdSXin Li unsigned length = lodepng_chunk_length(chunk);
2503*e47783fdSXin Li unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]);
2504*e47783fdSXin Li /*the CRC is taken of the data and the 4 chunk type letters, not the length*/
2505*e47783fdSXin Li unsigned checksum = lodepng_crc32(&chunk[4], length + 4);
2506*e47783fdSXin Li if(CRC != checksum) return 1;
2507*e47783fdSXin Li else return 0;
2508*e47783fdSXin Li }
2509*e47783fdSXin Li
lodepng_chunk_generate_crc(unsigned char * chunk)2510*e47783fdSXin Li void lodepng_chunk_generate_crc(unsigned char* chunk) {
2511*e47783fdSXin Li unsigned length = lodepng_chunk_length(chunk);
2512*e47783fdSXin Li unsigned CRC = lodepng_crc32(&chunk[4], length + 4);
2513*e47783fdSXin Li lodepng_set32bitInt(chunk + 8 + length, CRC);
2514*e47783fdSXin Li }
2515*e47783fdSXin Li
lodepng_chunk_next(unsigned char * chunk,unsigned char * end)2516*e47783fdSXin Li unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) {
2517*e47783fdSXin Li if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/
2518*e47783fdSXin Li if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
2519*e47783fdSXin Li && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
2520*e47783fdSXin Li /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
2521*e47783fdSXin Li return chunk + 8;
2522*e47783fdSXin Li } else {
2523*e47783fdSXin Li size_t total_chunk_length;
2524*e47783fdSXin Li unsigned char* result;
2525*e47783fdSXin Li if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end;
2526*e47783fdSXin Li result = chunk + total_chunk_length;
2527*e47783fdSXin Li if(result < chunk) return end; /*pointer overflow*/
2528*e47783fdSXin Li return result;
2529*e47783fdSXin Li }
2530*e47783fdSXin Li }
2531*e47783fdSXin Li
lodepng_chunk_next_const(const unsigned char * chunk,const unsigned char * end)2532*e47783fdSXin Li const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) {
2533*e47783fdSXin Li if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/
2534*e47783fdSXin Li if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
2535*e47783fdSXin Li && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
2536*e47783fdSXin Li /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
2537*e47783fdSXin Li return chunk + 8;
2538*e47783fdSXin Li } else {
2539*e47783fdSXin Li size_t total_chunk_length;
2540*e47783fdSXin Li const unsigned char* result;
2541*e47783fdSXin Li if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end;
2542*e47783fdSXin Li result = chunk + total_chunk_length;
2543*e47783fdSXin Li if(result < chunk) return end; /*pointer overflow*/
2544*e47783fdSXin Li return result;
2545*e47783fdSXin Li }
2546*e47783fdSXin Li }
2547*e47783fdSXin Li
lodepng_chunk_find(unsigned char * chunk,unsigned char * end,const char type[5])2548*e47783fdSXin Li unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]) {
2549*e47783fdSXin Li for(;;) {
2550*e47783fdSXin Li if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */
2551*e47783fdSXin Li if(lodepng_chunk_type_equals(chunk, type)) return chunk;
2552*e47783fdSXin Li chunk = lodepng_chunk_next(chunk, end);
2553*e47783fdSXin Li }
2554*e47783fdSXin Li }
2555*e47783fdSXin Li
lodepng_chunk_find_const(const unsigned char * chunk,const unsigned char * end,const char type[5])2556*e47783fdSXin Li const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) {
2557*e47783fdSXin Li for(;;) {
2558*e47783fdSXin Li if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */
2559*e47783fdSXin Li if(lodepng_chunk_type_equals(chunk, type)) return chunk;
2560*e47783fdSXin Li chunk = lodepng_chunk_next_const(chunk, end);
2561*e47783fdSXin Li }
2562*e47783fdSXin Li }
2563*e47783fdSXin Li
lodepng_chunk_append(unsigned char ** out,size_t * outsize,const unsigned char * chunk)2564*e47783fdSXin Li unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) {
2565*e47783fdSXin Li unsigned i;
2566*e47783fdSXin Li size_t total_chunk_length, new_length;
2567*e47783fdSXin Li unsigned char *chunk_start, *new_buffer;
2568*e47783fdSXin Li
2569*e47783fdSXin Li if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77;
2570*e47783fdSXin Li if(lodepng_addofl(*outsize, total_chunk_length, &new_length)) return 77;
2571*e47783fdSXin Li
2572*e47783fdSXin Li new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
2573*e47783fdSXin Li if(!new_buffer) return 83; /*alloc fail*/
2574*e47783fdSXin Li (*out) = new_buffer;
2575*e47783fdSXin Li (*outsize) = new_length;
2576*e47783fdSXin Li chunk_start = &(*out)[new_length - total_chunk_length];
2577*e47783fdSXin Li
2578*e47783fdSXin Li for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i];
2579*e47783fdSXin Li
2580*e47783fdSXin Li return 0;
2581*e47783fdSXin Li }
2582*e47783fdSXin Li
2583*e47783fdSXin Li /*Sets length and name and allocates the space for data and crc but does not
2584*e47783fdSXin Li set data or crc yet. Returns the start of the chunk in chunk. The start of
2585*e47783fdSXin Li the data is at chunk + 8. To finalize chunk, add the data, then use
2586*e47783fdSXin Li lodepng_chunk_generate_crc */
lodepng_chunk_init(unsigned char ** chunk,ucvector * out,unsigned length,const char * type)2587*e47783fdSXin Li static unsigned lodepng_chunk_init(unsigned char** chunk,
2588*e47783fdSXin Li ucvector* out,
2589*e47783fdSXin Li unsigned length, const char* type) {
2590*e47783fdSXin Li size_t new_length = out->size;
2591*e47783fdSXin Li if(lodepng_addofl(new_length, length, &new_length)) return 77;
2592*e47783fdSXin Li if(lodepng_addofl(new_length, 12, &new_length)) return 77;
2593*e47783fdSXin Li if(!ucvector_resize(out, new_length)) return 83; /*alloc fail*/
2594*e47783fdSXin Li *chunk = out->data + new_length - length - 12u;
2595*e47783fdSXin Li
2596*e47783fdSXin Li /*1: length*/
2597*e47783fdSXin Li lodepng_set32bitInt(*chunk, length);
2598*e47783fdSXin Li
2599*e47783fdSXin Li /*2: chunk name (4 letters)*/
2600*e47783fdSXin Li lodepng_memcpy(*chunk + 4, type, 4);
2601*e47783fdSXin Li
2602*e47783fdSXin Li return 0;
2603*e47783fdSXin Li }
2604*e47783fdSXin Li
2605*e47783fdSXin Li /* like lodepng_chunk_create but with custom allocsize */
lodepng_chunk_createv(ucvector * out,unsigned length,const char * type,const unsigned char * data)2606*e47783fdSXin Li static unsigned lodepng_chunk_createv(ucvector* out,
2607*e47783fdSXin Li unsigned length, const char* type, const unsigned char* data) {
2608*e47783fdSXin Li unsigned char* chunk;
2609*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, length, type));
2610*e47783fdSXin Li
2611*e47783fdSXin Li /*3: the data*/
2612*e47783fdSXin Li lodepng_memcpy(chunk + 8, data, length);
2613*e47783fdSXin Li
2614*e47783fdSXin Li /*4: CRC (of the chunkname characters and the data)*/
2615*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
2616*e47783fdSXin Li
2617*e47783fdSXin Li return 0;
2618*e47783fdSXin Li }
2619*e47783fdSXin Li
lodepng_chunk_create(unsigned char ** out,size_t * outsize,unsigned length,const char * type,const unsigned char * data)2620*e47783fdSXin Li unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize,
2621*e47783fdSXin Li unsigned length, const char* type, const unsigned char* data) {
2622*e47783fdSXin Li ucvector v = ucvector_init(*out, *outsize);
2623*e47783fdSXin Li unsigned error = lodepng_chunk_createv(&v, length, type, data);
2624*e47783fdSXin Li *out = v.data;
2625*e47783fdSXin Li *outsize = v.size;
2626*e47783fdSXin Li return error;
2627*e47783fdSXin Li }
2628*e47783fdSXin Li
2629*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2630*e47783fdSXin Li /* / Color types, channels, bits / */
2631*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2632*e47783fdSXin Li
2633*e47783fdSXin Li /*checks if the colortype is valid and the bitdepth bd is allowed for this colortype.
2634*e47783fdSXin Li Return value is a LodePNG error code.*/
checkColorValidity(LodePNGColorType colortype,unsigned bd)2635*e47783fdSXin Li static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) {
2636*e47783fdSXin Li switch(colortype) {
2637*e47783fdSXin Li case LCT_GREY: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break;
2638*e47783fdSXin Li case LCT_RGB: if(!( bd == 8 || bd == 16)) return 37; break;
2639*e47783fdSXin Li case LCT_PALETTE: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break;
2640*e47783fdSXin Li case LCT_GREY_ALPHA: if(!( bd == 8 || bd == 16)) return 37; break;
2641*e47783fdSXin Li case LCT_RGBA: if(!( bd == 8 || bd == 16)) return 37; break;
2642*e47783fdSXin Li case LCT_MAX_OCTET_VALUE: return 31; /* invalid color type */
2643*e47783fdSXin Li default: return 31; /* invalid color type */
2644*e47783fdSXin Li }
2645*e47783fdSXin Li return 0; /*allowed color type / bits combination*/
2646*e47783fdSXin Li }
2647*e47783fdSXin Li
getNumColorChannels(LodePNGColorType colortype)2648*e47783fdSXin Li static unsigned getNumColorChannels(LodePNGColorType colortype) {
2649*e47783fdSXin Li switch(colortype) {
2650*e47783fdSXin Li case LCT_GREY: return 1;
2651*e47783fdSXin Li case LCT_RGB: return 3;
2652*e47783fdSXin Li case LCT_PALETTE: return 1;
2653*e47783fdSXin Li case LCT_GREY_ALPHA: return 2;
2654*e47783fdSXin Li case LCT_RGBA: return 4;
2655*e47783fdSXin Li case LCT_MAX_OCTET_VALUE: return 0; /* invalid color type */
2656*e47783fdSXin Li default: return 0; /*invalid color type*/
2657*e47783fdSXin Li }
2658*e47783fdSXin Li }
2659*e47783fdSXin Li
lodepng_get_bpp_lct(LodePNGColorType colortype,unsigned bitdepth)2660*e47783fdSXin Li static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) {
2661*e47783fdSXin Li /*bits per pixel is amount of channels * bits per channel*/
2662*e47783fdSXin Li return getNumColorChannels(colortype) * bitdepth;
2663*e47783fdSXin Li }
2664*e47783fdSXin Li
2665*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
2666*e47783fdSXin Li
lodepng_color_mode_init(LodePNGColorMode * info)2667*e47783fdSXin Li void lodepng_color_mode_init(LodePNGColorMode* info) {
2668*e47783fdSXin Li info->key_defined = 0;
2669*e47783fdSXin Li info->key_r = info->key_g = info->key_b = 0;
2670*e47783fdSXin Li info->colortype = LCT_RGBA;
2671*e47783fdSXin Li info->bitdepth = 8;
2672*e47783fdSXin Li info->palette = 0;
2673*e47783fdSXin Li info->palettesize = 0;
2674*e47783fdSXin Li }
2675*e47783fdSXin Li
2676*e47783fdSXin Li /*allocates palette memory if needed, and initializes all colors to black*/
lodepng_color_mode_alloc_palette(LodePNGColorMode * info)2677*e47783fdSXin Li static void lodepng_color_mode_alloc_palette(LodePNGColorMode* info) {
2678*e47783fdSXin Li size_t i;
2679*e47783fdSXin Li /*if the palette is already allocated, it will have size 1024 so no reallocation needed in that case*/
2680*e47783fdSXin Li /*the palette must have room for up to 256 colors with 4 bytes each.*/
2681*e47783fdSXin Li if(!info->palette) info->palette = (unsigned char*)lodepng_malloc(1024);
2682*e47783fdSXin Li if(!info->palette) return; /*alloc fail*/
2683*e47783fdSXin Li for(i = 0; i != 256; ++i) {
2684*e47783fdSXin Li /*Initialize all unused colors with black, the value used for invalid palette indices.
2685*e47783fdSXin Li This is an error according to the PNG spec, but common PNG decoders make it black instead.
2686*e47783fdSXin Li That makes color conversion slightly faster due to no error handling needed.*/
2687*e47783fdSXin Li info->palette[i * 4 + 0] = 0;
2688*e47783fdSXin Li info->palette[i * 4 + 1] = 0;
2689*e47783fdSXin Li info->palette[i * 4 + 2] = 0;
2690*e47783fdSXin Li info->palette[i * 4 + 3] = 255;
2691*e47783fdSXin Li }
2692*e47783fdSXin Li }
2693*e47783fdSXin Li
lodepng_color_mode_cleanup(LodePNGColorMode * info)2694*e47783fdSXin Li void lodepng_color_mode_cleanup(LodePNGColorMode* info) {
2695*e47783fdSXin Li lodepng_palette_clear(info);
2696*e47783fdSXin Li }
2697*e47783fdSXin Li
lodepng_color_mode_copy(LodePNGColorMode * dest,const LodePNGColorMode * source)2698*e47783fdSXin Li unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) {
2699*e47783fdSXin Li lodepng_color_mode_cleanup(dest);
2700*e47783fdSXin Li lodepng_memcpy(dest, source, sizeof(LodePNGColorMode));
2701*e47783fdSXin Li if(source->palette) {
2702*e47783fdSXin Li dest->palette = (unsigned char*)lodepng_malloc(1024);
2703*e47783fdSXin Li if(!dest->palette && source->palettesize) return 83; /*alloc fail*/
2704*e47783fdSXin Li lodepng_memcpy(dest->palette, source->palette, source->palettesize * 4);
2705*e47783fdSXin Li }
2706*e47783fdSXin Li return 0;
2707*e47783fdSXin Li }
2708*e47783fdSXin Li
lodepng_color_mode_make(LodePNGColorType colortype,unsigned bitdepth)2709*e47783fdSXin Li LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) {
2710*e47783fdSXin Li LodePNGColorMode result;
2711*e47783fdSXin Li lodepng_color_mode_init(&result);
2712*e47783fdSXin Li result.colortype = colortype;
2713*e47783fdSXin Li result.bitdepth = bitdepth;
2714*e47783fdSXin Li return result;
2715*e47783fdSXin Li }
2716*e47783fdSXin Li
lodepng_color_mode_equal(const LodePNGColorMode * a,const LodePNGColorMode * b)2717*e47783fdSXin Li static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) {
2718*e47783fdSXin Li size_t i;
2719*e47783fdSXin Li if(a->colortype != b->colortype) return 0;
2720*e47783fdSXin Li if(a->bitdepth != b->bitdepth) return 0;
2721*e47783fdSXin Li if(a->key_defined != b->key_defined) return 0;
2722*e47783fdSXin Li if(a->key_defined) {
2723*e47783fdSXin Li if(a->key_r != b->key_r) return 0;
2724*e47783fdSXin Li if(a->key_g != b->key_g) return 0;
2725*e47783fdSXin Li if(a->key_b != b->key_b) return 0;
2726*e47783fdSXin Li }
2727*e47783fdSXin Li if(a->palettesize != b->palettesize) return 0;
2728*e47783fdSXin Li for(i = 0; i != a->palettesize * 4; ++i) {
2729*e47783fdSXin Li if(a->palette[i] != b->palette[i]) return 0;
2730*e47783fdSXin Li }
2731*e47783fdSXin Li return 1;
2732*e47783fdSXin Li }
2733*e47783fdSXin Li
lodepng_palette_clear(LodePNGColorMode * info)2734*e47783fdSXin Li void lodepng_palette_clear(LodePNGColorMode* info) {
2735*e47783fdSXin Li if(info->palette) lodepng_free(info->palette);
2736*e47783fdSXin Li info->palette = 0;
2737*e47783fdSXin Li info->palettesize = 0;
2738*e47783fdSXin Li }
2739*e47783fdSXin Li
lodepng_palette_add(LodePNGColorMode * info,unsigned char r,unsigned char g,unsigned char b,unsigned char a)2740*e47783fdSXin Li unsigned lodepng_palette_add(LodePNGColorMode* info,
2741*e47783fdSXin Li unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
2742*e47783fdSXin Li if(!info->palette) /*allocate palette if empty*/ {
2743*e47783fdSXin Li lodepng_color_mode_alloc_palette(info);
2744*e47783fdSXin Li if(!info->palette) return 83; /*alloc fail*/
2745*e47783fdSXin Li }
2746*e47783fdSXin Li if(info->palettesize >= 256) {
2747*e47783fdSXin Li return 108; /*too many palette values*/
2748*e47783fdSXin Li }
2749*e47783fdSXin Li info->palette[4 * info->palettesize + 0] = r;
2750*e47783fdSXin Li info->palette[4 * info->palettesize + 1] = g;
2751*e47783fdSXin Li info->palette[4 * info->palettesize + 2] = b;
2752*e47783fdSXin Li info->palette[4 * info->palettesize + 3] = a;
2753*e47783fdSXin Li ++info->palettesize;
2754*e47783fdSXin Li return 0;
2755*e47783fdSXin Li }
2756*e47783fdSXin Li
2757*e47783fdSXin Li /*calculate bits per pixel out of colortype and bitdepth*/
lodepng_get_bpp(const LodePNGColorMode * info)2758*e47783fdSXin Li unsigned lodepng_get_bpp(const LodePNGColorMode* info) {
2759*e47783fdSXin Li return lodepng_get_bpp_lct(info->colortype, info->bitdepth);
2760*e47783fdSXin Li }
2761*e47783fdSXin Li
lodepng_get_channels(const LodePNGColorMode * info)2762*e47783fdSXin Li unsigned lodepng_get_channels(const LodePNGColorMode* info) {
2763*e47783fdSXin Li return getNumColorChannels(info->colortype);
2764*e47783fdSXin Li }
2765*e47783fdSXin Li
lodepng_is_greyscale_type(const LodePNGColorMode * info)2766*e47783fdSXin Li unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) {
2767*e47783fdSXin Li return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA;
2768*e47783fdSXin Li }
2769*e47783fdSXin Li
lodepng_is_alpha_type(const LodePNGColorMode * info)2770*e47783fdSXin Li unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) {
2771*e47783fdSXin Li return (info->colortype & 4) != 0; /*4 or 6*/
2772*e47783fdSXin Li }
2773*e47783fdSXin Li
lodepng_is_palette_type(const LodePNGColorMode * info)2774*e47783fdSXin Li unsigned lodepng_is_palette_type(const LodePNGColorMode* info) {
2775*e47783fdSXin Li return info->colortype == LCT_PALETTE;
2776*e47783fdSXin Li }
2777*e47783fdSXin Li
lodepng_has_palette_alpha(const LodePNGColorMode * info)2778*e47783fdSXin Li unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) {
2779*e47783fdSXin Li size_t i;
2780*e47783fdSXin Li for(i = 0; i != info->palettesize; ++i) {
2781*e47783fdSXin Li if(info->palette[i * 4 + 3] < 255) return 1;
2782*e47783fdSXin Li }
2783*e47783fdSXin Li return 0;
2784*e47783fdSXin Li }
2785*e47783fdSXin Li
lodepng_can_have_alpha(const LodePNGColorMode * info)2786*e47783fdSXin Li unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) {
2787*e47783fdSXin Li return info->key_defined
2788*e47783fdSXin Li || lodepng_is_alpha_type(info)
2789*e47783fdSXin Li || lodepng_has_palette_alpha(info);
2790*e47783fdSXin Li }
2791*e47783fdSXin Li
lodepng_get_raw_size_lct(unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)2792*e47783fdSXin Li static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
2793*e47783fdSXin Li size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);
2794*e47783fdSXin Li size_t n = (size_t)w * (size_t)h;
2795*e47783fdSXin Li return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u;
2796*e47783fdSXin Li }
2797*e47783fdSXin Li
lodepng_get_raw_size(unsigned w,unsigned h,const LodePNGColorMode * color)2798*e47783fdSXin Li size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) {
2799*e47783fdSXin Li return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth);
2800*e47783fdSXin Li }
2801*e47783fdSXin Li
2802*e47783fdSXin Li
2803*e47783fdSXin Li #ifdef LODEPNG_COMPILE_PNG
2804*e47783fdSXin Li
2805*e47783fdSXin Li /*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer,
2806*e47783fdSXin Li and in addition has one extra byte per line: the filter byte. So this gives a larger
2807*e47783fdSXin Li result than lodepng_get_raw_size. Set h to 1 to get the size of 1 row including filter byte. */
lodepng_get_raw_size_idat(unsigned w,unsigned h,unsigned bpp)2808*e47783fdSXin Li static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, unsigned bpp) {
2809*e47783fdSXin Li /* + 1 for the filter byte, and possibly plus padding bits per line. */
2810*e47783fdSXin Li /* Ignoring casts, the expression is equal to (w * bpp + 7) / 8 + 1, but avoids overflow of w * bpp */
2811*e47783fdSXin Li size_t line = ((size_t)(w / 8u) * bpp) + 1u + ((w & 7u) * bpp + 7u) / 8u;
2812*e47783fdSXin Li return (size_t)h * line;
2813*e47783fdSXin Li }
2814*e47783fdSXin Li
2815*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
2816*e47783fdSXin Li /*Safely checks whether size_t overflow can be caused due to amount of pixels.
2817*e47783fdSXin Li This check is overcautious rather than precise. If this check indicates no overflow,
2818*e47783fdSXin Li you can safely compute in a size_t (but not an unsigned):
2819*e47783fdSXin Li -(size_t)w * (size_t)h * 8
2820*e47783fdSXin Li -amount of bytes in IDAT (including filter, padding and Adam7 bytes)
2821*e47783fdSXin Li -amount of bytes in raw color model
2822*e47783fdSXin Li Returns 1 if overflow possible, 0 if not.
2823*e47783fdSXin Li */
lodepng_pixel_overflow(unsigned w,unsigned h,const LodePNGColorMode * pngcolor,const LodePNGColorMode * rawcolor)2824*e47783fdSXin Li static int lodepng_pixel_overflow(unsigned w, unsigned h,
2825*e47783fdSXin Li const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) {
2826*e47783fdSXin Li size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor));
2827*e47783fdSXin Li size_t numpixels, total;
2828*e47783fdSXin Li size_t line; /* bytes per line in worst case */
2829*e47783fdSXin Li
2830*e47783fdSXin Li if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1;
2831*e47783fdSXin Li if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */
2832*e47783fdSXin Li
2833*e47783fdSXin Li /* Bytes per scanline with the expression "(w / 8u) * bpp) + ((w & 7u) * bpp + 7u) / 8u" */
2834*e47783fdSXin Li if(lodepng_mulofl((size_t)(w / 8u), bpp, &line)) return 1;
2835*e47783fdSXin Li if(lodepng_addofl(line, ((w & 7u) * bpp + 7u) / 8u, &line)) return 1;
2836*e47783fdSXin Li
2837*e47783fdSXin Li if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */
2838*e47783fdSXin Li if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */
2839*e47783fdSXin Li
2840*e47783fdSXin Li return 0; /* no overflow */
2841*e47783fdSXin Li }
2842*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
2843*e47783fdSXin Li #endif /*LODEPNG_COMPILE_PNG*/
2844*e47783fdSXin Li
2845*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
2846*e47783fdSXin Li
LodePNGUnknownChunks_init(LodePNGInfo * info)2847*e47783fdSXin Li static void LodePNGUnknownChunks_init(LodePNGInfo* info) {
2848*e47783fdSXin Li unsigned i;
2849*e47783fdSXin Li for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0;
2850*e47783fdSXin Li for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0;
2851*e47783fdSXin Li }
2852*e47783fdSXin Li
LodePNGUnknownChunks_cleanup(LodePNGInfo * info)2853*e47783fdSXin Li static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) {
2854*e47783fdSXin Li unsigned i;
2855*e47783fdSXin Li for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]);
2856*e47783fdSXin Li }
2857*e47783fdSXin Li
LodePNGUnknownChunks_copy(LodePNGInfo * dest,const LodePNGInfo * src)2858*e47783fdSXin Li static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) {
2859*e47783fdSXin Li unsigned i;
2860*e47783fdSXin Li
2861*e47783fdSXin Li LodePNGUnknownChunks_cleanup(dest);
2862*e47783fdSXin Li
2863*e47783fdSXin Li for(i = 0; i != 3; ++i) {
2864*e47783fdSXin Li size_t j;
2865*e47783fdSXin Li dest->unknown_chunks_size[i] = src->unknown_chunks_size[i];
2866*e47783fdSXin Li dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]);
2867*e47783fdSXin Li if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/
2868*e47783fdSXin Li for(j = 0; j < src->unknown_chunks_size[i]; ++j) {
2869*e47783fdSXin Li dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j];
2870*e47783fdSXin Li }
2871*e47783fdSXin Li }
2872*e47783fdSXin Li
2873*e47783fdSXin Li return 0;
2874*e47783fdSXin Li }
2875*e47783fdSXin Li
2876*e47783fdSXin Li /******************************************************************************/
2877*e47783fdSXin Li
LodePNGText_init(LodePNGInfo * info)2878*e47783fdSXin Li static void LodePNGText_init(LodePNGInfo* info) {
2879*e47783fdSXin Li info->text_num = 0;
2880*e47783fdSXin Li info->text_keys = NULL;
2881*e47783fdSXin Li info->text_strings = NULL;
2882*e47783fdSXin Li }
2883*e47783fdSXin Li
LodePNGText_cleanup(LodePNGInfo * info)2884*e47783fdSXin Li static void LodePNGText_cleanup(LodePNGInfo* info) {
2885*e47783fdSXin Li size_t i;
2886*e47783fdSXin Li for(i = 0; i != info->text_num; ++i) {
2887*e47783fdSXin Li string_cleanup(&info->text_keys[i]);
2888*e47783fdSXin Li string_cleanup(&info->text_strings[i]);
2889*e47783fdSXin Li }
2890*e47783fdSXin Li lodepng_free(info->text_keys);
2891*e47783fdSXin Li lodepng_free(info->text_strings);
2892*e47783fdSXin Li }
2893*e47783fdSXin Li
LodePNGText_copy(LodePNGInfo * dest,const LodePNGInfo * source)2894*e47783fdSXin Li static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
2895*e47783fdSXin Li size_t i = 0;
2896*e47783fdSXin Li dest->text_keys = NULL;
2897*e47783fdSXin Li dest->text_strings = NULL;
2898*e47783fdSXin Li dest->text_num = 0;
2899*e47783fdSXin Li for(i = 0; i != source->text_num; ++i) {
2900*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
2901*e47783fdSXin Li }
2902*e47783fdSXin Li return 0;
2903*e47783fdSXin Li }
2904*e47783fdSXin Li
lodepng_add_text_sized(LodePNGInfo * info,const char * key,const char * str,size_t size)2905*e47783fdSXin Li static unsigned lodepng_add_text_sized(LodePNGInfo* info, const char* key, const char* str, size_t size) {
2906*e47783fdSXin Li char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1)));
2907*e47783fdSXin Li char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1)));
2908*e47783fdSXin Li
2909*e47783fdSXin Li if(new_keys) info->text_keys = new_keys;
2910*e47783fdSXin Li if(new_strings) info->text_strings = new_strings;
2911*e47783fdSXin Li
2912*e47783fdSXin Li if(!new_keys || !new_strings) return 83; /*alloc fail*/
2913*e47783fdSXin Li
2914*e47783fdSXin Li ++info->text_num;
2915*e47783fdSXin Li info->text_keys[info->text_num - 1] = alloc_string(key);
2916*e47783fdSXin Li info->text_strings[info->text_num - 1] = alloc_string_sized(str, size);
2917*e47783fdSXin Li if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/
2918*e47783fdSXin Li
2919*e47783fdSXin Li return 0;
2920*e47783fdSXin Li }
2921*e47783fdSXin Li
lodepng_add_text(LodePNGInfo * info,const char * key,const char * str)2922*e47783fdSXin Li unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) {
2923*e47783fdSXin Li return lodepng_add_text_sized(info, key, str, lodepng_strlen(str));
2924*e47783fdSXin Li }
2925*e47783fdSXin Li
lodepng_clear_text(LodePNGInfo * info)2926*e47783fdSXin Li void lodepng_clear_text(LodePNGInfo* info) {
2927*e47783fdSXin Li LodePNGText_cleanup(info);
2928*e47783fdSXin Li }
2929*e47783fdSXin Li
2930*e47783fdSXin Li /******************************************************************************/
2931*e47783fdSXin Li
LodePNGIText_init(LodePNGInfo * info)2932*e47783fdSXin Li static void LodePNGIText_init(LodePNGInfo* info) {
2933*e47783fdSXin Li info->itext_num = 0;
2934*e47783fdSXin Li info->itext_keys = NULL;
2935*e47783fdSXin Li info->itext_langtags = NULL;
2936*e47783fdSXin Li info->itext_transkeys = NULL;
2937*e47783fdSXin Li info->itext_strings = NULL;
2938*e47783fdSXin Li }
2939*e47783fdSXin Li
LodePNGIText_cleanup(LodePNGInfo * info)2940*e47783fdSXin Li static void LodePNGIText_cleanup(LodePNGInfo* info) {
2941*e47783fdSXin Li size_t i;
2942*e47783fdSXin Li for(i = 0; i != info->itext_num; ++i) {
2943*e47783fdSXin Li string_cleanup(&info->itext_keys[i]);
2944*e47783fdSXin Li string_cleanup(&info->itext_langtags[i]);
2945*e47783fdSXin Li string_cleanup(&info->itext_transkeys[i]);
2946*e47783fdSXin Li string_cleanup(&info->itext_strings[i]);
2947*e47783fdSXin Li }
2948*e47783fdSXin Li lodepng_free(info->itext_keys);
2949*e47783fdSXin Li lodepng_free(info->itext_langtags);
2950*e47783fdSXin Li lodepng_free(info->itext_transkeys);
2951*e47783fdSXin Li lodepng_free(info->itext_strings);
2952*e47783fdSXin Li }
2953*e47783fdSXin Li
LodePNGIText_copy(LodePNGInfo * dest,const LodePNGInfo * source)2954*e47783fdSXin Li static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
2955*e47783fdSXin Li size_t i = 0;
2956*e47783fdSXin Li dest->itext_keys = NULL;
2957*e47783fdSXin Li dest->itext_langtags = NULL;
2958*e47783fdSXin Li dest->itext_transkeys = NULL;
2959*e47783fdSXin Li dest->itext_strings = NULL;
2960*e47783fdSXin Li dest->itext_num = 0;
2961*e47783fdSXin Li for(i = 0; i != source->itext_num; ++i) {
2962*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
2963*e47783fdSXin Li source->itext_transkeys[i], source->itext_strings[i]));
2964*e47783fdSXin Li }
2965*e47783fdSXin Li return 0;
2966*e47783fdSXin Li }
2967*e47783fdSXin Li
lodepng_clear_itext(LodePNGInfo * info)2968*e47783fdSXin Li void lodepng_clear_itext(LodePNGInfo* info) {
2969*e47783fdSXin Li LodePNGIText_cleanup(info);
2970*e47783fdSXin Li }
2971*e47783fdSXin Li
lodepng_add_itext_sized(LodePNGInfo * info,const char * key,const char * langtag,const char * transkey,const char * str,size_t size)2972*e47783fdSXin Li static unsigned lodepng_add_itext_sized(LodePNGInfo* info, const char* key, const char* langtag,
2973*e47783fdSXin Li const char* transkey, const char* str, size_t size) {
2974*e47783fdSXin Li char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1)));
2975*e47783fdSXin Li char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1)));
2976*e47783fdSXin Li char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1)));
2977*e47783fdSXin Li char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1)));
2978*e47783fdSXin Li
2979*e47783fdSXin Li if(new_keys) info->itext_keys = new_keys;
2980*e47783fdSXin Li if(new_langtags) info->itext_langtags = new_langtags;
2981*e47783fdSXin Li if(new_transkeys) info->itext_transkeys = new_transkeys;
2982*e47783fdSXin Li if(new_strings) info->itext_strings = new_strings;
2983*e47783fdSXin Li
2984*e47783fdSXin Li if(!new_keys || !new_langtags || !new_transkeys || !new_strings) return 83; /*alloc fail*/
2985*e47783fdSXin Li
2986*e47783fdSXin Li ++info->itext_num;
2987*e47783fdSXin Li
2988*e47783fdSXin Li info->itext_keys[info->itext_num - 1] = alloc_string(key);
2989*e47783fdSXin Li info->itext_langtags[info->itext_num - 1] = alloc_string(langtag);
2990*e47783fdSXin Li info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey);
2991*e47783fdSXin Li info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size);
2992*e47783fdSXin Li
2993*e47783fdSXin Li return 0;
2994*e47783fdSXin Li }
2995*e47783fdSXin Li
lodepng_add_itext(LodePNGInfo * info,const char * key,const char * langtag,const char * transkey,const char * str)2996*e47783fdSXin Li unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,
2997*e47783fdSXin Li const char* transkey, const char* str) {
2998*e47783fdSXin Li return lodepng_add_itext_sized(info, key, langtag, transkey, str, lodepng_strlen(str));
2999*e47783fdSXin Li }
3000*e47783fdSXin Li
3001*e47783fdSXin Li /* same as set but does not delete */
lodepng_assign_icc(LodePNGInfo * info,const char * name,const unsigned char * profile,unsigned profile_size)3002*e47783fdSXin Li static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
3003*e47783fdSXin Li if(profile_size == 0) return 100; /*invalid ICC profile size*/
3004*e47783fdSXin Li
3005*e47783fdSXin Li info->iccp_name = alloc_string(name);
3006*e47783fdSXin Li info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size);
3007*e47783fdSXin Li
3008*e47783fdSXin Li if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/
3009*e47783fdSXin Li
3010*e47783fdSXin Li lodepng_memcpy(info->iccp_profile, profile, profile_size);
3011*e47783fdSXin Li info->iccp_profile_size = profile_size;
3012*e47783fdSXin Li
3013*e47783fdSXin Li return 0; /*ok*/
3014*e47783fdSXin Li }
3015*e47783fdSXin Li
lodepng_set_icc(LodePNGInfo * info,const char * name,const unsigned char * profile,unsigned profile_size)3016*e47783fdSXin Li unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
3017*e47783fdSXin Li if(info->iccp_name) lodepng_clear_icc(info);
3018*e47783fdSXin Li info->iccp_defined = 1;
3019*e47783fdSXin Li
3020*e47783fdSXin Li return lodepng_assign_icc(info, name, profile, profile_size);
3021*e47783fdSXin Li }
3022*e47783fdSXin Li
lodepng_clear_icc(LodePNGInfo * info)3023*e47783fdSXin Li void lodepng_clear_icc(LodePNGInfo* info) {
3024*e47783fdSXin Li string_cleanup(&info->iccp_name);
3025*e47783fdSXin Li lodepng_free(info->iccp_profile);
3026*e47783fdSXin Li info->iccp_profile = NULL;
3027*e47783fdSXin Li info->iccp_profile_size = 0;
3028*e47783fdSXin Li info->iccp_defined = 0;
3029*e47783fdSXin Li }
3030*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
3031*e47783fdSXin Li
lodepng_info_init(LodePNGInfo * info)3032*e47783fdSXin Li void lodepng_info_init(LodePNGInfo* info) {
3033*e47783fdSXin Li lodepng_color_mode_init(&info->color);
3034*e47783fdSXin Li info->interlace_method = 0;
3035*e47783fdSXin Li info->compression_method = 0;
3036*e47783fdSXin Li info->filter_method = 0;
3037*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
3038*e47783fdSXin Li info->background_defined = 0;
3039*e47783fdSXin Li info->background_r = info->background_g = info->background_b = 0;
3040*e47783fdSXin Li
3041*e47783fdSXin Li LodePNGText_init(info);
3042*e47783fdSXin Li LodePNGIText_init(info);
3043*e47783fdSXin Li
3044*e47783fdSXin Li info->time_defined = 0;
3045*e47783fdSXin Li info->phys_defined = 0;
3046*e47783fdSXin Li
3047*e47783fdSXin Li info->gama_defined = 0;
3048*e47783fdSXin Li info->chrm_defined = 0;
3049*e47783fdSXin Li info->srgb_defined = 0;
3050*e47783fdSXin Li info->iccp_defined = 0;
3051*e47783fdSXin Li info->iccp_name = NULL;
3052*e47783fdSXin Li info->iccp_profile = NULL;
3053*e47783fdSXin Li
3054*e47783fdSXin Li LodePNGUnknownChunks_init(info);
3055*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
3056*e47783fdSXin Li }
3057*e47783fdSXin Li
lodepng_info_cleanup(LodePNGInfo * info)3058*e47783fdSXin Li void lodepng_info_cleanup(LodePNGInfo* info) {
3059*e47783fdSXin Li lodepng_color_mode_cleanup(&info->color);
3060*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
3061*e47783fdSXin Li LodePNGText_cleanup(info);
3062*e47783fdSXin Li LodePNGIText_cleanup(info);
3063*e47783fdSXin Li
3064*e47783fdSXin Li lodepng_clear_icc(info);
3065*e47783fdSXin Li
3066*e47783fdSXin Li LodePNGUnknownChunks_cleanup(info);
3067*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
3068*e47783fdSXin Li }
3069*e47783fdSXin Li
lodepng_info_copy(LodePNGInfo * dest,const LodePNGInfo * source)3070*e47783fdSXin Li unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
3071*e47783fdSXin Li lodepng_info_cleanup(dest);
3072*e47783fdSXin Li lodepng_memcpy(dest, source, sizeof(LodePNGInfo));
3073*e47783fdSXin Li lodepng_color_mode_init(&dest->color);
3074*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color));
3075*e47783fdSXin Li
3076*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
3077*e47783fdSXin Li CERROR_TRY_RETURN(LodePNGText_copy(dest, source));
3078*e47783fdSXin Li CERROR_TRY_RETURN(LodePNGIText_copy(dest, source));
3079*e47783fdSXin Li if(source->iccp_defined) {
3080*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size));
3081*e47783fdSXin Li }
3082*e47783fdSXin Li
3083*e47783fdSXin Li LodePNGUnknownChunks_init(dest);
3084*e47783fdSXin Li CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source));
3085*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
3086*e47783fdSXin Li return 0;
3087*e47783fdSXin Li }
3088*e47783fdSXin Li
3089*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
3090*e47783fdSXin Li
3091*e47783fdSXin Li /*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/
addColorBits(unsigned char * out,size_t index,unsigned bits,unsigned in)3092*e47783fdSXin Li static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) {
3093*e47783fdSXin Li unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/
3094*e47783fdSXin Li /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/
3095*e47783fdSXin Li unsigned p = index & m;
3096*e47783fdSXin Li in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/
3097*e47783fdSXin Li in = in << (bits * (m - p));
3098*e47783fdSXin Li if(p == 0) out[index * bits / 8u] = in;
3099*e47783fdSXin Li else out[index * bits / 8u] |= in;
3100*e47783fdSXin Li }
3101*e47783fdSXin Li
3102*e47783fdSXin Li typedef struct ColorTree ColorTree;
3103*e47783fdSXin Li
3104*e47783fdSXin Li /*
3105*e47783fdSXin Li One node of a color tree
3106*e47783fdSXin Li This is the data structure used to count the number of unique colors and to get a palette
3107*e47783fdSXin Li index for a color. It's like an octree, but because the alpha channel is used too, each
3108*e47783fdSXin Li node has 16 instead of 8 children.
3109*e47783fdSXin Li */
3110*e47783fdSXin Li struct ColorTree {
3111*e47783fdSXin Li ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/
3112*e47783fdSXin Li int index; /*the payload. Only has a meaningful value if this is in the last level*/
3113*e47783fdSXin Li };
3114*e47783fdSXin Li
color_tree_init(ColorTree * tree)3115*e47783fdSXin Li static void color_tree_init(ColorTree* tree) {
3116*e47783fdSXin Li lodepng_memset(tree->children, 0, 16 * sizeof(*tree->children));
3117*e47783fdSXin Li tree->index = -1;
3118*e47783fdSXin Li }
3119*e47783fdSXin Li
color_tree_cleanup(ColorTree * tree)3120*e47783fdSXin Li static void color_tree_cleanup(ColorTree* tree) {
3121*e47783fdSXin Li int i;
3122*e47783fdSXin Li for(i = 0; i != 16; ++i) {
3123*e47783fdSXin Li if(tree->children[i]) {
3124*e47783fdSXin Li color_tree_cleanup(tree->children[i]);
3125*e47783fdSXin Li lodepng_free(tree->children[i]);
3126*e47783fdSXin Li }
3127*e47783fdSXin Li }
3128*e47783fdSXin Li }
3129*e47783fdSXin Li
3130*e47783fdSXin Li /*returns -1 if color not present, its index otherwise*/
color_tree_get(ColorTree * tree,unsigned char r,unsigned char g,unsigned char b,unsigned char a)3131*e47783fdSXin Li static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
3132*e47783fdSXin Li int bit = 0;
3133*e47783fdSXin Li for(bit = 0; bit < 8; ++bit) {
3134*e47783fdSXin Li int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
3135*e47783fdSXin Li if(!tree->children[i]) return -1;
3136*e47783fdSXin Li else tree = tree->children[i];
3137*e47783fdSXin Li }
3138*e47783fdSXin Li return tree ? tree->index : -1;
3139*e47783fdSXin Li }
3140*e47783fdSXin Li
3141*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
color_tree_has(ColorTree * tree,unsigned char r,unsigned char g,unsigned char b,unsigned char a)3142*e47783fdSXin Li static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
3143*e47783fdSXin Li return color_tree_get(tree, r, g, b, a) >= 0;
3144*e47783fdSXin Li }
3145*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
3146*e47783fdSXin Li
3147*e47783fdSXin Li /*color is not allowed to already exist.
3148*e47783fdSXin Li Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")
3149*e47783fdSXin Li Returns error code, or 0 if ok*/
color_tree_add(ColorTree * tree,unsigned char r,unsigned char g,unsigned char b,unsigned char a,unsigned index)3150*e47783fdSXin Li static unsigned color_tree_add(ColorTree* tree,
3151*e47783fdSXin Li unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) {
3152*e47783fdSXin Li int bit;
3153*e47783fdSXin Li for(bit = 0; bit < 8; ++bit) {
3154*e47783fdSXin Li int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
3155*e47783fdSXin Li if(!tree->children[i]) {
3156*e47783fdSXin Li tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree));
3157*e47783fdSXin Li if(!tree->children[i]) return 83; /*alloc fail*/
3158*e47783fdSXin Li color_tree_init(tree->children[i]);
3159*e47783fdSXin Li }
3160*e47783fdSXin Li tree = tree->children[i];
3161*e47783fdSXin Li }
3162*e47783fdSXin Li tree->index = (int)index;
3163*e47783fdSXin Li return 0;
3164*e47783fdSXin Li }
3165*e47783fdSXin Li
3166*e47783fdSXin Li /*put a pixel, given its RGBA color, into image of any color type*/
rgba8ToPixel(unsigned char * out,size_t i,const LodePNGColorMode * mode,ColorTree * tree,unsigned char r,unsigned char g,unsigned char b,unsigned char a)3167*e47783fdSXin Li static unsigned rgba8ToPixel(unsigned char* out, size_t i,
3168*e47783fdSXin Li const LodePNGColorMode* mode, ColorTree* tree /*for palette*/,
3169*e47783fdSXin Li unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
3170*e47783fdSXin Li if(mode->colortype == LCT_GREY) {
3171*e47783fdSXin Li unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/
3172*e47783fdSXin Li if(mode->bitdepth == 8) out[i] = gray;
3173*e47783fdSXin Li else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray;
3174*e47783fdSXin Li else {
3175*e47783fdSXin Li /*take the most significant bits of gray*/
3176*e47783fdSXin Li gray = ((unsigned)gray >> (8u - mode->bitdepth)) & ((1u << mode->bitdepth) - 1u);
3177*e47783fdSXin Li addColorBits(out, i, mode->bitdepth, gray);
3178*e47783fdSXin Li }
3179*e47783fdSXin Li } else if(mode->colortype == LCT_RGB) {
3180*e47783fdSXin Li if(mode->bitdepth == 8) {
3181*e47783fdSXin Li out[i * 3 + 0] = r;
3182*e47783fdSXin Li out[i * 3 + 1] = g;
3183*e47783fdSXin Li out[i * 3 + 2] = b;
3184*e47783fdSXin Li } else {
3185*e47783fdSXin Li out[i * 6 + 0] = out[i * 6 + 1] = r;
3186*e47783fdSXin Li out[i * 6 + 2] = out[i * 6 + 3] = g;
3187*e47783fdSXin Li out[i * 6 + 4] = out[i * 6 + 5] = b;
3188*e47783fdSXin Li }
3189*e47783fdSXin Li } else if(mode->colortype == LCT_PALETTE) {
3190*e47783fdSXin Li int index = color_tree_get(tree, r, g, b, a);
3191*e47783fdSXin Li if(index < 0) return 82; /*color not in palette*/
3192*e47783fdSXin Li if(mode->bitdepth == 8) out[i] = index;
3193*e47783fdSXin Li else addColorBits(out, i, mode->bitdepth, (unsigned)index);
3194*e47783fdSXin Li } else if(mode->colortype == LCT_GREY_ALPHA) {
3195*e47783fdSXin Li unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/
3196*e47783fdSXin Li if(mode->bitdepth == 8) {
3197*e47783fdSXin Li out[i * 2 + 0] = gray;
3198*e47783fdSXin Li out[i * 2 + 1] = a;
3199*e47783fdSXin Li } else if(mode->bitdepth == 16) {
3200*e47783fdSXin Li out[i * 4 + 0] = out[i * 4 + 1] = gray;
3201*e47783fdSXin Li out[i * 4 + 2] = out[i * 4 + 3] = a;
3202*e47783fdSXin Li }
3203*e47783fdSXin Li } else if(mode->colortype == LCT_RGBA) {
3204*e47783fdSXin Li if(mode->bitdepth == 8) {
3205*e47783fdSXin Li out[i * 4 + 0] = r;
3206*e47783fdSXin Li out[i * 4 + 1] = g;
3207*e47783fdSXin Li out[i * 4 + 2] = b;
3208*e47783fdSXin Li out[i * 4 + 3] = a;
3209*e47783fdSXin Li } else {
3210*e47783fdSXin Li out[i * 8 + 0] = out[i * 8 + 1] = r;
3211*e47783fdSXin Li out[i * 8 + 2] = out[i * 8 + 3] = g;
3212*e47783fdSXin Li out[i * 8 + 4] = out[i * 8 + 5] = b;
3213*e47783fdSXin Li out[i * 8 + 6] = out[i * 8 + 7] = a;
3214*e47783fdSXin Li }
3215*e47783fdSXin Li }
3216*e47783fdSXin Li
3217*e47783fdSXin Li return 0; /*no error*/
3218*e47783fdSXin Li }
3219*e47783fdSXin Li
3220*e47783fdSXin Li /*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/
rgba16ToPixel(unsigned char * out,size_t i,const LodePNGColorMode * mode,unsigned short r,unsigned short g,unsigned short b,unsigned short a)3221*e47783fdSXin Li static void rgba16ToPixel(unsigned char* out, size_t i,
3222*e47783fdSXin Li const LodePNGColorMode* mode,
3223*e47783fdSXin Li unsigned short r, unsigned short g, unsigned short b, unsigned short a) {
3224*e47783fdSXin Li if(mode->colortype == LCT_GREY) {
3225*e47783fdSXin Li unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/
3226*e47783fdSXin Li out[i * 2 + 0] = (gray >> 8) & 255;
3227*e47783fdSXin Li out[i * 2 + 1] = gray & 255;
3228*e47783fdSXin Li } else if(mode->colortype == LCT_RGB) {
3229*e47783fdSXin Li out[i * 6 + 0] = (r >> 8) & 255;
3230*e47783fdSXin Li out[i * 6 + 1] = r & 255;
3231*e47783fdSXin Li out[i * 6 + 2] = (g >> 8) & 255;
3232*e47783fdSXin Li out[i * 6 + 3] = g & 255;
3233*e47783fdSXin Li out[i * 6 + 4] = (b >> 8) & 255;
3234*e47783fdSXin Li out[i * 6 + 5] = b & 255;
3235*e47783fdSXin Li } else if(mode->colortype == LCT_GREY_ALPHA) {
3236*e47783fdSXin Li unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/
3237*e47783fdSXin Li out[i * 4 + 0] = (gray >> 8) & 255;
3238*e47783fdSXin Li out[i * 4 + 1] = gray & 255;
3239*e47783fdSXin Li out[i * 4 + 2] = (a >> 8) & 255;
3240*e47783fdSXin Li out[i * 4 + 3] = a & 255;
3241*e47783fdSXin Li } else if(mode->colortype == LCT_RGBA) {
3242*e47783fdSXin Li out[i * 8 + 0] = (r >> 8) & 255;
3243*e47783fdSXin Li out[i * 8 + 1] = r & 255;
3244*e47783fdSXin Li out[i * 8 + 2] = (g >> 8) & 255;
3245*e47783fdSXin Li out[i * 8 + 3] = g & 255;
3246*e47783fdSXin Li out[i * 8 + 4] = (b >> 8) & 255;
3247*e47783fdSXin Li out[i * 8 + 5] = b & 255;
3248*e47783fdSXin Li out[i * 8 + 6] = (a >> 8) & 255;
3249*e47783fdSXin Li out[i * 8 + 7] = a & 255;
3250*e47783fdSXin Li }
3251*e47783fdSXin Li }
3252*e47783fdSXin Li
3253*e47783fdSXin Li /*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/
getPixelColorRGBA8(unsigned char * r,unsigned char * g,unsigned char * b,unsigned char * a,const unsigned char * in,size_t i,const LodePNGColorMode * mode)3254*e47783fdSXin Li static void getPixelColorRGBA8(unsigned char* r, unsigned char* g,
3255*e47783fdSXin Li unsigned char* b, unsigned char* a,
3256*e47783fdSXin Li const unsigned char* in, size_t i,
3257*e47783fdSXin Li const LodePNGColorMode* mode) {
3258*e47783fdSXin Li if(mode->colortype == LCT_GREY) {
3259*e47783fdSXin Li if(mode->bitdepth == 8) {
3260*e47783fdSXin Li *r = *g = *b = in[i];
3261*e47783fdSXin Li if(mode->key_defined && *r == mode->key_r) *a = 0;
3262*e47783fdSXin Li else *a = 255;
3263*e47783fdSXin Li } else if(mode->bitdepth == 16) {
3264*e47783fdSXin Li *r = *g = *b = in[i * 2 + 0];
3265*e47783fdSXin Li if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
3266*e47783fdSXin Li else *a = 255;
3267*e47783fdSXin Li } else {
3268*e47783fdSXin Li unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
3269*e47783fdSXin Li size_t j = i * mode->bitdepth;
3270*e47783fdSXin Li unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
3271*e47783fdSXin Li *r = *g = *b = (value * 255) / highest;
3272*e47783fdSXin Li if(mode->key_defined && value == mode->key_r) *a = 0;
3273*e47783fdSXin Li else *a = 255;
3274*e47783fdSXin Li }
3275*e47783fdSXin Li } else if(mode->colortype == LCT_RGB) {
3276*e47783fdSXin Li if(mode->bitdepth == 8) {
3277*e47783fdSXin Li *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2];
3278*e47783fdSXin Li if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0;
3279*e47783fdSXin Li else *a = 255;
3280*e47783fdSXin Li } else {
3281*e47783fdSXin Li *r = in[i * 6 + 0];
3282*e47783fdSXin Li *g = in[i * 6 + 2];
3283*e47783fdSXin Li *b = in[i * 6 + 4];
3284*e47783fdSXin Li if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
3285*e47783fdSXin Li && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
3286*e47783fdSXin Li && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
3287*e47783fdSXin Li else *a = 255;
3288*e47783fdSXin Li }
3289*e47783fdSXin Li } else if(mode->colortype == LCT_PALETTE) {
3290*e47783fdSXin Li unsigned index;
3291*e47783fdSXin Li if(mode->bitdepth == 8) index = in[i];
3292*e47783fdSXin Li else {
3293*e47783fdSXin Li size_t j = i * mode->bitdepth;
3294*e47783fdSXin Li index = readBitsFromReversedStream(&j, in, mode->bitdepth);
3295*e47783fdSXin Li }
3296*e47783fdSXin Li /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/
3297*e47783fdSXin Li *r = mode->palette[index * 4 + 0];
3298*e47783fdSXin Li *g = mode->palette[index * 4 + 1];
3299*e47783fdSXin Li *b = mode->palette[index * 4 + 2];
3300*e47783fdSXin Li *a = mode->palette[index * 4 + 3];
3301*e47783fdSXin Li } else if(mode->colortype == LCT_GREY_ALPHA) {
3302*e47783fdSXin Li if(mode->bitdepth == 8) {
3303*e47783fdSXin Li *r = *g = *b = in[i * 2 + 0];
3304*e47783fdSXin Li *a = in[i * 2 + 1];
3305*e47783fdSXin Li } else {
3306*e47783fdSXin Li *r = *g = *b = in[i * 4 + 0];
3307*e47783fdSXin Li *a = in[i * 4 + 2];
3308*e47783fdSXin Li }
3309*e47783fdSXin Li } else if(mode->colortype == LCT_RGBA) {
3310*e47783fdSXin Li if(mode->bitdepth == 8) {
3311*e47783fdSXin Li *r = in[i * 4 + 0];
3312*e47783fdSXin Li *g = in[i * 4 + 1];
3313*e47783fdSXin Li *b = in[i * 4 + 2];
3314*e47783fdSXin Li *a = in[i * 4 + 3];
3315*e47783fdSXin Li } else {
3316*e47783fdSXin Li *r = in[i * 8 + 0];
3317*e47783fdSXin Li *g = in[i * 8 + 2];
3318*e47783fdSXin Li *b = in[i * 8 + 4];
3319*e47783fdSXin Li *a = in[i * 8 + 6];
3320*e47783fdSXin Li }
3321*e47783fdSXin Li }
3322*e47783fdSXin Li }
3323*e47783fdSXin Li
3324*e47783fdSXin Li /*Similar to getPixelColorRGBA8, but with all the for loops inside of the color
3325*e47783fdSXin Li mode test cases, optimized to convert the colors much faster, when converting
3326*e47783fdSXin Li to the common case of RGBA with 8 bit per channel. buffer must be RGBA with
3327*e47783fdSXin Li enough memory.*/
getPixelColorsRGBA8(unsigned char * LODEPNG_RESTRICT buffer,size_t numpixels,const unsigned char * LODEPNG_RESTRICT in,const LodePNGColorMode * mode)3328*e47783fdSXin Li static void getPixelColorsRGBA8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels,
3329*e47783fdSXin Li const unsigned char* LODEPNG_RESTRICT in,
3330*e47783fdSXin Li const LodePNGColorMode* mode) {
3331*e47783fdSXin Li unsigned num_channels = 4;
3332*e47783fdSXin Li size_t i;
3333*e47783fdSXin Li if(mode->colortype == LCT_GREY) {
3334*e47783fdSXin Li if(mode->bitdepth == 8) {
3335*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3336*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i];
3337*e47783fdSXin Li buffer[3] = 255;
3338*e47783fdSXin Li }
3339*e47783fdSXin Li if(mode->key_defined) {
3340*e47783fdSXin Li buffer -= numpixels * num_channels;
3341*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3342*e47783fdSXin Li if(buffer[0] == mode->key_r) buffer[3] = 0;
3343*e47783fdSXin Li }
3344*e47783fdSXin Li }
3345*e47783fdSXin Li } else if(mode->bitdepth == 16) {
3346*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3347*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i * 2];
3348*e47783fdSXin Li buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255;
3349*e47783fdSXin Li }
3350*e47783fdSXin Li } else {
3351*e47783fdSXin Li unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
3352*e47783fdSXin Li size_t j = 0;
3353*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3354*e47783fdSXin Li unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
3355*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;
3356*e47783fdSXin Li buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255;
3357*e47783fdSXin Li }
3358*e47783fdSXin Li }
3359*e47783fdSXin Li } else if(mode->colortype == LCT_RGB) {
3360*e47783fdSXin Li if(mode->bitdepth == 8) {
3361*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3362*e47783fdSXin Li lodepng_memcpy(buffer, &in[i * 3], 3);
3363*e47783fdSXin Li buffer[3] = 255;
3364*e47783fdSXin Li }
3365*e47783fdSXin Li if(mode->key_defined) {
3366*e47783fdSXin Li buffer -= numpixels * num_channels;
3367*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3368*e47783fdSXin Li if(buffer[0] == mode->key_r && buffer[1]== mode->key_g && buffer[2] == mode->key_b) buffer[3] = 0;
3369*e47783fdSXin Li }
3370*e47783fdSXin Li }
3371*e47783fdSXin Li } else {
3372*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3373*e47783fdSXin Li buffer[0] = in[i * 6 + 0];
3374*e47783fdSXin Li buffer[1] = in[i * 6 + 2];
3375*e47783fdSXin Li buffer[2] = in[i * 6 + 4];
3376*e47783fdSXin Li buffer[3] = mode->key_defined
3377*e47783fdSXin Li && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
3378*e47783fdSXin Li && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
3379*e47783fdSXin Li && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255;
3380*e47783fdSXin Li }
3381*e47783fdSXin Li }
3382*e47783fdSXin Li } else if(mode->colortype == LCT_PALETTE) {
3383*e47783fdSXin Li if(mode->bitdepth == 8) {
3384*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3385*e47783fdSXin Li unsigned index = in[i];
3386*e47783fdSXin Li /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/
3387*e47783fdSXin Li lodepng_memcpy(buffer, &mode->palette[index * 4], 4);
3388*e47783fdSXin Li }
3389*e47783fdSXin Li } else {
3390*e47783fdSXin Li size_t j = 0;
3391*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3392*e47783fdSXin Li unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth);
3393*e47783fdSXin Li /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/
3394*e47783fdSXin Li lodepng_memcpy(buffer, &mode->palette[index * 4], 4);
3395*e47783fdSXin Li }
3396*e47783fdSXin Li }
3397*e47783fdSXin Li } else if(mode->colortype == LCT_GREY_ALPHA) {
3398*e47783fdSXin Li if(mode->bitdepth == 8) {
3399*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3400*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];
3401*e47783fdSXin Li buffer[3] = in[i * 2 + 1];
3402*e47783fdSXin Li }
3403*e47783fdSXin Li } else {
3404*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3405*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];
3406*e47783fdSXin Li buffer[3] = in[i * 4 + 2];
3407*e47783fdSXin Li }
3408*e47783fdSXin Li }
3409*e47783fdSXin Li } else if(mode->colortype == LCT_RGBA) {
3410*e47783fdSXin Li if(mode->bitdepth == 8) {
3411*e47783fdSXin Li lodepng_memcpy(buffer, in, numpixels * 4);
3412*e47783fdSXin Li } else {
3413*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3414*e47783fdSXin Li buffer[0] = in[i * 8 + 0];
3415*e47783fdSXin Li buffer[1] = in[i * 8 + 2];
3416*e47783fdSXin Li buffer[2] = in[i * 8 + 4];
3417*e47783fdSXin Li buffer[3] = in[i * 8 + 6];
3418*e47783fdSXin Li }
3419*e47783fdSXin Li }
3420*e47783fdSXin Li }
3421*e47783fdSXin Li }
3422*e47783fdSXin Li
3423*e47783fdSXin Li /*Similar to getPixelColorsRGBA8, but with 3-channel RGB output.*/
getPixelColorsRGB8(unsigned char * LODEPNG_RESTRICT buffer,size_t numpixels,const unsigned char * LODEPNG_RESTRICT in,const LodePNGColorMode * mode)3424*e47783fdSXin Li static void getPixelColorsRGB8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels,
3425*e47783fdSXin Li const unsigned char* LODEPNG_RESTRICT in,
3426*e47783fdSXin Li const LodePNGColorMode* mode) {
3427*e47783fdSXin Li const unsigned num_channels = 3;
3428*e47783fdSXin Li size_t i;
3429*e47783fdSXin Li if(mode->colortype == LCT_GREY) {
3430*e47783fdSXin Li if(mode->bitdepth == 8) {
3431*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3432*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i];
3433*e47783fdSXin Li }
3434*e47783fdSXin Li } else if(mode->bitdepth == 16) {
3435*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3436*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i * 2];
3437*e47783fdSXin Li }
3438*e47783fdSXin Li } else {
3439*e47783fdSXin Li unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
3440*e47783fdSXin Li size_t j = 0;
3441*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3442*e47783fdSXin Li unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
3443*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;
3444*e47783fdSXin Li }
3445*e47783fdSXin Li }
3446*e47783fdSXin Li } else if(mode->colortype == LCT_RGB) {
3447*e47783fdSXin Li if(mode->bitdepth == 8) {
3448*e47783fdSXin Li lodepng_memcpy(buffer, in, numpixels * 3);
3449*e47783fdSXin Li } else {
3450*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3451*e47783fdSXin Li buffer[0] = in[i * 6 + 0];
3452*e47783fdSXin Li buffer[1] = in[i * 6 + 2];
3453*e47783fdSXin Li buffer[2] = in[i * 6 + 4];
3454*e47783fdSXin Li }
3455*e47783fdSXin Li }
3456*e47783fdSXin Li } else if(mode->colortype == LCT_PALETTE) {
3457*e47783fdSXin Li if(mode->bitdepth == 8) {
3458*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3459*e47783fdSXin Li unsigned index = in[i];
3460*e47783fdSXin Li /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/
3461*e47783fdSXin Li lodepng_memcpy(buffer, &mode->palette[index * 4], 3);
3462*e47783fdSXin Li }
3463*e47783fdSXin Li } else {
3464*e47783fdSXin Li size_t j = 0;
3465*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3466*e47783fdSXin Li unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth);
3467*e47783fdSXin Li /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/
3468*e47783fdSXin Li lodepng_memcpy(buffer, &mode->palette[index * 4], 3);
3469*e47783fdSXin Li }
3470*e47783fdSXin Li }
3471*e47783fdSXin Li } else if(mode->colortype == LCT_GREY_ALPHA) {
3472*e47783fdSXin Li if(mode->bitdepth == 8) {
3473*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3474*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];
3475*e47783fdSXin Li }
3476*e47783fdSXin Li } else {
3477*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3478*e47783fdSXin Li buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];
3479*e47783fdSXin Li }
3480*e47783fdSXin Li }
3481*e47783fdSXin Li } else if(mode->colortype == LCT_RGBA) {
3482*e47783fdSXin Li if(mode->bitdepth == 8) {
3483*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3484*e47783fdSXin Li lodepng_memcpy(buffer, &in[i * 4], 3);
3485*e47783fdSXin Li }
3486*e47783fdSXin Li } else {
3487*e47783fdSXin Li for(i = 0; i != numpixels; ++i, buffer += num_channels) {
3488*e47783fdSXin Li buffer[0] = in[i * 8 + 0];
3489*e47783fdSXin Li buffer[1] = in[i * 8 + 2];
3490*e47783fdSXin Li buffer[2] = in[i * 8 + 4];
3491*e47783fdSXin Li }
3492*e47783fdSXin Li }
3493*e47783fdSXin Li }
3494*e47783fdSXin Li }
3495*e47783fdSXin Li
3496*e47783fdSXin Li /*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with
3497*e47783fdSXin Li given color type, but the given color type must be 16-bit itself.*/
getPixelColorRGBA16(unsigned short * r,unsigned short * g,unsigned short * b,unsigned short * a,const unsigned char * in,size_t i,const LodePNGColorMode * mode)3498*e47783fdSXin Li static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a,
3499*e47783fdSXin Li const unsigned char* in, size_t i, const LodePNGColorMode* mode) {
3500*e47783fdSXin Li if(mode->colortype == LCT_GREY) {
3501*e47783fdSXin Li *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1];
3502*e47783fdSXin Li if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
3503*e47783fdSXin Li else *a = 65535;
3504*e47783fdSXin Li } else if(mode->colortype == LCT_RGB) {
3505*e47783fdSXin Li *r = 256u * in[i * 6 + 0] + in[i * 6 + 1];
3506*e47783fdSXin Li *g = 256u * in[i * 6 + 2] + in[i * 6 + 3];
3507*e47783fdSXin Li *b = 256u * in[i * 6 + 4] + in[i * 6 + 5];
3508*e47783fdSXin Li if(mode->key_defined
3509*e47783fdSXin Li && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
3510*e47783fdSXin Li && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
3511*e47783fdSXin Li && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
3512*e47783fdSXin Li else *a = 65535;
3513*e47783fdSXin Li } else if(mode->colortype == LCT_GREY_ALPHA) {
3514*e47783fdSXin Li *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1];
3515*e47783fdSXin Li *a = 256u * in[i * 4 + 2] + in[i * 4 + 3];
3516*e47783fdSXin Li } else if(mode->colortype == LCT_RGBA) {
3517*e47783fdSXin Li *r = 256u * in[i * 8 + 0] + in[i * 8 + 1];
3518*e47783fdSXin Li *g = 256u * in[i * 8 + 2] + in[i * 8 + 3];
3519*e47783fdSXin Li *b = 256u * in[i * 8 + 4] + in[i * 8 + 5];
3520*e47783fdSXin Li *a = 256u * in[i * 8 + 6] + in[i * 8 + 7];
3521*e47783fdSXin Li }
3522*e47783fdSXin Li }
3523*e47783fdSXin Li
lodepng_convert(unsigned char * out,const unsigned char * in,const LodePNGColorMode * mode_out,const LodePNGColorMode * mode_in,unsigned w,unsigned h)3524*e47783fdSXin Li unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
3525*e47783fdSXin Li const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
3526*e47783fdSXin Li unsigned w, unsigned h) {
3527*e47783fdSXin Li size_t i;
3528*e47783fdSXin Li ColorTree tree;
3529*e47783fdSXin Li size_t numpixels = (size_t)w * (size_t)h;
3530*e47783fdSXin Li unsigned error = 0;
3531*e47783fdSXin Li
3532*e47783fdSXin Li if(mode_in->colortype == LCT_PALETTE && !mode_in->palette) {
3533*e47783fdSXin Li return 107; /* error: must provide palette if input mode is palette */
3534*e47783fdSXin Li }
3535*e47783fdSXin Li
3536*e47783fdSXin Li if(lodepng_color_mode_equal(mode_out, mode_in)) {
3537*e47783fdSXin Li size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
3538*e47783fdSXin Li lodepng_memcpy(out, in, numbytes);
3539*e47783fdSXin Li return 0;
3540*e47783fdSXin Li }
3541*e47783fdSXin Li
3542*e47783fdSXin Li if(mode_out->colortype == LCT_PALETTE) {
3543*e47783fdSXin Li size_t palettesize = mode_out->palettesize;
3544*e47783fdSXin Li const unsigned char* palette = mode_out->palette;
3545*e47783fdSXin Li size_t palsize = (size_t)1u << mode_out->bitdepth;
3546*e47783fdSXin Li /*if the user specified output palette but did not give the values, assume
3547*e47783fdSXin Li they want the values of the input color type (assuming that one is palette).
3548*e47783fdSXin Li Note that we never create a new palette ourselves.*/
3549*e47783fdSXin Li if(palettesize == 0) {
3550*e47783fdSXin Li palettesize = mode_in->palettesize;
3551*e47783fdSXin Li palette = mode_in->palette;
3552*e47783fdSXin Li /*if the input was also palette with same bitdepth, then the color types are also
3553*e47783fdSXin Li equal, so copy literally. This to preserve the exact indices that were in the PNG
3554*e47783fdSXin Li even in case there are duplicate colors in the palette.*/
3555*e47783fdSXin Li if(mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) {
3556*e47783fdSXin Li size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
3557*e47783fdSXin Li lodepng_memcpy(out, in, numbytes);
3558*e47783fdSXin Li return 0;
3559*e47783fdSXin Li }
3560*e47783fdSXin Li }
3561*e47783fdSXin Li if(palettesize < palsize) palsize = palettesize;
3562*e47783fdSXin Li color_tree_init(&tree);
3563*e47783fdSXin Li for(i = 0; i != palsize; ++i) {
3564*e47783fdSXin Li const unsigned char* p = &palette[i * 4];
3565*e47783fdSXin Li error = color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i);
3566*e47783fdSXin Li if(error) break;
3567*e47783fdSXin Li }
3568*e47783fdSXin Li }
3569*e47783fdSXin Li
3570*e47783fdSXin Li if(!error) {
3571*e47783fdSXin Li if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) {
3572*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3573*e47783fdSXin Li unsigned short r = 0, g = 0, b = 0, a = 0;
3574*e47783fdSXin Li getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
3575*e47783fdSXin Li rgba16ToPixel(out, i, mode_out, r, g, b, a);
3576*e47783fdSXin Li }
3577*e47783fdSXin Li } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) {
3578*e47783fdSXin Li getPixelColorsRGBA8(out, numpixels, in, mode_in);
3579*e47783fdSXin Li } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) {
3580*e47783fdSXin Li getPixelColorsRGB8(out, numpixels, in, mode_in);
3581*e47783fdSXin Li } else {
3582*e47783fdSXin Li unsigned char r = 0, g = 0, b = 0, a = 0;
3583*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3584*e47783fdSXin Li getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
3585*e47783fdSXin Li error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);
3586*e47783fdSXin Li if(error) break;
3587*e47783fdSXin Li }
3588*e47783fdSXin Li }
3589*e47783fdSXin Li }
3590*e47783fdSXin Li
3591*e47783fdSXin Li if(mode_out->colortype == LCT_PALETTE) {
3592*e47783fdSXin Li color_tree_cleanup(&tree);
3593*e47783fdSXin Li }
3594*e47783fdSXin Li
3595*e47783fdSXin Li return error;
3596*e47783fdSXin Li }
3597*e47783fdSXin Li
3598*e47783fdSXin Li
3599*e47783fdSXin Li /* Converts a single rgb color without alpha from one type to another, color bits truncated to
3600*e47783fdSXin Li their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow
3601*e47783fdSXin Li function, do not use to process all pixels of an image. Alpha channel not supported on purpose:
3602*e47783fdSXin Li this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the
3603*e47783fdSXin Li specification it looks like bKGD should ignore the alpha values of the palette since it can use
3604*e47783fdSXin Li any palette index but doesn't have an alpha channel. Idem with ignoring color key. */
lodepng_convert_rgb(unsigned * r_out,unsigned * g_out,unsigned * b_out,unsigned r_in,unsigned g_in,unsigned b_in,const LodePNGColorMode * mode_out,const LodePNGColorMode * mode_in)3605*e47783fdSXin Li unsigned lodepng_convert_rgb(
3606*e47783fdSXin Li unsigned* r_out, unsigned* g_out, unsigned* b_out,
3607*e47783fdSXin Li unsigned r_in, unsigned g_in, unsigned b_in,
3608*e47783fdSXin Li const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) {
3609*e47783fdSXin Li unsigned r = 0, g = 0, b = 0;
3610*e47783fdSXin Li unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/
3611*e47783fdSXin Li unsigned shift = 16 - mode_out->bitdepth;
3612*e47783fdSXin Li
3613*e47783fdSXin Li if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) {
3614*e47783fdSXin Li r = g = b = r_in * mul;
3615*e47783fdSXin Li } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) {
3616*e47783fdSXin Li r = r_in * mul;
3617*e47783fdSXin Li g = g_in * mul;
3618*e47783fdSXin Li b = b_in * mul;
3619*e47783fdSXin Li } else if(mode_in->colortype == LCT_PALETTE) {
3620*e47783fdSXin Li if(r_in >= mode_in->palettesize) return 82;
3621*e47783fdSXin Li r = mode_in->palette[r_in * 4 + 0] * 257u;
3622*e47783fdSXin Li g = mode_in->palette[r_in * 4 + 1] * 257u;
3623*e47783fdSXin Li b = mode_in->palette[r_in * 4 + 2] * 257u;
3624*e47783fdSXin Li } else {
3625*e47783fdSXin Li return 31;
3626*e47783fdSXin Li }
3627*e47783fdSXin Li
3628*e47783fdSXin Li /* now convert to output format */
3629*e47783fdSXin Li if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) {
3630*e47783fdSXin Li *r_out = r >> shift ;
3631*e47783fdSXin Li } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) {
3632*e47783fdSXin Li *r_out = r >> shift ;
3633*e47783fdSXin Li *g_out = g >> shift ;
3634*e47783fdSXin Li *b_out = b >> shift ;
3635*e47783fdSXin Li } else if(mode_out->colortype == LCT_PALETTE) {
3636*e47783fdSXin Li unsigned i;
3637*e47783fdSXin Li /* a 16-bit color cannot be in the palette */
3638*e47783fdSXin Li if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82;
3639*e47783fdSXin Li for(i = 0; i < mode_out->palettesize; i++) {
3640*e47783fdSXin Li unsigned j = i * 4;
3641*e47783fdSXin Li if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] &&
3642*e47783fdSXin Li (b >> 8) == mode_out->palette[j + 2]) {
3643*e47783fdSXin Li *r_out = i;
3644*e47783fdSXin Li return 0;
3645*e47783fdSXin Li }
3646*e47783fdSXin Li }
3647*e47783fdSXin Li return 82;
3648*e47783fdSXin Li } else {
3649*e47783fdSXin Li return 31;
3650*e47783fdSXin Li }
3651*e47783fdSXin Li
3652*e47783fdSXin Li return 0;
3653*e47783fdSXin Li }
3654*e47783fdSXin Li
3655*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
3656*e47783fdSXin Li
lodepng_color_stats_init(LodePNGColorStats * stats)3657*e47783fdSXin Li void lodepng_color_stats_init(LodePNGColorStats* stats) {
3658*e47783fdSXin Li /*stats*/
3659*e47783fdSXin Li stats->colored = 0;
3660*e47783fdSXin Li stats->key = 0;
3661*e47783fdSXin Li stats->key_r = stats->key_g = stats->key_b = 0;
3662*e47783fdSXin Li stats->alpha = 0;
3663*e47783fdSXin Li stats->numcolors = 0;
3664*e47783fdSXin Li stats->bits = 1;
3665*e47783fdSXin Li stats->numpixels = 0;
3666*e47783fdSXin Li /*settings*/
3667*e47783fdSXin Li stats->allow_palette = 1;
3668*e47783fdSXin Li stats->allow_greyscale = 1;
3669*e47783fdSXin Li }
3670*e47783fdSXin Li
3671*e47783fdSXin Li /*function used for debug purposes with C++*/
3672*e47783fdSXin Li /*void printColorStats(LodePNGColorStats* p) {
3673*e47783fdSXin Li std::cout << "colored: " << (int)p->colored << ", ";
3674*e47783fdSXin Li std::cout << "key: " << (int)p->key << ", ";
3675*e47783fdSXin Li std::cout << "key_r: " << (int)p->key_r << ", ";
3676*e47783fdSXin Li std::cout << "key_g: " << (int)p->key_g << ", ";
3677*e47783fdSXin Li std::cout << "key_b: " << (int)p->key_b << ", ";
3678*e47783fdSXin Li std::cout << "alpha: " << (int)p->alpha << ", ";
3679*e47783fdSXin Li std::cout << "numcolors: " << (int)p->numcolors << ", ";
3680*e47783fdSXin Li std::cout << "bits: " << (int)p->bits << std::endl;
3681*e47783fdSXin Li }*/
3682*e47783fdSXin Li
3683*e47783fdSXin Li /*Returns how many bits needed to represent given value (max 8 bit)*/
getValueRequiredBits(unsigned char value)3684*e47783fdSXin Li static unsigned getValueRequiredBits(unsigned char value) {
3685*e47783fdSXin Li if(value == 0 || value == 255) return 1;
3686*e47783fdSXin Li /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/
3687*e47783fdSXin Li if(value % 17 == 0) return value % 85 == 0 ? 2 : 4;
3688*e47783fdSXin Li return 8;
3689*e47783fdSXin Li }
3690*e47783fdSXin Li
3691*e47783fdSXin Li /*stats must already have been inited. */
lodepng_compute_color_stats(LodePNGColorStats * stats,const unsigned char * in,unsigned w,unsigned h,const LodePNGColorMode * mode_in)3692*e47783fdSXin Li unsigned lodepng_compute_color_stats(LodePNGColorStats* stats,
3693*e47783fdSXin Li const unsigned char* in, unsigned w, unsigned h,
3694*e47783fdSXin Li const LodePNGColorMode* mode_in) {
3695*e47783fdSXin Li size_t i;
3696*e47783fdSXin Li ColorTree tree;
3697*e47783fdSXin Li size_t numpixels = (size_t)w * (size_t)h;
3698*e47783fdSXin Li unsigned error = 0;
3699*e47783fdSXin Li
3700*e47783fdSXin Li /* mark things as done already if it would be impossible to have a more expensive case */
3701*e47783fdSXin Li unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0;
3702*e47783fdSXin Li unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1;
3703*e47783fdSXin Li unsigned numcolors_done = 0;
3704*e47783fdSXin Li unsigned bpp = lodepng_get_bpp(mode_in);
3705*e47783fdSXin Li unsigned bits_done = (stats->bits == 1 && bpp == 1) ? 1 : 0;
3706*e47783fdSXin Li unsigned sixteen = 0; /* whether the input image is 16 bit */
3707*e47783fdSXin Li unsigned maxnumcolors = 257;
3708*e47783fdSXin Li if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, stats->numcolors + (1u << bpp));
3709*e47783fdSXin Li
3710*e47783fdSXin Li stats->numpixels += numpixels;
3711*e47783fdSXin Li
3712*e47783fdSXin Li /*if palette not allowed, no need to compute numcolors*/
3713*e47783fdSXin Li if(!stats->allow_palette) numcolors_done = 1;
3714*e47783fdSXin Li
3715*e47783fdSXin Li color_tree_init(&tree);
3716*e47783fdSXin Li
3717*e47783fdSXin Li /*If the stats was already filled in from previous data, fill its palette in tree
3718*e47783fdSXin Li and mark things as done already if we know they are the most expensive case already*/
3719*e47783fdSXin Li if(stats->alpha) alpha_done = 1;
3720*e47783fdSXin Li if(stats->colored) colored_done = 1;
3721*e47783fdSXin Li if(stats->bits == 16) numcolors_done = 1;
3722*e47783fdSXin Li if(stats->bits >= bpp) bits_done = 1;
3723*e47783fdSXin Li if(stats->numcolors >= maxnumcolors) numcolors_done = 1;
3724*e47783fdSXin Li
3725*e47783fdSXin Li if(!numcolors_done) {
3726*e47783fdSXin Li for(i = 0; i < stats->numcolors; i++) {
3727*e47783fdSXin Li const unsigned char* color = &stats->palette[i * 4];
3728*e47783fdSXin Li error = color_tree_add(&tree, color[0], color[1], color[2], color[3], i);
3729*e47783fdSXin Li if(error) goto cleanup;
3730*e47783fdSXin Li }
3731*e47783fdSXin Li }
3732*e47783fdSXin Li
3733*e47783fdSXin Li /*Check if the 16-bit input is truly 16-bit*/
3734*e47783fdSXin Li if(mode_in->bitdepth == 16 && !sixteen) {
3735*e47783fdSXin Li unsigned short r = 0, g = 0, b = 0, a = 0;
3736*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3737*e47783fdSXin Li getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
3738*e47783fdSXin Li if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) ||
3739*e47783fdSXin Li (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ {
3740*e47783fdSXin Li stats->bits = 16;
3741*e47783fdSXin Li sixteen = 1;
3742*e47783fdSXin Li bits_done = 1;
3743*e47783fdSXin Li numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/
3744*e47783fdSXin Li break;
3745*e47783fdSXin Li }
3746*e47783fdSXin Li }
3747*e47783fdSXin Li }
3748*e47783fdSXin Li
3749*e47783fdSXin Li if(sixteen) {
3750*e47783fdSXin Li unsigned short r = 0, g = 0, b = 0, a = 0;
3751*e47783fdSXin Li
3752*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3753*e47783fdSXin Li getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
3754*e47783fdSXin Li
3755*e47783fdSXin Li if(!colored_done && (r != g || r != b)) {
3756*e47783fdSXin Li stats->colored = 1;
3757*e47783fdSXin Li colored_done = 1;
3758*e47783fdSXin Li }
3759*e47783fdSXin Li
3760*e47783fdSXin Li if(!alpha_done) {
3761*e47783fdSXin Li unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b);
3762*e47783fdSXin Li if(a != 65535 && (a != 0 || (stats->key && !matchkey))) {
3763*e47783fdSXin Li stats->alpha = 1;
3764*e47783fdSXin Li stats->key = 0;
3765*e47783fdSXin Li alpha_done = 1;
3766*e47783fdSXin Li } else if(a == 0 && !stats->alpha && !stats->key) {
3767*e47783fdSXin Li stats->key = 1;
3768*e47783fdSXin Li stats->key_r = r;
3769*e47783fdSXin Li stats->key_g = g;
3770*e47783fdSXin Li stats->key_b = b;
3771*e47783fdSXin Li } else if(a == 65535 && stats->key && matchkey) {
3772*e47783fdSXin Li /* Color key cannot be used if an opaque pixel also has that RGB color. */
3773*e47783fdSXin Li stats->alpha = 1;
3774*e47783fdSXin Li stats->key = 0;
3775*e47783fdSXin Li alpha_done = 1;
3776*e47783fdSXin Li }
3777*e47783fdSXin Li }
3778*e47783fdSXin Li if(alpha_done && numcolors_done && colored_done && bits_done) break;
3779*e47783fdSXin Li }
3780*e47783fdSXin Li
3781*e47783fdSXin Li if(stats->key && !stats->alpha) {
3782*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3783*e47783fdSXin Li getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
3784*e47783fdSXin Li if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) {
3785*e47783fdSXin Li /* Color key cannot be used if an opaque pixel also has that RGB color. */
3786*e47783fdSXin Li stats->alpha = 1;
3787*e47783fdSXin Li stats->key = 0;
3788*e47783fdSXin Li alpha_done = 1;
3789*e47783fdSXin Li }
3790*e47783fdSXin Li }
3791*e47783fdSXin Li }
3792*e47783fdSXin Li } else /* < 16-bit */ {
3793*e47783fdSXin Li unsigned char r = 0, g = 0, b = 0, a = 0;
3794*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3795*e47783fdSXin Li getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
3796*e47783fdSXin Li
3797*e47783fdSXin Li if(!bits_done && stats->bits < 8) {
3798*e47783fdSXin Li /*only r is checked, < 8 bits is only relevant for grayscale*/
3799*e47783fdSXin Li unsigned bits = getValueRequiredBits(r);
3800*e47783fdSXin Li if(bits > stats->bits) stats->bits = bits;
3801*e47783fdSXin Li }
3802*e47783fdSXin Li bits_done = (stats->bits >= bpp);
3803*e47783fdSXin Li
3804*e47783fdSXin Li if(!colored_done && (r != g || r != b)) {
3805*e47783fdSXin Li stats->colored = 1;
3806*e47783fdSXin Li colored_done = 1;
3807*e47783fdSXin Li if(stats->bits < 8) stats->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/
3808*e47783fdSXin Li }
3809*e47783fdSXin Li
3810*e47783fdSXin Li if(!alpha_done) {
3811*e47783fdSXin Li unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b);
3812*e47783fdSXin Li if(a != 255 && (a != 0 || (stats->key && !matchkey))) {
3813*e47783fdSXin Li stats->alpha = 1;
3814*e47783fdSXin Li stats->key = 0;
3815*e47783fdSXin Li alpha_done = 1;
3816*e47783fdSXin Li if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
3817*e47783fdSXin Li } else if(a == 0 && !stats->alpha && !stats->key) {
3818*e47783fdSXin Li stats->key = 1;
3819*e47783fdSXin Li stats->key_r = r;
3820*e47783fdSXin Li stats->key_g = g;
3821*e47783fdSXin Li stats->key_b = b;
3822*e47783fdSXin Li } else if(a == 255 && stats->key && matchkey) {
3823*e47783fdSXin Li /* Color key cannot be used if an opaque pixel also has that RGB color. */
3824*e47783fdSXin Li stats->alpha = 1;
3825*e47783fdSXin Li stats->key = 0;
3826*e47783fdSXin Li alpha_done = 1;
3827*e47783fdSXin Li if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
3828*e47783fdSXin Li }
3829*e47783fdSXin Li }
3830*e47783fdSXin Li
3831*e47783fdSXin Li if(!numcolors_done) {
3832*e47783fdSXin Li if(!color_tree_has(&tree, r, g, b, a)) {
3833*e47783fdSXin Li error = color_tree_add(&tree, r, g, b, a, stats->numcolors);
3834*e47783fdSXin Li if(error) goto cleanup;
3835*e47783fdSXin Li if(stats->numcolors < 256) {
3836*e47783fdSXin Li unsigned char* p = stats->palette;
3837*e47783fdSXin Li unsigned n = stats->numcolors;
3838*e47783fdSXin Li p[n * 4 + 0] = r;
3839*e47783fdSXin Li p[n * 4 + 1] = g;
3840*e47783fdSXin Li p[n * 4 + 2] = b;
3841*e47783fdSXin Li p[n * 4 + 3] = a;
3842*e47783fdSXin Li }
3843*e47783fdSXin Li ++stats->numcolors;
3844*e47783fdSXin Li numcolors_done = stats->numcolors >= maxnumcolors;
3845*e47783fdSXin Li }
3846*e47783fdSXin Li }
3847*e47783fdSXin Li
3848*e47783fdSXin Li if(alpha_done && numcolors_done && colored_done && bits_done) break;
3849*e47783fdSXin Li }
3850*e47783fdSXin Li
3851*e47783fdSXin Li if(stats->key && !stats->alpha) {
3852*e47783fdSXin Li for(i = 0; i != numpixels; ++i) {
3853*e47783fdSXin Li getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
3854*e47783fdSXin Li if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) {
3855*e47783fdSXin Li /* Color key cannot be used if an opaque pixel also has that RGB color. */
3856*e47783fdSXin Li stats->alpha = 1;
3857*e47783fdSXin Li stats->key = 0;
3858*e47783fdSXin Li alpha_done = 1;
3859*e47783fdSXin Li if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
3860*e47783fdSXin Li }
3861*e47783fdSXin Li }
3862*e47783fdSXin Li }
3863*e47783fdSXin Li
3864*e47783fdSXin Li /*make the stats's key always 16-bit for consistency - repeat each byte twice*/
3865*e47783fdSXin Li stats->key_r += (stats->key_r << 8);
3866*e47783fdSXin Li stats->key_g += (stats->key_g << 8);
3867*e47783fdSXin Li stats->key_b += (stats->key_b << 8);
3868*e47783fdSXin Li }
3869*e47783fdSXin Li
3870*e47783fdSXin Li cleanup:
3871*e47783fdSXin Li color_tree_cleanup(&tree);
3872*e47783fdSXin Li return error;
3873*e47783fdSXin Li }
3874*e47783fdSXin Li
3875*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
3876*e47783fdSXin Li /*Adds a single color to the color stats. The stats must already have been inited. The color must be given as 16-bit
3877*e47783fdSXin Li (with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for
3878*e47783fdSXin Li all pixels of an image but only for a few additional values. */
lodepng_color_stats_add(LodePNGColorStats * stats,unsigned r,unsigned g,unsigned b,unsigned a)3879*e47783fdSXin Li static unsigned lodepng_color_stats_add(LodePNGColorStats* stats,
3880*e47783fdSXin Li unsigned r, unsigned g, unsigned b, unsigned a) {
3881*e47783fdSXin Li unsigned error = 0;
3882*e47783fdSXin Li unsigned char image[8];
3883*e47783fdSXin Li LodePNGColorMode mode;
3884*e47783fdSXin Li lodepng_color_mode_init(&mode);
3885*e47783fdSXin Li image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g;
3886*e47783fdSXin Li image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a;
3887*e47783fdSXin Li mode.bitdepth = 16;
3888*e47783fdSXin Li mode.colortype = LCT_RGBA;
3889*e47783fdSXin Li error = lodepng_compute_color_stats(stats, image, 1, 1, &mode);
3890*e47783fdSXin Li lodepng_color_mode_cleanup(&mode);
3891*e47783fdSXin Li return error;
3892*e47783fdSXin Li }
3893*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
3894*e47783fdSXin Li
3895*e47783fdSXin Li /*Computes a minimal PNG color model that can contain all colors as indicated by the stats.
3896*e47783fdSXin Li The stats should be computed with lodepng_compute_color_stats.
3897*e47783fdSXin Li mode_in is raw color profile of the image the stats were computed on, to copy palette order from when relevant.
3898*e47783fdSXin Li Minimal PNG color model means the color type and bit depth that gives smallest amount of bits in the output image,
3899*e47783fdSXin Li e.g. gray if only grayscale pixels, palette if less than 256 colors, color key if only single transparent color, ...
3900*e47783fdSXin Li This is used if auto_convert is enabled (it is by default).
3901*e47783fdSXin Li */
auto_choose_color(LodePNGColorMode * mode_out,const LodePNGColorMode * mode_in,const LodePNGColorStats * stats)3902*e47783fdSXin Li static unsigned auto_choose_color(LodePNGColorMode* mode_out,
3903*e47783fdSXin Li const LodePNGColorMode* mode_in,
3904*e47783fdSXin Li const LodePNGColorStats* stats) {
3905*e47783fdSXin Li unsigned error = 0;
3906*e47783fdSXin Li unsigned palettebits;
3907*e47783fdSXin Li size_t i, n;
3908*e47783fdSXin Li size_t numpixels = stats->numpixels;
3909*e47783fdSXin Li unsigned palette_ok, gray_ok;
3910*e47783fdSXin Li
3911*e47783fdSXin Li unsigned alpha = stats->alpha;
3912*e47783fdSXin Li unsigned key = stats->key;
3913*e47783fdSXin Li unsigned bits = stats->bits;
3914*e47783fdSXin Li
3915*e47783fdSXin Li mode_out->key_defined = 0;
3916*e47783fdSXin Li
3917*e47783fdSXin Li if(key && numpixels <= 16) {
3918*e47783fdSXin Li alpha = 1; /*too few pixels to justify tRNS chunk overhead*/
3919*e47783fdSXin Li key = 0;
3920*e47783fdSXin Li if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
3921*e47783fdSXin Li }
3922*e47783fdSXin Li
3923*e47783fdSXin Li gray_ok = !stats->colored;
3924*e47783fdSXin Li if(!stats->allow_greyscale) gray_ok = 0;
3925*e47783fdSXin Li if(!gray_ok && bits < 8) bits = 8;
3926*e47783fdSXin Li
3927*e47783fdSXin Li n = stats->numcolors;
3928*e47783fdSXin Li palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));
3929*e47783fdSXin Li palette_ok = n <= 256 && bits <= 8 && n != 0; /*n==0 means likely numcolors wasn't computed*/
3930*e47783fdSXin Li if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/
3931*e47783fdSXin Li if(gray_ok && !alpha && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/
3932*e47783fdSXin Li if(!stats->allow_palette) palette_ok = 0;
3933*e47783fdSXin Li
3934*e47783fdSXin Li if(palette_ok) {
3935*e47783fdSXin Li const unsigned char* p = stats->palette;
3936*e47783fdSXin Li lodepng_palette_clear(mode_out); /*remove potential earlier palette*/
3937*e47783fdSXin Li for(i = 0; i != stats->numcolors; ++i) {
3938*e47783fdSXin Li error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]);
3939*e47783fdSXin Li if(error) break;
3940*e47783fdSXin Li }
3941*e47783fdSXin Li
3942*e47783fdSXin Li mode_out->colortype = LCT_PALETTE;
3943*e47783fdSXin Li mode_out->bitdepth = palettebits;
3944*e47783fdSXin Li
3945*e47783fdSXin Li if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize
3946*e47783fdSXin Li && mode_in->bitdepth == mode_out->bitdepth) {
3947*e47783fdSXin Li /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/
3948*e47783fdSXin Li lodepng_color_mode_cleanup(mode_out);
3949*e47783fdSXin Li lodepng_color_mode_copy(mode_out, mode_in);
3950*e47783fdSXin Li }
3951*e47783fdSXin Li } else /*8-bit or 16-bit per channel*/ {
3952*e47783fdSXin Li mode_out->bitdepth = bits;
3953*e47783fdSXin Li mode_out->colortype = alpha ? (gray_ok ? LCT_GREY_ALPHA : LCT_RGBA)
3954*e47783fdSXin Li : (gray_ok ? LCT_GREY : LCT_RGB);
3955*e47783fdSXin Li if(key) {
3956*e47783fdSXin Li unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/
3957*e47783fdSXin Li mode_out->key_r = stats->key_r & mask;
3958*e47783fdSXin Li mode_out->key_g = stats->key_g & mask;
3959*e47783fdSXin Li mode_out->key_b = stats->key_b & mask;
3960*e47783fdSXin Li mode_out->key_defined = 1;
3961*e47783fdSXin Li }
3962*e47783fdSXin Li }
3963*e47783fdSXin Li
3964*e47783fdSXin Li return error;
3965*e47783fdSXin Li }
3966*e47783fdSXin Li
3967*e47783fdSXin Li #endif /* #ifdef LODEPNG_COMPILE_ENCODER */
3968*e47783fdSXin Li
3969*e47783fdSXin Li /*
3970*e47783fdSXin Li Paeth predictor, used by PNG filter type 4
3971*e47783fdSXin Li The parameters are of type short, but should come from unsigned chars, the shorts
3972*e47783fdSXin Li are only needed to make the paeth calculation correct.
3973*e47783fdSXin Li */
paethPredictor(short a,short b,short c)3974*e47783fdSXin Li static unsigned char paethPredictor(short a, short b, short c) {
3975*e47783fdSXin Li short pa = LODEPNG_ABS(b - c);
3976*e47783fdSXin Li short pb = LODEPNG_ABS(a - c);
3977*e47783fdSXin Li short pc = LODEPNG_ABS(a + b - c - c);
3978*e47783fdSXin Li /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */
3979*e47783fdSXin Li if(pb < pa) { a = b; pa = pb; }
3980*e47783fdSXin Li return (pc < pa) ? c : a;
3981*e47783fdSXin Li }
3982*e47783fdSXin Li
3983*e47783fdSXin Li /*shared values used by multiple Adam7 related functions*/
3984*e47783fdSXin Li
3985*e47783fdSXin Li static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
3986*e47783fdSXin Li static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
3987*e47783fdSXin Li static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
3988*e47783fdSXin Li static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
3989*e47783fdSXin Li
3990*e47783fdSXin Li /*
3991*e47783fdSXin Li Outputs various dimensions and positions in the image related to the Adam7 reduced images.
3992*e47783fdSXin Li passw: output containing the width of the 7 passes
3993*e47783fdSXin Li passh: output containing the height of the 7 passes
3994*e47783fdSXin Li filter_passstart: output containing the index of the start and end of each
3995*e47783fdSXin Li reduced image with filter bytes
3996*e47783fdSXin Li padded_passstart output containing the index of the start and end of each
3997*e47783fdSXin Li reduced image when without filter bytes but with padded scanlines
3998*e47783fdSXin Li passstart: output containing the index of the start and end of each reduced
3999*e47783fdSXin Li image without padding between scanlines, but still padding between the images
4000*e47783fdSXin Li w, h: width and height of non-interlaced image
4001*e47783fdSXin Li bpp: bits per pixel
4002*e47783fdSXin Li "padded" is only relevant if bpp is less than 8 and a scanline or image does not
4003*e47783fdSXin Li end at a full byte
4004*e47783fdSXin Li */
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)4005*e47783fdSXin Li static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8],
4006*e47783fdSXin Li size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) {
4007*e47783fdSXin Li /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/
4008*e47783fdSXin Li unsigned i;
4009*e47783fdSXin Li
4010*e47783fdSXin Li /*calculate width and height in pixels of each pass*/
4011*e47783fdSXin Li for(i = 0; i != 7; ++i) {
4012*e47783fdSXin Li passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];
4013*e47783fdSXin Li passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];
4014*e47783fdSXin Li if(passw[i] == 0) passh[i] = 0;
4015*e47783fdSXin Li if(passh[i] == 0) passw[i] = 0;
4016*e47783fdSXin Li }
4017*e47783fdSXin Li
4018*e47783fdSXin Li filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
4019*e47783fdSXin Li for(i = 0; i != 7; ++i) {
4020*e47783fdSXin Li /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/
4021*e47783fdSXin Li filter_passstart[i + 1] = filter_passstart[i]
4022*e47783fdSXin Li + ((passw[i] && passh[i]) ? passh[i] * (1u + (passw[i] * bpp + 7u) / 8u) : 0);
4023*e47783fdSXin Li /*bits padded if needed to fill full byte at end of each scanline*/
4024*e47783fdSXin Li padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7u) / 8u);
4025*e47783fdSXin Li /*only padded at end of reduced image*/
4026*e47783fdSXin Li passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7u) / 8u;
4027*e47783fdSXin Li }
4028*e47783fdSXin Li }
4029*e47783fdSXin Li
4030*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
4031*e47783fdSXin Li
4032*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
4033*e47783fdSXin Li /* / PNG Decoder / */
4034*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
4035*e47783fdSXin Li
4036*e47783fdSXin Li /*read the information from the header and store it in the LodePNGInfo. return value is error*/
lodepng_inspect(unsigned * w,unsigned * h,LodePNGState * state,const unsigned char * in,size_t insize)4037*e47783fdSXin Li unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state,
4038*e47783fdSXin Li const unsigned char* in, size_t insize) {
4039*e47783fdSXin Li unsigned width, height;
4040*e47783fdSXin Li LodePNGInfo* info = &state->info_png;
4041*e47783fdSXin Li if(insize == 0 || in == 0) {
4042*e47783fdSXin Li CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/
4043*e47783fdSXin Li }
4044*e47783fdSXin Li if(insize < 33) {
4045*e47783fdSXin Li CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/
4046*e47783fdSXin Li }
4047*e47783fdSXin Li
4048*e47783fdSXin Li /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/
4049*e47783fdSXin Li /* TODO: remove this. One should use a new LodePNGState for new sessions */
4050*e47783fdSXin Li lodepng_info_cleanup(info);
4051*e47783fdSXin Li lodepng_info_init(info);
4052*e47783fdSXin Li
4053*e47783fdSXin Li if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71
4054*e47783fdSXin Li || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) {
4055*e47783fdSXin Li CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/
4056*e47783fdSXin Li }
4057*e47783fdSXin Li if(lodepng_chunk_length(in + 8) != 13) {
4058*e47783fdSXin Li CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/
4059*e47783fdSXin Li }
4060*e47783fdSXin Li if(!lodepng_chunk_type_equals(in + 8, "IHDR")) {
4061*e47783fdSXin Li CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/
4062*e47783fdSXin Li }
4063*e47783fdSXin Li
4064*e47783fdSXin Li /*read the values given in the header*/
4065*e47783fdSXin Li width = lodepng_read32bitInt(&in[16]);
4066*e47783fdSXin Li height = lodepng_read32bitInt(&in[20]);
4067*e47783fdSXin Li /*TODO: remove the undocumented feature that allows to give null pointers to width or height*/
4068*e47783fdSXin Li if(w) *w = width;
4069*e47783fdSXin Li if(h) *h = height;
4070*e47783fdSXin Li info->color.bitdepth = in[24];
4071*e47783fdSXin Li info->color.colortype = (LodePNGColorType)in[25];
4072*e47783fdSXin Li info->compression_method = in[26];
4073*e47783fdSXin Li info->filter_method = in[27];
4074*e47783fdSXin Li info->interlace_method = in[28];
4075*e47783fdSXin Li
4076*e47783fdSXin Li /*errors returned only after the parsing so other values are still output*/
4077*e47783fdSXin Li
4078*e47783fdSXin Li /*error: invalid image size*/
4079*e47783fdSXin Li if(width == 0 || height == 0) CERROR_RETURN_ERROR(state->error, 93);
4080*e47783fdSXin Li /*error: invalid colortype or bitdepth combination*/
4081*e47783fdSXin Li state->error = checkColorValidity(info->color.colortype, info->color.bitdepth);
4082*e47783fdSXin Li if(state->error) return state->error;
4083*e47783fdSXin Li /*error: only compression method 0 is allowed in the specification*/
4084*e47783fdSXin Li if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32);
4085*e47783fdSXin Li /*error: only filter method 0 is allowed in the specification*/
4086*e47783fdSXin Li if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33);
4087*e47783fdSXin Li /*error: only interlace methods 0 and 1 exist in the specification*/
4088*e47783fdSXin Li if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34);
4089*e47783fdSXin Li
4090*e47783fdSXin Li if(!state->decoder.ignore_crc) {
4091*e47783fdSXin Li unsigned CRC = lodepng_read32bitInt(&in[29]);
4092*e47783fdSXin Li unsigned checksum = lodepng_crc32(&in[12], 17);
4093*e47783fdSXin Li if(CRC != checksum) {
4094*e47783fdSXin Li CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/
4095*e47783fdSXin Li }
4096*e47783fdSXin Li }
4097*e47783fdSXin Li
4098*e47783fdSXin Li return state->error;
4099*e47783fdSXin Li }
4100*e47783fdSXin Li
unfilterScanline(unsigned char * recon,const unsigned char * scanline,const unsigned char * precon,size_t bytewidth,unsigned char filterType,size_t length)4101*e47783fdSXin Li static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon,
4102*e47783fdSXin Li size_t bytewidth, unsigned char filterType, size_t length) {
4103*e47783fdSXin Li /*
4104*e47783fdSXin Li For PNG filter method 0
4105*e47783fdSXin Li unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte,
4106*e47783fdSXin Li the filter works byte per byte (bytewidth = 1)
4107*e47783fdSXin Li precon is the previous unfiltered scanline, recon the result, scanline the current one
4108*e47783fdSXin Li the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead
4109*e47783fdSXin Li recon and scanline MAY be the same memory address! precon must be disjoint.
4110*e47783fdSXin Li */
4111*e47783fdSXin Li
4112*e47783fdSXin Li size_t i;
4113*e47783fdSXin Li switch(filterType) {
4114*e47783fdSXin Li case 0:
4115*e47783fdSXin Li for(i = 0; i != length; ++i) recon[i] = scanline[i];
4116*e47783fdSXin Li break;
4117*e47783fdSXin Li case 1:
4118*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
4119*e47783fdSXin Li for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];
4120*e47783fdSXin Li break;
4121*e47783fdSXin Li case 2:
4122*e47783fdSXin Li if(precon) {
4123*e47783fdSXin Li for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
4124*e47783fdSXin Li } else {
4125*e47783fdSXin Li for(i = 0; i != length; ++i) recon[i] = scanline[i];
4126*e47783fdSXin Li }
4127*e47783fdSXin Li break;
4128*e47783fdSXin Li case 3:
4129*e47783fdSXin Li if(precon) {
4130*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
4131*e47783fdSXin Li for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u);
4132*e47783fdSXin Li } else {
4133*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
4134*e47783fdSXin Li for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u);
4135*e47783fdSXin Li }
4136*e47783fdSXin Li break;
4137*e47783fdSXin Li case 4:
4138*e47783fdSXin Li if(precon) {
4139*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) {
4140*e47783fdSXin Li recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
4141*e47783fdSXin Li }
4142*e47783fdSXin Li
4143*e47783fdSXin Li /* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that
4144*e47783fdSXin Li adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */
4145*e47783fdSXin Li if(bytewidth >= 4) {
4146*e47783fdSXin Li for(; i + 3 < length; i += 4) {
4147*e47783fdSXin Li size_t j = i - bytewidth;
4148*e47783fdSXin Li unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
4149*e47783fdSXin Li unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
4150*e47783fdSXin Li unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
4151*e47783fdSXin Li unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2], q3 = precon[j + 3];
4152*e47783fdSXin Li recon[i + 0] = s0 + paethPredictor(r0, p0, q0);
4153*e47783fdSXin Li recon[i + 1] = s1 + paethPredictor(r1, p1, q1);
4154*e47783fdSXin Li recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
4155*e47783fdSXin Li recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
4156*e47783fdSXin Li }
4157*e47783fdSXin Li } else if(bytewidth >= 3) {
4158*e47783fdSXin Li for(; i + 2 < length; i += 3) {
4159*e47783fdSXin Li size_t j = i - bytewidth;
4160*e47783fdSXin Li unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
4161*e47783fdSXin Li unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
4162*e47783fdSXin Li unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
4163*e47783fdSXin Li unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2];
4164*e47783fdSXin Li recon[i + 0] = s0 + paethPredictor(r0, p0, q0);
4165*e47783fdSXin Li recon[i + 1] = s1 + paethPredictor(r1, p1, q1);
4166*e47783fdSXin Li recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
4167*e47783fdSXin Li }
4168*e47783fdSXin Li } else if(bytewidth >= 2) {
4169*e47783fdSXin Li for(; i + 1 < length; i += 2) {
4170*e47783fdSXin Li size_t j = i - bytewidth;
4171*e47783fdSXin Li unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
4172*e47783fdSXin Li unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
4173*e47783fdSXin Li unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
4174*e47783fdSXin Li unsigned char q0 = precon[j + 0], q1 = precon[j + 1];
4175*e47783fdSXin Li recon[i + 0] = s0 + paethPredictor(r0, p0, q0);
4176*e47783fdSXin Li recon[i + 1] = s1 + paethPredictor(r1, p1, q1);
4177*e47783fdSXin Li }
4178*e47783fdSXin Li }
4179*e47783fdSXin Li
4180*e47783fdSXin Li for(; i != length; ++i) {
4181*e47783fdSXin Li recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
4182*e47783fdSXin Li }
4183*e47783fdSXin Li } else {
4184*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) {
4185*e47783fdSXin Li recon[i] = scanline[i];
4186*e47783fdSXin Li }
4187*e47783fdSXin Li for(i = bytewidth; i < length; ++i) {
4188*e47783fdSXin Li /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
4189*e47783fdSXin Li recon[i] = (scanline[i] + recon[i - bytewidth]);
4190*e47783fdSXin Li }
4191*e47783fdSXin Li }
4192*e47783fdSXin Li break;
4193*e47783fdSXin Li default: return 36; /*error: invalid filter type given*/
4194*e47783fdSXin Li }
4195*e47783fdSXin Li return 0;
4196*e47783fdSXin Li }
4197*e47783fdSXin Li
unfilter(unsigned char * out,const unsigned char * in,unsigned w,unsigned h,unsigned bpp)4198*e47783fdSXin Li static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
4199*e47783fdSXin Li /*
4200*e47783fdSXin Li For PNG filter method 0
4201*e47783fdSXin Li this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)
4202*e47783fdSXin Li out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
4203*e47783fdSXin Li w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
4204*e47783fdSXin Li in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)
4205*e47783fdSXin Li */
4206*e47783fdSXin Li
4207*e47783fdSXin Li unsigned y;
4208*e47783fdSXin Li unsigned char* prevline = 0;
4209*e47783fdSXin Li
4210*e47783fdSXin Li /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
4211*e47783fdSXin Li size_t bytewidth = (bpp + 7u) / 8u;
4212*e47783fdSXin Li /*the width of a scanline in bytes, not including the filter type*/
4213*e47783fdSXin Li size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u;
4214*e47783fdSXin Li
4215*e47783fdSXin Li for(y = 0; y < h; ++y) {
4216*e47783fdSXin Li size_t outindex = linebytes * y;
4217*e47783fdSXin Li size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
4218*e47783fdSXin Li unsigned char filterType = in[inindex];
4219*e47783fdSXin Li
4220*e47783fdSXin Li CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes));
4221*e47783fdSXin Li
4222*e47783fdSXin Li prevline = &out[outindex];
4223*e47783fdSXin Li }
4224*e47783fdSXin Li
4225*e47783fdSXin Li return 0;
4226*e47783fdSXin Li }
4227*e47783fdSXin Li
4228*e47783fdSXin Li /*
4229*e47783fdSXin Li in: Adam7 interlaced image, with no padding bits between scanlines, but between
4230*e47783fdSXin Li reduced images so that each reduced image starts at a byte.
4231*e47783fdSXin Li out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h
4232*e47783fdSXin Li bpp: bits per pixel
4233*e47783fdSXin Li out has the following size in bits: w * h * bpp.
4234*e47783fdSXin Li in is possibly bigger due to padding bits between reduced images.
4235*e47783fdSXin Li out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation
4236*e47783fdSXin Li (because that's likely a little bit faster)
4237*e47783fdSXin Li NOTE: comments about padding bits are only relevant if bpp < 8
4238*e47783fdSXin Li */
Adam7_deinterlace(unsigned char * out,const unsigned char * in,unsigned w,unsigned h,unsigned bpp)4239*e47783fdSXin Li static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
4240*e47783fdSXin Li unsigned passw[7], passh[7];
4241*e47783fdSXin Li size_t filter_passstart[8], padded_passstart[8], passstart[8];
4242*e47783fdSXin Li unsigned i;
4243*e47783fdSXin Li
4244*e47783fdSXin Li Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
4245*e47783fdSXin Li
4246*e47783fdSXin Li if(bpp >= 8) {
4247*e47783fdSXin Li for(i = 0; i != 7; ++i) {
4248*e47783fdSXin Li unsigned x, y, b;
4249*e47783fdSXin Li size_t bytewidth = bpp / 8u;
4250*e47783fdSXin Li for(y = 0; y < passh[i]; ++y)
4251*e47783fdSXin Li for(x = 0; x < passw[i]; ++x) {
4252*e47783fdSXin Li size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
4253*e47783fdSXin Li size_t pixeloutstart = ((ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * (size_t)w
4254*e47783fdSXin Li + ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bytewidth;
4255*e47783fdSXin Li for(b = 0; b < bytewidth; ++b) {
4256*e47783fdSXin Li out[pixeloutstart + b] = in[pixelinstart + b];
4257*e47783fdSXin Li }
4258*e47783fdSXin Li }
4259*e47783fdSXin Li }
4260*e47783fdSXin Li } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ {
4261*e47783fdSXin Li for(i = 0; i != 7; ++i) {
4262*e47783fdSXin Li unsigned x, y, b;
4263*e47783fdSXin Li unsigned ilinebits = bpp * passw[i];
4264*e47783fdSXin Li unsigned olinebits = bpp * w;
4265*e47783fdSXin Li size_t obp, ibp; /*bit pointers (for out and in buffer)*/
4266*e47783fdSXin Li for(y = 0; y < passh[i]; ++y)
4267*e47783fdSXin Li for(x = 0; x < passw[i]; ++x) {
4268*e47783fdSXin Li ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
4269*e47783fdSXin Li obp = (ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bpp;
4270*e47783fdSXin Li for(b = 0; b < bpp; ++b) {
4271*e47783fdSXin Li unsigned char bit = readBitFromReversedStream(&ibp, in);
4272*e47783fdSXin Li setBitOfReversedStream(&obp, out, bit);
4273*e47783fdSXin Li }
4274*e47783fdSXin Li }
4275*e47783fdSXin Li }
4276*e47783fdSXin Li }
4277*e47783fdSXin Li }
4278*e47783fdSXin Li
removePaddingBits(unsigned char * out,const unsigned char * in,size_t olinebits,size_t ilinebits,unsigned h)4279*e47783fdSXin Li static void removePaddingBits(unsigned char* out, const unsigned char* in,
4280*e47783fdSXin Li size_t olinebits, size_t ilinebits, unsigned h) {
4281*e47783fdSXin Li /*
4282*e47783fdSXin Li After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need
4283*e47783fdSXin Li to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers
4284*e47783fdSXin Li for the Adam7 code, the color convert code and the output to the user.
4285*e47783fdSXin Li in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must
4286*e47783fdSXin Li have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits
4287*e47783fdSXin Li also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7
4288*e47783fdSXin Li only useful if (ilinebits - olinebits) is a value in the range 1..7
4289*e47783fdSXin Li */
4290*e47783fdSXin Li unsigned y;
4291*e47783fdSXin Li size_t diff = ilinebits - olinebits;
4292*e47783fdSXin Li size_t ibp = 0, obp = 0; /*input and output bit pointers*/
4293*e47783fdSXin Li for(y = 0; y < h; ++y) {
4294*e47783fdSXin Li size_t x;
4295*e47783fdSXin Li for(x = 0; x < olinebits; ++x) {
4296*e47783fdSXin Li unsigned char bit = readBitFromReversedStream(&ibp, in);
4297*e47783fdSXin Li setBitOfReversedStream(&obp, out, bit);
4298*e47783fdSXin Li }
4299*e47783fdSXin Li ibp += diff;
4300*e47783fdSXin Li }
4301*e47783fdSXin Li }
4302*e47783fdSXin Li
4303*e47783fdSXin Li /*out must be buffer big enough to contain full image, and in must contain the full decompressed data from
4304*e47783fdSXin Li the IDAT chunks (with filter index bytes and possible padding bits)
4305*e47783fdSXin Li return value is error*/
postProcessScanlines(unsigned char * out,unsigned char * in,unsigned w,unsigned h,const LodePNGInfo * info_png)4306*e47783fdSXin Li static unsigned postProcessScanlines(unsigned char* out, unsigned char* in,
4307*e47783fdSXin Li unsigned w, unsigned h, const LodePNGInfo* info_png) {
4308*e47783fdSXin Li /*
4309*e47783fdSXin Li This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.
4310*e47783fdSXin Li Steps:
4311*e47783fdSXin Li *) if no Adam7: 1) unfilter 2) remove padding bits (= possible extra bits per scanline if bpp < 8)
4312*e47783fdSXin Li *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
4313*e47783fdSXin Li NOTE: the in buffer will be overwritten with intermediate data!
4314*e47783fdSXin Li */
4315*e47783fdSXin Li unsigned bpp = lodepng_get_bpp(&info_png->color);
4316*e47783fdSXin Li if(bpp == 0) return 31; /*error: invalid colortype*/
4317*e47783fdSXin Li
4318*e47783fdSXin Li if(info_png->interlace_method == 0) {
4319*e47783fdSXin Li if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) {
4320*e47783fdSXin Li CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));
4321*e47783fdSXin Li removePaddingBits(out, in, w * bpp, ((w * bpp + 7u) / 8u) * 8u, h);
4322*e47783fdSXin Li }
4323*e47783fdSXin Li /*we can immediately filter into the out buffer, no other steps needed*/
4324*e47783fdSXin Li else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp));
4325*e47783fdSXin Li } else /*interlace_method is 1 (Adam7)*/ {
4326*e47783fdSXin Li unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
4327*e47783fdSXin Li unsigned i;
4328*e47783fdSXin Li
4329*e47783fdSXin Li Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
4330*e47783fdSXin Li
4331*e47783fdSXin Li for(i = 0; i != 7; ++i) {
4332*e47783fdSXin Li CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp));
4333*e47783fdSXin Li /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,
4334*e47783fdSXin Li move bytes instead of bits or move not at all*/
4335*e47783fdSXin Li if(bpp < 8) {
4336*e47783fdSXin Li /*remove padding bits in scanlines; after this there still may be padding
4337*e47783fdSXin Li bits between the different reduced images: each reduced image still starts nicely at a byte*/
4338*e47783fdSXin Li removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,
4339*e47783fdSXin Li ((passw[i] * bpp + 7u) / 8u) * 8u, passh[i]);
4340*e47783fdSXin Li }
4341*e47783fdSXin Li }
4342*e47783fdSXin Li
4343*e47783fdSXin Li Adam7_deinterlace(out, in, w, h, bpp);
4344*e47783fdSXin Li }
4345*e47783fdSXin Li
4346*e47783fdSXin Li return 0;
4347*e47783fdSXin Li }
4348*e47783fdSXin Li
readChunk_PLTE(LodePNGColorMode * color,const unsigned char * data,size_t chunkLength)4349*e47783fdSXin Li static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) {
4350*e47783fdSXin Li unsigned pos = 0, i;
4351*e47783fdSXin Li color->palettesize = chunkLength / 3u;
4352*e47783fdSXin Li if(color->palettesize == 0 || color->palettesize > 256) return 38; /*error: palette too small or big*/
4353*e47783fdSXin Li lodepng_color_mode_alloc_palette(color);
4354*e47783fdSXin Li if(!color->palette && color->palettesize) {
4355*e47783fdSXin Li color->palettesize = 0;
4356*e47783fdSXin Li return 83; /*alloc fail*/
4357*e47783fdSXin Li }
4358*e47783fdSXin Li
4359*e47783fdSXin Li for(i = 0; i != color->palettesize; ++i) {
4360*e47783fdSXin Li color->palette[4 * i + 0] = data[pos++]; /*R*/
4361*e47783fdSXin Li color->palette[4 * i + 1] = data[pos++]; /*G*/
4362*e47783fdSXin Li color->palette[4 * i + 2] = data[pos++]; /*B*/
4363*e47783fdSXin Li color->palette[4 * i + 3] = 255; /*alpha*/
4364*e47783fdSXin Li }
4365*e47783fdSXin Li
4366*e47783fdSXin Li return 0; /* OK */
4367*e47783fdSXin Li }
4368*e47783fdSXin Li
readChunk_tRNS(LodePNGColorMode * color,const unsigned char * data,size_t chunkLength)4369*e47783fdSXin Li static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) {
4370*e47783fdSXin Li unsigned i;
4371*e47783fdSXin Li if(color->colortype == LCT_PALETTE) {
4372*e47783fdSXin Li /*error: more alpha values given than there are palette entries*/
4373*e47783fdSXin Li if(chunkLength > color->palettesize) return 39;
4374*e47783fdSXin Li
4375*e47783fdSXin Li for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i];
4376*e47783fdSXin Li } else if(color->colortype == LCT_GREY) {
4377*e47783fdSXin Li /*error: this chunk must be 2 bytes for grayscale image*/
4378*e47783fdSXin Li if(chunkLength != 2) return 30;
4379*e47783fdSXin Li
4380*e47783fdSXin Li color->key_defined = 1;
4381*e47783fdSXin Li color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1];
4382*e47783fdSXin Li } else if(color->colortype == LCT_RGB) {
4383*e47783fdSXin Li /*error: this chunk must be 6 bytes for RGB image*/
4384*e47783fdSXin Li if(chunkLength != 6) return 41;
4385*e47783fdSXin Li
4386*e47783fdSXin Li color->key_defined = 1;
4387*e47783fdSXin Li color->key_r = 256u * data[0] + data[1];
4388*e47783fdSXin Li color->key_g = 256u * data[2] + data[3];
4389*e47783fdSXin Li color->key_b = 256u * data[4] + data[5];
4390*e47783fdSXin Li }
4391*e47783fdSXin Li else return 42; /*error: tRNS chunk not allowed for other color models*/
4392*e47783fdSXin Li
4393*e47783fdSXin Li return 0; /* OK */
4394*e47783fdSXin Li }
4395*e47783fdSXin Li
4396*e47783fdSXin Li
4397*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4398*e47783fdSXin Li /*background color chunk (bKGD)*/
readChunk_bKGD(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4399*e47783fdSXin Li static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4400*e47783fdSXin Li if(info->color.colortype == LCT_PALETTE) {
4401*e47783fdSXin Li /*error: this chunk must be 1 byte for indexed color image*/
4402*e47783fdSXin Li if(chunkLength != 1) return 43;
4403*e47783fdSXin Li
4404*e47783fdSXin Li /*error: invalid palette index, or maybe this chunk appeared before PLTE*/
4405*e47783fdSXin Li if(data[0] >= info->color.palettesize) return 103;
4406*e47783fdSXin Li
4407*e47783fdSXin Li info->background_defined = 1;
4408*e47783fdSXin Li info->background_r = info->background_g = info->background_b = data[0];
4409*e47783fdSXin Li } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
4410*e47783fdSXin Li /*error: this chunk must be 2 bytes for grayscale image*/
4411*e47783fdSXin Li if(chunkLength != 2) return 44;
4412*e47783fdSXin Li
4413*e47783fdSXin Li /*the values are truncated to bitdepth in the PNG file*/
4414*e47783fdSXin Li info->background_defined = 1;
4415*e47783fdSXin Li info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1];
4416*e47783fdSXin Li } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
4417*e47783fdSXin Li /*error: this chunk must be 6 bytes for grayscale image*/
4418*e47783fdSXin Li if(chunkLength != 6) return 45;
4419*e47783fdSXin Li
4420*e47783fdSXin Li /*the values are truncated to bitdepth in the PNG file*/
4421*e47783fdSXin Li info->background_defined = 1;
4422*e47783fdSXin Li info->background_r = 256u * data[0] + data[1];
4423*e47783fdSXin Li info->background_g = 256u * data[2] + data[3];
4424*e47783fdSXin Li info->background_b = 256u * data[4] + data[5];
4425*e47783fdSXin Li }
4426*e47783fdSXin Li
4427*e47783fdSXin Li return 0; /* OK */
4428*e47783fdSXin Li }
4429*e47783fdSXin Li
4430*e47783fdSXin Li /*text chunk (tEXt)*/
readChunk_tEXt(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4431*e47783fdSXin Li static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4432*e47783fdSXin Li unsigned error = 0;
4433*e47783fdSXin Li char *key = 0, *str = 0;
4434*e47783fdSXin Li
4435*e47783fdSXin Li while(!error) /*not really a while loop, only used to break on error*/ {
4436*e47783fdSXin Li unsigned length, string2_begin;
4437*e47783fdSXin Li
4438*e47783fdSXin Li length = 0;
4439*e47783fdSXin Li while(length < chunkLength && data[length] != 0) ++length;
4440*e47783fdSXin Li /*even though it's not allowed by the standard, no error is thrown if
4441*e47783fdSXin Li there's no null termination char, if the text is empty*/
4442*e47783fdSXin Li if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
4443*e47783fdSXin Li
4444*e47783fdSXin Li key = (char*)lodepng_malloc(length + 1);
4445*e47783fdSXin Li if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
4446*e47783fdSXin Li
4447*e47783fdSXin Li lodepng_memcpy(key, data, length);
4448*e47783fdSXin Li key[length] = 0;
4449*e47783fdSXin Li
4450*e47783fdSXin Li string2_begin = length + 1; /*skip keyword null terminator*/
4451*e47783fdSXin Li
4452*e47783fdSXin Li length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin);
4453*e47783fdSXin Li str = (char*)lodepng_malloc(length + 1);
4454*e47783fdSXin Li if(!str) CERROR_BREAK(error, 83); /*alloc fail*/
4455*e47783fdSXin Li
4456*e47783fdSXin Li lodepng_memcpy(str, data + string2_begin, length);
4457*e47783fdSXin Li str[length] = 0;
4458*e47783fdSXin Li
4459*e47783fdSXin Li error = lodepng_add_text(info, key, str);
4460*e47783fdSXin Li
4461*e47783fdSXin Li break;
4462*e47783fdSXin Li }
4463*e47783fdSXin Li
4464*e47783fdSXin Li lodepng_free(key);
4465*e47783fdSXin Li lodepng_free(str);
4466*e47783fdSXin Li
4467*e47783fdSXin Li return error;
4468*e47783fdSXin Li }
4469*e47783fdSXin Li
4470*e47783fdSXin Li /*compressed text chunk (zTXt)*/
readChunk_zTXt(LodePNGInfo * info,const LodePNGDecoderSettings * decoder,const unsigned char * data,size_t chunkLength)4471*e47783fdSXin Li static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
4472*e47783fdSXin Li const unsigned char* data, size_t chunkLength) {
4473*e47783fdSXin Li unsigned error = 0;
4474*e47783fdSXin Li
4475*e47783fdSXin Li /*copy the object to change parameters in it*/
4476*e47783fdSXin Li LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
4477*e47783fdSXin Li
4478*e47783fdSXin Li unsigned length, string2_begin;
4479*e47783fdSXin Li char *key = 0;
4480*e47783fdSXin Li unsigned char* str = 0;
4481*e47783fdSXin Li size_t size = 0;
4482*e47783fdSXin Li
4483*e47783fdSXin Li while(!error) /*not really a while loop, only used to break on error*/ {
4484*e47783fdSXin Li for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
4485*e47783fdSXin Li if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
4486*e47783fdSXin Li if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
4487*e47783fdSXin Li
4488*e47783fdSXin Li key = (char*)lodepng_malloc(length + 1);
4489*e47783fdSXin Li if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
4490*e47783fdSXin Li
4491*e47783fdSXin Li lodepng_memcpy(key, data, length);
4492*e47783fdSXin Li key[length] = 0;
4493*e47783fdSXin Li
4494*e47783fdSXin Li if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
4495*e47783fdSXin Li
4496*e47783fdSXin Li string2_begin = length + 2;
4497*e47783fdSXin Li if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
4498*e47783fdSXin Li
4499*e47783fdSXin Li length = (unsigned)chunkLength - string2_begin;
4500*e47783fdSXin Li zlibsettings.max_output_size = decoder->max_text_size;
4501*e47783fdSXin Li /*will fail if zlib error, e.g. if length is too small*/
4502*e47783fdSXin Li error = zlib_decompress(&str, &size, 0, &data[string2_begin],
4503*e47783fdSXin Li length, &zlibsettings);
4504*e47783fdSXin Li /*error: compressed text larger than decoder->max_text_size*/
4505*e47783fdSXin Li if(error && size > zlibsettings.max_output_size) error = 112;
4506*e47783fdSXin Li if(error) break;
4507*e47783fdSXin Li error = lodepng_add_text_sized(info, key, (char*)str, size);
4508*e47783fdSXin Li break;
4509*e47783fdSXin Li }
4510*e47783fdSXin Li
4511*e47783fdSXin Li lodepng_free(key);
4512*e47783fdSXin Li lodepng_free(str);
4513*e47783fdSXin Li
4514*e47783fdSXin Li return error;
4515*e47783fdSXin Li }
4516*e47783fdSXin Li
4517*e47783fdSXin Li /*international text chunk (iTXt)*/
readChunk_iTXt(LodePNGInfo * info,const LodePNGDecoderSettings * decoder,const unsigned char * data,size_t chunkLength)4518*e47783fdSXin Li static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
4519*e47783fdSXin Li const unsigned char* data, size_t chunkLength) {
4520*e47783fdSXin Li unsigned error = 0;
4521*e47783fdSXin Li unsigned i;
4522*e47783fdSXin Li
4523*e47783fdSXin Li /*copy the object to change parameters in it*/
4524*e47783fdSXin Li LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
4525*e47783fdSXin Li
4526*e47783fdSXin Li unsigned length, begin, compressed;
4527*e47783fdSXin Li char *key = 0, *langtag = 0, *transkey = 0;
4528*e47783fdSXin Li
4529*e47783fdSXin Li while(!error) /*not really a while loop, only used to break on error*/ {
4530*e47783fdSXin Li /*Quick check if the chunk length isn't too small. Even without check
4531*e47783fdSXin Li it'd still fail with other error checks below if it's too short. This just gives a different error code.*/
4532*e47783fdSXin Li if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/
4533*e47783fdSXin Li
4534*e47783fdSXin Li /*read the key*/
4535*e47783fdSXin Li for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
4536*e47783fdSXin Li if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/
4537*e47783fdSXin Li if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
4538*e47783fdSXin Li
4539*e47783fdSXin Li key = (char*)lodepng_malloc(length + 1);
4540*e47783fdSXin Li if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
4541*e47783fdSXin Li
4542*e47783fdSXin Li lodepng_memcpy(key, data, length);
4543*e47783fdSXin Li key[length] = 0;
4544*e47783fdSXin Li
4545*e47783fdSXin Li /*read the compression method*/
4546*e47783fdSXin Li compressed = data[length + 1];
4547*e47783fdSXin Li if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
4548*e47783fdSXin Li
4549*e47783fdSXin Li /*even though it's not allowed by the standard, no error is thrown if
4550*e47783fdSXin Li there's no null termination char, if the text is empty for the next 3 texts*/
4551*e47783fdSXin Li
4552*e47783fdSXin Li /*read the langtag*/
4553*e47783fdSXin Li begin = length + 3;
4554*e47783fdSXin Li length = 0;
4555*e47783fdSXin Li for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;
4556*e47783fdSXin Li
4557*e47783fdSXin Li langtag = (char*)lodepng_malloc(length + 1);
4558*e47783fdSXin Li if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/
4559*e47783fdSXin Li
4560*e47783fdSXin Li lodepng_memcpy(langtag, data + begin, length);
4561*e47783fdSXin Li langtag[length] = 0;
4562*e47783fdSXin Li
4563*e47783fdSXin Li /*read the transkey*/
4564*e47783fdSXin Li begin += length + 1;
4565*e47783fdSXin Li length = 0;
4566*e47783fdSXin Li for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;
4567*e47783fdSXin Li
4568*e47783fdSXin Li transkey = (char*)lodepng_malloc(length + 1);
4569*e47783fdSXin Li if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/
4570*e47783fdSXin Li
4571*e47783fdSXin Li lodepng_memcpy(transkey, data + begin, length);
4572*e47783fdSXin Li transkey[length] = 0;
4573*e47783fdSXin Li
4574*e47783fdSXin Li /*read the actual text*/
4575*e47783fdSXin Li begin += length + 1;
4576*e47783fdSXin Li
4577*e47783fdSXin Li length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin;
4578*e47783fdSXin Li
4579*e47783fdSXin Li if(compressed) {
4580*e47783fdSXin Li unsigned char* str = 0;
4581*e47783fdSXin Li size_t size = 0;
4582*e47783fdSXin Li zlibsettings.max_output_size = decoder->max_text_size;
4583*e47783fdSXin Li /*will fail if zlib error, e.g. if length is too small*/
4584*e47783fdSXin Li error = zlib_decompress(&str, &size, 0, &data[begin],
4585*e47783fdSXin Li length, &zlibsettings);
4586*e47783fdSXin Li /*error: compressed text larger than decoder->max_text_size*/
4587*e47783fdSXin Li if(error && size > zlibsettings.max_output_size) error = 112;
4588*e47783fdSXin Li if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
4589*e47783fdSXin Li lodepng_free(str);
4590*e47783fdSXin Li } else {
4591*e47783fdSXin Li error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)(data + begin), length);
4592*e47783fdSXin Li }
4593*e47783fdSXin Li
4594*e47783fdSXin Li break;
4595*e47783fdSXin Li }
4596*e47783fdSXin Li
4597*e47783fdSXin Li lodepng_free(key);
4598*e47783fdSXin Li lodepng_free(langtag);
4599*e47783fdSXin Li lodepng_free(transkey);
4600*e47783fdSXin Li
4601*e47783fdSXin Li return error;
4602*e47783fdSXin Li }
4603*e47783fdSXin Li
readChunk_tIME(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4604*e47783fdSXin Li static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4605*e47783fdSXin Li if(chunkLength != 7) return 73; /*invalid tIME chunk size*/
4606*e47783fdSXin Li
4607*e47783fdSXin Li info->time_defined = 1;
4608*e47783fdSXin Li info->time.year = 256u * data[0] + data[1];
4609*e47783fdSXin Li info->time.month = data[2];
4610*e47783fdSXin Li info->time.day = data[3];
4611*e47783fdSXin Li info->time.hour = data[4];
4612*e47783fdSXin Li info->time.minute = data[5];
4613*e47783fdSXin Li info->time.second = data[6];
4614*e47783fdSXin Li
4615*e47783fdSXin Li return 0; /* OK */
4616*e47783fdSXin Li }
4617*e47783fdSXin Li
readChunk_pHYs(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4618*e47783fdSXin Li static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4619*e47783fdSXin Li if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/
4620*e47783fdSXin Li
4621*e47783fdSXin Li info->phys_defined = 1;
4622*e47783fdSXin Li info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];
4623*e47783fdSXin Li info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7];
4624*e47783fdSXin Li info->phys_unit = data[8];
4625*e47783fdSXin Li
4626*e47783fdSXin Li return 0; /* OK */
4627*e47783fdSXin Li }
4628*e47783fdSXin Li
readChunk_gAMA(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4629*e47783fdSXin Li static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4630*e47783fdSXin Li if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/
4631*e47783fdSXin Li
4632*e47783fdSXin Li info->gama_defined = 1;
4633*e47783fdSXin Li info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];
4634*e47783fdSXin Li
4635*e47783fdSXin Li return 0; /* OK */
4636*e47783fdSXin Li }
4637*e47783fdSXin Li
readChunk_cHRM(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4638*e47783fdSXin Li static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4639*e47783fdSXin Li if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/
4640*e47783fdSXin Li
4641*e47783fdSXin Li info->chrm_defined = 1;
4642*e47783fdSXin Li info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3];
4643*e47783fdSXin Li info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7];
4644*e47783fdSXin Li info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11];
4645*e47783fdSXin Li info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15];
4646*e47783fdSXin Li info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19];
4647*e47783fdSXin Li info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23];
4648*e47783fdSXin Li info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27];
4649*e47783fdSXin Li info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31];
4650*e47783fdSXin Li
4651*e47783fdSXin Li return 0; /* OK */
4652*e47783fdSXin Li }
4653*e47783fdSXin Li
readChunk_sRGB(LodePNGInfo * info,const unsigned char * data,size_t chunkLength)4654*e47783fdSXin Li static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
4655*e47783fdSXin Li if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/
4656*e47783fdSXin Li
4657*e47783fdSXin Li info->srgb_defined = 1;
4658*e47783fdSXin Li info->srgb_intent = data[0];
4659*e47783fdSXin Li
4660*e47783fdSXin Li return 0; /* OK */
4661*e47783fdSXin Li }
4662*e47783fdSXin Li
readChunk_iCCP(LodePNGInfo * info,const LodePNGDecoderSettings * decoder,const unsigned char * data,size_t chunkLength)4663*e47783fdSXin Li static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
4664*e47783fdSXin Li const unsigned char* data, size_t chunkLength) {
4665*e47783fdSXin Li unsigned error = 0;
4666*e47783fdSXin Li unsigned i;
4667*e47783fdSXin Li size_t size = 0;
4668*e47783fdSXin Li /*copy the object to change parameters in it*/
4669*e47783fdSXin Li LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
4670*e47783fdSXin Li
4671*e47783fdSXin Li unsigned length, string2_begin;
4672*e47783fdSXin Li
4673*e47783fdSXin Li info->iccp_defined = 1;
4674*e47783fdSXin Li if(info->iccp_name) lodepng_clear_icc(info);
4675*e47783fdSXin Li
4676*e47783fdSXin Li for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
4677*e47783fdSXin Li if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/
4678*e47783fdSXin Li if(length < 1 || length > 79) return 89; /*keyword too short or long*/
4679*e47783fdSXin Li
4680*e47783fdSXin Li info->iccp_name = (char*)lodepng_malloc(length + 1);
4681*e47783fdSXin Li if(!info->iccp_name) return 83; /*alloc fail*/
4682*e47783fdSXin Li
4683*e47783fdSXin Li info->iccp_name[length] = 0;
4684*e47783fdSXin Li for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i];
4685*e47783fdSXin Li
4686*e47783fdSXin Li if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/
4687*e47783fdSXin Li
4688*e47783fdSXin Li string2_begin = length + 2;
4689*e47783fdSXin Li if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
4690*e47783fdSXin Li
4691*e47783fdSXin Li length = (unsigned)chunkLength - string2_begin;
4692*e47783fdSXin Li zlibsettings.max_output_size = decoder->max_icc_size;
4693*e47783fdSXin Li error = zlib_decompress(&info->iccp_profile, &size, 0,
4694*e47783fdSXin Li &data[string2_begin],
4695*e47783fdSXin Li length, &zlibsettings);
4696*e47783fdSXin Li /*error: ICC profile larger than decoder->max_icc_size*/
4697*e47783fdSXin Li if(error && size > zlibsettings.max_output_size) error = 113;
4698*e47783fdSXin Li info->iccp_profile_size = size;
4699*e47783fdSXin Li if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
4700*e47783fdSXin Li return error;
4701*e47783fdSXin Li }
4702*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4703*e47783fdSXin Li
lodepng_inspect_chunk(LodePNGState * state,size_t pos,const unsigned char * in,size_t insize)4704*e47783fdSXin Li unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
4705*e47783fdSXin Li const unsigned char* in, size_t insize) {
4706*e47783fdSXin Li const unsigned char* chunk = in + pos;
4707*e47783fdSXin Li unsigned chunkLength;
4708*e47783fdSXin Li const unsigned char* data;
4709*e47783fdSXin Li unsigned unhandled = 0;
4710*e47783fdSXin Li unsigned error = 0;
4711*e47783fdSXin Li
4712*e47783fdSXin Li if(pos + 4 > insize) return 30;
4713*e47783fdSXin Li chunkLength = lodepng_chunk_length(chunk);
4714*e47783fdSXin Li if(chunkLength > 2147483647) return 63;
4715*e47783fdSXin Li data = lodepng_chunk_data_const(chunk);
4716*e47783fdSXin Li if(data + chunkLength + 4 > in + insize) return 30;
4717*e47783fdSXin Li
4718*e47783fdSXin Li if(lodepng_chunk_type_equals(chunk, "PLTE")) {
4719*e47783fdSXin Li error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
4720*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "tRNS")) {
4721*e47783fdSXin Li error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
4722*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4723*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "bKGD")) {
4724*e47783fdSXin Li error = readChunk_bKGD(&state->info_png, data, chunkLength);
4725*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
4726*e47783fdSXin Li error = readChunk_tEXt(&state->info_png, data, chunkLength);
4727*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
4728*e47783fdSXin Li error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
4729*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
4730*e47783fdSXin Li error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
4731*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
4732*e47783fdSXin Li error = readChunk_tIME(&state->info_png, data, chunkLength);
4733*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
4734*e47783fdSXin Li error = readChunk_pHYs(&state->info_png, data, chunkLength);
4735*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "gAMA")) {
4736*e47783fdSXin Li error = readChunk_gAMA(&state->info_png, data, chunkLength);
4737*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "cHRM")) {
4738*e47783fdSXin Li error = readChunk_cHRM(&state->info_png, data, chunkLength);
4739*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
4740*e47783fdSXin Li error = readChunk_sRGB(&state->info_png, data, chunkLength);
4741*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
4742*e47783fdSXin Li error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
4743*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4744*e47783fdSXin Li } else {
4745*e47783fdSXin Li /* unhandled chunk is ok (is not an error) */
4746*e47783fdSXin Li unhandled = 1;
4747*e47783fdSXin Li }
4748*e47783fdSXin Li
4749*e47783fdSXin Li if(!error && !unhandled && !state->decoder.ignore_crc) {
4750*e47783fdSXin Li if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/
4751*e47783fdSXin Li }
4752*e47783fdSXin Li
4753*e47783fdSXin Li return error;
4754*e47783fdSXin Li }
4755*e47783fdSXin Li
4756*e47783fdSXin Li /*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
decodeGeneric(unsigned char ** out,unsigned * w,unsigned * h,LodePNGState * state,const unsigned char * in,size_t insize)4757*e47783fdSXin Li static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
4758*e47783fdSXin Li LodePNGState* state,
4759*e47783fdSXin Li const unsigned char* in, size_t insize) {
4760*e47783fdSXin Li unsigned char IEND = 0;
4761*e47783fdSXin Li const unsigned char* chunk;
4762*e47783fdSXin Li unsigned char* idat; /*the data from idat chunks, zlib compressed*/
4763*e47783fdSXin Li size_t idatsize = 0;
4764*e47783fdSXin Li unsigned char* scanlines = 0;
4765*e47783fdSXin Li size_t scanlines_size = 0, expected_size = 0;
4766*e47783fdSXin Li size_t outsize = 0;
4767*e47783fdSXin Li
4768*e47783fdSXin Li /*for unknown chunk order*/
4769*e47783fdSXin Li unsigned unknown = 0;
4770*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4771*e47783fdSXin Li unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/
4772*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4773*e47783fdSXin Li
4774*e47783fdSXin Li
4775*e47783fdSXin Li /* safe output values in case error happens */
4776*e47783fdSXin Li *out = 0;
4777*e47783fdSXin Li *w = *h = 0;
4778*e47783fdSXin Li
4779*e47783fdSXin Li state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/
4780*e47783fdSXin Li if(state->error) return;
4781*e47783fdSXin Li
4782*e47783fdSXin Li if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) {
4783*e47783fdSXin Li CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/
4784*e47783fdSXin Li }
4785*e47783fdSXin Li
4786*e47783fdSXin Li /*the input filesize is a safe upper bound for the sum of idat chunks size*/
4787*e47783fdSXin Li idat = (unsigned char*)lodepng_malloc(insize);
4788*e47783fdSXin Li if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/
4789*e47783fdSXin Li
4790*e47783fdSXin Li chunk = &in[33]; /*first byte of the first chunk after the header*/
4791*e47783fdSXin Li
4792*e47783fdSXin Li /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.
4793*e47783fdSXin Li IDAT data is put at the start of the in buffer*/
4794*e47783fdSXin Li while(!IEND && !state->error) {
4795*e47783fdSXin Li unsigned chunkLength;
4796*e47783fdSXin Li const unsigned char* data; /*the data in the chunk*/
4797*e47783fdSXin Li
4798*e47783fdSXin Li /*error: size of the in buffer too small to contain next chunk*/
4799*e47783fdSXin Li if((size_t)((chunk - in) + 12) > insize || chunk < in) {
4800*e47783fdSXin Li if(state->decoder.ignore_end) break; /*other errors may still happen though*/
4801*e47783fdSXin Li CERROR_BREAK(state->error, 30);
4802*e47783fdSXin Li }
4803*e47783fdSXin Li
4804*e47783fdSXin Li /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
4805*e47783fdSXin Li chunkLength = lodepng_chunk_length(chunk);
4806*e47783fdSXin Li /*error: chunk length larger than the max PNG chunk size*/
4807*e47783fdSXin Li if(chunkLength > 2147483647) {
4808*e47783fdSXin Li if(state->decoder.ignore_end) break; /*other errors may still happen though*/
4809*e47783fdSXin Li CERROR_BREAK(state->error, 63);
4810*e47783fdSXin Li }
4811*e47783fdSXin Li
4812*e47783fdSXin Li if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) {
4813*e47783fdSXin Li CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/
4814*e47783fdSXin Li }
4815*e47783fdSXin Li
4816*e47783fdSXin Li data = lodepng_chunk_data_const(chunk);
4817*e47783fdSXin Li
4818*e47783fdSXin Li unknown = 0;
4819*e47783fdSXin Li
4820*e47783fdSXin Li /*IDAT chunk, containing compressed image data*/
4821*e47783fdSXin Li if(lodepng_chunk_type_equals(chunk, "IDAT")) {
4822*e47783fdSXin Li size_t newsize;
4823*e47783fdSXin Li if(lodepng_addofl(idatsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95);
4824*e47783fdSXin Li if(newsize > insize) CERROR_BREAK(state->error, 95);
4825*e47783fdSXin Li lodepng_memcpy(idat + idatsize, data, chunkLength);
4826*e47783fdSXin Li idatsize += chunkLength;
4827*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4828*e47783fdSXin Li critical_pos = 3;
4829*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4830*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "IEND")) {
4831*e47783fdSXin Li /*IEND chunk*/
4832*e47783fdSXin Li IEND = 1;
4833*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "PLTE")) {
4834*e47783fdSXin Li /*palette chunk (PLTE)*/
4835*e47783fdSXin Li state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
4836*e47783fdSXin Li if(state->error) break;
4837*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4838*e47783fdSXin Li critical_pos = 2;
4839*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4840*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "tRNS")) {
4841*e47783fdSXin Li /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled
4842*e47783fdSXin Li in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that
4843*e47783fdSXin Li affects the alpha channel of pixels. */
4844*e47783fdSXin Li state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
4845*e47783fdSXin Li if(state->error) break;
4846*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4847*e47783fdSXin Li /*background color chunk (bKGD)*/
4848*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "bKGD")) {
4849*e47783fdSXin Li state->error = readChunk_bKGD(&state->info_png, data, chunkLength);
4850*e47783fdSXin Li if(state->error) break;
4851*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
4852*e47783fdSXin Li /*text chunk (tEXt)*/
4853*e47783fdSXin Li if(state->decoder.read_text_chunks) {
4854*e47783fdSXin Li state->error = readChunk_tEXt(&state->info_png, data, chunkLength);
4855*e47783fdSXin Li if(state->error) break;
4856*e47783fdSXin Li }
4857*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
4858*e47783fdSXin Li /*compressed text chunk (zTXt)*/
4859*e47783fdSXin Li if(state->decoder.read_text_chunks) {
4860*e47783fdSXin Li state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
4861*e47783fdSXin Li if(state->error) break;
4862*e47783fdSXin Li }
4863*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
4864*e47783fdSXin Li /*international text chunk (iTXt)*/
4865*e47783fdSXin Li if(state->decoder.read_text_chunks) {
4866*e47783fdSXin Li state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
4867*e47783fdSXin Li if(state->error) break;
4868*e47783fdSXin Li }
4869*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
4870*e47783fdSXin Li state->error = readChunk_tIME(&state->info_png, data, chunkLength);
4871*e47783fdSXin Li if(state->error) break;
4872*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
4873*e47783fdSXin Li state->error = readChunk_pHYs(&state->info_png, data, chunkLength);
4874*e47783fdSXin Li if(state->error) break;
4875*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "gAMA")) {
4876*e47783fdSXin Li state->error = readChunk_gAMA(&state->info_png, data, chunkLength);
4877*e47783fdSXin Li if(state->error) break;
4878*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "cHRM")) {
4879*e47783fdSXin Li state->error = readChunk_cHRM(&state->info_png, data, chunkLength);
4880*e47783fdSXin Li if(state->error) break;
4881*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
4882*e47783fdSXin Li state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
4883*e47783fdSXin Li if(state->error) break;
4884*e47783fdSXin Li } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
4885*e47783fdSXin Li state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
4886*e47783fdSXin Li if(state->error) break;
4887*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4888*e47783fdSXin Li } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
4889*e47783fdSXin Li /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
4890*e47783fdSXin Li if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) {
4891*e47783fdSXin Li CERROR_BREAK(state->error, 69);
4892*e47783fdSXin Li }
4893*e47783fdSXin Li
4894*e47783fdSXin Li unknown = 1;
4895*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4896*e47783fdSXin Li if(state->decoder.remember_unknown_chunks) {
4897*e47783fdSXin Li state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1],
4898*e47783fdSXin Li &state->info_png.unknown_chunks_size[critical_pos - 1], chunk);
4899*e47783fdSXin Li if(state->error) break;
4900*e47783fdSXin Li }
4901*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4902*e47783fdSXin Li }
4903*e47783fdSXin Li
4904*e47783fdSXin Li if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ {
4905*e47783fdSXin Li if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/
4906*e47783fdSXin Li }
4907*e47783fdSXin Li
4908*e47783fdSXin Li if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
4909*e47783fdSXin Li }
4910*e47783fdSXin Li
4911*e47783fdSXin Li if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
4912*e47783fdSXin Li state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
4913*e47783fdSXin Li }
4914*e47783fdSXin Li
4915*e47783fdSXin Li if(!state->error) {
4916*e47783fdSXin Li /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.
4917*e47783fdSXin Li If the decompressed size does not match the prediction, the image must be corrupt.*/
4918*e47783fdSXin Li if(state->info_png.interlace_method == 0) {
4919*e47783fdSXin Li size_t bpp = lodepng_get_bpp(&state->info_png.color);
4920*e47783fdSXin Li expected_size = lodepng_get_raw_size_idat(*w, *h, bpp);
4921*e47783fdSXin Li } else {
4922*e47783fdSXin Li size_t bpp = lodepng_get_bpp(&state->info_png.color);
4923*e47783fdSXin Li /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/
4924*e47783fdSXin Li expected_size = 0;
4925*e47783fdSXin Li expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, bpp);
4926*e47783fdSXin Li if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, bpp);
4927*e47783fdSXin Li expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, bpp);
4928*e47783fdSXin Li if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, bpp);
4929*e47783fdSXin Li expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, bpp);
4930*e47783fdSXin Li if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, bpp);
4931*e47783fdSXin Li expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, bpp);
4932*e47783fdSXin Li }
4933*e47783fdSXin Li
4934*e47783fdSXin Li state->error = zlib_decompress(&scanlines, &scanlines_size, expected_size, idat, idatsize, &state->decoder.zlibsettings);
4935*e47783fdSXin Li }
4936*e47783fdSXin Li if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/
4937*e47783fdSXin Li lodepng_free(idat);
4938*e47783fdSXin Li
4939*e47783fdSXin Li if(!state->error) {
4940*e47783fdSXin Li outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);
4941*e47783fdSXin Li *out = (unsigned char*)lodepng_malloc(outsize);
4942*e47783fdSXin Li if(!*out) state->error = 83; /*alloc fail*/
4943*e47783fdSXin Li }
4944*e47783fdSXin Li if(!state->error) {
4945*e47783fdSXin Li lodepng_memset(*out, 0, outsize);
4946*e47783fdSXin Li state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png);
4947*e47783fdSXin Li }
4948*e47783fdSXin Li lodepng_free(scanlines);
4949*e47783fdSXin Li }
4950*e47783fdSXin Li
lodepng_decode(unsigned char ** out,unsigned * w,unsigned * h,LodePNGState * state,const unsigned char * in,size_t insize)4951*e47783fdSXin Li unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
4952*e47783fdSXin Li LodePNGState* state,
4953*e47783fdSXin Li const unsigned char* in, size_t insize) {
4954*e47783fdSXin Li *out = 0;
4955*e47783fdSXin Li decodeGeneric(out, w, h, state, in, insize);
4956*e47783fdSXin Li if(state->error) return state->error;
4957*e47783fdSXin Li if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) {
4958*e47783fdSXin Li /*same color type, no copying or converting of data needed*/
4959*e47783fdSXin Li /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype
4960*e47783fdSXin Li the raw image has to the end user*/
4961*e47783fdSXin Li if(!state->decoder.color_convert) {
4962*e47783fdSXin Li state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color);
4963*e47783fdSXin Li if(state->error) return state->error;
4964*e47783fdSXin Li }
4965*e47783fdSXin Li } else { /*color conversion needed*/
4966*e47783fdSXin Li unsigned char* data = *out;
4967*e47783fdSXin Li size_t outsize;
4968*e47783fdSXin Li
4969*e47783fdSXin Li /*TODO: check if this works according to the statement in the documentation: "The converter can convert
4970*e47783fdSXin Li from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/
4971*e47783fdSXin Li if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA)
4972*e47783fdSXin Li && !(state->info_raw.bitdepth == 8)) {
4973*e47783fdSXin Li return 56; /*unsupported color mode conversion*/
4974*e47783fdSXin Li }
4975*e47783fdSXin Li
4976*e47783fdSXin Li outsize = lodepng_get_raw_size(*w, *h, &state->info_raw);
4977*e47783fdSXin Li *out = (unsigned char*)lodepng_malloc(outsize);
4978*e47783fdSXin Li if(!(*out)) {
4979*e47783fdSXin Li state->error = 83; /*alloc fail*/
4980*e47783fdSXin Li }
4981*e47783fdSXin Li else state->error = lodepng_convert(*out, data, &state->info_raw,
4982*e47783fdSXin Li &state->info_png.color, *w, *h);
4983*e47783fdSXin Li lodepng_free(data);
4984*e47783fdSXin Li }
4985*e47783fdSXin Li return state->error;
4986*e47783fdSXin Li }
4987*e47783fdSXin Li
lodepng_decode_memory(unsigned char ** out,unsigned * w,unsigned * h,const unsigned char * in,size_t insize,LodePNGColorType colortype,unsigned bitdepth)4988*e47783fdSXin Li unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in,
4989*e47783fdSXin Li size_t insize, LodePNGColorType colortype, unsigned bitdepth) {
4990*e47783fdSXin Li unsigned error;
4991*e47783fdSXin Li LodePNGState state;
4992*e47783fdSXin Li lodepng_state_init(&state);
4993*e47783fdSXin Li state.info_raw.colortype = colortype;
4994*e47783fdSXin Li state.info_raw.bitdepth = bitdepth;
4995*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4996*e47783fdSXin Li /*disable reading things that this function doesn't output*/
4997*e47783fdSXin Li state.decoder.read_text_chunks = 0;
4998*e47783fdSXin Li state.decoder.remember_unknown_chunks = 0;
4999*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5000*e47783fdSXin Li error = lodepng_decode(out, w, h, &state, in, insize);
5001*e47783fdSXin Li lodepng_state_cleanup(&state);
5002*e47783fdSXin Li return error;
5003*e47783fdSXin Li }
5004*e47783fdSXin Li
lodepng_decode32(unsigned char ** out,unsigned * w,unsigned * h,const unsigned char * in,size_t insize)5005*e47783fdSXin Li unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) {
5006*e47783fdSXin Li return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8);
5007*e47783fdSXin Li }
5008*e47783fdSXin Li
lodepng_decode24(unsigned char ** out,unsigned * w,unsigned * h,const unsigned char * in,size_t insize)5009*e47783fdSXin Li unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) {
5010*e47783fdSXin Li return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8);
5011*e47783fdSXin Li }
5012*e47783fdSXin Li
5013*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
lodepng_decode_file(unsigned char ** out,unsigned * w,unsigned * h,const char * filename,LodePNGColorType colortype,unsigned bitdepth)5014*e47783fdSXin Li unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,
5015*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
5016*e47783fdSXin Li unsigned char* buffer = 0;
5017*e47783fdSXin Li size_t buffersize;
5018*e47783fdSXin Li unsigned error;
5019*e47783fdSXin Li /* safe output values in case error happens */
5020*e47783fdSXin Li *out = 0;
5021*e47783fdSXin Li *w = *h = 0;
5022*e47783fdSXin Li error = lodepng_load_file(&buffer, &buffersize, filename);
5023*e47783fdSXin Li if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth);
5024*e47783fdSXin Li lodepng_free(buffer);
5025*e47783fdSXin Li return error;
5026*e47783fdSXin Li }
5027*e47783fdSXin Li
lodepng_decode32_file(unsigned char ** out,unsigned * w,unsigned * h,const char * filename)5028*e47783fdSXin Li unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) {
5029*e47783fdSXin Li return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8);
5030*e47783fdSXin Li }
5031*e47783fdSXin Li
lodepng_decode24_file(unsigned char ** out,unsigned * w,unsigned * h,const char * filename)5032*e47783fdSXin Li unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) {
5033*e47783fdSXin Li return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8);
5034*e47783fdSXin Li }
5035*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DISK*/
5036*e47783fdSXin Li
lodepng_decoder_settings_init(LodePNGDecoderSettings * settings)5037*e47783fdSXin Li void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) {
5038*e47783fdSXin Li settings->color_convert = 1;
5039*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5040*e47783fdSXin Li settings->read_text_chunks = 1;
5041*e47783fdSXin Li settings->remember_unknown_chunks = 0;
5042*e47783fdSXin Li settings->max_text_size = 16777216;
5043*e47783fdSXin Li settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */
5044*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5045*e47783fdSXin Li settings->ignore_crc = 0;
5046*e47783fdSXin Li settings->ignore_critical = 0;
5047*e47783fdSXin Li settings->ignore_end = 0;
5048*e47783fdSXin Li lodepng_decompress_settings_init(&settings->zlibsettings);
5049*e47783fdSXin Li }
5050*e47783fdSXin Li
5051*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
5052*e47783fdSXin Li
5053*e47783fdSXin Li #if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
5054*e47783fdSXin Li
lodepng_state_init(LodePNGState * state)5055*e47783fdSXin Li void lodepng_state_init(LodePNGState* state) {
5056*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
5057*e47783fdSXin Li lodepng_decoder_settings_init(&state->decoder);
5058*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DECODER*/
5059*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
5060*e47783fdSXin Li lodepng_encoder_settings_init(&state->encoder);
5061*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
5062*e47783fdSXin Li lodepng_color_mode_init(&state->info_raw);
5063*e47783fdSXin Li lodepng_info_init(&state->info_png);
5064*e47783fdSXin Li state->error = 1;
5065*e47783fdSXin Li }
5066*e47783fdSXin Li
lodepng_state_cleanup(LodePNGState * state)5067*e47783fdSXin Li void lodepng_state_cleanup(LodePNGState* state) {
5068*e47783fdSXin Li lodepng_color_mode_cleanup(&state->info_raw);
5069*e47783fdSXin Li lodepng_info_cleanup(&state->info_png);
5070*e47783fdSXin Li }
5071*e47783fdSXin Li
lodepng_state_copy(LodePNGState * dest,const LodePNGState * source)5072*e47783fdSXin Li void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) {
5073*e47783fdSXin Li lodepng_state_cleanup(dest);
5074*e47783fdSXin Li *dest = *source;
5075*e47783fdSXin Li lodepng_color_mode_init(&dest->info_raw);
5076*e47783fdSXin Li lodepng_info_init(&dest->info_png);
5077*e47783fdSXin Li dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return;
5078*e47783fdSXin Li dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return;
5079*e47783fdSXin Li }
5080*e47783fdSXin Li
5081*e47783fdSXin Li #endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */
5082*e47783fdSXin Li
5083*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
5084*e47783fdSXin Li
5085*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
5086*e47783fdSXin Li /* / PNG Encoder / */
5087*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
5088*e47783fdSXin Li
5089*e47783fdSXin Li
writeSignature(ucvector * out)5090*e47783fdSXin Li static unsigned writeSignature(ucvector* out) {
5091*e47783fdSXin Li size_t pos = out->size;
5092*e47783fdSXin Li const unsigned char signature[] = {137, 80, 78, 71, 13, 10, 26, 10};
5093*e47783fdSXin Li /*8 bytes PNG signature, aka the magic bytes*/
5094*e47783fdSXin Li if(!ucvector_resize(out, out->size + 8)) return 83; /*alloc fail*/
5095*e47783fdSXin Li lodepng_memcpy(out->data + pos, signature, 8);
5096*e47783fdSXin Li return 0;
5097*e47783fdSXin Li }
5098*e47783fdSXin Li
addChunk_IHDR(ucvector * out,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth,unsigned interlace_method)5099*e47783fdSXin Li static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,
5100*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) {
5101*e47783fdSXin Li unsigned char *chunk, *data;
5102*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 13, "IHDR"));
5103*e47783fdSXin Li data = chunk + 8;
5104*e47783fdSXin Li
5105*e47783fdSXin Li lodepng_set32bitInt(data + 0, w); /*width*/
5106*e47783fdSXin Li lodepng_set32bitInt(data + 4, h); /*height*/
5107*e47783fdSXin Li data[8] = (unsigned char)bitdepth; /*bit depth*/
5108*e47783fdSXin Li data[9] = (unsigned char)colortype; /*color type*/
5109*e47783fdSXin Li data[10] = 0; /*compression method*/
5110*e47783fdSXin Li data[11] = 0; /*filter method*/
5111*e47783fdSXin Li data[12] = interlace_method; /*interlace method*/
5112*e47783fdSXin Li
5113*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5114*e47783fdSXin Li return 0;
5115*e47783fdSXin Li }
5116*e47783fdSXin Li
5117*e47783fdSXin Li /* only adds the chunk if needed (there is a key or palette with alpha) */
addChunk_PLTE(ucvector * out,const LodePNGColorMode * info)5118*e47783fdSXin Li static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) {
5119*e47783fdSXin Li unsigned char* chunk;
5120*e47783fdSXin Li size_t i, j = 8;
5121*e47783fdSXin Li
5122*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE"));
5123*e47783fdSXin Li
5124*e47783fdSXin Li for(i = 0; i != info->palettesize; ++i) {
5125*e47783fdSXin Li /*add all channels except alpha channel*/
5126*e47783fdSXin Li chunk[j++] = info->palette[i * 4 + 0];
5127*e47783fdSXin Li chunk[j++] = info->palette[i * 4 + 1];
5128*e47783fdSXin Li chunk[j++] = info->palette[i * 4 + 2];
5129*e47783fdSXin Li }
5130*e47783fdSXin Li
5131*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5132*e47783fdSXin Li return 0;
5133*e47783fdSXin Li }
5134*e47783fdSXin Li
addChunk_tRNS(ucvector * out,const LodePNGColorMode * info)5135*e47783fdSXin Li static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) {
5136*e47783fdSXin Li unsigned char* chunk = 0;
5137*e47783fdSXin Li
5138*e47783fdSXin Li if(info->colortype == LCT_PALETTE) {
5139*e47783fdSXin Li size_t i, amount = info->palettesize;
5140*e47783fdSXin Li /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/
5141*e47783fdSXin Li for(i = info->palettesize; i != 0; --i) {
5142*e47783fdSXin Li if(info->palette[4 * (i - 1) + 3] != 255) break;
5143*e47783fdSXin Li --amount;
5144*e47783fdSXin Li }
5145*e47783fdSXin Li if(amount) {
5146*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, amount, "tRNS"));
5147*e47783fdSXin Li /*add the alpha channel values from the palette*/
5148*e47783fdSXin Li for(i = 0; i != amount; ++i) chunk[8 + i] = info->palette[4 * i + 3];
5149*e47783fdSXin Li }
5150*e47783fdSXin Li } else if(info->colortype == LCT_GREY) {
5151*e47783fdSXin Li if(info->key_defined) {
5152*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "tRNS"));
5153*e47783fdSXin Li chunk[8] = (unsigned char)(info->key_r >> 8);
5154*e47783fdSXin Li chunk[9] = (unsigned char)(info->key_r & 255);
5155*e47783fdSXin Li }
5156*e47783fdSXin Li } else if(info->colortype == LCT_RGB) {
5157*e47783fdSXin Li if(info->key_defined) {
5158*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "tRNS"));
5159*e47783fdSXin Li chunk[8] = (unsigned char)(info->key_r >> 8);
5160*e47783fdSXin Li chunk[9] = (unsigned char)(info->key_r & 255);
5161*e47783fdSXin Li chunk[10] = (unsigned char)(info->key_g >> 8);
5162*e47783fdSXin Li chunk[11] = (unsigned char)(info->key_g & 255);
5163*e47783fdSXin Li chunk[12] = (unsigned char)(info->key_b >> 8);
5164*e47783fdSXin Li chunk[13] = (unsigned char)(info->key_b & 255);
5165*e47783fdSXin Li }
5166*e47783fdSXin Li }
5167*e47783fdSXin Li
5168*e47783fdSXin Li if(chunk) lodepng_chunk_generate_crc(chunk);
5169*e47783fdSXin Li return 0;
5170*e47783fdSXin Li }
5171*e47783fdSXin Li
addChunk_IDAT(ucvector * out,const unsigned char * data,size_t datasize,LodePNGCompressSettings * zlibsettings)5172*e47783fdSXin Li static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize,
5173*e47783fdSXin Li LodePNGCompressSettings* zlibsettings) {
5174*e47783fdSXin Li unsigned error = 0;
5175*e47783fdSXin Li unsigned char* zlib = 0;
5176*e47783fdSXin Li size_t zlibsize = 0;
5177*e47783fdSXin Li
5178*e47783fdSXin Li error = zlib_compress(&zlib, &zlibsize, data, datasize, zlibsettings);
5179*e47783fdSXin Li if(!error) {
5180*e47783fdSXin Li error = lodepng_chunk_createv(out, zlibsize, "IDAT", zlib);
5181*e47783fdSXin Li }
5182*e47783fdSXin Li lodepng_free(zlib);
5183*e47783fdSXin Li return error;
5184*e47783fdSXin Li }
5185*e47783fdSXin Li
addChunk_IEND(ucvector * out)5186*e47783fdSXin Li static unsigned addChunk_IEND(ucvector* out) {
5187*e47783fdSXin Li return lodepng_chunk_createv(out, 0, "IEND", 0);
5188*e47783fdSXin Li }
5189*e47783fdSXin Li
5190*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5191*e47783fdSXin Li
addChunk_tEXt(ucvector * out,const char * keyword,const char * textstring)5192*e47783fdSXin Li static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) {
5193*e47783fdSXin Li unsigned char* chunk = 0;
5194*e47783fdSXin Li size_t keysize = lodepng_strlen(keyword), textsize = lodepng_strlen(textstring);
5195*e47783fdSXin Li size_t size = keysize + 1 + textsize;
5196*e47783fdSXin Li if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/
5197*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, size, "tEXt"));
5198*e47783fdSXin Li lodepng_memcpy(chunk + 8, keyword, keysize);
5199*e47783fdSXin Li chunk[8 + keysize] = 0; /*null termination char*/
5200*e47783fdSXin Li lodepng_memcpy(chunk + 9 + keysize, textstring, textsize);
5201*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5202*e47783fdSXin Li return 0;
5203*e47783fdSXin Li }
5204*e47783fdSXin Li
addChunk_zTXt(ucvector * out,const char * keyword,const char * textstring,LodePNGCompressSettings * zlibsettings)5205*e47783fdSXin Li static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring,
5206*e47783fdSXin Li LodePNGCompressSettings* zlibsettings) {
5207*e47783fdSXin Li unsigned error = 0;
5208*e47783fdSXin Li unsigned char* chunk = 0;
5209*e47783fdSXin Li unsigned char* compressed = 0;
5210*e47783fdSXin Li size_t compressedsize = 0;
5211*e47783fdSXin Li size_t textsize = lodepng_strlen(textstring);
5212*e47783fdSXin Li size_t keysize = lodepng_strlen(keyword);
5213*e47783fdSXin Li if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/
5214*e47783fdSXin Li
5215*e47783fdSXin Li error = zlib_compress(&compressed, &compressedsize,
5216*e47783fdSXin Li (const unsigned char*)textstring, textsize, zlibsettings);
5217*e47783fdSXin Li if(!error) {
5218*e47783fdSXin Li size_t size = keysize + 2 + compressedsize;
5219*e47783fdSXin Li error = lodepng_chunk_init(&chunk, out, size, "zTXt");
5220*e47783fdSXin Li }
5221*e47783fdSXin Li if(!error) {
5222*e47783fdSXin Li lodepng_memcpy(chunk + 8, keyword, keysize);
5223*e47783fdSXin Li chunk[8 + keysize] = 0; /*null termination char*/
5224*e47783fdSXin Li chunk[9 + keysize] = 0; /*compression method: 0*/
5225*e47783fdSXin Li lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize);
5226*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5227*e47783fdSXin Li }
5228*e47783fdSXin Li
5229*e47783fdSXin Li lodepng_free(compressed);
5230*e47783fdSXin Li return error;
5231*e47783fdSXin Li }
5232*e47783fdSXin Li
addChunk_iTXt(ucvector * out,unsigned compress,const char * keyword,const char * langtag,const char * transkey,const char * textstring,LodePNGCompressSettings * zlibsettings)5233*e47783fdSXin Li static unsigned addChunk_iTXt(ucvector* out, unsigned compress, const char* keyword, const char* langtag,
5234*e47783fdSXin Li const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) {
5235*e47783fdSXin Li unsigned error = 0;
5236*e47783fdSXin Li unsigned char* chunk = 0;
5237*e47783fdSXin Li unsigned char* compressed = 0;
5238*e47783fdSXin Li size_t compressedsize = 0;
5239*e47783fdSXin Li size_t textsize = lodepng_strlen(textstring);
5240*e47783fdSXin Li size_t keysize = lodepng_strlen(keyword), langsize = lodepng_strlen(langtag), transsize = lodepng_strlen(transkey);
5241*e47783fdSXin Li
5242*e47783fdSXin Li if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/
5243*e47783fdSXin Li
5244*e47783fdSXin Li if(compress) {
5245*e47783fdSXin Li error = zlib_compress(&compressed, &compressedsize,
5246*e47783fdSXin Li (const unsigned char*)textstring, textsize, zlibsettings);
5247*e47783fdSXin Li }
5248*e47783fdSXin Li if(!error) {
5249*e47783fdSXin Li size_t size = keysize + 3 + langsize + 1 + transsize + 1 + (compress ? compressedsize : textsize);
5250*e47783fdSXin Li error = lodepng_chunk_init(&chunk, out, size, "iTXt");
5251*e47783fdSXin Li }
5252*e47783fdSXin Li if(!error) {
5253*e47783fdSXin Li size_t pos = 8;
5254*e47783fdSXin Li lodepng_memcpy(chunk + pos, keyword, keysize);
5255*e47783fdSXin Li pos += keysize;
5256*e47783fdSXin Li chunk[pos++] = 0; /*null termination char*/
5257*e47783fdSXin Li chunk[pos++] = (compress ? 1 : 0); /*compression flag*/
5258*e47783fdSXin Li chunk[pos++] = 0; /*compression method: 0*/
5259*e47783fdSXin Li lodepng_memcpy(chunk + pos, langtag, langsize);
5260*e47783fdSXin Li pos += langsize;
5261*e47783fdSXin Li chunk[pos++] = 0; /*null termination char*/
5262*e47783fdSXin Li lodepng_memcpy(chunk + pos, transkey, transsize);
5263*e47783fdSXin Li pos += transsize;
5264*e47783fdSXin Li chunk[pos++] = 0; /*null termination char*/
5265*e47783fdSXin Li if(compress) {
5266*e47783fdSXin Li lodepng_memcpy(chunk + pos, compressed, compressedsize);
5267*e47783fdSXin Li } else {
5268*e47783fdSXin Li lodepng_memcpy(chunk + pos, textstring, textsize);
5269*e47783fdSXin Li }
5270*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5271*e47783fdSXin Li }
5272*e47783fdSXin Li
5273*e47783fdSXin Li lodepng_free(compressed);
5274*e47783fdSXin Li return error;
5275*e47783fdSXin Li }
5276*e47783fdSXin Li
addChunk_bKGD(ucvector * out,const LodePNGInfo * info)5277*e47783fdSXin Li static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) {
5278*e47783fdSXin Li unsigned char* chunk = 0;
5279*e47783fdSXin Li if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
5280*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "bKGD"));
5281*e47783fdSXin Li chunk[8] = (unsigned char)(info->background_r >> 8);
5282*e47783fdSXin Li chunk[9] = (unsigned char)(info->background_r & 255);
5283*e47783fdSXin Li } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
5284*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "bKGD"));
5285*e47783fdSXin Li chunk[8] = (unsigned char)(info->background_r >> 8);
5286*e47783fdSXin Li chunk[9] = (unsigned char)(info->background_r & 255);
5287*e47783fdSXin Li chunk[10] = (unsigned char)(info->background_g >> 8);
5288*e47783fdSXin Li chunk[11] = (unsigned char)(info->background_g & 255);
5289*e47783fdSXin Li chunk[12] = (unsigned char)(info->background_b >> 8);
5290*e47783fdSXin Li chunk[13] = (unsigned char)(info->background_b & 255);
5291*e47783fdSXin Li } else if(info->color.colortype == LCT_PALETTE) {
5292*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "bKGD"));
5293*e47783fdSXin Li chunk[8] = (unsigned char)(info->background_r & 255); /*palette index*/
5294*e47783fdSXin Li }
5295*e47783fdSXin Li if(chunk) lodepng_chunk_generate_crc(chunk);
5296*e47783fdSXin Li return 0;
5297*e47783fdSXin Li }
5298*e47783fdSXin Li
addChunk_tIME(ucvector * out,const LodePNGTime * time)5299*e47783fdSXin Li static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) {
5300*e47783fdSXin Li unsigned char* chunk;
5301*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 7, "tIME"));
5302*e47783fdSXin Li chunk[8] = (unsigned char)(time->year >> 8);
5303*e47783fdSXin Li chunk[9] = (unsigned char)(time->year & 255);
5304*e47783fdSXin Li chunk[10] = (unsigned char)time->month;
5305*e47783fdSXin Li chunk[11] = (unsigned char)time->day;
5306*e47783fdSXin Li chunk[12] = (unsigned char)time->hour;
5307*e47783fdSXin Li chunk[13] = (unsigned char)time->minute;
5308*e47783fdSXin Li chunk[14] = (unsigned char)time->second;
5309*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5310*e47783fdSXin Li return 0;
5311*e47783fdSXin Li }
5312*e47783fdSXin Li
addChunk_pHYs(ucvector * out,const LodePNGInfo * info)5313*e47783fdSXin Li static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) {
5314*e47783fdSXin Li unsigned char* chunk;
5315*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 9, "pHYs"));
5316*e47783fdSXin Li lodepng_set32bitInt(chunk + 8, info->phys_x);
5317*e47783fdSXin Li lodepng_set32bitInt(chunk + 12, info->phys_y);
5318*e47783fdSXin Li chunk[16] = info->phys_unit;
5319*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5320*e47783fdSXin Li return 0;
5321*e47783fdSXin Li }
5322*e47783fdSXin Li
addChunk_gAMA(ucvector * out,const LodePNGInfo * info)5323*e47783fdSXin Li static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) {
5324*e47783fdSXin Li unsigned char* chunk;
5325*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "gAMA"));
5326*e47783fdSXin Li lodepng_set32bitInt(chunk + 8, info->gama_gamma);
5327*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5328*e47783fdSXin Li return 0;
5329*e47783fdSXin Li }
5330*e47783fdSXin Li
addChunk_cHRM(ucvector * out,const LodePNGInfo * info)5331*e47783fdSXin Li static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) {
5332*e47783fdSXin Li unsigned char* chunk;
5333*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 32, "cHRM"));
5334*e47783fdSXin Li lodepng_set32bitInt(chunk + 8, info->chrm_white_x);
5335*e47783fdSXin Li lodepng_set32bitInt(chunk + 12, info->chrm_white_y);
5336*e47783fdSXin Li lodepng_set32bitInt(chunk + 16, info->chrm_red_x);
5337*e47783fdSXin Li lodepng_set32bitInt(chunk + 20, info->chrm_red_y);
5338*e47783fdSXin Li lodepng_set32bitInt(chunk + 24, info->chrm_green_x);
5339*e47783fdSXin Li lodepng_set32bitInt(chunk + 28, info->chrm_green_y);
5340*e47783fdSXin Li lodepng_set32bitInt(chunk + 32, info->chrm_blue_x);
5341*e47783fdSXin Li lodepng_set32bitInt(chunk + 36, info->chrm_blue_y);
5342*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5343*e47783fdSXin Li return 0;
5344*e47783fdSXin Li }
5345*e47783fdSXin Li
addChunk_sRGB(ucvector * out,const LodePNGInfo * info)5346*e47783fdSXin Li static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) {
5347*e47783fdSXin Li unsigned char data = info->srgb_intent;
5348*e47783fdSXin Li return lodepng_chunk_createv(out, 1, "sRGB", &data);
5349*e47783fdSXin Li }
5350*e47783fdSXin Li
addChunk_iCCP(ucvector * out,const LodePNGInfo * info,LodePNGCompressSettings * zlibsettings)5351*e47783fdSXin Li static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) {
5352*e47783fdSXin Li unsigned error = 0;
5353*e47783fdSXin Li unsigned char* chunk = 0;
5354*e47783fdSXin Li unsigned char* compressed = 0;
5355*e47783fdSXin Li size_t compressedsize = 0;
5356*e47783fdSXin Li size_t keysize = lodepng_strlen(info->iccp_name);
5357*e47783fdSXin Li
5358*e47783fdSXin Li if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/
5359*e47783fdSXin Li error = zlib_compress(&compressed, &compressedsize,
5360*e47783fdSXin Li info->iccp_profile, info->iccp_profile_size, zlibsettings);
5361*e47783fdSXin Li if(!error) {
5362*e47783fdSXin Li size_t size = keysize + 2 + compressedsize;
5363*e47783fdSXin Li error = lodepng_chunk_init(&chunk, out, size, "iCCP");
5364*e47783fdSXin Li }
5365*e47783fdSXin Li if(!error) {
5366*e47783fdSXin Li lodepng_memcpy(chunk + 8, info->iccp_name, keysize);
5367*e47783fdSXin Li chunk[8 + keysize] = 0; /*null termination char*/
5368*e47783fdSXin Li chunk[9 + keysize] = 0; /*compression method: 0*/
5369*e47783fdSXin Li lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize);
5370*e47783fdSXin Li lodepng_chunk_generate_crc(chunk);
5371*e47783fdSXin Li }
5372*e47783fdSXin Li
5373*e47783fdSXin Li lodepng_free(compressed);
5374*e47783fdSXin Li return error;
5375*e47783fdSXin Li }
5376*e47783fdSXin Li
5377*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5378*e47783fdSXin Li
filterScanline(unsigned char * out,const unsigned char * scanline,const unsigned char * prevline,size_t length,size_t bytewidth,unsigned char filterType)5379*e47783fdSXin Li static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,
5380*e47783fdSXin Li size_t length, size_t bytewidth, unsigned char filterType) {
5381*e47783fdSXin Li size_t i;
5382*e47783fdSXin Li switch(filterType) {
5383*e47783fdSXin Li case 0: /*None*/
5384*e47783fdSXin Li for(i = 0; i != length; ++i) out[i] = scanline[i];
5385*e47783fdSXin Li break;
5386*e47783fdSXin Li case 1: /*Sub*/
5387*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
5388*e47783fdSXin Li for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth];
5389*e47783fdSXin Li break;
5390*e47783fdSXin Li case 2: /*Up*/
5391*e47783fdSXin Li if(prevline) {
5392*e47783fdSXin Li for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i];
5393*e47783fdSXin Li } else {
5394*e47783fdSXin Li for(i = 0; i != length; ++i) out[i] = scanline[i];
5395*e47783fdSXin Li }
5396*e47783fdSXin Li break;
5397*e47783fdSXin Li case 3: /*Average*/
5398*e47783fdSXin Li if(prevline) {
5399*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1);
5400*e47783fdSXin Li for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1);
5401*e47783fdSXin Li } else {
5402*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
5403*e47783fdSXin Li for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1);
5404*e47783fdSXin Li }
5405*e47783fdSXin Li break;
5406*e47783fdSXin Li case 4: /*Paeth*/
5407*e47783fdSXin Li if(prevline) {
5408*e47783fdSXin Li /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/
5409*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]);
5410*e47783fdSXin Li for(i = bytewidth; i < length; ++i) {
5411*e47783fdSXin Li out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth]));
5412*e47783fdSXin Li }
5413*e47783fdSXin Li } else {
5414*e47783fdSXin Li for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
5415*e47783fdSXin Li /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/
5416*e47783fdSXin Li for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]);
5417*e47783fdSXin Li }
5418*e47783fdSXin Li break;
5419*e47783fdSXin Li default: return; /*invalid filter type given*/
5420*e47783fdSXin Li }
5421*e47783fdSXin Li }
5422*e47783fdSXin Li
5423*e47783fdSXin Li /* integer binary logarithm, max return value is 31 */
ilog2(size_t i)5424*e47783fdSXin Li static size_t ilog2(size_t i) {
5425*e47783fdSXin Li size_t result = 0;
5426*e47783fdSXin Li if(i >= 65536) { result += 16; i >>= 16; }
5427*e47783fdSXin Li if(i >= 256) { result += 8; i >>= 8; }
5428*e47783fdSXin Li if(i >= 16) { result += 4; i >>= 4; }
5429*e47783fdSXin Li if(i >= 4) { result += 2; i >>= 2; }
5430*e47783fdSXin Li if(i >= 2) { result += 1; /*i >>= 1;*/ }
5431*e47783fdSXin Li return result;
5432*e47783fdSXin Li }
5433*e47783fdSXin Li
5434*e47783fdSXin Li /* integer approximation for i * log2(i), helper function for LFS_ENTROPY */
ilog2i(size_t i)5435*e47783fdSXin Li static size_t ilog2i(size_t i) {
5436*e47783fdSXin Li size_t l;
5437*e47783fdSXin Li if(i == 0) return 0;
5438*e47783fdSXin Li l = ilog2(i);
5439*e47783fdSXin Li /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u)
5440*e47783fdSXin Li linearly approximates the missing fractional part multiplied by i */
5441*e47783fdSXin Li return i * l + ((i - (1u << l)) << 1u);
5442*e47783fdSXin Li }
5443*e47783fdSXin Li
filter(unsigned char * out,const unsigned char * in,unsigned w,unsigned h,const LodePNGColorMode * color,const LodePNGEncoderSettings * settings)5444*e47783fdSXin Li static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
5445*e47783fdSXin Li const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) {
5446*e47783fdSXin Li /*
5447*e47783fdSXin Li For PNG filter method 0
5448*e47783fdSXin Li out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are
5449*e47783fdSXin Li the scanlines with 1 extra byte per scanline
5450*e47783fdSXin Li */
5451*e47783fdSXin Li
5452*e47783fdSXin Li unsigned bpp = lodepng_get_bpp(color);
5453*e47783fdSXin Li /*the width of a scanline in bytes, not including the filter type*/
5454*e47783fdSXin Li size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u;
5455*e47783fdSXin Li
5456*e47783fdSXin Li /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
5457*e47783fdSXin Li size_t bytewidth = (bpp + 7u) / 8u;
5458*e47783fdSXin Li const unsigned char* prevline = 0;
5459*e47783fdSXin Li unsigned x, y;
5460*e47783fdSXin Li unsigned error = 0;
5461*e47783fdSXin Li LodePNGFilterStrategy strategy = settings->filter_strategy;
5462*e47783fdSXin Li
5463*e47783fdSXin Li /*
5464*e47783fdSXin Li There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:
5465*e47783fdSXin Li * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.
5466*e47783fdSXin Li use fixed filtering, with the filter None).
5467*e47783fdSXin Li * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is
5468*e47783fdSXin Li not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply
5469*e47783fdSXin Li all five filters and select the filter that produces the smallest sum of absolute values per row.
5470*e47783fdSXin Li This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.
5471*e47783fdSXin Li
5472*e47783fdSXin Li If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,
5473*e47783fdSXin Li but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum
5474*e47783fdSXin Li heuristic is used.
5475*e47783fdSXin Li */
5476*e47783fdSXin Li if(settings->filter_palette_zero &&
5477*e47783fdSXin Li (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO;
5478*e47783fdSXin Li
5479*e47783fdSXin Li if(bpp == 0) return 31; /*error: invalid color type*/
5480*e47783fdSXin Li
5481*e47783fdSXin Li if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) {
5482*e47783fdSXin Li unsigned char type = (unsigned char)strategy;
5483*e47783fdSXin Li for(y = 0; y != h; ++y) {
5484*e47783fdSXin Li size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
5485*e47783fdSXin Li size_t inindex = linebytes * y;
5486*e47783fdSXin Li out[outindex] = type; /*filter type byte*/
5487*e47783fdSXin Li filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
5488*e47783fdSXin Li prevline = &in[inindex];
5489*e47783fdSXin Li }
5490*e47783fdSXin Li } else if(strategy == LFS_MINSUM) {
5491*e47783fdSXin Li /*adaptive filtering*/
5492*e47783fdSXin Li unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
5493*e47783fdSXin Li size_t smallest = 0;
5494*e47783fdSXin Li unsigned char type, bestType = 0;
5495*e47783fdSXin Li
5496*e47783fdSXin Li for(type = 0; type != 5; ++type) {
5497*e47783fdSXin Li attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
5498*e47783fdSXin Li if(!attempt[type]) error = 83; /*alloc fail*/
5499*e47783fdSXin Li }
5500*e47783fdSXin Li
5501*e47783fdSXin Li if(!error) {
5502*e47783fdSXin Li for(y = 0; y != h; ++y) {
5503*e47783fdSXin Li /*try the 5 filter types*/
5504*e47783fdSXin Li for(type = 0; type != 5; ++type) {
5505*e47783fdSXin Li size_t sum = 0;
5506*e47783fdSXin Li filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
5507*e47783fdSXin Li
5508*e47783fdSXin Li /*calculate the sum of the result*/
5509*e47783fdSXin Li if(type == 0) {
5510*e47783fdSXin Li for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]);
5511*e47783fdSXin Li } else {
5512*e47783fdSXin Li for(x = 0; x != linebytes; ++x) {
5513*e47783fdSXin Li /*For differences, each byte should be treated as signed, values above 127 are negative
5514*e47783fdSXin Li (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.
5515*e47783fdSXin Li This means filtertype 0 is almost never chosen, but that is justified.*/
5516*e47783fdSXin Li unsigned char s = attempt[type][x];
5517*e47783fdSXin Li sum += s < 128 ? s : (255U - s);
5518*e47783fdSXin Li }
5519*e47783fdSXin Li }
5520*e47783fdSXin Li
5521*e47783fdSXin Li /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
5522*e47783fdSXin Li if(type == 0 || sum < smallest) {
5523*e47783fdSXin Li bestType = type;
5524*e47783fdSXin Li smallest = sum;
5525*e47783fdSXin Li }
5526*e47783fdSXin Li }
5527*e47783fdSXin Li
5528*e47783fdSXin Li prevline = &in[y * linebytes];
5529*e47783fdSXin Li
5530*e47783fdSXin Li /*now fill the out values*/
5531*e47783fdSXin Li out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
5532*e47783fdSXin Li for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
5533*e47783fdSXin Li }
5534*e47783fdSXin Li }
5535*e47783fdSXin Li
5536*e47783fdSXin Li for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
5537*e47783fdSXin Li } else if(strategy == LFS_ENTROPY) {
5538*e47783fdSXin Li unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
5539*e47783fdSXin Li size_t bestSum = 0;
5540*e47783fdSXin Li unsigned type, bestType = 0;
5541*e47783fdSXin Li unsigned count[256];
5542*e47783fdSXin Li
5543*e47783fdSXin Li for(type = 0; type != 5; ++type) {
5544*e47783fdSXin Li attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
5545*e47783fdSXin Li if(!attempt[type]) error = 83; /*alloc fail*/
5546*e47783fdSXin Li }
5547*e47783fdSXin Li
5548*e47783fdSXin Li if(!error) {
5549*e47783fdSXin Li for(y = 0; y != h; ++y) {
5550*e47783fdSXin Li /*try the 5 filter types*/
5551*e47783fdSXin Li for(type = 0; type != 5; ++type) {
5552*e47783fdSXin Li size_t sum = 0;
5553*e47783fdSXin Li filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
5554*e47783fdSXin Li lodepng_memset(count, 0, 256 * sizeof(*count));
5555*e47783fdSXin Li for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];
5556*e47783fdSXin Li ++count[type]; /*the filter type itself is part of the scanline*/
5557*e47783fdSXin Li for(x = 0; x != 256; ++x) {
5558*e47783fdSXin Li sum += ilog2i(count[x]);
5559*e47783fdSXin Li }
5560*e47783fdSXin Li /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
5561*e47783fdSXin Li if(type == 0 || sum > bestSum) {
5562*e47783fdSXin Li bestType = type;
5563*e47783fdSXin Li bestSum = sum;
5564*e47783fdSXin Li }
5565*e47783fdSXin Li }
5566*e47783fdSXin Li
5567*e47783fdSXin Li prevline = &in[y * linebytes];
5568*e47783fdSXin Li
5569*e47783fdSXin Li /*now fill the out values*/
5570*e47783fdSXin Li out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
5571*e47783fdSXin Li for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
5572*e47783fdSXin Li }
5573*e47783fdSXin Li }
5574*e47783fdSXin Li
5575*e47783fdSXin Li for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
5576*e47783fdSXin Li } else if(strategy == LFS_PREDEFINED) {
5577*e47783fdSXin Li for(y = 0; y != h; ++y) {
5578*e47783fdSXin Li size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
5579*e47783fdSXin Li size_t inindex = linebytes * y;
5580*e47783fdSXin Li unsigned char type = settings->predefined_filters[y];
5581*e47783fdSXin Li out[outindex] = type; /*filter type byte*/
5582*e47783fdSXin Li filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
5583*e47783fdSXin Li prevline = &in[inindex];
5584*e47783fdSXin Li }
5585*e47783fdSXin Li } else if(strategy == LFS_BRUTE_FORCE) {
5586*e47783fdSXin Li /*brute force filter chooser.
5587*e47783fdSXin Li deflate the scanline after every filter attempt to see which one deflates best.
5588*e47783fdSXin Li This is very slow and gives only slightly smaller, sometimes even larger, result*/
5589*e47783fdSXin Li size_t size[5];
5590*e47783fdSXin Li unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
5591*e47783fdSXin Li size_t smallest = 0;
5592*e47783fdSXin Li unsigned type = 0, bestType = 0;
5593*e47783fdSXin Li unsigned char* dummy;
5594*e47783fdSXin Li LodePNGCompressSettings zlibsettings;
5595*e47783fdSXin Li lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings));
5596*e47783fdSXin Li /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,
5597*e47783fdSXin Li to simulate the true case where the tree is the same for the whole image. Sometimes it gives
5598*e47783fdSXin Li better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare
5599*e47783fdSXin Li cases better compression. It does make this a bit less slow, so it's worth doing this.*/
5600*e47783fdSXin Li zlibsettings.btype = 1;
5601*e47783fdSXin Li /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG
5602*e47783fdSXin Li images only, so disable it*/
5603*e47783fdSXin Li zlibsettings.custom_zlib = 0;
5604*e47783fdSXin Li zlibsettings.custom_deflate = 0;
5605*e47783fdSXin Li for(type = 0; type != 5; ++type) {
5606*e47783fdSXin Li attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
5607*e47783fdSXin Li if(!attempt[type]) error = 83; /*alloc fail*/
5608*e47783fdSXin Li }
5609*e47783fdSXin Li if(!error) {
5610*e47783fdSXin Li for(y = 0; y != h; ++y) /*try the 5 filter types*/ {
5611*e47783fdSXin Li for(type = 0; type != 5; ++type) {
5612*e47783fdSXin Li unsigned testsize = (unsigned)linebytes;
5613*e47783fdSXin Li /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/
5614*e47783fdSXin Li
5615*e47783fdSXin Li filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
5616*e47783fdSXin Li size[type] = 0;
5617*e47783fdSXin Li dummy = 0;
5618*e47783fdSXin Li zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);
5619*e47783fdSXin Li lodepng_free(dummy);
5620*e47783fdSXin Li /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/
5621*e47783fdSXin Li if(type == 0 || size[type] < smallest) {
5622*e47783fdSXin Li bestType = type;
5623*e47783fdSXin Li smallest = size[type];
5624*e47783fdSXin Li }
5625*e47783fdSXin Li }
5626*e47783fdSXin Li prevline = &in[y * linebytes];
5627*e47783fdSXin Li out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
5628*e47783fdSXin Li for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
5629*e47783fdSXin Li }
5630*e47783fdSXin Li }
5631*e47783fdSXin Li for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
5632*e47783fdSXin Li }
5633*e47783fdSXin Li else return 88; /* unknown filter strategy */
5634*e47783fdSXin Li
5635*e47783fdSXin Li return error;
5636*e47783fdSXin Li }
5637*e47783fdSXin Li
addPaddingBits(unsigned char * out,const unsigned char * in,size_t olinebits,size_t ilinebits,unsigned h)5638*e47783fdSXin Li static void addPaddingBits(unsigned char* out, const unsigned char* in,
5639*e47783fdSXin Li size_t olinebits, size_t ilinebits, unsigned h) {
5640*e47783fdSXin Li /*The opposite of the removePaddingBits function
5641*e47783fdSXin Li olinebits must be >= ilinebits*/
5642*e47783fdSXin Li unsigned y;
5643*e47783fdSXin Li size_t diff = olinebits - ilinebits;
5644*e47783fdSXin Li size_t obp = 0, ibp = 0; /*bit pointers*/
5645*e47783fdSXin Li for(y = 0; y != h; ++y) {
5646*e47783fdSXin Li size_t x;
5647*e47783fdSXin Li for(x = 0; x < ilinebits; ++x) {
5648*e47783fdSXin Li unsigned char bit = readBitFromReversedStream(&ibp, in);
5649*e47783fdSXin Li setBitOfReversedStream(&obp, out, bit);
5650*e47783fdSXin Li }
5651*e47783fdSXin Li /*obp += diff; --> no, fill in some value in the padding bits too, to avoid
5652*e47783fdSXin Li "Use of uninitialised value of size ###" warning from valgrind*/
5653*e47783fdSXin Li for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0);
5654*e47783fdSXin Li }
5655*e47783fdSXin Li }
5656*e47783fdSXin Li
5657*e47783fdSXin Li /*
5658*e47783fdSXin Li in: non-interlaced image with size w*h
5659*e47783fdSXin Li out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with
5660*e47783fdSXin Li no padding bits between scanlines, but between reduced images so that each
5661*e47783fdSXin Li reduced image starts at a byte.
5662*e47783fdSXin Li bpp: bits per pixel
5663*e47783fdSXin Li there are no padding bits, not between scanlines, not between reduced images
5664*e47783fdSXin Li in has the following size in bits: w * h * bpp.
5665*e47783fdSXin Li out is possibly bigger due to padding bits between reduced images
5666*e47783fdSXin Li NOTE: comments about padding bits are only relevant if bpp < 8
5667*e47783fdSXin Li */
Adam7_interlace(unsigned char * out,const unsigned char * in,unsigned w,unsigned h,unsigned bpp)5668*e47783fdSXin Li static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
5669*e47783fdSXin Li unsigned passw[7], passh[7];
5670*e47783fdSXin Li size_t filter_passstart[8], padded_passstart[8], passstart[8];
5671*e47783fdSXin Li unsigned i;
5672*e47783fdSXin Li
5673*e47783fdSXin Li Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
5674*e47783fdSXin Li
5675*e47783fdSXin Li if(bpp >= 8) {
5676*e47783fdSXin Li for(i = 0; i != 7; ++i) {
5677*e47783fdSXin Li unsigned x, y, b;
5678*e47783fdSXin Li size_t bytewidth = bpp / 8u;
5679*e47783fdSXin Li for(y = 0; y < passh[i]; ++y)
5680*e47783fdSXin Li for(x = 0; x < passw[i]; ++x) {
5681*e47783fdSXin Li size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
5682*e47783fdSXin Li size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth;
5683*e47783fdSXin Li for(b = 0; b < bytewidth; ++b) {
5684*e47783fdSXin Li out[pixeloutstart + b] = in[pixelinstart + b];
5685*e47783fdSXin Li }
5686*e47783fdSXin Li }
5687*e47783fdSXin Li }
5688*e47783fdSXin Li } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ {
5689*e47783fdSXin Li for(i = 0; i != 7; ++i) {
5690*e47783fdSXin Li unsigned x, y, b;
5691*e47783fdSXin Li unsigned ilinebits = bpp * passw[i];
5692*e47783fdSXin Li unsigned olinebits = bpp * w;
5693*e47783fdSXin Li size_t obp, ibp; /*bit pointers (for out and in buffer)*/
5694*e47783fdSXin Li for(y = 0; y < passh[i]; ++y)
5695*e47783fdSXin Li for(x = 0; x < passw[i]; ++x) {
5696*e47783fdSXin Li ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
5697*e47783fdSXin Li obp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
5698*e47783fdSXin Li for(b = 0; b < bpp; ++b) {
5699*e47783fdSXin Li unsigned char bit = readBitFromReversedStream(&ibp, in);
5700*e47783fdSXin Li setBitOfReversedStream(&obp, out, bit);
5701*e47783fdSXin Li }
5702*e47783fdSXin Li }
5703*e47783fdSXin Li }
5704*e47783fdSXin Li }
5705*e47783fdSXin Li }
5706*e47783fdSXin Li
5707*e47783fdSXin Li /*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image.
5708*e47783fdSXin Li return value is error**/
preProcessScanlines(unsigned char ** out,size_t * outsize,const unsigned char * in,unsigned w,unsigned h,const LodePNGInfo * info_png,const LodePNGEncoderSettings * settings)5709*e47783fdSXin Li static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in,
5710*e47783fdSXin Li unsigned w, unsigned h,
5711*e47783fdSXin Li const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) {
5712*e47783fdSXin Li /*
5713*e47783fdSXin Li This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps:
5714*e47783fdSXin Li *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter
5715*e47783fdSXin Li *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter
5716*e47783fdSXin Li */
5717*e47783fdSXin Li unsigned bpp = lodepng_get_bpp(&info_png->color);
5718*e47783fdSXin Li unsigned error = 0;
5719*e47783fdSXin Li
5720*e47783fdSXin Li if(info_png->interlace_method == 0) {
5721*e47783fdSXin Li *outsize = h + (h * ((w * bpp + 7u) / 8u)); /*image size plus an extra byte per scanline + possible padding bits*/
5722*e47783fdSXin Li *out = (unsigned char*)lodepng_malloc(*outsize);
5723*e47783fdSXin Li if(!(*out) && (*outsize)) error = 83; /*alloc fail*/
5724*e47783fdSXin Li
5725*e47783fdSXin Li if(!error) {
5726*e47783fdSXin Li /*non multiple of 8 bits per scanline, padding bits needed per scanline*/
5727*e47783fdSXin Li if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) {
5728*e47783fdSXin Li unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7u) / 8u));
5729*e47783fdSXin Li if(!padded) error = 83; /*alloc fail*/
5730*e47783fdSXin Li if(!error) {
5731*e47783fdSXin Li addPaddingBits(padded, in, ((w * bpp + 7u) / 8u) * 8u, w * bpp, h);
5732*e47783fdSXin Li error = filter(*out, padded, w, h, &info_png->color, settings);
5733*e47783fdSXin Li }
5734*e47783fdSXin Li lodepng_free(padded);
5735*e47783fdSXin Li } else {
5736*e47783fdSXin Li /*we can immediately filter into the out buffer, no other steps needed*/
5737*e47783fdSXin Li error = filter(*out, in, w, h, &info_png->color, settings);
5738*e47783fdSXin Li }
5739*e47783fdSXin Li }
5740*e47783fdSXin Li } else /*interlace_method is 1 (Adam7)*/ {
5741*e47783fdSXin Li unsigned passw[7], passh[7];
5742*e47783fdSXin Li size_t filter_passstart[8], padded_passstart[8], passstart[8];
5743*e47783fdSXin Li unsigned char* adam7;
5744*e47783fdSXin Li
5745*e47783fdSXin Li Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
5746*e47783fdSXin Li
5747*e47783fdSXin Li *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/
5748*e47783fdSXin Li *out = (unsigned char*)lodepng_malloc(*outsize);
5749*e47783fdSXin Li if(!(*out)) error = 83; /*alloc fail*/
5750*e47783fdSXin Li
5751*e47783fdSXin Li adam7 = (unsigned char*)lodepng_malloc(passstart[7]);
5752*e47783fdSXin Li if(!adam7 && passstart[7]) error = 83; /*alloc fail*/
5753*e47783fdSXin Li
5754*e47783fdSXin Li if(!error) {
5755*e47783fdSXin Li unsigned i;
5756*e47783fdSXin Li
5757*e47783fdSXin Li Adam7_interlace(adam7, in, w, h, bpp);
5758*e47783fdSXin Li for(i = 0; i != 7; ++i) {
5759*e47783fdSXin Li if(bpp < 8) {
5760*e47783fdSXin Li unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]);
5761*e47783fdSXin Li if(!padded) ERROR_BREAK(83); /*alloc fail*/
5762*e47783fdSXin Li addPaddingBits(padded, &adam7[passstart[i]],
5763*e47783fdSXin Li ((passw[i] * bpp + 7u) / 8u) * 8u, passw[i] * bpp, passh[i]);
5764*e47783fdSXin Li error = filter(&(*out)[filter_passstart[i]], padded,
5765*e47783fdSXin Li passw[i], passh[i], &info_png->color, settings);
5766*e47783fdSXin Li lodepng_free(padded);
5767*e47783fdSXin Li } else {
5768*e47783fdSXin Li error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]],
5769*e47783fdSXin Li passw[i], passh[i], &info_png->color, settings);
5770*e47783fdSXin Li }
5771*e47783fdSXin Li
5772*e47783fdSXin Li if(error) break;
5773*e47783fdSXin Li }
5774*e47783fdSXin Li }
5775*e47783fdSXin Li
5776*e47783fdSXin Li lodepng_free(adam7);
5777*e47783fdSXin Li }
5778*e47783fdSXin Li
5779*e47783fdSXin Li return error;
5780*e47783fdSXin Li }
5781*e47783fdSXin Li
5782*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
addUnknownChunks(ucvector * out,unsigned char * data,size_t datasize)5783*e47783fdSXin Li static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) {
5784*e47783fdSXin Li unsigned char* inchunk = data;
5785*e47783fdSXin Li while((size_t)(inchunk - data) < datasize) {
5786*e47783fdSXin Li CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));
5787*e47783fdSXin Li out->allocsize = out->size; /*fix the allocsize again*/
5788*e47783fdSXin Li inchunk = lodepng_chunk_next(inchunk, data + datasize);
5789*e47783fdSXin Li }
5790*e47783fdSXin Li return 0;
5791*e47783fdSXin Li }
5792*e47783fdSXin Li
isGrayICCProfile(const unsigned char * profile,unsigned size)5793*e47783fdSXin Li static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) {
5794*e47783fdSXin Li /*
5795*e47783fdSXin Li It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19
5796*e47783fdSXin Li are "RGB ". We do not perform any full parsing of the ICC profile here, other
5797*e47783fdSXin Li than check those 4 bytes to grayscale profile. Other than that, validity of
5798*e47783fdSXin Li the profile is not checked. This is needed only because the PNG specification
5799*e47783fdSXin Li requires using a non-gray color model if there is an ICC profile with "RGB "
5800*e47783fdSXin Li (sadly limiting compression opportunities if the input data is grayscale RGB
5801*e47783fdSXin Li data), and requires using a gray color model if it is "GRAY".
5802*e47783fdSXin Li */
5803*e47783fdSXin Li if(size < 20) return 0;
5804*e47783fdSXin Li return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y';
5805*e47783fdSXin Li }
5806*e47783fdSXin Li
isRGBICCProfile(const unsigned char * profile,unsigned size)5807*e47783fdSXin Li static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) {
5808*e47783fdSXin Li /* See comment in isGrayICCProfile*/
5809*e47783fdSXin Li if(size < 20) return 0;
5810*e47783fdSXin Li return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' ';
5811*e47783fdSXin Li }
5812*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5813*e47783fdSXin Li
lodepng_encode(unsigned char ** out,size_t * outsize,const unsigned char * image,unsigned w,unsigned h,LodePNGState * state)5814*e47783fdSXin Li unsigned lodepng_encode(unsigned char** out, size_t* outsize,
5815*e47783fdSXin Li const unsigned char* image, unsigned w, unsigned h,
5816*e47783fdSXin Li LodePNGState* state) {
5817*e47783fdSXin Li unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/
5818*e47783fdSXin Li size_t datasize = 0;
5819*e47783fdSXin Li ucvector outv = ucvector_init(NULL, 0);
5820*e47783fdSXin Li LodePNGInfo info;
5821*e47783fdSXin Li const LodePNGInfo* info_png = &state->info_png;
5822*e47783fdSXin Li
5823*e47783fdSXin Li lodepng_info_init(&info);
5824*e47783fdSXin Li
5825*e47783fdSXin Li /*provide some proper output values if error will happen*/
5826*e47783fdSXin Li *out = 0;
5827*e47783fdSXin Li *outsize = 0;
5828*e47783fdSXin Li state->error = 0;
5829*e47783fdSXin Li
5830*e47783fdSXin Li /*check input values validity*/
5831*e47783fdSXin Li if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette)
5832*e47783fdSXin Li && (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) {
5833*e47783fdSXin Li state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/
5834*e47783fdSXin Li goto cleanup;
5835*e47783fdSXin Li }
5836*e47783fdSXin Li if(state->encoder.zlibsettings.btype > 2) {
5837*e47783fdSXin Li state->error = 61; /*error: invalid btype*/
5838*e47783fdSXin Li goto cleanup;
5839*e47783fdSXin Li }
5840*e47783fdSXin Li if(info_png->interlace_method > 1) {
5841*e47783fdSXin Li state->error = 71; /*error: invalid interlace mode*/
5842*e47783fdSXin Li goto cleanup;
5843*e47783fdSXin Li }
5844*e47783fdSXin Li state->error = checkColorValidity(info_png->color.colortype, info_png->color.bitdepth);
5845*e47783fdSXin Li if(state->error) goto cleanup; /*error: invalid color type given*/
5846*e47783fdSXin Li state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);
5847*e47783fdSXin Li if(state->error) goto cleanup; /*error: invalid color type given*/
5848*e47783fdSXin Li
5849*e47783fdSXin Li /* color convert and compute scanline filter types */
5850*e47783fdSXin Li lodepng_info_copy(&info, &state->info_png);
5851*e47783fdSXin Li if(state->encoder.auto_convert) {
5852*e47783fdSXin Li LodePNGColorStats stats;
5853*e47783fdSXin Li lodepng_color_stats_init(&stats);
5854*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5855*e47783fdSXin Li if(info_png->iccp_defined &&
5856*e47783fdSXin Li isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) {
5857*e47783fdSXin Li /*the PNG specification does not allow to use palette with a GRAY ICC profile, even
5858*e47783fdSXin Li if the palette has only gray colors, so disallow it.*/
5859*e47783fdSXin Li stats.allow_palette = 0;
5860*e47783fdSXin Li }
5861*e47783fdSXin Li if(info_png->iccp_defined &&
5862*e47783fdSXin Li isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) {
5863*e47783fdSXin Li /*the PNG specification does not allow to use grayscale color with RGB ICC profile, so disallow gray.*/
5864*e47783fdSXin Li stats.allow_greyscale = 0;
5865*e47783fdSXin Li }
5866*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
5867*e47783fdSXin Li state->error = lodepng_compute_color_stats(&stats, image, w, h, &state->info_raw);
5868*e47783fdSXin Li if(state->error) goto cleanup;
5869*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5870*e47783fdSXin Li if(info_png->background_defined) {
5871*e47783fdSXin Li /*the background chunk's color must be taken into account as well*/
5872*e47783fdSXin Li unsigned r = 0, g = 0, b = 0;
5873*e47783fdSXin Li LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16);
5874*e47783fdSXin Li lodepng_convert_rgb(&r, &g, &b, info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color);
5875*e47783fdSXin Li state->error = lodepng_color_stats_add(&stats, r, g, b, 65535);
5876*e47783fdSXin Li if(state->error) goto cleanup;
5877*e47783fdSXin Li }
5878*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
5879*e47783fdSXin Li state->error = auto_choose_color(&info.color, &state->info_raw, &stats);
5880*e47783fdSXin Li if(state->error) goto cleanup;
5881*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5882*e47783fdSXin Li /*also convert the background chunk*/
5883*e47783fdSXin Li if(info_png->background_defined) {
5884*e47783fdSXin Li if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b,
5885*e47783fdSXin Li info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) {
5886*e47783fdSXin Li state->error = 104;
5887*e47783fdSXin Li goto cleanup;
5888*e47783fdSXin Li }
5889*e47783fdSXin Li }
5890*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
5891*e47783fdSXin Li }
5892*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5893*e47783fdSXin Li if(info_png->iccp_defined) {
5894*e47783fdSXin Li unsigned gray_icc = isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size);
5895*e47783fdSXin Li unsigned rgb_icc = isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size);
5896*e47783fdSXin Li unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA;
5897*e47783fdSXin Li if(!gray_icc && !rgb_icc) {
5898*e47783fdSXin Li state->error = 100; /* Disallowed profile color type for PNG */
5899*e47783fdSXin Li goto cleanup;
5900*e47783fdSXin Li }
5901*e47783fdSXin Li if(gray_icc != gray_png) {
5902*e47783fdSXin Li /*Not allowed to use RGB/RGBA/palette with GRAY ICC profile or vice versa,
5903*e47783fdSXin Li or in case of auto_convert, it wasn't possible to find appropriate model*/
5904*e47783fdSXin Li state->error = state->encoder.auto_convert ? 102 : 101;
5905*e47783fdSXin Li goto cleanup;
5906*e47783fdSXin Li }
5907*e47783fdSXin Li }
5908*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5909*e47783fdSXin Li if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) {
5910*e47783fdSXin Li unsigned char* converted;
5911*e47783fdSXin Li size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u;
5912*e47783fdSXin Li
5913*e47783fdSXin Li converted = (unsigned char*)lodepng_malloc(size);
5914*e47783fdSXin Li if(!converted && size) state->error = 83; /*alloc fail*/
5915*e47783fdSXin Li if(!state->error) {
5916*e47783fdSXin Li state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);
5917*e47783fdSXin Li }
5918*e47783fdSXin Li if(!state->error) {
5919*e47783fdSXin Li state->error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
5920*e47783fdSXin Li }
5921*e47783fdSXin Li lodepng_free(converted);
5922*e47783fdSXin Li if(state->error) goto cleanup;
5923*e47783fdSXin Li } else {
5924*e47783fdSXin Li state->error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
5925*e47783fdSXin Li if(state->error) goto cleanup;
5926*e47783fdSXin Li }
5927*e47783fdSXin Li
5928*e47783fdSXin Li /* output all PNG chunks */ {
5929*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5930*e47783fdSXin Li size_t i;
5931*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5932*e47783fdSXin Li /*write signature and chunks*/
5933*e47783fdSXin Li state->error = writeSignature(&outv);
5934*e47783fdSXin Li if(state->error) goto cleanup;
5935*e47783fdSXin Li /*IHDR*/
5936*e47783fdSXin Li state->error = addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method);
5937*e47783fdSXin Li if(state->error) goto cleanup;
5938*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5939*e47783fdSXin Li /*unknown chunks between IHDR and PLTE*/
5940*e47783fdSXin Li if(info.unknown_chunks_data[0]) {
5941*e47783fdSXin Li state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]);
5942*e47783fdSXin Li if(state->error) goto cleanup;
5943*e47783fdSXin Li }
5944*e47783fdSXin Li /*color profile chunks must come before PLTE */
5945*e47783fdSXin Li if(info.iccp_defined) {
5946*e47783fdSXin Li state->error = addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings);
5947*e47783fdSXin Li if(state->error) goto cleanup;
5948*e47783fdSXin Li }
5949*e47783fdSXin Li if(info.srgb_defined) {
5950*e47783fdSXin Li state->error = addChunk_sRGB(&outv, &info);
5951*e47783fdSXin Li if(state->error) goto cleanup;
5952*e47783fdSXin Li }
5953*e47783fdSXin Li if(info.gama_defined) {
5954*e47783fdSXin Li state->error = addChunk_gAMA(&outv, &info);
5955*e47783fdSXin Li if(state->error) goto cleanup;
5956*e47783fdSXin Li }
5957*e47783fdSXin Li if(info.chrm_defined) {
5958*e47783fdSXin Li state->error = addChunk_cHRM(&outv, &info);
5959*e47783fdSXin Li if(state->error) goto cleanup;
5960*e47783fdSXin Li }
5961*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5962*e47783fdSXin Li /*PLTE*/
5963*e47783fdSXin Li if(info.color.colortype == LCT_PALETTE) {
5964*e47783fdSXin Li state->error = addChunk_PLTE(&outv, &info.color);
5965*e47783fdSXin Li if(state->error) goto cleanup;
5966*e47783fdSXin Li }
5967*e47783fdSXin Li if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) {
5968*e47783fdSXin Li /*force_palette means: write suggested palette for truecolor in PLTE chunk*/
5969*e47783fdSXin Li state->error = addChunk_PLTE(&outv, &info.color);
5970*e47783fdSXin Li if(state->error) goto cleanup;
5971*e47783fdSXin Li }
5972*e47783fdSXin Li /*tRNS (this will only add if when necessary) */
5973*e47783fdSXin Li state->error = addChunk_tRNS(&outv, &info.color);
5974*e47783fdSXin Li if(state->error) goto cleanup;
5975*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5976*e47783fdSXin Li /*bKGD (must come between PLTE and the IDAt chunks*/
5977*e47783fdSXin Li if(info.background_defined) {
5978*e47783fdSXin Li state->error = addChunk_bKGD(&outv, &info);
5979*e47783fdSXin Li if(state->error) goto cleanup;
5980*e47783fdSXin Li }
5981*e47783fdSXin Li /*pHYs (must come before the IDAT chunks)*/
5982*e47783fdSXin Li if(info.phys_defined) {
5983*e47783fdSXin Li state->error = addChunk_pHYs(&outv, &info);
5984*e47783fdSXin Li if(state->error) goto cleanup;
5985*e47783fdSXin Li }
5986*e47783fdSXin Li
5987*e47783fdSXin Li /*unknown chunks between PLTE and IDAT*/
5988*e47783fdSXin Li if(info.unknown_chunks_data[1]) {
5989*e47783fdSXin Li state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]);
5990*e47783fdSXin Li if(state->error) goto cleanup;
5991*e47783fdSXin Li }
5992*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5993*e47783fdSXin Li /*IDAT (multiple IDAT chunks must be consecutive)*/
5994*e47783fdSXin Li state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings);
5995*e47783fdSXin Li if(state->error) goto cleanup;
5996*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5997*e47783fdSXin Li /*tIME*/
5998*e47783fdSXin Li if(info.time_defined) {
5999*e47783fdSXin Li state->error = addChunk_tIME(&outv, &info.time);
6000*e47783fdSXin Li if(state->error) goto cleanup;
6001*e47783fdSXin Li }
6002*e47783fdSXin Li /*tEXt and/or zTXt*/
6003*e47783fdSXin Li for(i = 0; i != info.text_num; ++i) {
6004*e47783fdSXin Li if(lodepng_strlen(info.text_keys[i]) > 79) {
6005*e47783fdSXin Li state->error = 66; /*text chunk too large*/
6006*e47783fdSXin Li goto cleanup;
6007*e47783fdSXin Li }
6008*e47783fdSXin Li if(lodepng_strlen(info.text_keys[i]) < 1) {
6009*e47783fdSXin Li state->error = 67; /*text chunk too small*/
6010*e47783fdSXin Li goto cleanup;
6011*e47783fdSXin Li }
6012*e47783fdSXin Li if(state->encoder.text_compression) {
6013*e47783fdSXin Li state->error = addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);
6014*e47783fdSXin Li if(state->error) goto cleanup;
6015*e47783fdSXin Li } else {
6016*e47783fdSXin Li state->error = addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);
6017*e47783fdSXin Li if(state->error) goto cleanup;
6018*e47783fdSXin Li }
6019*e47783fdSXin Li }
6020*e47783fdSXin Li /*LodePNG version id in text chunk*/
6021*e47783fdSXin Li if(state->encoder.add_id) {
6022*e47783fdSXin Li unsigned already_added_id_text = 0;
6023*e47783fdSXin Li for(i = 0; i != info.text_num; ++i) {
6024*e47783fdSXin Li const char* k = info.text_keys[i];
6025*e47783fdSXin Li /* Could use strcmp, but we're not calling or reimplementing this C library function for this use only */
6026*e47783fdSXin Li if(k[0] == 'L' && k[1] == 'o' && k[2] == 'd' && k[3] == 'e' &&
6027*e47783fdSXin Li k[4] == 'P' && k[5] == 'N' && k[6] == 'G' && k[7] == '\0') {
6028*e47783fdSXin Li already_added_id_text = 1;
6029*e47783fdSXin Li break;
6030*e47783fdSXin Li }
6031*e47783fdSXin Li }
6032*e47783fdSXin Li if(already_added_id_text == 0) {
6033*e47783fdSXin Li state->error = addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/
6034*e47783fdSXin Li if(state->error) goto cleanup;
6035*e47783fdSXin Li }
6036*e47783fdSXin Li }
6037*e47783fdSXin Li /*iTXt*/
6038*e47783fdSXin Li for(i = 0; i != info.itext_num; ++i) {
6039*e47783fdSXin Li if(lodepng_strlen(info.itext_keys[i]) > 79) {
6040*e47783fdSXin Li state->error = 66; /*text chunk too large*/
6041*e47783fdSXin Li goto cleanup;
6042*e47783fdSXin Li }
6043*e47783fdSXin Li if(lodepng_strlen(info.itext_keys[i]) < 1) {
6044*e47783fdSXin Li state->error = 67; /*text chunk too small*/
6045*e47783fdSXin Li goto cleanup;
6046*e47783fdSXin Li }
6047*e47783fdSXin Li state->error = addChunk_iTXt(
6048*e47783fdSXin Li &outv, state->encoder.text_compression,
6049*e47783fdSXin Li info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i],
6050*e47783fdSXin Li &state->encoder.zlibsettings);
6051*e47783fdSXin Li if(state->error) goto cleanup;
6052*e47783fdSXin Li }
6053*e47783fdSXin Li
6054*e47783fdSXin Li /*unknown chunks between IDAT and IEND*/
6055*e47783fdSXin Li if(info.unknown_chunks_data[2]) {
6056*e47783fdSXin Li state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]);
6057*e47783fdSXin Li if(state->error) goto cleanup;
6058*e47783fdSXin Li }
6059*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
6060*e47783fdSXin Li state->error = addChunk_IEND(&outv);
6061*e47783fdSXin Li if(state->error) goto cleanup;
6062*e47783fdSXin Li }
6063*e47783fdSXin Li
6064*e47783fdSXin Li cleanup:
6065*e47783fdSXin Li lodepng_info_cleanup(&info);
6066*e47783fdSXin Li lodepng_free(data);
6067*e47783fdSXin Li
6068*e47783fdSXin Li /*instead of cleaning the vector up, give it to the output*/
6069*e47783fdSXin Li *out = outv.data;
6070*e47783fdSXin Li *outsize = outv.size;
6071*e47783fdSXin Li
6072*e47783fdSXin Li return state->error;
6073*e47783fdSXin Li }
6074*e47783fdSXin Li
lodepng_encode_memory(unsigned char ** out,size_t * outsize,const unsigned char * image,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)6075*e47783fdSXin Li unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image,
6076*e47783fdSXin Li unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
6077*e47783fdSXin Li unsigned error;
6078*e47783fdSXin Li LodePNGState state;
6079*e47783fdSXin Li lodepng_state_init(&state);
6080*e47783fdSXin Li state.info_raw.colortype = colortype;
6081*e47783fdSXin Li state.info_raw.bitdepth = bitdepth;
6082*e47783fdSXin Li state.info_png.color.colortype = colortype;
6083*e47783fdSXin Li state.info_png.color.bitdepth = bitdepth;
6084*e47783fdSXin Li lodepng_encode(out, outsize, image, w, h, &state);
6085*e47783fdSXin Li error = state.error;
6086*e47783fdSXin Li lodepng_state_cleanup(&state);
6087*e47783fdSXin Li return error;
6088*e47783fdSXin Li }
6089*e47783fdSXin Li
lodepng_encode32(unsigned char ** out,size_t * outsize,const unsigned char * image,unsigned w,unsigned h)6090*e47783fdSXin Li unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) {
6091*e47783fdSXin Li return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8);
6092*e47783fdSXin Li }
6093*e47783fdSXin Li
lodepng_encode24(unsigned char ** out,size_t * outsize,const unsigned char * image,unsigned w,unsigned h)6094*e47783fdSXin Li unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) {
6095*e47783fdSXin Li return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8);
6096*e47783fdSXin Li }
6097*e47783fdSXin Li
6098*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
lodepng_encode_file(const char * filename,const unsigned char * image,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)6099*e47783fdSXin Li unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h,
6100*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
6101*e47783fdSXin Li unsigned char* buffer;
6102*e47783fdSXin Li size_t buffersize;
6103*e47783fdSXin Li unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth);
6104*e47783fdSXin Li if(!error) error = lodepng_save_file(buffer, buffersize, filename);
6105*e47783fdSXin Li lodepng_free(buffer);
6106*e47783fdSXin Li return error;
6107*e47783fdSXin Li }
6108*e47783fdSXin Li
lodepng_encode32_file(const char * filename,const unsigned char * image,unsigned w,unsigned h)6109*e47783fdSXin Li unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) {
6110*e47783fdSXin Li return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8);
6111*e47783fdSXin Li }
6112*e47783fdSXin Li
lodepng_encode24_file(const char * filename,const unsigned char * image,unsigned w,unsigned h)6113*e47783fdSXin Li unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) {
6114*e47783fdSXin Li return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8);
6115*e47783fdSXin Li }
6116*e47783fdSXin Li #endif /*LODEPNG_COMPILE_DISK*/
6117*e47783fdSXin Li
lodepng_encoder_settings_init(LodePNGEncoderSettings * settings)6118*e47783fdSXin Li void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) {
6119*e47783fdSXin Li lodepng_compress_settings_init(&settings->zlibsettings);
6120*e47783fdSXin Li settings->filter_palette_zero = 1;
6121*e47783fdSXin Li settings->filter_strategy = LFS_MINSUM;
6122*e47783fdSXin Li settings->auto_convert = 1;
6123*e47783fdSXin Li settings->force_palette = 0;
6124*e47783fdSXin Li settings->predefined_filters = 0;
6125*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
6126*e47783fdSXin Li settings->add_id = 0;
6127*e47783fdSXin Li settings->text_compression = 1;
6128*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
6129*e47783fdSXin Li }
6130*e47783fdSXin Li
6131*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ENCODER*/
6132*e47783fdSXin Li #endif /*LODEPNG_COMPILE_PNG*/
6133*e47783fdSXin Li
6134*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ERROR_TEXT
6135*e47783fdSXin Li /*
6136*e47783fdSXin Li This returns the description of a numerical error code in English. This is also
6137*e47783fdSXin Li the documentation of all the error codes.
6138*e47783fdSXin Li */
lodepng_error_text(unsigned code)6139*e47783fdSXin Li const char* lodepng_error_text(unsigned code) {
6140*e47783fdSXin Li switch(code) {
6141*e47783fdSXin Li case 0: return "no error, everything went ok";
6142*e47783fdSXin Li case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/
6143*e47783fdSXin Li case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/
6144*e47783fdSXin Li case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/
6145*e47783fdSXin Li case 13: return "problem while processing dynamic deflate block";
6146*e47783fdSXin Li case 14: return "problem while processing dynamic deflate block";
6147*e47783fdSXin Li case 15: return "problem while processing dynamic deflate block";
6148*e47783fdSXin Li /*this error could happen if there are only 0 or 1 symbols present in the huffman code:*/
6149*e47783fdSXin Li case 16: return "invalid code while processing dynamic deflate block";
6150*e47783fdSXin Li case 17: return "end of out buffer memory reached while inflating";
6151*e47783fdSXin Li case 18: return "invalid distance code while inflating";
6152*e47783fdSXin Li case 19: return "end of out buffer memory reached while inflating";
6153*e47783fdSXin Li case 20: return "invalid deflate block BTYPE encountered while decoding";
6154*e47783fdSXin Li case 21: return "NLEN is not ones complement of LEN in a deflate block";
6155*e47783fdSXin Li
6156*e47783fdSXin Li /*end of out buffer memory reached while inflating:
6157*e47783fdSXin Li This can happen if the inflated deflate data is longer than the amount of bytes required to fill up
6158*e47783fdSXin Li all the pixels of the image, given the color depth and image dimensions. Something that doesn't
6159*e47783fdSXin Li happen in a normal, well encoded, PNG image.*/
6160*e47783fdSXin Li case 22: return "end of out buffer memory reached while inflating";
6161*e47783fdSXin Li case 23: return "end of in buffer memory reached while inflating";
6162*e47783fdSXin Li case 24: return "invalid FCHECK in zlib header";
6163*e47783fdSXin Li case 25: return "invalid compression method in zlib header";
6164*e47783fdSXin Li case 26: return "FDICT encountered in zlib header while it's not used for PNG";
6165*e47783fdSXin Li case 27: return "PNG file is smaller than a PNG header";
6166*e47783fdSXin Li /*Checks the magic file header, the first 8 bytes of the PNG file*/
6167*e47783fdSXin Li case 28: return "incorrect PNG signature, it's no PNG or corrupted";
6168*e47783fdSXin Li case 29: return "first chunk is not the header chunk";
6169*e47783fdSXin Li case 30: return "chunk length too large, chunk broken off at end of file";
6170*e47783fdSXin Li case 31: return "illegal PNG color type or bpp";
6171*e47783fdSXin Li case 32: return "illegal PNG compression method";
6172*e47783fdSXin Li case 33: return "illegal PNG filter method";
6173*e47783fdSXin Li case 34: return "illegal PNG interlace method";
6174*e47783fdSXin Li case 35: return "chunk length of a chunk is too large or the chunk too small";
6175*e47783fdSXin Li case 36: return "illegal PNG filter type encountered";
6176*e47783fdSXin Li case 37: return "illegal bit depth for this color type given";
6177*e47783fdSXin Li case 38: return "the palette is too small or too big"; /*0, or more than 256 colors*/
6178*e47783fdSXin Li case 39: return "tRNS chunk before PLTE or has more entries than palette size";
6179*e47783fdSXin Li case 40: return "tRNS chunk has wrong size for grayscale image";
6180*e47783fdSXin Li case 41: return "tRNS chunk has wrong size for RGB image";
6181*e47783fdSXin Li case 42: return "tRNS chunk appeared while it was not allowed for this color type";
6182*e47783fdSXin Li case 43: return "bKGD chunk has wrong size for palette image";
6183*e47783fdSXin Li case 44: return "bKGD chunk has wrong size for grayscale image";
6184*e47783fdSXin Li case 45: return "bKGD chunk has wrong size for RGB image";
6185*e47783fdSXin Li case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?";
6186*e47783fdSXin Li case 49: return "jumped past memory while generating dynamic huffman tree";
6187*e47783fdSXin Li case 50: return "jumped past memory while generating dynamic huffman tree";
6188*e47783fdSXin Li case 51: return "jumped past memory while inflating huffman block";
6189*e47783fdSXin Li case 52: return "jumped past memory while inflating";
6190*e47783fdSXin Li case 53: return "size of zlib data too small";
6191*e47783fdSXin Li case 54: return "repeat symbol in tree while there was no value symbol yet";
6192*e47783fdSXin Li /*jumped past tree while generating huffman tree, this could be when the
6193*e47783fdSXin Li tree will have more leaves than symbols after generating it out of the
6194*e47783fdSXin Li given lengths. They call this an oversubscribed dynamic bit lengths tree in zlib.*/
6195*e47783fdSXin Li case 55: return "jumped past tree while generating huffman tree";
6196*e47783fdSXin Li case 56: return "given output image colortype or bitdepth not supported for color conversion";
6197*e47783fdSXin Li case 57: return "invalid CRC encountered (checking CRC can be disabled)";
6198*e47783fdSXin Li case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)";
6199*e47783fdSXin Li case 59: return "requested color conversion not supported";
6200*e47783fdSXin Li case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)";
6201*e47783fdSXin Li case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)";
6202*e47783fdSXin Li /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/
6203*e47783fdSXin Li case 62: return "conversion from color to grayscale not supported";
6204*e47783fdSXin Li /*(2^31-1)*/
6205*e47783fdSXin Li case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk";
6206*e47783fdSXin Li /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/
6207*e47783fdSXin Li case 64: return "the length of the END symbol 256 in the Huffman tree is 0";
6208*e47783fdSXin Li case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes";
6209*e47783fdSXin Li case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte";
6210*e47783fdSXin Li case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors";
6211*e47783fdSXin Li case 69: return "unknown chunk type with 'critical' flag encountered by the decoder";
6212*e47783fdSXin Li case 71: return "invalid interlace mode given to encoder (must be 0 or 1)";
6213*e47783fdSXin Li case 72: return "while decoding, invalid compression method encountering in zTXt or iTXt chunk (it must be 0)";
6214*e47783fdSXin Li case 73: return "invalid tIME chunk size";
6215*e47783fdSXin Li case 74: return "invalid pHYs chunk size";
6216*e47783fdSXin Li /*length could be wrong, or data chopped off*/
6217*e47783fdSXin Li case 75: return "no null termination char found while decoding text chunk";
6218*e47783fdSXin Li case 76: return "iTXt chunk too short to contain required bytes";
6219*e47783fdSXin Li case 77: return "integer overflow in buffer size";
6220*e47783fdSXin Li case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/
6221*e47783fdSXin Li case 79: return "failed to open file for writing";
6222*e47783fdSXin Li case 80: return "tried creating a tree of 0 symbols";
6223*e47783fdSXin Li case 81: return "lazy matching at pos 0 is impossible";
6224*e47783fdSXin Li case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds";
6225*e47783fdSXin Li case 83: return "memory allocation failed";
6226*e47783fdSXin Li case 84: return "given image too small to contain all pixels to be encoded";
6227*e47783fdSXin Li case 86: return "impossible offset in lz77 encoding (internal bug)";
6228*e47783fdSXin Li case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined";
6229*e47783fdSXin Li case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy";
6230*e47783fdSXin Li case 89: return "text chunk keyword too short or long: must have size 1-79";
6231*e47783fdSXin Li /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/
6232*e47783fdSXin Li case 90: return "windowsize must be a power of two";
6233*e47783fdSXin Li case 91: return "invalid decompressed idat size";
6234*e47783fdSXin Li case 92: return "integer overflow due to too many pixels";
6235*e47783fdSXin Li case 93: return "zero width or height is invalid";
6236*e47783fdSXin Li case 94: return "header chunk must have a size of 13 bytes";
6237*e47783fdSXin Li case 95: return "integer overflow with combined idat chunk size";
6238*e47783fdSXin Li case 96: return "invalid gAMA chunk size";
6239*e47783fdSXin Li case 97: return "invalid cHRM chunk size";
6240*e47783fdSXin Li case 98: return "invalid sRGB chunk size";
6241*e47783fdSXin Li case 99: return "invalid sRGB rendering intent";
6242*e47783fdSXin Li case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY";
6243*e47783fdSXin Li case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa";
6244*e47783fdSXin Li case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification";
6245*e47783fdSXin Li case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?";
6246*e47783fdSXin Li case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)";
6247*e47783fdSXin Li case 105: return "integer overflow of bitsize";
6248*e47783fdSXin Li case 106: return "PNG file must have PLTE chunk if color type is palette";
6249*e47783fdSXin Li case 107: return "color convert from palette mode requested without setting the palette data in it";
6250*e47783fdSXin Li case 108: return "tried to add more than 256 values to a palette";
6251*e47783fdSXin Li /*this limit can be configured in LodePNGDecompressSettings*/
6252*e47783fdSXin Li case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size";
6253*e47783fdSXin Li case 110: return "custom zlib or inflate decompression failed";
6254*e47783fdSXin Li case 111: return "custom zlib or deflate compression failed";
6255*e47783fdSXin Li /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents
6256*e47783fdSXin Li unreasonable memory consumption when decoding due to impossibly large text sizes.*/
6257*e47783fdSXin Li case 112: return "compressed text unreasonably large";
6258*e47783fdSXin Li /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents
6259*e47783fdSXin Li unreasonable memory consumption when decoding due to impossibly large ICC profile*/
6260*e47783fdSXin Li case 113: return "ICC profile unreasonably large";
6261*e47783fdSXin Li }
6262*e47783fdSXin Li return "unknown error code";
6263*e47783fdSXin Li }
6264*e47783fdSXin Li #endif /*LODEPNG_COMPILE_ERROR_TEXT*/
6265*e47783fdSXin Li
6266*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
6267*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
6268*e47783fdSXin Li /* // C++ Wrapper // */
6269*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
6270*e47783fdSXin Li /* ////////////////////////////////////////////////////////////////////////// */
6271*e47783fdSXin Li
6272*e47783fdSXin Li #ifdef LODEPNG_COMPILE_CPP
6273*e47783fdSXin Li namespace lodepng {
6274*e47783fdSXin Li
6275*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
load_file(std::vector<unsigned char> & buffer,const std::string & filename)6276*e47783fdSXin Li unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename) {
6277*e47783fdSXin Li long size = lodepng_filesize(filename.c_str());
6278*e47783fdSXin Li if(size < 0) return 78;
6279*e47783fdSXin Li buffer.resize((size_t)size);
6280*e47783fdSXin Li return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str());
6281*e47783fdSXin Li }
6282*e47783fdSXin Li
6283*e47783fdSXin Li /*write given buffer to the file, overwriting the file, it doesn't append to it.*/
save_file(const std::vector<unsigned char> & buffer,const std::string & filename)6284*e47783fdSXin Li unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename) {
6285*e47783fdSXin Li return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str());
6286*e47783fdSXin Li }
6287*e47783fdSXin Li #endif /* LODEPNG_COMPILE_DISK */
6288*e47783fdSXin Li
6289*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ZLIB
6290*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
decompress(std::vector<unsigned char> & out,const unsigned char * in,size_t insize,const LodePNGDecompressSettings & settings)6291*e47783fdSXin Li unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
6292*e47783fdSXin Li const LodePNGDecompressSettings& settings) {
6293*e47783fdSXin Li unsigned char* buffer = 0;
6294*e47783fdSXin Li size_t buffersize = 0;
6295*e47783fdSXin Li unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings);
6296*e47783fdSXin Li if(buffer) {
6297*e47783fdSXin Li out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6298*e47783fdSXin Li lodepng_free(buffer);
6299*e47783fdSXin Li }
6300*e47783fdSXin Li return error;
6301*e47783fdSXin Li }
6302*e47783fdSXin Li
decompress(std::vector<unsigned char> & out,const std::vector<unsigned char> & in,const LodePNGDecompressSettings & settings)6303*e47783fdSXin Li unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
6304*e47783fdSXin Li const LodePNGDecompressSettings& settings) {
6305*e47783fdSXin Li return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings);
6306*e47783fdSXin Li }
6307*e47783fdSXin Li #endif /* LODEPNG_COMPILE_DECODER */
6308*e47783fdSXin Li
6309*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
compress(std::vector<unsigned char> & out,const unsigned char * in,size_t insize,const LodePNGCompressSettings & settings)6310*e47783fdSXin Li unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
6311*e47783fdSXin Li const LodePNGCompressSettings& settings) {
6312*e47783fdSXin Li unsigned char* buffer = 0;
6313*e47783fdSXin Li size_t buffersize = 0;
6314*e47783fdSXin Li unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);
6315*e47783fdSXin Li if(buffer) {
6316*e47783fdSXin Li out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6317*e47783fdSXin Li lodepng_free(buffer);
6318*e47783fdSXin Li }
6319*e47783fdSXin Li return error;
6320*e47783fdSXin Li }
6321*e47783fdSXin Li
compress(std::vector<unsigned char> & out,const std::vector<unsigned char> & in,const LodePNGCompressSettings & settings)6322*e47783fdSXin Li unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
6323*e47783fdSXin Li const LodePNGCompressSettings& settings) {
6324*e47783fdSXin Li return compress(out, in.empty() ? 0 : &in[0], in.size(), settings);
6325*e47783fdSXin Li }
6326*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ENCODER */
6327*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ZLIB */
6328*e47783fdSXin Li
6329*e47783fdSXin Li
6330*e47783fdSXin Li #ifdef LODEPNG_COMPILE_PNG
6331*e47783fdSXin Li
State()6332*e47783fdSXin Li State::State() {
6333*e47783fdSXin Li lodepng_state_init(this);
6334*e47783fdSXin Li }
6335*e47783fdSXin Li
State(const State & other)6336*e47783fdSXin Li State::State(const State& other) {
6337*e47783fdSXin Li lodepng_state_init(this);
6338*e47783fdSXin Li lodepng_state_copy(this, &other);
6339*e47783fdSXin Li }
6340*e47783fdSXin Li
~State()6341*e47783fdSXin Li State::~State() {
6342*e47783fdSXin Li lodepng_state_cleanup(this);
6343*e47783fdSXin Li }
6344*e47783fdSXin Li
operator =(const State & other)6345*e47783fdSXin Li State& State::operator=(const State& other) {
6346*e47783fdSXin Li lodepng_state_copy(this, &other);
6347*e47783fdSXin Li return *this;
6348*e47783fdSXin Li }
6349*e47783fdSXin Li
6350*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DECODER
6351*e47783fdSXin Li
decode(std::vector<unsigned char> & out,unsigned & w,unsigned & h,const unsigned char * in,size_t insize,LodePNGColorType colortype,unsigned bitdepth)6352*e47783fdSXin Li unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const unsigned char* in,
6353*e47783fdSXin Li size_t insize, LodePNGColorType colortype, unsigned bitdepth) {
6354*e47783fdSXin Li unsigned char* buffer = 0;
6355*e47783fdSXin Li unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth);
6356*e47783fdSXin Li if(buffer && !error) {
6357*e47783fdSXin Li State state;
6358*e47783fdSXin Li state.info_raw.colortype = colortype;
6359*e47783fdSXin Li state.info_raw.bitdepth = bitdepth;
6360*e47783fdSXin Li size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
6361*e47783fdSXin Li out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6362*e47783fdSXin Li }
6363*e47783fdSXin Li lodepng_free(buffer);
6364*e47783fdSXin Li return error;
6365*e47783fdSXin Li }
6366*e47783fdSXin Li
decode(std::vector<unsigned char> & out,unsigned & w,unsigned & h,const std::vector<unsigned char> & in,LodePNGColorType colortype,unsigned bitdepth)6367*e47783fdSXin Li unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
6368*e47783fdSXin Li const std::vector<unsigned char>& in, LodePNGColorType colortype, unsigned bitdepth) {
6369*e47783fdSXin Li return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth);
6370*e47783fdSXin Li }
6371*e47783fdSXin Li
decode(std::vector<unsigned char> & out,unsigned & w,unsigned & h,State & state,const unsigned char * in,size_t insize)6372*e47783fdSXin Li unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
6373*e47783fdSXin Li State& state,
6374*e47783fdSXin Li const unsigned char* in, size_t insize) {
6375*e47783fdSXin Li unsigned char* buffer = NULL;
6376*e47783fdSXin Li unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);
6377*e47783fdSXin Li if(buffer && !error) {
6378*e47783fdSXin Li size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
6379*e47783fdSXin Li out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6380*e47783fdSXin Li }
6381*e47783fdSXin Li lodepng_free(buffer);
6382*e47783fdSXin Li return error;
6383*e47783fdSXin Li }
6384*e47783fdSXin Li
decode(std::vector<unsigned char> & out,unsigned & w,unsigned & h,State & state,const std::vector<unsigned char> & in)6385*e47783fdSXin Li unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
6386*e47783fdSXin Li State& state,
6387*e47783fdSXin Li const std::vector<unsigned char>& in) {
6388*e47783fdSXin Li return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size());
6389*e47783fdSXin Li }
6390*e47783fdSXin Li
6391*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
decode(std::vector<unsigned char> & out,unsigned & w,unsigned & h,const std::string & filename,LodePNGColorType colortype,unsigned bitdepth)6392*e47783fdSXin Li unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const std::string& filename,
6393*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
6394*e47783fdSXin Li std::vector<unsigned char> buffer;
6395*e47783fdSXin Li /* safe output values in case error happens */
6396*e47783fdSXin Li w = h = 0;
6397*e47783fdSXin Li unsigned error = load_file(buffer, filename);
6398*e47783fdSXin Li if(error) return error;
6399*e47783fdSXin Li return decode(out, w, h, buffer, colortype, bitdepth);
6400*e47783fdSXin Li }
6401*e47783fdSXin Li #endif /* LODEPNG_COMPILE_DECODER */
6402*e47783fdSXin Li #endif /* LODEPNG_COMPILE_DISK */
6403*e47783fdSXin Li
6404*e47783fdSXin Li #ifdef LODEPNG_COMPILE_ENCODER
encode(std::vector<unsigned char> & out,const unsigned char * in,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)6405*e47783fdSXin Li unsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned w, unsigned h,
6406*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
6407*e47783fdSXin Li unsigned char* buffer;
6408*e47783fdSXin Li size_t buffersize;
6409*e47783fdSXin Li unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);
6410*e47783fdSXin Li if(buffer) {
6411*e47783fdSXin Li out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6412*e47783fdSXin Li lodepng_free(buffer);
6413*e47783fdSXin Li }
6414*e47783fdSXin Li return error;
6415*e47783fdSXin Li }
6416*e47783fdSXin Li
encode(std::vector<unsigned char> & out,const std::vector<unsigned char> & in,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)6417*e47783fdSXin Li unsigned encode(std::vector<unsigned char>& out,
6418*e47783fdSXin Li const std::vector<unsigned char>& in, unsigned w, unsigned h,
6419*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
6420*e47783fdSXin Li if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
6421*e47783fdSXin Li return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
6422*e47783fdSXin Li }
6423*e47783fdSXin Li
encode(std::vector<unsigned char> & out,const unsigned char * in,unsigned w,unsigned h,State & state)6424*e47783fdSXin Li unsigned encode(std::vector<unsigned char>& out,
6425*e47783fdSXin Li const unsigned char* in, unsigned w, unsigned h,
6426*e47783fdSXin Li State& state) {
6427*e47783fdSXin Li unsigned char* buffer;
6428*e47783fdSXin Li size_t buffersize;
6429*e47783fdSXin Li unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);
6430*e47783fdSXin Li if(buffer) {
6431*e47783fdSXin Li out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6432*e47783fdSXin Li lodepng_free(buffer);
6433*e47783fdSXin Li }
6434*e47783fdSXin Li return error;
6435*e47783fdSXin Li }
6436*e47783fdSXin Li
encode(std::vector<unsigned char> & out,const std::vector<unsigned char> & in,unsigned w,unsigned h,State & state)6437*e47783fdSXin Li unsigned encode(std::vector<unsigned char>& out,
6438*e47783fdSXin Li const std::vector<unsigned char>& in, unsigned w, unsigned h,
6439*e47783fdSXin Li State& state) {
6440*e47783fdSXin Li if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84;
6441*e47783fdSXin Li return encode(out, in.empty() ? 0 : &in[0], w, h, state);
6442*e47783fdSXin Li }
6443*e47783fdSXin Li
6444*e47783fdSXin Li #ifdef LODEPNG_COMPILE_DISK
encode(const std::string & filename,const unsigned char * in,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)6445*e47783fdSXin Li unsigned encode(const std::string& filename,
6446*e47783fdSXin Li const unsigned char* in, unsigned w, unsigned h,
6447*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
6448*e47783fdSXin Li std::vector<unsigned char> buffer;
6449*e47783fdSXin Li unsigned error = encode(buffer, in, w, h, colortype, bitdepth);
6450*e47783fdSXin Li if(!error) error = save_file(buffer, filename);
6451*e47783fdSXin Li return error;
6452*e47783fdSXin Li }
6453*e47783fdSXin Li
encode(const std::string & filename,const std::vector<unsigned char> & in,unsigned w,unsigned h,LodePNGColorType colortype,unsigned bitdepth)6454*e47783fdSXin Li unsigned encode(const std::string& filename,
6455*e47783fdSXin Li const std::vector<unsigned char>& in, unsigned w, unsigned h,
6456*e47783fdSXin Li LodePNGColorType colortype, unsigned bitdepth) {
6457*e47783fdSXin Li if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
6458*e47783fdSXin Li return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
6459*e47783fdSXin Li }
6460*e47783fdSXin Li #endif /* LODEPNG_COMPILE_DISK */
6461*e47783fdSXin Li #endif /* LODEPNG_COMPILE_ENCODER */
6462*e47783fdSXin Li #endif /* LODEPNG_COMPILE_PNG */
6463*e47783fdSXin Li } /* namespace lodepng */
6464*e47783fdSXin Li #endif /*LODEPNG_COMPILE_CPP*/
6465