1337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
29ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode VandevenneLodePNG version 20131222
3337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneCopyright (c) 2005-2013 Lode Vandevenne
5337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThis software is provided 'as-is', without any express or implied
7337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennewarranty. In no event will the authors be held liable for any damages
8337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennearising from the use of this software.
9337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
10337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevennePermission is granted to anyone to use this software for any purpose,
11337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneincluding commercial applications, and to alter it and redistribute it
12337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennefreely, subject to the following restrictions:
13337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    1. The origin of this software must not be misrepresented; you must not
15337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    claim that you wrote the original software. If you use this software
16337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    in a product, an acknowledgment in the product documentation would be
17337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    appreciated but is not required.
18337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
19337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    2. Altered source versions must be plainly marked as such, and must not be
20337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    misrepresented as being the original software.
21337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
22337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    3. This notice may not be removed or altered from any source
23337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    distribution.
24337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
25337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
26337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
27337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThe manual and changelog are in the header file "lodepng.h"
28337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneRename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.
29337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
30337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
31337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#include "lodepng.h"
32337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
33337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#include <stdio.h>
34337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#include <stdlib.h>
35337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
36337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_CPP
37337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#include <fstream>
38337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_CPP*/
39337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
409ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne#define VERSION_STRING "20131222"
41337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
42337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
43337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThis source file is built up in the following large parts. The code sections
44337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennewith the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way.
45337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-Tools for C and common code for PNG and Zlib
46337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-C Code for Zlib (huffman, deflate, ...)
47337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)
48337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-The C++ wrapper around all of the above
49337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
50337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
51337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*The malloc, realloc and free functions defined here with "lodepng_" in front
52337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneof the name, so that you can easily change them to others related to your
53337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneplatform if needed. Everything else in the code calls these. Pass
54337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out
55337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and
56337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennedefine them in your own project's source files without needing to change
57337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennelodepng source code. Don't forget to remove "static" if you copypaste them
58337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennefrom here.*/
59337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
60337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ALLOCATORS
61337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void* lodepng_malloc(size_t size)
62337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
63337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return malloc(size);
64337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
65337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
66337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void* lodepng_realloc(void* ptr, size_t new_size)
67337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
68337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return realloc(ptr, new_size);
69337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
70337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
71337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void lodepng_free(void* ptr)
72337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
73337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  free(ptr);
74337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
75337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#else /*LODEPNG_COMPILE_ALLOCATORS*/
76337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid* lodepng_malloc(size_t size);
77337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid* lodepng_realloc(void* ptr, size_t new_size);
78337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_free(void* ptr);
79337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ALLOCATORS*/
80337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
81337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
82337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
83337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* // Tools for C, and common code for PNG and Zlib.                       // */
84337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
85337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
86337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
87337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
88337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneOften in case of an error a value is assigned to a variable and then it breaks
89337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneout of a loop (to go to the cleanup phase of a function). This macro does that.
90337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneIt makes the error handling code shorter and more readable.
91337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
92337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneExample: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);
93337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
94337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define CERROR_BREAK(errorvar, code)\
95337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{\
96337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  errorvar = code;\
97337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  break;\
98337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
99337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/
101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define ERROR_BREAK(code) CERROR_BREAK(error, code)
102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Set error var to the error code, and return it.*/
104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define CERROR_RETURN_ERROR(errorvar, code)\
105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{\
106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  errorvar = code;\
107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return code;\
108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Try the code, if it returns error, also return the error.*/
111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define CERROR_TRY_RETURN(call)\
112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{\
113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = call;\
114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(error) return error;\
115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneAbout uivector, ucvector and string:
119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-All of them wrap dynamic arrays or text strings in a similar way.
120337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.
121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.
122337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-They're not used in the interface, only internally in this file as static functions.
123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.
124337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
126337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ZLIB
127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*dynamic vector of unsigned ints*/
128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct uivector
129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* data;
131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t size; /*size in number of unsigned longs*/
132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t allocsize; /*allocated size in bytes*/
133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} uivector;
134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void uivector_cleanup(void* p)
136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ((uivector*)p)->size = ((uivector*)p)->allocsize = 0;
138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(((uivector*)p)->data);
139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ((uivector*)p)->data = NULL;
140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*returns 1 if success, 0 if failure ==> nothing done*/
143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned uivector_resize(uivector* p, size_t size)
144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(size * sizeof(unsigned) > p->allocsize)
146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t newsize = size * sizeof(unsigned) * 2;
148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    void* data = lodepng_realloc(p->data, newsize);
149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(data)
150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      p->allocsize = newsize;
152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      p->data = (unsigned*)data;
153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      p->size = size;
154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else return 0;
156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else p->size = size;
158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*resize and give all new elements the value*/
162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned uivector_resizev(uivector* p, size_t size, unsigned value)
163337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t oldsize = p->size, i;
165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!uivector_resize(p, size)) return 0;
166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = oldsize; i < size; i++) p->data[i] = value;
167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
170337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void uivector_init(uivector* p)
171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->data = NULL;
173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->size = p->allocsize = 0;
174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*returns 1 if success, 0 if failure ==> nothing done*/
178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned uivector_push_back(uivector* p, unsigned c)
179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!uivector_resize(p, p->size + 1)) return 0;
181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->data[p->size - 1] = c;
182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*copy q to p, returns 1 if success, 0 if failure ==> nothing done*/
186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned uivector_copy(uivector* p, const uivector* q)
187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!uivector_resize(p, q->size)) return 0;
190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < q->size; i++) p->data[i] = q->data[i];
191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ZLIB*/
195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* /////////////////////////////////////////////////////////////////////////// */
197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*dynamic vector of unsigned chars*/
199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct ucvector
200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* data;
202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t size; /*used size*/
203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t allocsize; /*allocated size*/
204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} ucvector;
205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*returns 1 if success, 0 if failure ==> nothing done*/
207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned ucvector_resize(ucvector* p, size_t size)
208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(size * sizeof(unsigned char) > p->allocsize)
210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t newsize = size * sizeof(unsigned char) * 2;
212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    void* data = lodepng_realloc(p->data, newsize);
213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(data)
214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      p->allocsize = newsize;
216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      p->data = (unsigned char*)data;
217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      p->size = size;
218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else return 0; /*error: not enough memory*/
220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else p->size = size;
222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_PNG
226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void ucvector_cleanup(void* p)
228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;
230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(((ucvector*)p)->data);
231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ((ucvector*)p)->data = NULL;
232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void ucvector_init(ucvector* p)
235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->data = NULL;
237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->size = p->allocsize = 0;
238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*resize and give all new elements the value*/
242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned ucvector_resizev(ucvector* p, size_t size, unsigned char value)
243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t oldsize = p->size, i;
245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!ucvector_resize(p, size)) return 0;
246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = oldsize; i < size; i++) p->data[i] = value;
247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_PNG*/
251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ZLIB
253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*you can both convert from vector to buffer&size and vica versa. If you use
254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneinit_buffer to take over a buffer and size, it is not needed to use cleanup*/
255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size)
256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->data = buffer;
258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->allocsize = p->size = size;
259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ZLIB*/
261337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
262337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER)
263337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*returns 1 if success, 0 if failure ==> nothing done*/
264337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned ucvector_push_back(ucvector* p, unsigned char c)
265337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
266337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!ucvector_resize(p, p->size + 1)) return 0;
267337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p->data[p->size - 1] = c;
268337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
269337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
270337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
271337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
272337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
273337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
274337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
275337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_PNG
276337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
277337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*returns 1 if success, 0 if failure ==> nothing done*/
278337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned string_resize(char** out, size_t size)
279337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
280337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char* data = (char*)lodepng_realloc(*out, size + 1);
281337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(data)
282337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
283337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    data[size] = 0; /*null termination char*/
284337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *out = data;
285337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
286337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return data != 0;
287337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
288337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
289337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*init a {char*, size_t} pair for use as string*/
290337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void string_init(char** out)
291337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
292337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = NULL;
293337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_resize(out, 0);
294337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
295337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
296337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*free the above pair again*/
297337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void string_cleanup(char** out)
298337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
299337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(*out);
300337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = NULL;
301337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
302337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
303337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void string_set(char** out, const char* in)
304337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
305337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t insize = strlen(in), i = 0;
306337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(string_resize(out, insize))
307337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
308337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < insize; i++)
309337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
310337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      (*out)[i] = in[i];
311337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
312337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
313337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
314337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
315337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_PNG*/
316337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
317337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
318337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
319337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_read32bitInt(const unsigned char* buffer)
320337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
321337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
322337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
323337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
324337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)
325337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*buffer must have at least 4 allocated bytes available*/
326337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void lodepng_set32bitInt(unsigned char* buffer, unsigned value)
327337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
328337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  buffer[0] = (unsigned char)((value >> 24) & 0xff);
329337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  buffer[1] = (unsigned char)((value >> 16) & 0xff);
330337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  buffer[2] = (unsigned char)((value >>  8) & 0xff);
331337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  buffer[3] = (unsigned char)((value      ) & 0xff);
332337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
333337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
334337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
335337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
336337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void lodepng_add32bitInt(ucvector* buffer, unsigned value)
337337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
338337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/
339337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_set32bitInt(&buffer->data[buffer->size - 4], value);
340337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
341337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
342337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
343337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
344337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / File IO                                                                / */
345337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
346337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
347337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DISK
348337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
349337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename)
350337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
351337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  FILE* file;
352337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  long size;
353337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
354337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*provide some proper output values if error will happen*/
355337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = 0;
356337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = 0;
357337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
358337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  file = fopen(filename, "rb");
359337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!file) return 78;
360337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
361337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*get filesize:*/
362337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  fseek(file , 0 , SEEK_END);
363337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size = ftell(file);
364337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  rewind(file);
365337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
366337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*read contents of the file into the vector*/
367337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = 0;
368337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = (unsigned char*)lodepng_malloc((size_t)size);
369337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(size && (*out)) (*outsize) = fread(*out, 1, (size_t)size, file);
370337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
371337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  fclose(file);
372337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!(*out) && size) return 83; /*the above malloc failed*/
373337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
374337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
375337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
376337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
377337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename)
378337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
379337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  FILE* file;
380337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  file = fopen(filename, "wb" );
381337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!file) return 79;
382337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  fwrite((char*)buffer , 1 , buffersize, file);
383337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  fclose(file);
384337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
385337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
386337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
387337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DISK*/
388337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
389337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
390337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
391337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* // End of common code and tools. Begin of Zlib related code.            // */
392337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
393337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
394337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
395337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ZLIB
396337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
397337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*TODO: this ignores potential out of memory errors*/
3989ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\
3999ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne{\
4009ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  /*add a new byte at the end*/\
4019ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\
4029ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\
4039ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\
4049ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  (*bitpointer)++;\
405337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
406337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
407337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)
408337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
409337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
410337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1));
411337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
412337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
413337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)
414337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
415337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
416337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1));
417337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
418337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
419337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
420337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
421337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
422337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1)
423337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
424337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream)
425337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
426337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream));
427337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*bitpointer)++;
428337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return result;
429337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
430337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
431337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)
432337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
433337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned result = 0, i;
434337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < nbits; i++)
435337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
436337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    result += ((unsigned)READBIT(*bitpointer, bitstream)) << i;
437337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    (*bitpointer)++;
438337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
439337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return result;
440337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
441337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
442337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
443337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
444337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Deflate - Huffman                                                      / */
445337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
446337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
447337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define FIRST_LENGTH_CODE_INDEX 257
448337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define LAST_LENGTH_CODE_INDEX 285
449337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*256 literals, the end code, some length codes, and 2 unused codes*/
450337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define NUM_DEFLATE_CODE_SYMBOLS 288
451337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the distance codes have their own symbols, 30 used, 2 unused*/
452337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define NUM_DISTANCE_SYMBOLS 32
453337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/
454337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define NUM_CODE_LENGTH_CODES 19
455337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
456337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the base lengths represented by codes 257-285*/
457337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned LENGTHBASE[29]
458337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
459337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     67, 83, 99, 115, 131, 163, 195, 227, 258};
460337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
461337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the extra bits used by codes 257-285 (added to base length)*/
462337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned LENGTHEXTRA[29]
463337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  = {0, 0, 0, 0, 0, 0, 0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,
464337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      4,  4,  4,   4,   5,   5,   5,   5,   0};
465337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
466337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/
467337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned DISTANCEBASE[30]
468337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
469337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
470337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
471337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the extra bits of backwards distances (added to base)*/
472337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned DISTANCEEXTRA[30]
473337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  = {0, 0, 0, 0, 1, 1, 2,  2,  3,  3,  4,  4,  5,  5,   6,   6,   7,   7,   8,
474337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne       8,    9,    9,   10,   10,   11,   11,   12,    12,    13,    13};
475337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
476337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the order in which "code length alphabet code lengths" are stored, out of this
477337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethe huffman tree of the dynamic huffman tree lengths is generated*/
478337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES]
479337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
480337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
481337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
482337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
483337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
484337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneHuffman tree struct, containing multiple representations of the tree
485337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
486337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct HuffmanTree
487337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
488337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* tree2d;
489337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* tree1d;
490337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* lengths; /*the lengths of the codes of the 1d-tree*/
491337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned maxbitlen; /*maximum number of bits a single code can get*/
492337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned numcodes; /*number of symbols in the alphabet = number of codes*/
493337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} HuffmanTree;
494337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
495337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*function used for debug purposes to draw the tree in ascii art with C++*/
496337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
497337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void HuffmanTree_draw(HuffmanTree* tree)
498337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
499337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl;
500337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(size_t i = 0; i < tree->tree1d.size; i++)
501337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
502337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(tree->lengths.data[i])
503337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl;
504337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
505337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << std::endl;
506337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}*/
507337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
508337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void HuffmanTree_init(HuffmanTree* tree)
509337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
510337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->tree2d = 0;
511337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->tree1d = 0;
512337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->lengths = 0;
513337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
514337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
515337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void HuffmanTree_cleanup(HuffmanTree* tree)
516337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
517337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(tree->tree2d);
518337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(tree->tree1d);
519337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(tree->lengths);
520337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
521337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
522337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*the tree representation used by the decoder. return value is error*/
523337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned HuffmanTree_make2DTree(HuffmanTree* tree)
524337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
525337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned nodefilled = 0; /*up to which node it is filled*/
526337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/
527337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned n, i;
528337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
529337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned));
530337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!tree->tree2d) return 83; /*alloc fail*/
531337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
532337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
533337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means
534337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uninited, a value >= numcodes is an address to another bit, a value < numcodes
535337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as
536337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  many columns as codes - 1.
537337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  A good huffmann tree has N * 2 - 1 nodes, of which N - 1 are internal nodes.
538337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Here, the internal nodes are stored (what their 0 and 1 option point to).
539337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  There is only memory for such good tree currently, if there are more nodes
540337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (due to too long length codes), error 55 will happen
541337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
542337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(n = 0; n < tree->numcodes * 2; n++)
543337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
544337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/
545337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
546337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
547337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(n = 0; n < tree->numcodes; n++) /*the codes*/
548337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
549337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < tree->lengths[n]; i++) /*the bits for this code*/
550337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
551337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1);
552337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(treepos > tree->numcodes - 2) return 55; /*oversubscribed, see comment in lodepng_error_text*/
553337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/
554337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
555337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(i + 1 == tree->lengths[n]) /*last bit*/
556337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
557337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/
558337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          treepos = 0;
559337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
560337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else
561337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
562337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*put address of the next step in here, first that address has to be found of course
563337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          (it's just nodefilled + 1)...*/
564337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          nodefilled++;
565337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*addresses encoded with numcodes added to it*/
566337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes;
567337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          treepos = nodefilled;
568337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
569337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
570337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes;
571337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
572337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
573337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5749ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  for(n = 0; n < tree->numcodes * 2; n++)
575337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
576337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/
577337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
578337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
579337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
580337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
581337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
582337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
583337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneSecond step for the ...makeFromLengths and ...makeFromFrequencies functions.
584337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennenumcodes, lengths and maxbitlen must already be filled in correctly. return
585337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevalue is error.
586337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
587337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree)
588337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
589337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector blcount;
590337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector nextcode;
591337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned bits, n, error = 0;
592337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
593337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&blcount);
594337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&nextcode);
595337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
596337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned));
597337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!tree->tree1d) error = 83; /*alloc fail*/
598337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
599337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0)
600337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0))
601337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = 83; /*alloc fail*/
602337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
603337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error)
604337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
605337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*step 1: count number of instances of each code length*/
606337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(bits = 0; bits < tree->numcodes; bits++) blcount.data[tree->lengths[bits]]++;
607337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*step 2: generate the nextcode values*/
608337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(bits = 1; bits <= tree->maxbitlen; bits++)
609337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
610337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1;
611337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
612337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*step 3: generate all the codes*/
613337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(n = 0; n < tree->numcodes; n++)
614337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
615337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++;
616337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
617337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
618337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
619337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&blcount);
620337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&nextcode);
621337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
622337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) return HuffmanTree_make2DTree(tree);
623337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else return error;
624337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
625337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
626337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
627337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennegiven the code lengths (as stored in the PNG file), generate the tree as defined
628337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneby Deflate. maxbitlen is the maximum bits that a code in the tree can have.
629337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturn value is error.
630337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
631337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen,
632337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                            size_t numcodes, unsigned maxbitlen)
633337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
634337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
635337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));
636337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!tree->lengths) return 83; /*alloc fail*/
637337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < numcodes; i++) tree->lengths[i] = bitlen[i];
638337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->numcodes = (unsigned)numcodes; /*number of symbols*/
639337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->maxbitlen = maxbitlen;
640337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return HuffmanTree_makeFromLengths2(tree);
641337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
642337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
643337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
644337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
645337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
646337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneA coin, this is the terminology used for the package-merge algorithm and the
647337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennecoin collector's problem. This is used to generate the huffman tree.
648337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneA coin can be multiple coins (when they're merged)
649337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
650337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct Coin
651337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
652337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector symbols;
653337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  float weight; /*the sum of all weights in this coin*/
654337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} Coin;
655337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
656337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void coin_init(Coin* c)
657337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
658337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&c->symbols);
659337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
660337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
661337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*argument c is void* so that this dtor can be given as function pointer to the vector resize function*/
662337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void coin_cleanup(void* c)
663337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
664337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&((Coin*)c)->symbols);
665337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
666337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
667337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void coin_copy(Coin* c1, const Coin* c2)
668337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
669337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  c1->weight = c2->weight;
670337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_copy(&c1->symbols, &c2->symbols);
671337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
672337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
673337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void add_coins(Coin* c1, const Coin* c2)
674337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
675337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
676337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < c2->symbols.size; i++) uivector_push_back(&c1->symbols, c2->symbols.data[i]);
677337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  c1->weight += c2->weight;
678337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
679337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
680337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void init_coins(Coin* coins, size_t num)
681337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
682337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
683337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < num; i++) coin_init(&coins[i]);
684337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
685337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
686337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void cleanup_coins(Coin* coins, size_t num)
687337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
688337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
689337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < num; i++) coin_cleanup(&coins[i]);
690337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
691337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6929ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevennestatic int coin_compare(const void* a, const void* b) {
6939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  float wa = ((const Coin*)a)->weight;
6949ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  float wb = ((const Coin*)b)->weight;
6959ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  return wa > wb ? 1 : wa < wb ? -1 : 0;
696337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
697337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
698337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned append_symbol_coins(Coin* coins, const unsigned* frequencies, unsigned numcodes, size_t sum)
699337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
700337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
701337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned j = 0; /*index of present symbols*/
702337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < numcodes; i++)
703337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
704337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(frequencies[i] != 0) /*only include symbols that are present*/
705337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
706337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      coins[j].weight = frequencies[i] / (float)sum;
707337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      uivector_push_back(&coins[j].symbols, i);
708337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      j++;
709337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
710337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
711337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
712337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
713337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
714337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
715337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                      size_t numcodes, unsigned maxbitlen)
716337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
717337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i, j;
718337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t sum = 0, numpresent = 0;
719337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
720337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Coin* coins; /*the coins of the currently calculated row*/
721337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Coin* prev_row; /*the previous row of coins*/
722337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned numcoins;
723337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned coinmem;
724337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
725337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/
726337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
727337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < numcodes; i++)
728337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
729337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(frequencies[i] > 0)
730337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
731337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      numpresent++;
732337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      sum += frequencies[i];
733337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
734337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
735337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
736337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < numcodes; i++) lengths[i] = 0;
737337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
738337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*ensure at least two present symbols. There should be at least one symbol
739337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  according to RFC 1951 section 3.2.7. To decoders incorrectly require two. To
740337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  make these work as well ensure there are at least two symbols. The
741337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Package-Merge code below also doesn't work correctly if there's only one
742337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/
743337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(numpresent == 0)
744337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
745337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/
746337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
747337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(numpresent == 1)
748337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
749337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numcodes; i++)
750337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
751337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(frequencies[i])
752337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
753337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        lengths[i] = 1;
754337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        lengths[i == 0 ? 1 : 0] = 1;
755337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
756337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
757337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
758337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
759337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
760337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
761337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Package-Merge algorithm represented by coin collector's problem
762337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    For every symbol, maxbitlen coins will be created*/
763337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
764337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    coinmem = numpresent * 2; /*max amount of coins needed with the current algo*/
765337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    coins = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem);
766337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    prev_row = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem);
7679ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(!coins || !prev_row)
7689ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
7699ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      lodepng_free(coins);
7709ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      lodepng_free(prev_row);
7719ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      return 83; /*alloc fail*/
7729ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
773337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    init_coins(coins, coinmem);
774337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    init_coins(prev_row, coinmem);
775337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
776337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*first row, lowest denominator*/
777337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = append_symbol_coins(coins, frequencies, numcodes, sum);
778337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    numcoins = numpresent;
7799ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    qsort(coins, numcoins, sizeof(Coin), coin_compare);
780337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error)
781337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
782337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned numprev = 0;
783337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(j = 1; j <= maxbitlen && !error; j++) /*each of the remaining rows*/
784337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
785337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned tempnum;
786337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        Coin* tempcoins;
787337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*swap prev_row and coins, and their amounts*/
788337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        tempcoins = prev_row; prev_row = coins; coins = tempcoins;
789337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        tempnum = numprev; numprev = numcoins; numcoins = tempnum;
790337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
791337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        cleanup_coins(coins, numcoins);
792337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        init_coins(coins, numcoins);
793337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
794337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        numcoins = 0;
795337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
796337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*fill in the merged coins of the previous row*/
797337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i + 1 < numprev; i += 2)
798337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
799337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*merge prev_row[i] and prev_row[i + 1] into new coin*/
800337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          Coin* coin = &coins[numcoins++];
801337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          coin_copy(coin, &prev_row[i]);
802337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          add_coins(coin, &prev_row[i + 1]);
803337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
804337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*fill in all the original symbols again*/
805337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(j < maxbitlen)
806337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
807337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          error = append_symbol_coins(coins + numcoins, frequencies, numcodes, sum);
808337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          numcoins += numpresent;
809337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
8109ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        qsort(coins, numcoins, sizeof(Coin), coin_compare);
811337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
812337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
813337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
814337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error)
815337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
816337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*calculate the lenghts of each symbol, as the amount of times a coin of each symbol is used*/
817337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpresent - 1; i++)
818337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
819337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        Coin* coin = &coins[i];
820337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(j = 0; j < coin->symbols.size; j++) lengths[coin->symbols.data[j]]++;
821337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
822337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
823337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
824337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    cleanup_coins(coins, coinmem);
825337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(coins);
826337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    cleanup_coins(prev_row, coinmem);
827337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(prev_row);
828337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
829337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
830337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
831337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
832337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
833337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Create the Huffman tree given the symbol frequencies*/
834337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,
835337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                                size_t mincodes, size_t numcodes, unsigned maxbitlen)
836337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
837337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
838337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!frequencies[numcodes - 1] && numcodes > mincodes) numcodes--; /*trim zeroes*/
839337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->maxbitlen = maxbitlen;
840337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->numcodes = (unsigned)numcodes; /*number of symbols*/
841337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned));
842337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!tree->lengths) return 83; /*alloc fail*/
843337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*initialize all lengths to 0*/
844337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  memset(tree->lengths, 0, numcodes * sizeof(unsigned));
845337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
846337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen);
847337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) error = HuffmanTree_makeFromLengths2(tree);
848337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
849337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
850337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
851337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index)
852337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
853337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return tree->tree1d[index];
854337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
855337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
856337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index)
857337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
858337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return tree->lengths[index];
859337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
860337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
861337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
862337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/
863337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned generateFixedLitLenTree(HuffmanTree* tree)
864337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
865337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i, error = 0;
866337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
867337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!bitlen) return 83; /*alloc fail*/
868337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
869337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/
870337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i =   0; i <= 143; i++) bitlen[i] = 8;
871337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 144; i <= 255; i++) bitlen[i] = 9;
872337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 256; i <= 279; i++) bitlen[i] = 7;
873337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 280; i <= 287; i++) bitlen[i] = 8;
874337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
875337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15);
876337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
877337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(bitlen);
878337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
879337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
880337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
881337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/
882337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned generateFixedDistanceTree(HuffmanTree* tree)
883337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
884337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i, error = 0;
885337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
886337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!bitlen) return 83; /*alloc fail*/
887337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
888337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*there are 32 distance codes, but 30-31 are unused*/
889337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < NUM_DISTANCE_SYMBOLS; i++) bitlen[i] = 5;
890337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15);
891337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
892337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(bitlen);
893337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
894337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
895337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
896337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
897337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
898337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
899337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturns the code, or (unsigned)(-1) if error happened
900337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneinbitlength is the length of the complete buffer, in bits (so its byte length times 8)
901337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
902337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp,
903337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    const HuffmanTree* codetree, size_t inbitlength)
904337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
905337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned treepos = 0, ct;
906337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(;;)
907337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
908337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/
909337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*
910337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    decode the symbol from the tree. The "readBitFromStream" code is inlined in
911337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    the expression below because this is the biggest bottleneck while decoding
912337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    */
913337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)];
914337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    (*bp)++;
915337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/
916337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/
917337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
918337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/
919337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
920337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
921337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
922337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
923337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
924337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
925337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
926337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Inflator (Decompressor)                                                / */
927337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
928337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
929337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/
930337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d)
931337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
932337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*TODO: check for out of memory errors*/
933337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  generateFixedLitLenTree(tree_ll);
934337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  generateFixedDistanceTree(tree_d);
935337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
936337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
937337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/
938337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
939337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                      const unsigned char* in, size_t* bp, size_t inlength)
940337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
941337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/
942337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
943337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned n, HLIT, HDIST, HCLEN, i;
944337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t inbitlength = inlength * 8;
945337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
946337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/
947337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* bitlen_ll = 0; /*lit,len code lengths*/
948337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* bitlen_d = 0; /*dist code lengths*/
949337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/
950337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned* bitlen_cl = 0;
951337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
952337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
953337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if((*bp) >> 3 >= inlength - 2) return 49; /*error: the bit pointer is or will go past the memory*/
954337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
955337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
956337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HLIT =  readBitsFromStream(bp, in, 5) + 257;
957337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/
958337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HDIST = readBitsFromStream(bp, in, 5) + 1;
959337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/
960337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HCLEN = readBitsFromStream(bp, in, 4) + 4;
961337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
962337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_cl);
963337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
964337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!error)
965337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
966337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*read the code length codes out of 3 * (amount of code length codes) bits*/
967337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
968337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));
969337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/);
970337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
971337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < NUM_CODE_LENGTH_CODES; i++)
972337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
973337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3);
974337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/
975337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
976337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
977337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7);
978337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
979337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
980337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*now we can use this tree to read the lengths for the tree that this function will return*/
981337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
982337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
983337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/);
984337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < NUM_DEFLATE_CODE_SYMBOLS; i++) bitlen_ll[i] = 0;
985337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < NUM_DISTANCE_SYMBOLS; i++) bitlen_d[i] = 0;
986337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
987337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/
988337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    i = 0;
989337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    while(i < HLIT + HDIST)
990337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
991337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength);
992337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(code <= 15) /*a length code*/
993337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
994337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(i < HLIT) bitlen_ll[i] = code;
995337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else bitlen_d[i - HLIT] = code;
996337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        i++;
997337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
998337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else if(code == 16) /*repeat previous*/
999337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1000337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/
1001337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned value; /*set value to the previous code*/
1002337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1003337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(*bp >= inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
1004337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if (i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/
1005337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1006337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        replength += readBitsFromStream(bp, in, 2);
1007337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1008337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(i < HLIT + 1) value = bitlen_ll[i - 1];
1009337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else value = bitlen_d[i - HLIT - 1];
1010337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*repeat this value in the next lengths*/
1011337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(n = 0; n < replength; n++)
1012337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1013337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/
1014337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(i < HLIT) bitlen_ll[i] = value;
1015337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          else bitlen_d[i - HLIT] = value;
1016337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          i++;
1017337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1018337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1019337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else if(code == 17) /*repeat "0" 3-10 times*/
1020337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1021337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned replength = 3; /*read in the bits that indicate repeat length*/
1022337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(*bp >= inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
1023337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1024337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        replength += readBitsFromStream(bp, in, 3);
1025337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1026337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*repeat this value in the next lengths*/
1027337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(n = 0; n < replength; n++)
1028337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1029337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/
1030337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1031337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(i < HLIT) bitlen_ll[i] = 0;
1032337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          else bitlen_d[i - HLIT] = 0;
1033337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          i++;
1034337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1035337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1036337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else if(code == 18) /*repeat "0" 11-138 times*/
1037337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1038337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned replength = 11; /*read in the bits that indicate repeat length*/
1039337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(*bp >= inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
1040337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1041337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        replength += readBitsFromStream(bp, in, 7);
1042337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1043337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*repeat this value in the next lengths*/
1044337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(n = 0; n < replength; n++)
1045337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1046337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/
1047337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1048337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(i < HLIT) bitlen_ll[i] = 0;
1049337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          else bitlen_d[i - HLIT] = 0;
1050337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          i++;
1051337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1052337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1053337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
1054337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1055337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(code == (unsigned)(-1))
1056337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1057337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
1058337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          (10=no endcode, 11=wrong jump outside of tree)*/
1059337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          error = (*bp) > inbitlength ? 10 : 11;
1060337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1061337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else error = 16; /*unexisting code, this can never happen*/
1062337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
1063337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1064337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1065337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
1066337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1067337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/
1068337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1069337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/
1070337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15);
1071337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
1072337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15);
1073337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1074337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    break; /*end of error-while*/
1075337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1076337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1077337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(bitlen_cl);
1078337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(bitlen_ll);
1079337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(bitlen_d);
1080337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_cl);
1081337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1082337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1083337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1084337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1085337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*inflate a block with dynamic of fixed Huffman tree*/
1086337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp,
1087337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    size_t* pos, size_t inlength, unsigned btype)
1088337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1089337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
1090337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
1091337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_d; /*the huffman tree for distance codes*/
1092337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t inbitlength = inlength * 8;
1093337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1094337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_ll);
1095337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_d);
1096337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1097337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d);
1098337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength);
1099337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!error) /*decode all symbols until end reached, breaks at end code*/
1101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*code_ll is literal, length or end code*/
1103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength);
1104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(code_ll <= 255) /*literal symbol*/
1105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if((*pos) >= out->size)
1107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*reserve more room at once*/
1109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!ucvector_resize(out, ((*pos) + 1) * 2)) ERROR_BREAK(83 /*alloc fail*/);
1110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out->data[(*pos)] = (unsigned char)(code_ll);
1112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      (*pos)++;
1113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/
1115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned code_d, distance;
1117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
1118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t start, forward, backward, length;
1119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1120337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*part 1: get length base*/
1121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];
1122337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*part 2: get extra bits and add the value of that to length*/
1124337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
1125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
1126337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      length += readBitsFromStream(bp, in, numextrabits_l);
1127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*part 3: get distance code*/
1129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);
1130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(code_d > 29)
1131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
1133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
1135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          (10=no endcode, 11=wrong jump outside of tree)*/
1136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          error = (*bp) > inlength * 8 ? 10 : 11;
1137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else error = 18; /*error: invalid distance code (30-31 are never used)*/
1139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
1140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      distance = DISTANCEBASE[code_d];
1142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*part 4: get extra bits from distance*/
1144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      numextrabits_d = DISTANCEEXTRA[code_d];
1145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
1146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      distance += readBitsFromStream(bp, in, numextrabits_d);
1148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*part 5: fill in all the out[n] values based on the length and dist*/
1150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      start = (*pos);
1151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
1152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      backward = start - distance;
1153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if((*pos) + length >= out->size)
1154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*reserve more room at once*/
1156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!ucvector_resize(out, ((*pos) + length) * 2)) ERROR_BREAK(83 /*alloc fail*/);
1157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(forward = 0; forward < length; forward++)
1160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        out->data[(*pos)] = out->data[backward];
1162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        (*pos)++;
1163337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        backward++;
1164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(backward >= start) backward = start - distance;
1165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(code_ll == 256)
1168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break; /*end code, break the loop*/
1170337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
1172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
1174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      (10=no endcode, 11=wrong jump outside of tree)*/
1175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = (*bp) > inlength * 8 ? 10 : 11;
1176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
1177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_ll);
1181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_d);
1182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength)
1187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*go to first boundary of byte*/
1189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t p;
1190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned LEN, NLEN, n, error = 0;
1191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(((*bp) & 0x7) != 0) (*bp)++;
1192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  p = (*bp) / 8; /*byte position*/
1193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*read LEN (2 bytes) and NLEN (2 bytes)*/
1195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(p >= inlength - 4) return 52; /*error, bit pointer will jump past memory*/
1196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LEN = in[p] + 256 * in[p + 1]; p += 2;
1197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  NLEN = in[p] + 256 * in[p + 1]; p += 2;
1198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*check if 16-bit NLEN is really the one's complement of LEN*/
1200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/
1201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if((*pos) + LEN >= out->size)
1203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/
1205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*read the literal data: LEN bytes are now stored in the out buffer*/
1208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/
1209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(n = 0; n < LEN; n++) out->data[(*pos)++] = in[p++];
1210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*bp) = p * 8;
1212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned lodepng_inflatev(ucvector* out,
1217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                 const unsigned char* in, size_t insize,
1218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                 const LodePNGDecompressSettings* settings)
1219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/
1221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t bp = 0;
1222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned BFINAL = 0;
1223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t pos = 0; /*byte position in the out buffer*/
1224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
1226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (void)settings;
1228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!BFINAL)
1230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned BTYPE;
1232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/
1233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    BFINAL = readBitFromStream(&bp, in);
1234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    BTYPE = 1 * readBitFromStream(&bp, in);
1235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    BTYPE += 2 * readBitFromStream(&bp, in);
1236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
1238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/
1239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/
1240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) return error;
1242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*Only now we know the true size of out, resize it to that*/
1245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!ucvector_resize(out, pos)) error = 83; /*alloc fail*/
1246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_inflate(unsigned char** out, size_t* outsize,
1251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         const unsigned char* in, size_t insize,
1252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         const LodePNGDecompressSettings* settings)
1253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error;
1255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector v;
1256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init_buffer(&v, *out, *outsize);
1257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = lodepng_inflatev(&v, in, insize, settings);
1258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = v.data;
1259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = v.size;
1260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1261337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1262337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1263337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned inflate(unsigned char** out, size_t* outsize,
1264337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        const unsigned char* in, size_t insize,
1265337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        const LodePNGDecompressSettings* settings)
1266337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1267337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->custom_inflate)
1268337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1269337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return settings->custom_inflate(out, outsize, in, insize, settings);
1270337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1271337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
1272337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1273337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return lodepng_inflate(out, outsize, in, insize, settings);
1274337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1275337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1276337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1277337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
1278337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1279337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
1280337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1281337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
1282337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Deflator (Compressor)                                                  / */
1283337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
1284337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1285337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258;
1286337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1287337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*bitlen is the size in bits of the code*/
1288337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen)
1289337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1290337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  addBitsToStreamReversed(bp, compressed, code, bitlen);
1291337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1292337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1293337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*search the index in the array, that has the largest value smaller than or equal to the given value,
1294337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennegiven array must be sorted (if no value is smaller, it returns the size of the given array)*/
1295337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value)
1296337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1297337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*linear search implementation*/
1298337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*for(size_t i = 1; i < array_size; i++) if(array[i] > value) return i - 1;
1299337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return array_size - 1;*/
1300337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1301337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*binary search implementation (not that much faster) (precondition: array_size > 0)*/
1302337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t left  = 1;
1303337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t right = array_size - 1;
1304337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(left <= right)
1305337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1306337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t mid = (left + right) / 2;
1307337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(array[mid] <= value) left = mid + 1; /*the value to find is more to the right*/
1308337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(array[mid - 1] > value) right = mid - 1; /*the value to find is more to the left*/
1309337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else return mid - 1;
1310337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1311337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return array_size - 1;
1312337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1313337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1314337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void addLengthDistance(uivector* values, size_t length, size_t distance)
1315337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1316337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*values in encoded vector are those used by deflate:
1317337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  0-255: literal bytes
1318337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  256: end
1319337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits)
1320337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  286-287: invalid*/
1321337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1322337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length);
1323337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]);
1324337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance);
1325337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]);
1326337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1327337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX);
1328337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_push_back(values, extra_length);
1329337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_push_back(values, dist_code);
1330337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_push_back(values, extra_distance);
1331337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1332337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
13339ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevennestatic const unsigned HASH_BIT_MASK = 65535;
1334337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned HASH_NUM_VALUES = 65536;
1335337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned HASH_NUM_CHARACTERS = 3;
1336337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned HASH_SHIFT = 2;
1337337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
1338337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThe HASH_NUM_CHARACTERS value is used to make encoding faster by using longer
1339337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennesequences to generate a hash value from the stream bytes. Setting it to 3
1340337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennegives exactly the same compression as the brute force method, since deflate's
1341337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennerun length encoding starts with lengths of 3. Setting it to higher values,
1342337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennelike 6, can make the encoding faster (not always though!), but will cause the
1343337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneencoding to miss any length between 3 and this value, so that the compression
1344337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennemay be worse (but this can vary too depending on the image, sometimes it is
1345337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneeven a bit better instead).
1346337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThe HASH_NUM_VALUES is the amount of unique possible hash values that
1347337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennecombinations of bytes can give, the higher it is the more memory is needed, but
1348337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneif it's too low the advantage of hashing is gone.
1349337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
1350337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1351337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct Hash
1352337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1353337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int* head; /*hash value to head circular pos*/
1354337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int* val; /*circular pos to hash value*/
1355337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*circular pos to prev circular pos*/
1356337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned short* chain;
1357337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned short* zeros;
1358337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} Hash;
1359337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1360337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned hash_init(Hash* hash, unsigned windowsize)
1361337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1362337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
1363337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES);
1364337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize);
1365337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
1366337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
1367337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1368337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!hash->head || !hash->val || !hash->chain || !hash->zeros) return 83; /*alloc fail*/
1369337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1370337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*initialize hash table*/
1371337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < HASH_NUM_VALUES; i++) hash->head[i] = -1;
1372337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < windowsize; i++) hash->val[i] = -1;
1373337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < windowsize; i++) hash->chain[i] = i; /*same value as index indicates uninitialized*/
1374337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1375337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
1376337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1377337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1378337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void hash_cleanup(Hash* hash)
1379337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1380337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(hash->head);
1381337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(hash->val);
1382337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(hash->chain);
1383337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(hash->zeros);
1384337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1385337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1386337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getHash(const unsigned char* data, size_t size, size_t pos)
1387337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1388337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned result = 0;
13899ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if (HASH_NUM_CHARACTERS == 3 && pos + 2 < size) {
13909ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    result ^= (data[pos + 0] << (0 * HASH_SHIFT));
13919ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    result ^= (data[pos + 1] << (1 * HASH_SHIFT));
13929ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    result ^= (data[pos + 2] << (2 * HASH_SHIFT));
13939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  } else {
13949ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    size_t amount, i;
13959ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(pos >= size) return 0;
13969ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    amount = HASH_NUM_CHARACTERS;
13979ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(pos + amount >= size) amount = size - pos;
13989ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    for(i = 0; i < amount; i++) result ^= (data[pos + i] << (i * HASH_SHIFT));
13999ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  }
14009ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  return result & HASH_BIT_MASK;
1401337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1402337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1403337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned countZeros(const unsigned char* data, size_t size, size_t pos)
1404337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1405337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  const unsigned char* start = data + pos;
1406337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH;
1407337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(end > data + size) end = data + size;
1408337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data = start;
1409337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while (data != end && *data == 0) data++;
1410337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/
1411337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (unsigned)(data - start);
1412337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1413337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14149ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne/*wpos = pos & (windowsize - 1)*/
14159ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevennestatic void updateHashChain(Hash* hash, size_t wpos, int hashval)
1416337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1417337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash->val[wpos] = hashval;
1418337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];
1419337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash->head[hashval] = wpos;
1420337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1421337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1422337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
1423337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneLZ77-encode the data. Return value is error code. The input are raw bytes, the output
1424337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneis in the form of unsigned integers with codes representing for example literal bytes, or
1425337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennelength/distance pairs.
1426337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneIt uses a hash table technique to let it encode faster. When doing LZ77 encoding, a
1427337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennesliding window (of windowsize) is used, and all past bytes in that window can be used as
1428337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethe "dictionary". A brute force search through all possible distances would be slow, and
1429337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethis hash technique is one out of several ways to speed this up.
1430337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
1431337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned encodeLZ77(uivector* out, Hash* hash,
1432337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                           const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
1433337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                           unsigned minmatch, unsigned nicematch, unsigned lazymatching)
1434337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1435337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned pos, i, error = 0;
1436337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
1437337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;
1438337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;
1439337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14409ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
14419ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned numzeros = 0;
1442337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14439ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned offset; /*the offset represents the distance in LZ77 terminology*/
14449ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned length;
14459ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned lazy = 0;
14469ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned lazylength = 0, lazyoffset = 0;
14479ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned hashval;
14489ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned current_offset, current_length;
14499ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  const unsigned char *lastptr, *foreptr, *backptr;
14509ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned hashpos, prevpos;
1451337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14529ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if(windowsize <= 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
14539ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/
1454337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14559ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;
1456337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14579ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  for(pos = inpos; pos < insize; pos++)
14589ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  {
14599ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
14609ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    unsigned chainlength = 0;
1461337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14629ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    hashval = getHash(in, insize, pos);
14639ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    updateHashChain(hash, wpos, hashval);
1464337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14659ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(usezeros && hashval == 0)
14669ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
14679ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if (numzeros == 0) numzeros = countZeros(in, insize, pos);
14689ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      else if (pos + numzeros >= insize || in[pos + numzeros - 1] != 0) numzeros--;
14699ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      hash->zeros[wpos] = numzeros;
14709ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
14719ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    else
14729ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
14739ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      numzeros = 0;
14749ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
1475337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14769ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    /*the length and offset found for the current position*/
14779ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    length = 0;
14789ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    offset = 0;
1479337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14809ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    prevpos = hash->head[hashval];
14819ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    hashpos = hash->chain[prevpos];
1482337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14839ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];
1484337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14859ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    /*search for the longest string*/
14869ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    for(;;)
14879ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
14889ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      /*stop when went completely around the circular buffer*/
14899ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(prevpos < wpos && hashpos > prevpos && hashpos <= wpos) break;
14909ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(prevpos > wpos && (hashpos <= wpos || hashpos > prevpos)) break;
14919ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(chainlength++ >= maxchainlength) break;
1492337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
14939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      current_offset = hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize;
14949ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(current_offset > 0)
14959ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      {
14969ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        /*test the next characters*/
14979ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        foreptr = &in[pos];
14989ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        backptr = &in[pos - current_offset];
1499337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
15009ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/
15019ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        if(usezeros && hashval == 0 && hash->val[hashpos] == 0 /*hashval[hashpos] may be out of date*/)
15029ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        {
15039ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          unsigned skip = hash->zeros[hashpos];
15049ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          if(skip > numzeros) skip = numzeros;
15059ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          backptr += skip;
15069ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          foreptr += skip;
1507337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1508337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
15099ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/
1510337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
15119ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          ++backptr;
15129ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          ++foreptr;
1513337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
15149ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        current_length = (unsigned)(foreptr - &in[pos]);
15159ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne
15169ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        if(current_length > length)
1517337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
15189ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          length = current_length; /*the longest length*/
15199ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          offset = current_offset; /*the offset that is related to this longest length*/
15209ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          /*jump out once a length of max length is found (speed gain). This also jumps
15219ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/
15229ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          if(current_length >= nicematch) break;
1523337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1524337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1525337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
15269ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(hashpos == hash->chain[hashpos]) break;
15279ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne
15289ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      prevpos = hashpos;
15299ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      hashpos = hash->chain[hashpos];
15309ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
15319ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne
15329ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(lazymatching)
15339ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
15349ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH)
1535337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
15369ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        lazy = 1;
15379ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        lazylength = length;
15389ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        lazyoffset = offset;
15399ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        continue; /*try the next byte*/
1540337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
15419ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(lazy)
1542337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
15439ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        lazy = 0;
15449ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        if(pos == 0) ERROR_BREAK(81);
15459ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        if(length > lazylength + 1)
15469ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        {
15479ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          /*push the previous character as literal*/
15489ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
15499ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        }
15509ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        else
15519ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        {
15529ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          length = lazylength;
15539ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          offset = lazyoffset;
15549ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
15559ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          pos--;
15569ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        }
1557337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
15589ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
15599ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
15609ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne
15619ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    /*encode it as length/distance pair or literal value*/
15629ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/
15639ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
15649ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
15659ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
15669ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    else if(length < minmatch || (length == 3 && offset > 4096))
15679ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
15689ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      /*compensate for the fact that longer offsets have more extra bits, a
15699ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      length of only 3 may be not worth it then*/
15709ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
15719ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
15729ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    else
15739ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    {
15749ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      addLengthDistance(out, length, offset);
15759ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      for(i = 1; i < length; i++)
1576337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
15779ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        pos++;
15789ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        wpos = pos & (windowsize - 1);
15799ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        hashval = getHash(in, insize, pos);
15809ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        updateHashChain(hash, wpos, hashval);
15819ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        if(usezeros && hashval == 0)
1582337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
15839ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          if (numzeros == 0) numzeros = countZeros(in, insize, pos);
15849ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          else if (pos + numzeros >= insize || in[pos + numzeros - 1] != 0) numzeros--;
15859ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          hash->zeros[wpos] = numzeros;
15869ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        }
15879ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        else
15889ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        {
15899ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          numzeros = 0;
1590337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1591337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
15929ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    }
15939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  } /*end of the loop through each character of input*/
1594337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1595337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1596337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1597337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1598337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* /////////////////////////////////////////////////////////////////////////// */
1599337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1600337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize)
1601337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1602337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte,
1603337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/
1604337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1605337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i, j, numdeflateblocks = (datasize + 65534) / 65535;
1606337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned datapos = 0;
1607337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < numdeflateblocks; i++)
1608337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1609337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned BFINAL, BTYPE, LEN, NLEN;
1610337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char firstbyte;
1611337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1612337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    BFINAL = (i == numdeflateblocks - 1);
1613337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    BTYPE = 0;
1614337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1615337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1));
1616337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(out, firstbyte);
1617337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1618337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    LEN = 65535;
1619337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos;
1620337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    NLEN = 65535 - LEN;
1621337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1622337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(out, (unsigned char)(LEN % 256));
1623337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(out, (unsigned char)(LEN / 256));
1624337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(out, (unsigned char)(NLEN % 256));
1625337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(out, (unsigned char)(NLEN / 256));
1626337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1627337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Decompressed data*/
1628337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(j = 0; j < 65535 && datapos < datasize; j++)
1629337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1630337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(out, data[datapos++]);
1631337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1632337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1633337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1634337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
1635337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1636337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1637337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
1638337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennewrite the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees.
1639337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetree_ll: the tree for lit and len codes.
1640337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetree_d: the tree for distance codes.
1641337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
1642337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded,
1643337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                          const HuffmanTree* tree_ll, const HuffmanTree* tree_d)
1644337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1645337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i = 0;
1646337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < lz77_encoded->size; i++)
1647337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1648337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned val = lz77_encoded->data[i];
1649337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val));
1650337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(val > 256) /*for a length code, 3 more things have to be added*/
1651337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1652337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned length_index = val - FIRST_LENGTH_CODE_INDEX;
1653337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned n_length_extra_bits = LENGTHEXTRA[length_index];
1654337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned length_extra_bits = lz77_encoded->data[++i];
1655337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1656337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned distance_code = lz77_encoded->data[++i];
1657337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1658337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned distance_index = distance_code;
1659337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index];
1660337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned distance_extra_bits = lz77_encoded->data[++i];
1661337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1662337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits);
1663337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code),
1664337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                       HuffmanTree_getLength(tree_d, distance_code));
1665337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits);
1666337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1667337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1668337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1669337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1670337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/
1671337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash,
1672337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               const unsigned char* data, size_t datapos, size_t dataend,
1673337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               const LodePNGCompressSettings* settings, int final)
1674337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1675337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
1676337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1677337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
1678337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  A block is compressed as follows: The PNG data is lz77 encoded, resulting in
1679337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  literal bytes and length/distance pairs. This is then huffman compressed with
1680337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  two huffman trees. One huffman tree is used for the lit and len values ("ll"),
1681337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  another huffman tree is used for the dist values ("d"). These two trees are
1682337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  stored using their code lengths, and to compress even more these code lengths
1683337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  are also run-length encoded and huffman compressed. This gives a huffman tree
1684337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  of code lengths "cl". The code lenghts used to describe this third tree are
1685337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  the code length code lengths ("clcl").
1686337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
1687337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1688337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/
1689337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector lz77_encoded;
1690337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_ll; /*tree for lit,len values*/
1691337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_d; /*tree for distance codes*/
1692337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/
1693337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector frequencies_ll; /*frequency of lit,len codes*/
1694337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector frequencies_d; /*frequency of dist codes*/
1695337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector frequencies_cl; /*frequency of code length codes*/
1696337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/
1697337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/
1698337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*bitlen_cl is the code length code lengths ("clcl"). The bit lengths of codes to represent tree_cl
1699337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (these are written as is in the file, it would be crazy to compress these using yet another huffman
1700337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree that needs to be represented by yet another set of code lengths)*/
1701337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector bitlen_cl;
1702337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t datasize = dataend - datapos;
1703337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1704337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
1705337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Due to the huffman compression of huffman tree representations ("two levels"), there are some anologies:
1706337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  bitlen_lld is to tree_cl what data is to tree_ll and tree_d.
1707337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  bitlen_lld_e is to bitlen_lld what lz77_encoded is to data.
1708337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded.
1709337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
1710337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1711337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned BFINAL = final;
1712337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t numcodes_ll, numcodes_d, i;
1713337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned HLIT, HDIST, HCLEN;
1714337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1715337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&lz77_encoded);
1716337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_ll);
1717337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_d);
1718337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_cl);
1719337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&frequencies_ll);
1720337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&frequencies_d);
1721337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&frequencies_cl);
1722337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&bitlen_lld);
1723337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&bitlen_lld_e);
1724337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_init(&bitlen_cl);
1725337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1726337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*This while loop never loops due to a break at the end, it is here to
1727337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  allow breaking out of it to the cleanup phase on error conditions.*/
1728337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!error)
1729337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1730337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(settings->use_lz77)
1731337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1732337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
1733337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         settings->minmatch, settings->nicematch, settings->lazymatching);
1734337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
1735337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1736337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
1737337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1738337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/);
1739337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = datapos; i < dataend; i++) lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/
1740337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1741337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1742337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/);
1743337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/);
1744337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1745337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Count the frequencies of lit, len and dist codes*/
1746337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < lz77_encoded.size; i++)
1747337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1748337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned symbol = lz77_encoded.data[i];
1749337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      frequencies_ll.data[symbol]++;
1750337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(symbol > 256)
1751337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1752337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned dist = lz77_encoded.data[i + 2];
1753337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        frequencies_d.data[dist]++;
1754337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        i += 3;
1755337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1756337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1757337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/
1758337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1759337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/
1760337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15);
1761337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
1762337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/
1763337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15);
1764337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
1765337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1766337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286;
1767337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30;
1768337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*store the code lengths of both generated trees in bitlen_lld*/
1769337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numcodes_ll; i++) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i));
1770337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numcodes_d; i++) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i));
1771337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1772337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times),
1773337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    17 (3-10 zeroes), 18 (11-138 zeroes)*/
1774337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < (unsigned)bitlen_lld.size; i++)
1775337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1776337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned j = 0; /*amount of repititions*/
1777337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) j++;
1778337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1779337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/
1780337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1781337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        j++; /*include the first zero*/
1782337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(j <= 10) /*repeat code 17 supports max 10 zeroes*/
1783337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1784337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, 17);
1785337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, j - 3);
1786337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1787337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else /*repeat code 18 supports max 138 zeroes*/
1788337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1789337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(j > 138) j = 138;
1790337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, 18);
1791337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, j - 11);
1792337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1793337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        i += (j - 1);
1794337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1795337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else if(j >= 3) /*repeat code for value other than zero*/
1796337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1797337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        size_t k;
1798337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned num = j / 6, rest = j % 6;
1799337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);
1800337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(k = 0; k < num; k++)
1801337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1802337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, 16);
1803337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, 6 - 3);
1804337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1805337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(rest >= 3)
1806337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
1807337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, 16);
1808337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          uivector_push_back(&bitlen_lld_e, rest - 3);
1809337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
1810337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else j -= rest;
1811337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        i += j;
1812337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1813337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else /*too short to benefit from repeat code*/
1814337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
1815337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);
1816337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
1817337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1818337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1819337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*generate tree_cl, the huffmantree of huffmantrees*/
1820337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1821337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/);
1822337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < bitlen_lld_e.size; i++)
1823337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1824337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      frequencies_cl.data[bitlen_lld_e.data[i]]++;
1825337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*after a repeat code come the bits that specify the number of repetitions,
1826337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      those don't need to be in the frequencies_cl calculation*/
1827337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(bitlen_lld_e.data[i] >= 16) i++;
1828337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1829337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1830337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data,
1831337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                            frequencies_cl.size, frequencies_cl.size, 7);
1832337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
1833337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1834337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/);
1835337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < tree_cl.numcodes; i++)
1836337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1837337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*lenghts of code length tree is in the order as specified by deflate*/
1838337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]);
1839337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1840337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4)
1841337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1842337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*remove zeros at the end, but minimum size must be 4*/
1843337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/);
1844337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1845337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
1846337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1847337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*
1848337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    Write everything into the output
1849337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1850337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    After the BFINAL and BTYPE, the dynamic block consists out of the following:
1851337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN
1852337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    - (HCLEN+4)*3 bits code lengths of code length alphabet
1853337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length
1854337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      alphabet, + possible repetition codes 16, 17, 18)
1855337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    - HDIST + 1 code lengths of distance alphabet (encoded using the code length
1856337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      alphabet, + possible repetition codes 16, 17, 18)
1857337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    - compressed data
1858337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    - 256 (end code)
1859337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    */
1860337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1861337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Write block type*/
1862337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addBitToStream(bp, out, BFINAL);
1863337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addBitToStream(bp, out, 0); /*first bit of BTYPE "dynamic"*/
1864337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addBitToStream(bp, out, 1); /*second bit of BTYPE "dynamic"*/
1865337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1866337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*write the HLIT, HDIST and HCLEN values*/
1867337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    HLIT = (unsigned)(numcodes_ll - 257);
1868337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    HDIST = (unsigned)(numcodes_d - 1);
1869337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    HCLEN = (unsigned)bitlen_cl.size - 4;
1870337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/
1871337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) HCLEN--;
1872337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addBitsToStream(bp, out, HLIT, 5);
1873337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addBitsToStream(bp, out, HDIST, 5);
1874337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addBitsToStream(bp, out, HCLEN, 4);
1875337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1876337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*write the code lenghts of the code length alphabet*/
1877337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < HCLEN + 4; i++) addBitsToStream(bp, out, bitlen_cl.data[i], 3);
1878337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1879337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*write the lenghts of the lit/len AND the dist alphabet*/
1880337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < bitlen_lld_e.size; i++)
1881337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1882337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]),
1883337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                       HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i]));
1884337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*extra bits of repeat codes*/
1885337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2);
1886337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3);
1887337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7);
1888337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1889337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1890337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*write the compressed data symbols*/
1891337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
1892337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: the length of the end code 256 must be larger than 0*/
1893337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64);
1894337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1895337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*write the end code*/
1896337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));
1897337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1898337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    break; /*end of error-while*/
1899337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1900337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1901337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*cleanup*/
1902337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&lz77_encoded);
1903337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_ll);
1904337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_d);
1905337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_cl);
1906337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&frequencies_ll);
1907337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&frequencies_d);
1908337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&frequencies_cl);
1909337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&bitlen_lld_e);
1910337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&bitlen_lld);
1911337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  uivector_cleanup(&bitlen_cl);
1912337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1913337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1914337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1915337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1916337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash,
1917337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             const unsigned char* data,
1918337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             size_t datapos, size_t dataend,
1919337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             const LodePNGCompressSettings* settings, int final)
1920337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1921337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_ll; /*tree for literal values and length codes*/
1922337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree tree_d; /*tree for distance codes*/
1923337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1924337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned BFINAL = final;
1925337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
1926337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
1927337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1928337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_ll);
1929337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_init(&tree_d);
1930337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1931337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  generateFixedLitLenTree(&tree_ll);
1932337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  generateFixedDistanceTree(&tree_d);
1933337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1934337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  addBitToStream(bp, out, BFINAL);
1935337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  addBitToStream(bp, out, 1); /*first bit of BTYPE*/
1936337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  addBitToStream(bp, out, 0); /*second bit of BTYPE*/
1937337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1938337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->use_lz77) /*LZ77 encoded*/
1939337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1940337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    uivector lz77_encoded;
1941337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    uivector_init(&lz77_encoded);
1942337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
1943337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                       settings->minmatch, settings->nicematch, settings->lazymatching);
1944337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
1945337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    uivector_cleanup(&lz77_encoded);
1946337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1947337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*no LZ77, but still will be Huffman compressed*/
1948337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1949337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = datapos; i < dataend; i++)
1950337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
1951337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i]));
1952337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
1953337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1954337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*add END code*/
1955337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));
1956337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1957337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*cleanup*/
1958337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_ll);
1959337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  HuffmanTree_cleanup(&tree_d);
1960337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1961337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
1962337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
1963337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1964337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize,
1965337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                 const LodePNGCompressSettings* settings)
1966337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
1967337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
1968337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i, blocksize, numdeflateblocks;
1969337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t bp = 0; /*the bit pointer*/
1970337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Hash hash;
1971337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1972337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->btype > 2) return 61;
1973337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(settings->btype == 0) return deflateNoCompression(out, in, insize);
1974337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(settings->btype == 1) blocksize = insize;
1975337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*if(settings->btype == 2)*/
1976337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1977337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    blocksize = insize / 8 + 8;
1978337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(blocksize < 65535) blocksize = 65535;
1979337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1980337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1981337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  numdeflateblocks = (insize + blocksize - 1) / blocksize;
1982337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(numdeflateblocks == 0) numdeflateblocks = 1;
1983337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1984337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = hash_init(&hash, settings->windowsize);
1985337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(error) return error;
1986337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1987337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < numdeflateblocks && !error; i++)
1988337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
1989337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    int final = i == numdeflateblocks - 1;
1990337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t start = i * blocksize;
1991337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t end = start + blocksize;
1992337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(end > insize) end = insize;
1993337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1994337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final);
1995337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final);
1996337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
1997337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
1998337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  hash_cleanup(&hash);
1999337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2000337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
2001337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2002337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2003337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_deflate(unsigned char** out, size_t* outsize,
2004337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         const unsigned char* in, size_t insize,
2005337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         const LodePNGCompressSettings* settings)
2006337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2007337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error;
2008337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector v;
2009337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init_buffer(&v, *out, *outsize);
2010337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = lodepng_deflatev(&v, in, insize, settings);
2011337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = v.data;
2012337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = v.size;
2013337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
2014337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2015337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2016337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned deflate(unsigned char** out, size_t* outsize,
2017337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        const unsigned char* in, size_t insize,
2018337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        const LodePNGCompressSettings* settings)
2019337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2020337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->custom_deflate)
2021337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2022337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return settings->custom_deflate(out, outsize, in, insize, settings);
2023337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2024337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
2025337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2026337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return lodepng_deflate(out, outsize, in, insize, settings);
2027337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2028337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2029337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2030337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
2031337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2032337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2033337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Adler32                                                                  */
2034337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2035337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2036337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len)
2037337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2038337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne   unsigned s1 = adler & 0xffff;
2039337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne   unsigned s2 = (adler >> 16) & 0xffff;
2040337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2041337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(len > 0)
2042337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2043337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*at least 5550 sums can be done before the sums overflow, saving a lot of module divisions*/
2044337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned amount = len > 5550 ? 5550 : len;
2045337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    len -= amount;
2046337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    while(amount > 0)
2047337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
2048337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      s1 += (*data++);
2049337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      s2 += s1;
2050337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      amount--;
2051337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
2052337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    s1 %= 65521;
2053337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    s2 %= 65521;
2054337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2055337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2056337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (s2 << 16) | s1;
2057337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2058337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2059337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Return the adler32 of the bytes data[0..len-1]*/
2060337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned adler32(const unsigned char* data, unsigned len)
2061337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2062337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return update_adler32(1L, data, len);
2063337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2064337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2065337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2066337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Zlib                                                                   / */
2067337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2068337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2069337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
2070337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2071337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
2072337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                 size_t insize, const LodePNGDecompressSettings* settings)
2073337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2074337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
2075337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned CM, CINFO, FDICT;
2076337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2077337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(insize < 2) return 53; /*error, size of zlib data too small*/
2078337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*read information from zlib header*/
2079337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if((in[0] * 256 + in[1]) % 31 != 0)
2080337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2081337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/
2082337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return 24;
2083337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2084337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2085337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CM = in[0] & 15;
2086337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CINFO = (in[0] >> 4) & 15;
2087337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/
2088337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  FDICT = (in[1] >> 5) & 1;
2089337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/
2090337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2091337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(CM != 8 || CINFO > 7)
2092337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2093337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/
2094337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return 25;
2095337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2096337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(FDICT != 0)
2097337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2098337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: the specification of PNG says about the zlib stream:
2099337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      "The additional flags shall not specify a preset dictionary."*/
2100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return 26;
2101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = inflate(out, outsize, in + 2, insize - 2, settings);
2104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(error) return error;
2105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!settings->ignore_adler32)
2107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]);
2109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned checksum = adler32(*out, (unsigned)(*outsize));
2110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/
2111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*no error*/
2114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
2117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                size_t insize, const LodePNGDecompressSettings* settings)
2118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->custom_zlib)
21209ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  {
2121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return settings->custom_zlib(out, outsize, in, insize, settings);
21229ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  }
2123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
21249ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  {
2125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return lodepng_zlib_decompress(out, outsize, in, insize, settings);
21269ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  }
2127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
2130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
2132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
2134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               size_t insize, const LodePNGCompressSettings* settings)
2135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*initially, *out must be NULL and outsize 0, if you just give some random *out
2137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  that's pointing to a non allocated buffer, this'll crash*/
2138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector outv;
2139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error;
2141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* deflatedata = 0;
2142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t deflatesize = 0;
2143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned ADLER32;
2145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/
2146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/
2147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned FLEVEL = 0;
2148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned FDICT = 0;
2149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64;
2150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned FCHECK = 31 - CMFFLG % 31;
2151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CMFFLG += FCHECK;
2152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*ucvector-controlled version of the output buffer, for dynamic array*/
2154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init_buffer(&outv, *out, *outsize);
2155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256));
2157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256));
2158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = deflate(&deflatedata, &deflatesize, in, insize, settings);
2160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error)
2162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2163337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ADLER32 = adler32(in, (unsigned)insize);
2164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < deflatesize; i++) ucvector_push_back(&outv, deflatedata[i]);
2165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(deflatedata);
2166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_add32bitInt(&outv, ADLER32);
2167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = outv.data;
2170337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = outv.size;
2171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
2173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* compress using the default or custom zlib function */
2176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
2177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              size_t insize, const LodePNGCompressSettings* settings)
2178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->custom_zlib)
2180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return settings->custom_zlib(out, outsize, in, insize, settings);
2182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
2184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return lodepng_zlib_compress(out, outsize, in, insize, settings);
2186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
2190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#else /*no LODEPNG_COMPILE_ZLIB*/
2192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
2194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
2195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                size_t insize, const LodePNGDecompressSettings* settings)
2196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if (!settings->custom_zlib) return 87; /*no custom zlib function provided */
2198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return settings->custom_zlib(out, outsize, in, insize, settings);
2199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
2201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
2202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
2203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              size_t insize, const LodePNGCompressSettings* settings)
2204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if (!settings->custom_zlib) return 87; /*no custom zlib function provided */
2206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return settings->custom_zlib(out, outsize, in, insize, settings);
2207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
2209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ZLIB*/
2211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
2215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*this is a good tradeoff between speed and compression ratio*/
2217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#define DEFAULT_WINDOWSIZE 2048
2218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_compress_settings_init(LodePNGCompressSettings* settings)
2220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/
2222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->btype = 2;
2223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->use_lz77 = 1;
2224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->windowsize = DEFAULT_WINDOWSIZE;
2225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->minmatch = 3;
2226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->nicematch = 128;
2227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->lazymatching = 1;
2228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->custom_zlib = 0;
2230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->custom_deflate = 0;
2231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->custom_context = 0;
2232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneconst LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0};
2235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
2238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
2240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_decompress_settings_init(LodePNGDecompressSettings* settings)
2242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->ignore_adler32 = 0;
2244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->custom_zlib = 0;
2246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->custom_inflate = 0;
2247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->custom_context = 0;
2248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneconst LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0};
2251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
2253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* // End of Zlib related code. Begin of PNG related code.                 // */
2257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_PNG
2261337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2262337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2263337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / CRC32                                                                  / */
2264337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2265337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
22669ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne/* CRC polynomial: 0xedb88320 */
22679ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevennestatic unsigned lodepng_crc32_table[256] = {
22689ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne           0u, 1996959894u, 3993919788u, 2567524794u,  124634137u, 1886057615u, 3915621685u, 2657392035u,
22699ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   249268274u, 2044508324u, 3772115230u, 2547177864u,  162941995u, 2125561021u, 3887607047u, 2428444049u,
22709ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   498536548u, 1789927666u, 4089016648u, 2227061214u,  450548861u, 1843258603u, 4107580753u, 2211677639u,
22719ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   325883990u, 1684777152u, 4251122042u, 2321926636u,  335633487u, 1661365465u, 4195302755u, 2366115317u,
22729ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
22739ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   901097722u, 1119000684u, 3686517206u, 2898065728u,  853044451u, 1172266101u, 3705015759u, 2882616665u,
22749ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   651767980u, 1373503546u, 3369554304u, 3218104598u,  565507253u, 1454621731u, 3485111705u, 3099436303u,
22759ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne   671266974u, 1594198024u, 3322730930u, 2970347812u,  795835527u, 1483230225u, 3244367275u, 3060149565u,
22769ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1994146192u,   31158534u, 2563907772u, 4023717930u, 1907459465u,  112637215u, 2680153253u, 3904427059u,
22779ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2013776290u,  251722036u, 2517215374u, 3775830040u, 2137656763u,  141376813u, 2439277719u, 3865271297u,
22789ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1802195444u,  476864866u, 2238001368u, 4066508878u, 1812370925u,  453092731u, 2181625025u, 4111451223u,
22799ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1706088902u,  314042704u, 2344532202u, 4240017532u, 1658658271u,  366619977u, 2362670323u, 4224994405u,
22809ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1303535960u,  984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,
22819ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1131014506u,  879679996u, 2909243462u, 3663771856u, 1141124467u,  855842277u, 2852801631u, 3708648649u,
22829ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1342533948u,  654459306u, 3188396048u, 3373015174u, 1466479909u,  544179635u, 3110523913u, 3462522015u,
22839ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  1591671054u,  702138776u, 2966460450u, 3352799412u, 1504918807u,  783551873u, 3082640443u, 3233442989u,
22849ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3988292384u, 2596254646u,   62317068u, 1957810842u, 3939845945u, 2647816111u,   81470997u, 1943803523u,
22859ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3814918930u, 2489596804u,  225274430u, 2053790376u, 3826175755u, 2466906013u,  167816743u, 2097651377u,
22869ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  4027552580u, 2265490386u,  503444072u, 1762050814u, 4150417245u, 2154129355u,  426522225u, 1852507879u,
22879ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  4275313526u, 2312317920u,  282753626u, 1742555852u, 4189708143u, 2394877945u,  397917763u, 1622183637u,
22889ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3604390888u, 2714866558u,  953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,
22899ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3624741850u, 2936675148u,  906185462u, 1090812512u, 3747672003u, 2825379669u,  829329135u, 1181335161u,
22909ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3412177804u, 3160834842u,  628085408u, 1382605366u, 3423369109u, 3138078467u,  570562233u, 1426400815u,
22919ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3317316542u, 2998733608u,  733239954u, 1555261956u, 3268935591u, 3050360625u,  752459403u, 1541320221u,
22929ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2607071920u, 3965973030u, 1969922972u,   40735498u, 2617837225u, 3943577151u, 1913087877u,   83908371u,
22939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2512341634u, 3803740692u, 2075208622u,  213261112u, 2463272603u, 3855990285u, 2094854071u,  198958881u,
22949ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2262029012u, 4057260610u, 1759359992u,  534414190u, 2176718541u, 4139329115u, 1873836001u,  414664567u,
22959ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2282248934u, 4279200368u, 1711684554u,  285281116u, 2405801727u, 4167216745u, 1634467795u,  376229701u,
22969ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2685067896u, 3608007406u, 1308918612u,  956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,
22979ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  2932959818u, 3654703836u, 1088359270u,  936918000u, 2847714899u, 3736837829u, 1202900863u,  817233897u,
22989ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3183342108u, 3401237130u, 1404277552u,  615818150u, 3134207493u, 3453421203u, 1423857449u,  601450431u,
22999ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  3009837614u, 3294710456u, 1567103746u,  711928724u, 3020668471u, 3272380065u, 1510334235u,  755167117u
23009ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne};
2301337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
23029ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne/*Return the CRC of the bytes buf[0..len-1].*/
23039ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenneunsigned lodepng_crc32(const unsigned char* buf, size_t len)
2304337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
23059ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned c = 0xffffffffL;
2306337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t n;
2307337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2308337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(n = 0; n < len; n++)
2309337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
23109ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    c = lodepng_crc32_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
2311337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
23129ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  return c ^ 0xffffffffL;
2313337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2314337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2315337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2316337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Reading and writing single bits and bytes from/to stream for LodePNG   / */
2317337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2318337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2319337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream)
2320337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2321337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);
2322337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*bitpointer)++;
2323337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return result;
2324337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2325337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2326337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)
2327337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2328337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned result = 0;
2329337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2330337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = nbits - 1; i < nbits; i--)
2331337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2332337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i;
2333337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2334337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return result;
2335337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2336337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2337337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
2338337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)
2339337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2340337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*the current bit in bitstream must be 0 for this to work*/
2341337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(bit)
2342337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2343337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/
2344337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7)));
2345337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2346337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*bitpointer)++;
2347337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2348337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
2349337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2350337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)
2351337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2352337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*the current bit in bitstream may be 0 or 1 for this to work*/
2353337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(bit == 0) bitstream[(*bitpointer) >> 3] &=  (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7))));
2354337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else         bitstream[(*bitpointer) >> 3] |=  (1 << (7 - ((*bitpointer) & 0x7)));
2355337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*bitpointer)++;
2356337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2357337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2358337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2359337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / PNG chunks                                                             / */
2360337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2361337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2362337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_chunk_length(const unsigned char* chunk)
2363337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2364337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_read32bitInt(&chunk[0]);
2365337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2366337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2367337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_chunk_type(char type[5], const unsigned char* chunk)
2368337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2369337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
2370337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 4; i++) type[i] = chunk[4 + i];
2371337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  type[4] = 0; /*null termination char*/
2372337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2373337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2374337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type)
2375337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2376337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(strlen(type) != 4) return 0;
2377337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);
2378337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2379337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2380337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned char lodepng_chunk_ancillary(const unsigned char* chunk)
2381337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2382337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return((chunk[4] & 32) != 0);
2383337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2384337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2385337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned char lodepng_chunk_private(const unsigned char* chunk)
2386337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2387337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return((chunk[6] & 32) != 0);
2388337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2389337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2390337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk)
2391337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2392337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return((chunk[7] & 32) != 0);
2393337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2394337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2395337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned char* lodepng_chunk_data(unsigned char* chunk)
2396337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2397337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return &chunk[8];
2398337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2399337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2400337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk)
2401337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2402337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return &chunk[8];
2403337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2404337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2405337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_chunk_check_crc(const unsigned char* chunk)
2406337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2407337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned length = lodepng_chunk_length(chunk);
2408337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]);
2409337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*the CRC is taken of the data and the 4 chunk type letters, not the length*/
2410337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned checksum = lodepng_crc32(&chunk[4], length + 4);
2411337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(CRC != checksum) return 1;
2412337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else return 0;
2413337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2414337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2415337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_chunk_generate_crc(unsigned char* chunk)
2416337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2417337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned length = lodepng_chunk_length(chunk);
2418337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned CRC = lodepng_crc32(&chunk[4], length + 4);
2419337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_set32bitInt(chunk + 8 + length, CRC);
2420337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2421337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2422337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned char* lodepng_chunk_next(unsigned char* chunk)
2423337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2424337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
2425337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return &chunk[total_chunk_length];
2426337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2427337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2428337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk)
2429337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2430337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
2431337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return &chunk[total_chunk_length];
2432337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2433337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2434337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk)
2435337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2436337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
2437337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
2438337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char *chunk_start, *new_buffer;
2439337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t new_length = (*outlength) + total_chunk_length;
2440337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/
2441337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2442337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
2443337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!new_buffer) return 83; /*alloc fail*/
2444337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*out) = new_buffer;
2445337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*outlength) = new_length;
2446337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk_start = &(*out)[new_length - total_chunk_length];
2447337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2448337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < total_chunk_length; i++) chunk_start[i] = chunk[i];
2449337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2450337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2451337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2452337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2453337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
2454337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              const char* type, const unsigned char* data)
2455337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2456337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
2457337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char *chunk, *new_buffer;
2458337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t new_length = (*outlength) + length + 12;
2459337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/
2460337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
2461337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!new_buffer) return 83; /*alloc fail*/
2462337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*out) = new_buffer;
2463337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  (*outlength) = new_length;
2464337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk = &(*out)[(*outlength) - length - 12];
2465337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2466337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*1: length*/
2467337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_set32bitInt(chunk, (unsigned)length);
2468337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2469337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*2: chunk name (4 letters)*/
2470337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk[4] = type[0];
2471337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk[5] = type[1];
2472337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk[6] = type[2];
2473337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk[7] = type[3];
2474337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2475337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*3: the data*/
2476337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < length; i++) chunk[8 + i] = data[i];
2477337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2478337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*4: CRC (of the chunkname characters and the data)*/
2479337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_chunk_generate_crc(chunk);
2480337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2481337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2482337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2483337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2484337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2485337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / Color types and such                                                   / */
2486337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2487337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2488337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*return type is a LodePNG error code*/
2489337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/
2490337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2491337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  switch(colortype)
2492337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2493337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/
2494337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 2: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*RGB*/
2495337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8            )) return 37; break; /*palette*/
2496337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 4: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/
2497337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 6: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*RGBA*/
2498337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    default: return 31;
2499337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2500337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*allowed color type / bits combination*/
2501337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2502337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2503337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getNumColorChannels(LodePNGColorType colortype)
2504337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2505337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  switch(colortype)
2506337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2507337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 0: return 1; /*grey*/
2508337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 2: return 3; /*RGB*/
2509337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 3: return 1; /*palette*/
2510337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 4: return 2; /*grey + alpha*/
2511337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 6: return 4; /*RGBA*/
2512337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2513337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*unexisting color type*/
2514337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2515337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2516337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth)
2517337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2518337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*bits per pixel is amount of channels * bits per channel*/
2519337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return getNumColorChannels(colortype) * bitdepth;
2520337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2521337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2522337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2523337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2524337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_color_mode_init(LodePNGColorMode* info)
2525337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2526337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->key_defined = 0;
2527337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->key_r = info->key_g = info->key_b = 0;
2528337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->colortype = LCT_RGBA;
2529337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->bitdepth = 8;
2530337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palette = 0;
2531337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palettesize = 0;
2532337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2533337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2534337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_color_mode_cleanup(LodePNGColorMode* info)
2535337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2536337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_palette_clear(info);
2537337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2538337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2539337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source)
2540337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2541337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2542337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_cleanup(dest);
2543337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *dest = *source;
2544337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(source->palette)
2545337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2546337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    dest->palette = (unsigned char*)lodepng_malloc(1024);
2547337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!dest->palette && source->palettesize) return 83; /*alloc fail*/
2548337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < source->palettesize * 4; i++) dest->palette[i] = source->palette[i];
2549337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2550337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2551337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2552337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2553337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b)
2554337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2555337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2556337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(a->colortype != b->colortype) return 0;
2557337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(a->bitdepth != b->bitdepth) return 0;
2558337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(a->key_defined != b->key_defined) return 0;
2559337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(a->key_defined)
2560337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2561337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(a->key_r != b->key_r) return 0;
2562337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(a->key_g != b->key_g) return 0;
2563337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(a->key_b != b->key_b) return 0;
2564337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2565337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(a->palettesize != b->palettesize) return 0;
2566337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < a->palettesize * 4; i++)
2567337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2568337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(a->palette[i] != b->palette[i]) return 0;
2569337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2570337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 1;
2571337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2572337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2573337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_palette_clear(LodePNGColorMode* info)
2574337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2575337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->palette) lodepng_free(info->palette);
2576337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palette = 0;
2577337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palettesize = 0;
2578337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2579337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2580337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_palette_add(LodePNGColorMode* info,
2581337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             unsigned char r, unsigned char g, unsigned char b, unsigned char a)
2582337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2583337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* data;
2584337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with
2585337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  the max of 256 colors, it'll have the exact alloc size*/
2586337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!info->palette) /*allocate palette if empty*/
2587337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2588337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*room for 256 colors with 4 bytes each*/
2589337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    data = (unsigned char*)lodepng_realloc(info->palette, 1024);
2590337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!data) return 83; /*alloc fail*/
2591337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else info->palette = data;
2592337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2593337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palette[4 * info->palettesize + 0] = r;
2594337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palette[4 * info->palettesize + 1] = g;
2595337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palette[4 * info->palettesize + 2] = b;
2596337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palette[4 * info->palettesize + 3] = a;
2597337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->palettesize++;
2598337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2599337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2600337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2601337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_get_bpp(const LodePNGColorMode* info)
2602337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2603337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*calculate bits per pixel out of colortype and bitdepth*/
2604337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_get_bpp_lct(info->colortype, info->bitdepth);
2605337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2606337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2607337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_get_channels(const LodePNGColorMode* info)
2608337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2609337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return getNumColorChannels(info->colortype);
2610337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2611337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2612337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_is_greyscale_type(const LodePNGColorMode* info)
2613337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2614337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA;
2615337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2616337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2617337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_is_alpha_type(const LodePNGColorMode* info)
2618337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2619337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (info->colortype & 4) != 0; /*4 or 6*/
2620337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2621337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2622337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_is_palette_type(const LodePNGColorMode* info)
2623337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2624337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return info->colortype == LCT_PALETTE;
2625337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2626337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2627337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_has_palette_alpha(const LodePNGColorMode* info)
2628337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2629337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2630337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < info->palettesize; i++)
2631337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2632337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info->palette[i * 4 + 3] < 255) return 1;
2633337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2634337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2635337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2636337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2637337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_can_have_alpha(const LodePNGColorMode* info)
2638337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2639337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return info->key_defined
2640337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      || lodepng_is_alpha_type(info)
2641337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      || lodepng_has_palette_alpha(info);
2642337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2643337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2644337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennesize_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color)
2645337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2646337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (w * h * lodepng_get_bpp(color) + 7) / 8;
2647337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2648337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2649337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennesize_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)
2650337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2651337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return (w * h * lodepng_get_bpp_lct(colortype, bitdepth) + 7) / 8;
2652337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2653337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2654337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
2655337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2656337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void LodePNGUnknownChunks_init(LodePNGInfo* info)
2657337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2658337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
2659337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 3; i++) info->unknown_chunks_data[i] = 0;
2660337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 3; i++) info->unknown_chunks_size[i] = 0;
2661337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2662337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2663337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void LodePNGUnknownChunks_cleanup(LodePNGInfo* info)
2664337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2665337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
2666337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 3; i++) lodepng_free(info->unknown_chunks_data[i]);
2667337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2668337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2669337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src)
2670337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2671337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
2672337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2673337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGUnknownChunks_cleanup(dest);
2674337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2675337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 3; i++)
2676337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2677337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t j;
2678337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    dest->unknown_chunks_size[i] = src->unknown_chunks_size[i];
2679337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]);
2680337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/
2681337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(j = 0; j < src->unknown_chunks_size[i]; j++)
2682337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
2683337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j];
2684337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
2685337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2686337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2687337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2688337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2689337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2690337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/******************************************************************************/
2691337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2692337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void LodePNGText_init(LodePNGInfo* info)
2693337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2694337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->text_num = 0;
2695337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->text_keys = NULL;
2696337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->text_strings = NULL;
2697337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2698337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2699337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void LodePNGText_cleanup(LodePNGInfo* info)
2700337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2701337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2702337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < info->text_num; i++)
2703337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2704337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string_cleanup(&info->text_keys[i]);
2705337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string_cleanup(&info->text_strings[i]);
2706337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2707337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(info->text_keys);
2708337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(info->text_strings);
2709337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2710337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2711337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source)
2712337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2713337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i = 0;
2714337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->text_keys = 0;
2715337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->text_strings = 0;
2716337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->text_num = 0;
2717337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < source->text_num; i++)
2718337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2719337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
2720337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2721337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2722337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2723337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2724337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_clear_text(LodePNGInfo* info)
2725337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2726337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGText_cleanup(info);
2727337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2728337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2729337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str)
2730337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2731337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1)));
2732337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1)));
2733337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!new_keys || !new_strings)
2734337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2735337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(new_keys);
2736337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(new_strings);
2737337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return 83; /*alloc fail*/
2738337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2739337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2740337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->text_num++;
2741337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->text_keys = new_keys;
2742337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->text_strings = new_strings;
2743337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2744337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_init(&info->text_keys[info->text_num - 1]);
2745337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_set(&info->text_keys[info->text_num - 1], key);
2746337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2747337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_init(&info->text_strings[info->text_num - 1]);
2748337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_set(&info->text_strings[info->text_num - 1], str);
2749337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2750337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2751337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2752337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2753337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/******************************************************************************/
2754337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2755337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void LodePNGIText_init(LodePNGInfo* info)
2756337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2757337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_num = 0;
2758337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_keys = NULL;
2759337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_langtags = NULL;
2760337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_transkeys = NULL;
2761337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_strings = NULL;
2762337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2763337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2764337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void LodePNGIText_cleanup(LodePNGInfo* info)
2765337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2766337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
2767337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < info->itext_num; i++)
2768337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2769337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string_cleanup(&info->itext_keys[i]);
2770337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string_cleanup(&info->itext_langtags[i]);
2771337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string_cleanup(&info->itext_transkeys[i]);
2772337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string_cleanup(&info->itext_strings[i]);
2773337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2774337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(info->itext_keys);
2775337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(info->itext_langtags);
2776337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(info->itext_transkeys);
2777337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(info->itext_strings);
2778337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2779337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2780337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source)
2781337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2782337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i = 0;
2783337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->itext_keys = 0;
2784337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->itext_langtags = 0;
2785337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->itext_transkeys = 0;
2786337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->itext_strings = 0;
2787337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->itext_num = 0;
2788337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < source->itext_num; i++)
2789337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2790337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
2791337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                        source->itext_transkeys[i], source->itext_strings[i]));
2792337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2793337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2794337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2795337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2796337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_clear_itext(LodePNGInfo* info)
2797337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2798337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGIText_cleanup(info);
2799337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2800337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2801337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,
2802337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                           const char* transkey, const char* str)
2803337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2804337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1)));
2805337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1)));
2806337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1)));
2807337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1)));
2808337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!new_keys || !new_langtags || !new_transkeys || !new_strings)
2809337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2810337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(new_keys);
2811337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(new_langtags);
2812337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(new_transkeys);
2813337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(new_strings);
2814337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return 83; /*alloc fail*/
2815337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2816337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2817337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_num++;
2818337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_keys = new_keys;
2819337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_langtags = new_langtags;
2820337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_transkeys = new_transkeys;
2821337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->itext_strings = new_strings;
2822337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2823337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_init(&info->itext_keys[info->itext_num - 1]);
2824337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_set(&info->itext_keys[info->itext_num - 1], key);
2825337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2826337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_init(&info->itext_langtags[info->itext_num - 1]);
2827337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_set(&info->itext_langtags[info->itext_num - 1], langtag);
2828337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2829337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_init(&info->itext_transkeys[info->itext_num - 1]);
2830337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_set(&info->itext_transkeys[info->itext_num - 1], transkey);
2831337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2832337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_init(&info->itext_strings[info->itext_num - 1]);
2833337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  string_set(&info->itext_strings[info->itext_num - 1], str);
2834337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2835337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2836337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2837337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
2838337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2839337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_info_init(LodePNGInfo* info)
2840337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2841337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_init(&info->color);
2842337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->interlace_method = 0;
2843337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->compression_method = 0;
2844337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->filter_method = 0;
2845337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
2846337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->background_defined = 0;
2847337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->background_r = info->background_g = info->background_b = 0;
2848337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2849337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGText_init(info);
2850337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGIText_init(info);
2851337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2852337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time_defined = 0;
2853337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->phys_defined = 0;
2854337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2855337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGUnknownChunks_init(info);
2856337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
2857337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2858337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2859337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_info_cleanup(LodePNGInfo* info)
2860337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2861337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_cleanup(&info->color);
2862337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
2863337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGText_cleanup(info);
2864337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGIText_cleanup(info);
2865337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2866337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGUnknownChunks_cleanup(info);
2867337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
2868337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2869337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2870337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source)
2871337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2872337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_cleanup(dest);
2873337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *dest = *source;
2874337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_init(&dest->color);
2875337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color));
2876337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2877337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
2878337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CERROR_TRY_RETURN(LodePNGText_copy(dest, source));
2879337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CERROR_TRY_RETURN(LodePNGIText_copy(dest, source));
2880337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2881337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGUnknownChunks_init(dest);
2882337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source));
2883337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
2884337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
2885337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2886337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2887337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_info_swap(LodePNGInfo* a, LodePNGInfo* b)
2888337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2889337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGInfo temp = *a;
2890337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *a = *b;
2891337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *b = temp;
2892337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2893337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2894337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
2895337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
28969ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/
2897337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in)
2898337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
28999ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/
2900337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/
29019ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned p = index & m;
2902337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  in &= (1 << bits) - 1; /*filter out any other bits of the input value*/
29039ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  in = in << (bits * (m - p));
2904337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(p == 0) out[index * bits / 8] = in;
2905337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else out[index * bits / 8] |= in;
2906337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2907337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2908337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct ColorTree ColorTree;
2909337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2910337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
2911337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneOne node of a color tree
2912337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThis is the data structure used to count the number of unique colors and to get a palette
2913337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneindex for a color. It's like an octree, but because the alpha channel is used too, each
2914337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennenode has 16 instead of 8 children.
2915337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
2916337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestruct ColorTree
2917337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2918337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/
2919337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int index; /*the payload. Only has a meaningful value if this is in the last level*/
2920337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne};
2921337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2922337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void color_tree_init(ColorTree* tree)
2923337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2924337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int i;
2925337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 16; i++) tree->children[i] = 0;
2926337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->index = -1;
2927337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2928337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2929337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void color_tree_cleanup(ColorTree* tree)
2930337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2931337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int i;
2932337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 16; i++)
2933337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2934337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(tree->children[i])
2935337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
2936337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      color_tree_cleanup(tree->children[i]);
2937337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      lodepng_free(tree->children[i]);
2938337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
2939337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2940337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2941337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2942337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*returns -1 if color not present, its index otherwise*/
2943337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
2944337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2945337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int bit = 0;
2946337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(bit = 0; bit < 8; bit++)
2947337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2948337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
2949337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!tree->children[i]) return -1;
2950337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else tree = tree->children[i];
2951337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2952337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return tree ? tree->index : -1;
2953337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2954337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2955337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
2956337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
2957337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2958337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return color_tree_get(tree, r, g, b, a) >= 0;
2959337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2960337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
2961337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2962337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*color is not allowed to already exist.
2963337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneIndex should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")*/
2964337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void color_tree_add(ColorTree* tree,
2965337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                           unsigned char r, unsigned char g, unsigned char b, unsigned char a, int index)
2966337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2967337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int bit;
2968337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(bit = 0; bit < 8; bit++)
2969337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2970337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
2971337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!tree->children[i])
2972337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
2973337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree));
2974337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      color_tree_init(tree->children[i]);
2975337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
2976337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    tree = tree->children[i];
2977337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2978337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  tree->index = index;
2979337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
2980337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
2981337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*put a pixel, given its RGBA color, into image of any color type*/
2982337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned rgba8ToPixel(unsigned char* out, size_t i,
2983337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             const LodePNGColorMode* mode, ColorTree* tree /*for palette*/,
2984337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             unsigned char r, unsigned char g, unsigned char b, unsigned char a)
2985337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
2986337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->colortype == LCT_GREY)
2987337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
2988337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/;
2989337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8) out[i] = grey;
2990337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = grey;
2991337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
2992337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
2993337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*take the most significant bits of grey*/
2994337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      grey = (grey >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1);
2995337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addColorBits(out, i, mode->bitdepth, grey);
2996337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
2997337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
2998337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGB)
2999337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3000337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3001337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3002337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 3 + 0] = r;
3003337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 3 + 1] = g;
3004337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 3 + 2] = b;
3005337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3006337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3007337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3008337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 6 + 0] = out[i * 6 + 1] = r;
3009337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 6 + 2] = out[i * 6 + 3] = g;
3010337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 6 + 4] = out[i * 6 + 5] = b;
3011337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3012337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3013337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_PALETTE)
3014337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3015337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    int index = color_tree_get(tree, r, g, b, a);
3016337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(index < 0) return 82; /*color not in palette*/
3017337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8) out[i] = index;
3018337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else addColorBits(out, i, mode->bitdepth, index);
3019337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3020337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_GREY_ALPHA)
3021337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3022337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/;
3023337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3024337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3025337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 2 + 0] = grey;
3026337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 2 + 1] = a;
3027337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3028337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(mode->bitdepth == 16)
3029337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3030337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 4 + 0] = out[i * 4 + 1] = grey;
3031337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 4 + 2] = out[i * 4 + 3] = a;
3032337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3033337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3034337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGBA)
3035337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3036337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3037337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3038337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 4 + 0] = r;
3039337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 4 + 1] = g;
3040337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 4 + 2] = b;
3041337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 4 + 3] = a;
3042337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3043337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3044337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3045337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 8 + 0] = out[i * 8 + 1] = r;
3046337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 8 + 2] = out[i * 8 + 3] = g;
3047337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 8 + 4] = out[i * 8 + 5] = b;
3048337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[i * 8 + 6] = out[i * 8 + 7] = a;
3049337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3050337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3051337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3052337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*no error*/
3053337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3054337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3055337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/
3056337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned rgba16ToPixel(unsigned char* out, size_t i,
3057337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              const LodePNGColorMode* mode,
3058337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              unsigned short r, unsigned short g, unsigned short b, unsigned short a)
3059337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3060337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->bitdepth != 16) return 85; /*must be 16 for this function*/
3061337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->colortype == LCT_GREY)
3062337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3063337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned short grey = r; /*((unsigned)r + g + b) / 3*/;
3064337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 2 + 0] = (grey >> 8) & 255;
3065337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 2 + 1] = grey & 255;
3066337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3067337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGB)
3068337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3069337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 6 + 0] = (r >> 8) & 255;
3070337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 6 + 1] = r & 255;
3071337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 6 + 2] = (g >> 8) & 255;
3072337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 6 + 3] = g & 255;
3073337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 6 + 4] = (b >> 8) & 255;
3074337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 6 + 5] = b & 255;
3075337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3076337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_GREY_ALPHA)
3077337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3078337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned short grey = r; /*((unsigned)r + g + b) / 3*/;
3079337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 4 + 0] = (grey >> 8) & 255;
3080337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 4 + 1] = grey & 255;
3081337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 4 + 2] = (a >> 8) & 255;
3082337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 4 + 3] = a & 255;
3083337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3084337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGBA)
3085337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3086337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 0] = (r >> 8) & 255;
3087337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 1] = r & 255;
3088337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 2] = (g >> 8) & 255;
3089337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 3] = g & 255;
3090337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 4] = (b >> 8) & 255;
3091337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 5] = b & 255;
3092337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 6] = (a >> 8) & 255;
3093337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out[i * 8 + 7] = a & 255;
3094337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3095337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3096337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*no error*/
3097337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3098337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3099337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/
3100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getPixelColorRGBA8(unsigned char* r, unsigned char* g,
3101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                   unsigned char* b, unsigned char* a,
3102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                   const unsigned char* in, size_t i,
3103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                   const LodePNGColorMode* mode,
3104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                   unsigned fix_png)
3105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->colortype == LCT_GREY)
3107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = *g = *b = in[i];
3111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(mode->key_defined && *r == mode->key_r) *a = 0;
3112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else *a = 255;
3113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(mode->bitdepth == 16)
3115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = *g = *b = in[i * 2 + 0];
3117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
3118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else *a = 255;
3119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3120337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3122337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
3123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t j = i * mode->bitdepth;
3124337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
3125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = *g = *b = (value * 255) / highest;
3126337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(mode->key_defined && value == mode->key_r) *a = 0;
3127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else *a = 255;
3128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGB)
3131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2];
3135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0;
3136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else *a = 255;
3137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = in[i * 6 + 0];
3141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *g = in[i * 6 + 2];
3142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *b = in[i * 6 + 4];
3143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
3144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne         && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
3145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne         && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
3146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else *a = 255;
3147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_PALETTE)
3150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned index;
3152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8) index = in[i];
3153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t j = i * mode->bitdepth;
3156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      index = readBitsFromReversedStream(&j, in, mode->bitdepth);
3157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(index >= mode->palettesize)
3160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*This is an error according to the PNG spec, but fix_png can ignore it*/
3162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!fix_png) return (mode->bitdepth == 8 ? 46 : 47); /*index out of palette*/
3163337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = *g = *b = 0;
3164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *a = 255;
3165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = mode->palette[index * 4 + 0];
3169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *g = mode->palette[index * 4 + 1];
3170337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *b = mode->palette[index * 4 + 2];
3171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *a = mode->palette[index * 4 + 3];
3172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_GREY_ALPHA)
3175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = *g = *b = in[i * 2 + 0];
3179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *a = in[i * 2 + 1];
3180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = *g = *b = in[i * 4 + 0];
3184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *a = in[i * 4 + 2];
3185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGBA)
3188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = in[i * 4 + 0];
3192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *g = in[i * 4 + 1];
3193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *b = in[i * 4 + 2];
3194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *a = in[i * 4 + 3];
3195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *r = in[i * 8 + 0];
3199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *g = in[i * 8 + 2];
3200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *b = in[i * 8 + 4];
3201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      *a = in[i * 8 + 6];
3202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*no error*/
3206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color
3209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennemode test cases, optimized to convert the colors much faster, when converting
3210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneto RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with
3211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneenough memory, if has_alpha is true the output is RGBA. mode has the color mode
3212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneof the input buffer.*/
3213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels,
3214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    unsigned has_alpha, const unsigned char* in,
3215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    const LodePNGColorMode* mode,
3216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    unsigned fix_png)
3217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned num_channels = has_alpha ? 4 : 3;
3219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
3220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->colortype == LCT_GREY)
3221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = buffer[1] = buffer[2] = in[i];
3227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255;
3228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(mode->bitdepth == 16)
3231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = buffer[1] = buffer[2] = in[i * 2];
3235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255;
3236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
3241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t j = 0;
3242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
3245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;
3246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255;
3247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGB)
3251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = in[i * 3 + 0];
3257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[1] = in[i * 3 + 1];
3258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[2] = in[i * 3 + 2];
3259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r
3260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne           && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255;
3261337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3262337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3263337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3264337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3265337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3266337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3267337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = in[i * 6 + 0];
3268337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[1] = in[i * 6 + 2];
3269337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[2] = in[i * 6 + 4];
3270337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = mode->key_defined
3271337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne           && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
3272337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne           && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
3273337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne           && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255;
3274337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3275337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3276337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3277337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_PALETTE)
3278337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3279337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned index;
3280337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t j = 0;
3281337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numpixels; i++, buffer += num_channels)
3282337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3283337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(mode->bitdepth == 8) index = in[i];
3284337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else index = readBitsFromReversedStream(&j, in, mode->bitdepth);
3285337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3286337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(index >= mode->palettesize)
3287337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3288337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*This is an error according to the PNG spec, but fix_png can ignore it*/
3289337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!fix_png) return (mode->bitdepth == 8 ? 46 : 47); /*index out of palette*/
3290337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = buffer[1] = buffer[2] = 0;
3291337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = 255;
3292337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3293337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
3294337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3295337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = mode->palette[index * 4 + 0];
3296337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[1] = mode->palette[index * 4 + 1];
3297337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[2] = mode->palette[index * 4 + 2];
3298337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = mode->palette[index * 4 + 3];
3299337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3300337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3301337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3302337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_GREY_ALPHA)
3303337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3304337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3305337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3306337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3307337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3308337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];
3309337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = in[i * 2 + 1];
3310337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3311337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3312337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3313337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3314337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3315337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3316337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];
3317337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = in[i * 4 + 2];
3318337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3319337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3320337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3321337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGBA)
3322337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3323337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->bitdepth == 8)
3324337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3325337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3326337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3327337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = in[i * 4 + 0];
3328337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[1] = in[i * 4 + 1];
3329337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[2] = in[i * 4 + 2];
3330337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = in[i * 4 + 3];
3331337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3332337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3333337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
3334337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3335337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < numpixels; i++, buffer += num_channels)
3336337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3337337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[0] = in[i * 8 + 0];
3338337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[1] = in[i * 8 + 2];
3339337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        buffer[2] = in[i * 8 + 4];
3340337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(has_alpha) buffer[3] = in[i * 8 + 6];
3341337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3342337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3343337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3344337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3345337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*no error*/
3346337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3347337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3348337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with
3349337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennegiven color type, but the given color type must be 16-bit itself.*/
3350337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a,
3351337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    const unsigned char* in, size_t i, const LodePNGColorMode* mode)
3352337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3353337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->bitdepth != 16) return 85; /*error: this function only supports 16-bit input*/
3354337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3355337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->colortype == LCT_GREY)
3356337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3357337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1];
3358337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
3359337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else *a = 65535;
3360337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3361337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGB)
3362337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3363337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *r = 256 * in[i * 6 + 0] + in[i * 6 + 1];
3364337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *g = 256 * in[i * 6 + 2] + in[i * 6 + 3];
3365337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *b = 256 * in[i * 6 + 4] + in[i * 6 + 5];
3366337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
3367337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne       && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
3368337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne       && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
3369337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else *a = 65535;
3370337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3371337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_GREY_ALPHA)
3372337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3373337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *r = *g = *b = 256 * in[i * 4 + 0] + in[i * 4 + 1];
3374337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *a = 256 * in[i * 4 + 2] + in[i * 4 + 3];
3375337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3376337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode->colortype == LCT_RGBA)
3377337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3378337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *r = 256 * in[i * 8 + 0] + in[i * 8 + 1];
3379337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *g = 256 * in[i * 8 + 2] + in[i * 8 + 3];
3380337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *b = 256 * in[i * 8 + 4] + in[i * 8 + 5];
3381337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *a = 256 * in[i * 8 + 6] + in[i * 8 + 7];
3382337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3383337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else return 85; /*error: this function only supports 16-bit input, not palettes*/
3384337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3385337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /*no error*/
3386337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3387337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3388337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
3389337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneconverts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code
3390337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethe out buffer must have (w * h * bpp + 7) / 8 bytes, where bpp is the bits per pixel of the output color type
3391337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne(lodepng_get_bpp) for < 8 bpp images, there may _not_ be padding bits at the end of scanlines.
3392337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
3393337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_convert(unsigned char* out, const unsigned char* in,
33949ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                         LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
3395337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         unsigned w, unsigned h, unsigned fix_png)
3396337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3397337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
3398337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
3399337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ColorTree tree;
3400337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t numpixels = w * h;
3401337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3402337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(lodepng_color_mode_equal(mode_out, mode_in))
3403337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3404337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
3405337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numbytes; i++) out[i] = in[i];
3406337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return error;
3407337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3408337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3409337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode_out->colortype == LCT_PALETTE)
3410337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3411337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t palsize = 1 << mode_out->bitdepth;
3412337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode_out->palettesize < palsize) palsize = mode_out->palettesize;
3413337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color_tree_init(&tree);
3414337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < palsize; i++)
3415337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3416337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned char* p = &mode_out->palette[i * 4];
3417337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      color_tree_add(&tree, p[0], p[1], p[2], p[3], i);
3418337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3419337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3420337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3421337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16)
3422337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3423337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numpixels; i++)
3424337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3425337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned short r = 0, g = 0, b = 0, a = 0;
3426337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
3427337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
3428337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = rgba16ToPixel(out, i, mode_out, r, g, b, a);
3429337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
3430337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3431337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3432337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA)
3433337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3434337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = getPixelColorsRGBA8(out, numpixels, 1, in, mode_in, fix_png);
3435337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3436337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB)
3437337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3438337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = getPixelColorsRGBA8(out, numpixels, 0, in, mode_in, fix_png);
3439337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3440337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
3441337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3442337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char r = 0, g = 0, b = 0, a = 0;
3443337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numpixels; i++)
3444337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3445337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in, fix_png);
3446337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
3447337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);
3448337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
3449337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3450337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3451337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3452337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode_out->colortype == LCT_PALETTE)
3453337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3454337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color_tree_cleanup(&tree);
3455337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3456337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3457337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
3458337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3459337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3460337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
3461337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3462337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennetypedef struct ColorProfile
3463337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3464337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char sixteenbit; /*needs more than 8 bits per channel*/
3465337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char sixteenbit_done;
3466337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3467337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3468337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char colored; /*not greyscale*/
3469337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char colored_done;
3470337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3471337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char key; /*a color key is required, or more*/
3472337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned short key_r; /*these values are always in 16-bit bitdepth in the profile*/
3473337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned short key_g;
3474337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned short key_b;
3475337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char alpha; /*alpha channel, or alpha palette, required*/
3476337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char alpha_done;
3477337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3478337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned numcolors;
3479337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ColorTree tree; /*for listing the counted colors, up to 256*/
3480337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* palette; /*size 1024. Remember up to the first 256 RGBA colors*/
3481337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned maxnumcolors; /*if more than that amount counted*/
3482337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char numcolors_done;
3483337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3484337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned greybits; /*amount of bits required for greyscale (1, 2, 4, 8). Does not take 16 bit into account.*/
3485337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char greybits_done;
3486337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3487337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} ColorProfile;
3488337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
34899ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevennestatic void color_profile_init(ColorProfile* profile, const LodePNGColorMode* mode)
3490337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3491337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->sixteenbit = 0;
3492337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->sixteenbit_done = mode->bitdepth == 16 ? 0 : 1;
3493337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3494337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->colored = 0;
3495337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0;
3496337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3497337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->key = 0;
3498337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->alpha = 0;
3499337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1;
3500337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3501337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->numcolors = 0;
3502337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  color_tree_init(&profile->tree);
3503337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->palette = (unsigned char*)lodepng_malloc(1024);
3504337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->maxnumcolors = 257;
3505337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(lodepng_get_bpp(mode) <= 8)
3506337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3507337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    int bpp = lodepng_get_bpp(mode);
3508337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile->maxnumcolors = bpp == 1 ? 2 : (bpp == 2 ? 4 : (bpp == 4 ? 16 : 256));
3509337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3510337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->numcolors_done = 0;
3511337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3512337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->greybits = 1;
3513337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  profile->greybits_done = lodepng_get_bpp(mode) == 1 ? 1 : 0;
3514337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3515337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3516337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void color_profile_cleanup(ColorProfile* profile)
3517337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3518337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  color_tree_cleanup(&profile->tree);
3519337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(profile->palette);
3520337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3521337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3522337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*function used for debug purposes with C++*/
3523337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*void printColorProfile(ColorProfile* p)
3524337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3525337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "sixteenbit: " << (int)p->sixteenbit << std::endl;
3526337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "sixteenbit_done: " << (int)p->sixteenbit_done << std::endl;
3527337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "colored: " << (int)p->colored << std::endl;
3528337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "colored_done: " << (int)p->colored_done << std::endl;
3529337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "key: " << (int)p->key << std::endl;
3530337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "key_r: " << (int)p->key_r << std::endl;
3531337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "key_g: " << (int)p->key_g << std::endl;
3532337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "key_b: " << (int)p->key_b << std::endl;
3533337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "alpha: " << (int)p->alpha << std::endl;
3534337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "alpha_done: " << (int)p->alpha_done << std::endl;
3535337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "numcolors: " << (int)p->numcolors << std::endl;
3536337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "maxnumcolors: " << (int)p->maxnumcolors << std::endl;
3537337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "numcolors_done: " << (int)p->numcolors_done << std::endl;
3538337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "greybits: " << (int)p->greybits << std::endl;
3539337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::cout << "greybits_done: " << (int)p->greybits_done << std::endl;
3540337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}*/
3541337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3542337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*Returns how many bits needed to represent given value (max 8 bit)*/
3543337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned getValueRequiredBits(unsigned short value)
3544337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3545337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(value == 0 || value == 255) return 1;
3546337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/
3547337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(value % 17 == 0) return value % 85 == 0 ? 2 : 4;
3548337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 8;
3549337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3550337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3551337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*profile must already have been inited with mode.
3552337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneIt's ok to set some parameters of profile to done already.*/
3553337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned get_color_profile(ColorProfile* profile,
35549ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                  const unsigned char* in,
35559ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                  size_t numpixels /*must be full image size, for certain filesize based choices*/,
35569ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                  const LodePNGColorMode* mode,
3557337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                  unsigned fix_png)
3558337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3559337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
3560337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
3561337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3562337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->bitdepth == 16)
3563337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3564337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numpixels; i++)
3565337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3566337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned short r, g, b, a;
3567337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);
3568337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
3569337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3570337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*a color is considered good for 8-bit if the first byte and the second byte are equal,
3571337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        (so if it's divisible through 257), NOT necessarily if the second byte is 0*/
3572337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->sixteenbit_done
3573337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          && (((r & 255) != ((r >> 8) & 255))
3574337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne           || ((g & 255) != ((g >> 8) & 255))
3575337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne           || ((b & 255) != ((b >> 8) & 255))))
3576337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3577337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->sixteenbit = 1;
3578337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->sixteenbit_done = 1;
3579337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->greybits_done = 1; /*greybits is not applicable anymore at 16-bit*/
3580337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/
3581337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3582337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3583337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->colored_done && (r != g || r != b))
3584337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3585337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->colored = 1;
3586337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->colored_done = 1;
3587337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->greybits_done = 1; /*greybits is not applicable anymore*/
3588337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3589337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3590337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->alpha_done && a != 65535)
3591337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
35929ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        /*only use color key if numpixels large enough to justify tRNS chunk size*/
35939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        if(a == 0 && numpixels > 16 && !(profile->key && (r != profile->key_r || g != profile->key_g || b != profile->key_b)))
3594337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
35959ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          if(!profile->alpha && !profile->key)
3596337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
3597337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key = 1;
3598337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key_r = r;
3599337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key_g = g;
3600337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key_b = b;
3601337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
3602337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3603337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else
3604337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3605337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha = 1;
3606337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha_done = 1;
3607337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->greybits_done = 1; /*greybits is not applicable anymore*/
3608337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3609337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3610337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3611337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /* Color key cannot be used if an opaque pixel also has that RGB color. */
3612337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->alpha_done && a == 65535 && profile->key
3613337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          && r == profile->key_r && g == profile->key_g && b == profile->key_b)
3614337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3615337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha = 1;
3616337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha_done = 1;
3617337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->greybits_done = 1; /*greybits is not applicable anymore*/
3618337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3619337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3620337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->greybits_done)
3621337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3622337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*assuming 8-bit r, this test does not care about 16-bit*/
3623337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned bits = getValueRequiredBits(r);
3624337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(bits > profile->greybits) profile->greybits = bits;
3625337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(profile->greybits >= 8) profile->greybits_done = 1;
3626337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3627337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3628337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->numcolors_done)
3629337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3630337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*assuming 8-bit rgba, this test does not care about 16-bit*/
3631337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!color_tree_has(&profile->tree, (unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a))
3632337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3633337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          color_tree_add(&profile->tree, (unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a,
3634337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->numcolors);
3635337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(profile->numcolors < 256)
3636337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
3637337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            unsigned char* p = profile->palette;
3638337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            unsigned i = profile->numcolors;
3639337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 0] = (unsigned char)r;
3640337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 1] = (unsigned char)g;
3641337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 2] = (unsigned char)b;
3642337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 3] = (unsigned char)a;
3643337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
3644337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->numcolors++;
3645337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(profile->numcolors >= profile->maxnumcolors) profile->numcolors_done = 1;
3646337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3647337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3648337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3649337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(profile->alpha_done && profile->numcolors_done
3650337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      && profile->colored_done && profile->sixteenbit_done && profile->greybits_done)
3651337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3652337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
3653337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3654337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    };
3655337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3656337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /* < 16-bit */
3657337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3658337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < numpixels; i++)
3659337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3660337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned char r = 0, g = 0, b = 0, a = 0;
3661337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode, fix_png);
3662337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
3663337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3664337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->colored_done && (r != g || r != b))
3665337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3666337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->colored = 1;
3667337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->colored_done = 1;
3668337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        profile->greybits_done = 1; /*greybits is not applicable anymore*/
3669337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3670337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3671337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->alpha_done && a != 255)
3672337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3673337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(a == 0 && !(profile->key && (r != profile->key_r || g != profile->key_g || b != profile->key_b)))
3674337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3675337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(!profile->key)
3676337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
3677337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key = 1;
3678337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key_r = r;
3679337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key_g = g;
3680337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            profile->key_b = b;
3681337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
3682337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3683337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else
3684337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3685337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha = 1;
3686337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha_done = 1;
3687337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->greybits_done = 1; /*greybits is not applicable anymore*/
3688337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3689337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3690337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3691337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /* Color key cannot be used if an opaque pixel also has that RGB color. */
3692337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->alpha_done && a == 255 && profile->key
3693337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          && r == profile->key_r && g == profile->key_g && b == profile->key_b)
3694337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3695337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha = 1;
3696337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->alpha_done = 1;
3697337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->greybits_done = 1; /*greybits is not applicable anymore*/
3698337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3699337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3700337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->greybits_done)
3701337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3702337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned bits = getValueRequiredBits(r);
3703337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(bits > profile->greybits) profile->greybits = bits;
3704337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(profile->greybits >= 8) profile->greybits_done = 1;
3705337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3706337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3707337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!profile->numcolors_done)
3708337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3709337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!color_tree_has(&profile->tree, r, g, b, a))
3710337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3711337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3712337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          color_tree_add(&profile->tree, r, g, b, a, profile->numcolors);
3713337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(profile->numcolors < 256)
3714337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
3715337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            unsigned char* p = profile->palette;
3716337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            unsigned i = profile->numcolors;
3717337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 0] = r;
3718337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 1] = g;
3719337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 2] = b;
3720337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            p[i * 4 + 3] = a;
3721337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
3722337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          profile->numcolors++;
3723337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(profile->numcolors >= profile->maxnumcolors) profile->numcolors_done = 1;
3724337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3725337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3726337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3727337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(profile->alpha_done && profile->numcolors_done && profile->colored_done && profile->greybits_done)
3728337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3729337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
3730337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3731337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    };
3732337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3733337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3734337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*make the profile's key always 16-bit for consistency*/
3735337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode->bitdepth < 16)
3736337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3737337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*repeat each byte twice*/
3738337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile->key_r *= 257;
3739337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile->key_g *= 257;
3740337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile->key_b *= 257;
3741337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3742337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3743337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
3744337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3745337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3746337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void setColorKeyFrom16bit(LodePNGColorMode* mode_out, unsigned r, unsigned g, unsigned b, unsigned bitdepth)
3747337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3748337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned mask = (1 << bitdepth) - 1;
3749337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  mode_out->key_defined = 1;
3750337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  mode_out->key_r = r & mask;
3751337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  mode_out->key_g = g & mask;
3752337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  mode_out->key_b = b & mask;
3753337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3754337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3755337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*updates values of mode with a potentially smaller color model. mode_out should
3756337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennecontain the user chosen color model, but will be overwritten with the new chosen one.*/
37579ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenneunsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
37589ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                   const unsigned char* image, unsigned w, unsigned h,
37599ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                   const LodePNGColorMode* mode_in,
37609ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                   LodePNGAutoConvert auto_convert)
3761337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3762337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ColorProfile profile;
3763337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
3764337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int no_nibbles = auto_convert == LAC_AUTO_NO_NIBBLES || auto_convert == LAC_AUTO_NO_NIBBLES_NO_PALETTE;
3765337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  int no_palette = auto_convert == LAC_AUTO_NO_PALETTE || auto_convert == LAC_AUTO_NO_NIBBLES_NO_PALETTE;
3766337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3767337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(auto_convert == LAC_ALPHA)
3768337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3769337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(mode_out->colortype != LCT_RGBA && mode_out->colortype != LCT_GREY_ALPHA) return 0;
3770337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3771337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3772337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  color_profile_init(&profile, mode_in);
3773337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(auto_convert == LAC_ALPHA)
3774337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3775337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile.colored_done = 1;
3776337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile.greybits_done = 1;
3777337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile.numcolors_done = 1;
3778337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    profile.sixteenbit_done = 1;
3779337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3780337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = get_color_profile(&profile, image, w * h, mode_in, 0 /*fix_png*/);
3781337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error && auto_convert == LAC_ALPHA)
3782337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3783337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!profile.alpha)
3784337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3785337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      mode_out->colortype = (mode_out->colortype == LCT_RGBA ? LCT_RGB : LCT_GREY);
3786337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(profile.key) setColorKeyFrom16bit(mode_out, profile.key_r, profile.key_g, profile.key_b, mode_out->bitdepth);
3787337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3788337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3789337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(!error && auto_convert != LAC_ALPHA)
3790337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3791337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    mode_out->key_defined = 0;
3792337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3793337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(profile.sixteenbit)
3794337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3795337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      mode_out->bitdepth = 16;
3796337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(profile.alpha)
3797337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3798337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        mode_out->colortype = profile.colored ? LCT_RGBA : LCT_GREY_ALPHA;
3799337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3800337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
3801337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3802337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        mode_out->colortype = profile.colored ? LCT_RGB : LCT_GREY;
3803337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(profile.key) setColorKeyFrom16bit(mode_out, profile.key_r, profile.key_g, profile.key_b, mode_out->bitdepth);
3804337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3805337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3806337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else /*less than 16 bits per channel*/
3807337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3808337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*don't add palette overhead if image hasn't got a lot of pixels*/
3809337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned n = profile.numcolors;
3810337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      int palette_ok = !no_palette && n <= 256 && (n * 2 < w * h);
3811337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));
3812337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      int grey_ok = !profile.colored && !profile.alpha; /*grey without alpha, with potentially low bits*/
3813337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(palette_ok || grey_ok)
3814337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3815337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!palette_ok || (grey_ok && profile.greybits <= palettebits))
3816337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
38179ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne          unsigned grey = profile.key_r;
3818337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          mode_out->colortype = LCT_GREY;
3819337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          mode_out->bitdepth = profile.greybits;
3820337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(profile.key) setColorKeyFrom16bit(mode_out, grey, grey, grey, mode_out->bitdepth);
3821337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3822337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else
3823337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3824337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*fill in the palette*/
3825337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          unsigned i;
3826337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          unsigned char* p = profile.palette;
3827337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*remove potential earlier palette*/
3828337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          lodepng_palette_clear(mode_out);
3829337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          for(i = 0; i < profile.numcolors; i++)
3830337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
3831337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]);
3832337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            if(error) break;
3833337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
3834337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3835337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          mode_out->colortype = LCT_PALETTE;
3836337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          mode_out->bitdepth = palettebits;
3837337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3838337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3839337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else /*8-bit per channel*/
3840337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
3841337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        mode_out->bitdepth = 8;
3842337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(profile.alpha)
3843337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3844337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          mode_out->colortype = profile.colored ? LCT_RGBA : LCT_GREY_ALPHA;
3845337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3846337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else
3847337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
3848337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          mode_out->colortype = profile.colored ? LCT_RGB : LCT_GREY /*LCT_GREY normally won't occur, already done earlier*/;
3849337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(profile.key) setColorKeyFrom16bit(mode_out, profile.key_r, profile.key_g, profile.key_b, mode_out->bitdepth);
3850337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
3851337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
3852337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3853337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3854337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3855337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  color_profile_cleanup(&profile);
3856337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3857337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(mode_out->colortype == LCT_PALETTE && mode_in->palettesize == mode_out->palettesize)
3858337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3859337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*In this case keep the palette order of the input, so that the user can choose an optimal one*/
3860337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t i;
3861337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < mode_in->palettesize * 4; i++)
3862337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3863337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      mode_out->palette[i] = mode_in->palette[i];
3864337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3865337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3866337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3867337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(no_nibbles && mode_out->bitdepth < 8)
3868337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3869337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*palette can keep its small amount of colors, as long as no indices use it*/
3870337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    mode_out->bitdepth = 8;
3871337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3872337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3873337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
3874337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3875337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3876337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /* #ifdef LODEPNG_COMPILE_ENCODER */
3877337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3878337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
3879337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevennePaeth predicter, used by PNG filter type 4
3880337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThe parameters are of type short, but should come from unsigned chars, the shorts
3881337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneare only needed to make the paeth calculation correct.
3882337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
3883337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned char paethPredictor(short a, short b, short c)
3884337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3885337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  short pa = abs(b - c);
3886337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  short pb = abs(a - c);
3887337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  short pc = abs(a + b - c - c);
3888337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3889337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(pc < pa && pc < pb) return (unsigned char)c;
3890337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(pb < pa) return (unsigned char)b;
3891337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else return (unsigned char)a;
3892337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3893337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3894337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*shared values used by multiple Adam7 related functions*/
3895337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3896337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
3897337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
3898337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
3899337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
3900337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3901337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
3902337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneOutputs various dimensions and positions in the image related to the Adam7 reduced images.
3903337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennepassw: output containing the width of the 7 passes
3904337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennepassh: output containing the height of the 7 passes
3905337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennefilter_passstart: output containing the index of the start and end of each
3906337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne reduced image with filter bytes
3907337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennepadded_passstart output containing the index of the start and end of each
3908337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne reduced image when without filter bytes but with padded scanlines
3909337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennepassstart: output containing the index of the start and end of each reduced
3910337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne image without padding between scanlines, but still padding between the images
3911337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennew, h: width and height of non-interlaced image
3912337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennebpp: bits per pixel
3913337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne"padded" is only relevant if bpp is less than 8 and a scanline or image does not
3914337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne end at a full byte
3915337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
3916337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8],
3917337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp)
3918337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3919337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/
3920337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
3921337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3922337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*calculate width and height in pixels of each pass*/
3923337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 7; i++)
3924337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3925337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];
3926337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];
3927337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(passw[i] == 0) passh[i] = 0;
3928337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(passh[i] == 0) passw[i] = 0;
3929337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3930337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3931337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
3932337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < 7; i++)
3933337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3934337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/
3935337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    filter_passstart[i + 1] = filter_passstart[i]
3936337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                            + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0);
3937337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*bits padded if needed to fill full byte at end of each scanline*/
3938337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8);
3939337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*only padded at end of reduced image*/
3940337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8;
3941337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3942337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
3943337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3944337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
3945337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3946337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
3947337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / PNG Decoder                                                            / */
3948337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
3949337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3950337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*read the information from the header and store it in the LodePNGInfo. return value is error*/
3951337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state,
3952337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         const unsigned char* in, size_t insize)
3953337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
3954337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGInfo* info = &state->info_png;
3955337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(insize == 0 || in == 0)
3956337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3957337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/
3958337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3959337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(insize < 29)
3960337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3961337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/
3962337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3963337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3964337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/
3965337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_cleanup(info);
3966337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_init(info);
3967337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3968337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71
3969337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10)
3970337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3971337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/
3972337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3973337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R')
3974337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3975337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/
3976337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3977337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3978337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*read the values given in the header*/
3979337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *w = lodepng_read32bitInt(&in[16]);
3980337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *h = lodepng_read32bitInt(&in[20]);
3981337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->color.bitdepth = in[24];
3982337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->color.colortype = (LodePNGColorType)in[25];
3983337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->compression_method = in[26];
3984337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->filter_method = in[27];
3985337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->interlace_method = in[28];
3986337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3987337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!state->decoder.ignore_crc)
3988337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
3989337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned CRC = lodepng_read32bitInt(&in[29]);
3990337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned checksum = lodepng_crc32(&in[12], 17);
3991337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(CRC != checksum)
3992337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
3993337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/
3994337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
3995337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
3996337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
3997337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*error: only compression method 0 is allowed in the specification*/
3998337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32);
3999337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*error: only filter method 0 is allowed in the specification*/
4000337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33);
4001337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*error: only interlace methods 0 and 1 exist in the specification*/
4002337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34);
4003337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4004337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state->error = checkColorValidity(info->color.colortype, info->color.bitdepth);
4005337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return state->error;
4006337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4007337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4008337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon,
4009337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                 size_t bytewidth, unsigned char filterType, size_t length)
4010337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4011337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
4012337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  For PNG filter method 0
4013337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte,
4014337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  the filter works byte per byte (bytewidth = 1)
4015337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  precon is the previous unfiltered scanline, recon the result, scanline the current one
4016337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead
4017337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  recon and scanline MAY be the same memory address! precon must be disjoint.
4018337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
4019337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4020337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
4021337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  switch(filterType)
4022337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4023337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 0:
4024337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < length; i++) recon[i] = scanline[i];
4025337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
4026337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 1:
4027337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
4028337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
4029337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
4030337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 2:
4031337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(precon)
4032337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4033337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
4034337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4035337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
4036337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4037337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < length; i++) recon[i] = scanline[i];
4038337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4039337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
4040337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 3:
4041337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(precon)
4042337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4043337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
4044337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
4045337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4046337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
4047337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4048337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
4049337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
4050337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4051337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
4052337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 4:
4053337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(precon)
4054337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4055337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++)
4056337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
4057337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
4058337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
4059337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++)
4060337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
4061337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
4062337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
4063337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4064337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
4065337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4066337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++)
4067337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
4068337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          recon[i] = scanline[i];
4069337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
4070337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++)
4071337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
4072337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
4073337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          recon[i] = (scanline[i] + recon[i - bytewidth]);
4074337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
4075337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4076337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
4077337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    default: return 36; /*error: unexisting filter type given*/
4078337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4079337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
4080337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4081337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4082337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
4083337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4084337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
4085337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  For PNG filter method 0
4086337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)
4087337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
4088337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
4089337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)
4090337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
4091337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4092337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned y;
4093337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* prevline = 0;
4094337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4095337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
4096337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t bytewidth = (bpp + 7) / 8;
4097337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t linebytes = (w * bpp + 7) / 8;
4098337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4099337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(y = 0; y < h; y++)
4100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t outindex = linebytes * y;
4102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
4103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char filterType = in[inindex];
4104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes));
4106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    prevline = &out[outindex];
4108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
4111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
4114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennein: Adam7 interlaced image, with no padding bits between scanlines, but between
4115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne reduced images so that each reduced image starts at a byte.
4116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneout: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h
4117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennebpp: bits per pixel
4118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneout has the following size in bits: w * h * bpp.
4119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennein is possibly bigger due to padding bits between reduced images.
4120337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneout must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation
4121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne(because that's likely a little bit faster)
4122337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneNOTE: comments about padding bits are only relevant if bpp < 8
4123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
4124337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
4125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4126337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned passw[7], passh[7];
4127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t filter_passstart[8], padded_passstart[8], passstart[8];
4128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
4129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
4131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(bpp >= 8)
4133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < 7; i++)
4135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned x, y, b;
4137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t bytewidth = bpp / 8;
4138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(y = 0; y < passh[i]; y++)
4139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(x = 0; x < passw[i]; x++)
4140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
4142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
4143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(b = 0; b < bytewidth; b++)
4144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
4145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          out[pixeloutstart + b] = in[pixelinstart + b];
4146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
4147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/
4151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < 7; i++)
4153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned x, y, b;
4155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned ilinebits = bpp * passw[i];
4156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned olinebits = bpp * w;
4157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t obp, ibp; /*bit pointers (for out and in buffer)*/
4158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(y = 0; y < passh[i]; y++)
4159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(x = 0; x < passw[i]; x++)
4160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
4162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
4163337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(b = 0; b < bpp; b++)
4164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
4165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          unsigned char bit = readBitFromReversedStream(&ibp, in);
4166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/
4167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          setBitOfReversedStream0(&obp, out, bit);
4168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
4169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4170337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void removePaddingBits(unsigned char* out, const unsigned char* in,
4175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              size_t olinebits, size_t ilinebits, unsigned h)
4176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
4178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need
4179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers
4180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for the Adam7 code, the color convert code and the output to the user.
4181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must
4182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits
4183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7
4184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  only useful if (ilinebits - olinebits) is a value in the range 1..7
4185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
4186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned y;
4187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t diff = ilinebits - olinebits;
4188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t ibp = 0, obp = 0; /*input and output bit pointers*/
4189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(y = 0; y < h; y++)
4190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t x;
4192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(x = 0; x < olinebits; x++)
4193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned char bit = readBitFromReversedStream(&ibp, in);
4195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      setBitOfReversedStream(&obp, out, bit);
4196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ibp += diff;
4198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from
4202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethe IDAT chunks (with filter index bytes and possible padding bits)
4203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturn value is error*/
4204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned postProcessScanlines(unsigned char* out, unsigned char* in,
4205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                     unsigned w, unsigned h, const LodePNGInfo* info_png)
4206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
4208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.
4209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Steps:
4210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)
4211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
4212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  NOTE: the in buffer will be overwritten with intermediate data!
4213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
4214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned bpp = lodepng_get_bpp(&info_png->color);
4215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(bpp == 0) return 31; /*error: invalid colortype*/
4216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info_png->interlace_method == 0)
4218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)
4220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));
4222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);
4223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*we can immediatly filter into the out buffer, no other steps needed*/
4225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp));
4226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*interlace_method is 1 (Adam7)*/
4228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
4230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned i;
4231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
4233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < 7; i++)
4235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp));
4237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,
4238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      move bytes instead of bits or move not at all*/
4239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(bpp < 8)
4240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*remove padding bits in scanlines; after this there still may be padding
4242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        bits between the different reduced images: each reduced image still starts nicely at a byte*/
4243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,
4244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                          ((passw[i] * bpp + 7) / 8) * 8, passh[i]);
4245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    Adam7_deinterlace(out, in, w, h, bpp);
4249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
4252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength)
4255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned pos = 0, i;
4257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(color->palette) lodepng_free(color->palette);
4258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  color->palettesize = chunkLength / 3;
4259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize);
4260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!color->palette && color->palettesize)
4261337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4262337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->palettesize = 0;
4263337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return 83; /*alloc fail*/
4264337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4265337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(color->palettesize > 256) return 38; /*error: palette too big*/
4266337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4267337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < color->palettesize; i++)
4268337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4269337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->palette[4 * i + 0] = data[pos++]; /*R*/
4270337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->palette[4 * i + 1] = data[pos++]; /*G*/
4271337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->palette[4 * i + 2] = data[pos++]; /*B*/
4272337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->palette[4 * i + 3] = 255; /*alpha*/
4273337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4274337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4275337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /* OK */
4276337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4277337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4278337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength)
4279337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4280337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
4281337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(color->colortype == LCT_PALETTE)
4282337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4283337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: more alpha values given than there are palette entries*/
4284337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength > color->palettesize) return 38;
4285337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4286337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < chunkLength; i++) color->palette[4 * i + 3] = data[i];
4287337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4288337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(color->colortype == LCT_GREY)
4289337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4290337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: this chunk must be 2 bytes for greyscale image*/
4291337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength != 2) return 30;
4292337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4293337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->key_defined = 1;
4294337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->key_r = color->key_g = color->key_b = 256 * data[0] + data[1];
4295337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4296337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(color->colortype == LCT_RGB)
4297337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4298337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: this chunk must be 6 bytes for RGB image*/
4299337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength != 6) return 41;
4300337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4301337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->key_defined = 1;
4302337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->key_r = 256 * data[0] + data[1];
4303337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->key_g = 256 * data[2] + data[3];
4304337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    color->key_b = 256 * data[4] + data[5];
4305337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4306337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else return 42; /*error: tRNS chunk not allowed for other color models*/
4307337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4308337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /* OK */
4309337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4310337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4311337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4312337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4313337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*background color chunk (bKGD)*/
4314337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)
4315337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4316337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->color.colortype == LCT_PALETTE)
4317337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4318337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: this chunk must be 1 byte for indexed color image*/
4319337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength != 1) return 43;
4320337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4321337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_defined = 1;
4322337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_r = info->background_g = info->background_b = data[0];
4323337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4324337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA)
4325337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4326337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: this chunk must be 2 bytes for greyscale image*/
4327337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength != 2) return 44;
4328337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4329337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_defined = 1;
4330337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_r = info->background_g = info->background_b
4331337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                 = 256 * data[0] + data[1];
4332337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4333337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA)
4334337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4335337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: this chunk must be 6 bytes for greyscale image*/
4336337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength != 6) return 45;
4337337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4338337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_defined = 1;
4339337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_r = 256 * data[0] + data[1];
4340337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_g = 256 * data[2] + data[3];
4341337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    info->background_b = 256 * data[4] + data[5];
4342337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4343337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4344337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /* OK */
4345337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4346337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4347337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*text chunk (tEXt)*/
4348337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)
4349337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4350337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4351337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char *key = 0, *str = 0;
4352337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
4353337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4354337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!error) /*not really a while loop, only used to break on error*/
4355337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4356337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned length, string2_begin;
4357337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4358337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    length = 0;
4359337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    while(length < chunkLength && data[length] != 0) length++;
4360337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*even though it's not allowed by the standard, no error is thrown if
4361337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    there's no null termination char, if the text is empty*/
4362337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
4363337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4364337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    key = (char*)lodepng_malloc(length + 1);
4365337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
4366337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4367337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    key[length] = 0;
4368337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < length; i++) key[i] = data[i];
4369337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4370337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string2_begin = length + 1; /*skip keyword null terminator*/
4371337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4372337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    length = chunkLength < string2_begin ? 0 : chunkLength - string2_begin;
4373337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    str = (char*)lodepng_malloc(length + 1);
4374337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!str) CERROR_BREAK(error, 83); /*alloc fail*/
4375337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4376337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    str[length] = 0;
4377337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < length; i++) str[i] = data[string2_begin + i];
4378337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4379337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = lodepng_add_text(info, key, str);
4380337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4381337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    break;
4382337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4383337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4384337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(key);
4385337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(str);
4386337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4387337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4388337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4389337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4390337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*compressed text chunk (zTXt)*/
4391337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
4392337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               const unsigned char* data, size_t chunkLength)
4393337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4394337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4395337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
4396337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4397337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned length, string2_begin;
4398337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char *key = 0;
4399337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector decoded;
4400337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4401337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&decoded);
4402337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4403337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!error) /*not really a while loop, only used to break on error*/
4404337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4405337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(length = 0; length < chunkLength && data[length] != 0; length++) ;
4406337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
4407337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
4408337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4409337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    key = (char*)lodepng_malloc(length + 1);
4410337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
4411337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4412337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    key[length] = 0;
4413337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < length; i++) key[i] = data[i];
4414337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4415337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
4416337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4417337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    string2_begin = length + 2;
4418337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
4419337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4420337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    length = chunkLength - string2_begin;
4421337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*will fail if zlib error, e.g. if length is too small*/
4422337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = zlib_decompress(&decoded.data, &decoded.size,
4423337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                            (unsigned char*)(&data[string2_begin]),
4424337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                            length, zlibsettings);
4425337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(error) break;
4426337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&decoded, 0);
4427337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4428337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = lodepng_add_text(info, key, (char*)decoded.data);
4429337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4430337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    break;
4431337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4432337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4433337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(key);
4434337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&decoded);
4435337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4436337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4437337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4438337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4439337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*international text chunk (iTXt)*/
4440337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
4441337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               const unsigned char* data, size_t chunkLength)
4442337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4443337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4444337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
4445337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4446337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned length, begin, compressed;
4447337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  char *key = 0, *langtag = 0, *transkey = 0;
4448337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector decoded;
4449337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&decoded);
4450337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4451337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!error) /*not really a while loop, only used to break on error*/
4452337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4453337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Quick check if the chunk length isn't too small. Even without check
4454337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    it'd still fail with other error checks below if it's too short. This just gives a different error code.*/
4455337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/
4456337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4457337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*read the key*/
4458337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(length = 0; length < chunkLength && data[length] != 0; length++) ;
4459337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/
4460337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
4461337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4462337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    key = (char*)lodepng_malloc(length + 1);
4463337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
4464337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4465337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    key[length] = 0;
4466337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < length; i++) key[i] = data[i];
4467337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4468337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*read the compression method*/
4469337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    compressed = data[length + 1];
4470337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
4471337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4472337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*even though it's not allowed by the standard, no error is thrown if
4473337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    there's no null termination char, if the text is empty for the next 3 texts*/
4474337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4475337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*read the langtag*/
4476337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    begin = length + 3;
4477337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    length = 0;
4478337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = begin; i < chunkLength && data[i] != 0; i++) length++;
4479337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4480337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    langtag = (char*)lodepng_malloc(length + 1);
4481337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/
4482337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4483337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    langtag[length] = 0;
4484337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < length; i++) langtag[i] = data[begin + i];
4485337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4486337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*read the transkey*/
4487337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    begin += length + 1;
4488337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    length = 0;
4489337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = begin; i < chunkLength && data[i] != 0; i++) length++;
4490337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4491337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    transkey = (char*)lodepng_malloc(length + 1);
4492337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/
4493337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4494337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    transkey[length] = 0;
4495337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < length; i++) transkey[i] = data[begin + i];
4496337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4497337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*read the actual text*/
4498337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    begin += length + 1;
4499337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4500337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    length = chunkLength < begin ? 0 : chunkLength - begin;
4501337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4502337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(compressed)
4503337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4504337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*will fail if zlib error, e.g. if length is too small*/
4505337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      error = zlib_decompress(&decoded.data, &decoded.size,
4506337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              (unsigned char*)(&data[begin]),
4507337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              length, zlibsettings);
4508337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(error) break;
4509337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size;
4510337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&decoded, 0);
4511337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4512337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else
4513337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4514337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/);
4515337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4516337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      decoded.data[length] = 0;
4517337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < length; i++) decoded.data[i] = data[begin + i];
4518337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4519337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4520337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data);
4521337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4522337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    break;
4523337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4524337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4525337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(key);
4526337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(langtag);
4527337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(transkey);
4528337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&decoded);
4529337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4530337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4531337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4532337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4533337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)
4534337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4535337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(chunkLength != 7) return 73; /*invalid tIME chunk size*/
4536337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4537337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time_defined = 1;
4538337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time.year = 256 * data[0] + data[+ 1];
4539337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time.month = data[2];
4540337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time.day = data[3];
4541337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time.hour = data[4];
4542337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time.minute = data[5];
4543337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->time.second = data[6];
4544337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4545337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /* OK */
4546337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4547337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4548337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)
4549337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4550337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/
4551337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4552337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->phys_defined = 1;
4553337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->phys_x = 16777216 * data[0] + 65536 * data[1] + 256 * data[2] + data[3];
4554337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->phys_y = 16777216 * data[4] + 65536 * data[5] + 256 * data[6] + data[7];
4555337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  info->phys_unit = data[8];
4556337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4557337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0; /* OK */
4558337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4559337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4560337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4561337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
4562337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
4563337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                          LodePNGState* state,
4564337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                          const unsigned char* in, size_t insize)
4565337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4566337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char IEND = 0;
4567337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  const unsigned char* chunk;
4568337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
4569337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector idat; /*the data from idat chunks*/
45709ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  ucvector scanlines;
4571337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4572337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*for unknown chunk order*/
4573337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned unknown = 0;
4574337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4575337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/
4576337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4577337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4578337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*provide some proper output values if error will happen*/
4579337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = 0;
4580337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4581337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/
4582337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->error) return;
4583337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4584337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&idat);
4585337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  chunk = &in[33]; /*first byte of the first chunk after the header*/
4586337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4587337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.
4588337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  IDAT data is put at the start of the in buffer*/
4589337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!IEND && !state->error)
4590337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4591337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned chunkLength;
4592337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    const unsigned char* data; /*the data in the chunk*/
4593337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4594337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: size of the in buffer too small to contain next chunk*/
4595337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30);
4596337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4597337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
4598337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    chunkLength = lodepng_chunk_length(chunk);
4599337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*error: chunk length larger than the max PNG chunk size*/
4600337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(chunkLength > 2147483647) CERROR_BREAK(state->error, 63);
4601337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4602337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in)
4603337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4604337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/
4605337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4606337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4607337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    data = lodepng_chunk_data_const(chunk);
4608337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4609337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*IDAT chunk, containing compressed image data*/
4610337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(lodepng_chunk_type_equals(chunk, "IDAT"))
4611337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4612337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t oldsize = idat.size;
4613337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/);
4614337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < chunkLength; i++) idat.data[oldsize + i] = data[i];
4615337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4616337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      critical_pos = 3;
4617337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4618337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4619337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*IEND chunk*/
4620337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "IEND"))
4621337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4622337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      IEND = 1;
4623337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4624337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*palette chunk (PLTE)*/
4625337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "PLTE"))
4626337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4627337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
4628337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
4629337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4630337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      critical_pos = 2;
4631337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4632337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4633337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*palette transparency chunk (tRNS)*/
4634337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "tRNS"))
4635337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4636337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
4637337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
4638337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4639337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4640337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*background color chunk (bKGD)*/
4641337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "bKGD"))
4642337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4643337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = readChunk_bKGD(&state->info_png, data, chunkLength);
4644337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
4645337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4646337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*text chunk (tEXt)*/
4647337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "tEXt"))
4648337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4649337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->decoder.read_text_chunks)
4650337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4651337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = readChunk_tEXt(&state->info_png, data, chunkLength);
4652337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(state->error) break;
4653337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4654337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4655337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*compressed text chunk (zTXt)*/
4656337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "zTXt"))
4657337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4658337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->decoder.read_text_chunks)
4659337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4660337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
4661337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(state->error) break;
4662337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4663337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4664337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*international text chunk (iTXt)*/
4665337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "iTXt"))
4666337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4667337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->decoder.read_text_chunks)
4668337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4669337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
4670337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(state->error) break;
4671337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4672337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4673337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "tIME"))
4674337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4675337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = readChunk_tIME(&state->info_png, data, chunkLength);
4676337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
4677337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4678337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(lodepng_chunk_type_equals(chunk, "pHYs"))
4679337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4680337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = readChunk_pHYs(&state->info_png, data, chunkLength);
4681337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
4682337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4683337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4684337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else /*it's not an implemented chunk type, so ignore it: skip over the data*/
4685337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4686337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
4687337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!lodepng_chunk_ancillary(chunk)) CERROR_BREAK(state->error, 69);
4688337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4689337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unknown = 1;
4690337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4691337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->decoder.remember_unknown_chunks)
4692337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
4693337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1],
4694337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                            &state->info_png.unknown_chunks_size[critical_pos - 1], chunk);
4695337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(state->error) break;
4696337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
4697337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4698337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4699337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4700337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/
4701337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4702337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/
4703337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4704337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4705337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!IEND) chunk = lodepng_chunk_next_const(chunk);
4706337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4707337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
47089ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  ucvector_init(&scanlines);
4709337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!state->error)
4710337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4711337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*maximum final image length is already reserved in the vector's length - this is not really necessary*/
4712337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!ucvector_resize(&scanlines, lodepng_get_raw_size(*w, *h, &state->info_png.color) + *h))
4713337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4714337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = 83; /*alloc fail*/
4715337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4716337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
47179ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if(!state->error)
47189ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  {
47199ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    /*decompress with the Zlib decompressor*/
47209ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
47219ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                   idat.size, &state->decoder.zlibsettings);
47229ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  }
4723337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&idat);
47249ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne
47259ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  if(!state->error)
47269ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  {
47279ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    ucvector outv;
47289ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    ucvector_init(&outv);
47299ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(!ucvector_resizev(&outv,
47309ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne        lodepng_get_raw_size(*w, *h, &state->info_png.color), 0)) state->error = 83; /*alloc fail*/
47319ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    if(!state->error) state->error = postProcessScanlines(outv.data, scanlines.data, *w, *h, &state->info_png);
47329ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    *out = outv.data;
47339ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  }
47349ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  ucvector_cleanup(&scanlines);
4735337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4736337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4737337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
4738337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        LodePNGState* state,
4739337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        const unsigned char* in, size_t insize)
4740337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4741337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = 0;
4742337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  decodeGeneric(out, w, h, state, in, insize);
4743337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->error) return state->error;
4744337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color))
4745337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4746337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*same color type, no copying or converting of data needed*/
4747337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype
4748337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    the raw image has to the end user*/
4749337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!state->decoder.color_convert)
4750337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4751337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color);
4752337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) return state->error;
4753337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4754337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4755337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else
4756337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4757337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*color conversion needed; sort of copy of the data*/
4758337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char* data = *out;
4759337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t outsize;
4760337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4761337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*TODO: check if this works according to the statement in the documentation: "The converter can convert
4762337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/
4763337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA)
4764337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne       && !(state->info_raw.bitdepth == 8))
4765337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4766337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      return 56; /*unsupported color mode conversion*/
4767337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4768337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4769337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    outsize = lodepng_get_raw_size(*w, *h, &state->info_raw);
4770337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *out = (unsigned char*)lodepng_malloc(outsize);
4771337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!(*out))
4772337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4773337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = 83; /*alloc fail*/
4774337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4775337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else state->error = lodepng_convert(*out, data, &state->info_raw, &state->info_png.color, *w, *h, state->decoder.fix_png);
4776337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(data);
4777337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4778337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return state->error;
4779337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4780337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4781337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in,
4782337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               size_t insize, LodePNGColorType colortype, unsigned bitdepth)
4783337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4784337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error;
4785337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGState state;
4786337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_init(&state);
4787337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state.info_raw.colortype = colortype;
4788337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state.info_raw.bitdepth = bitdepth;
4789337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = lodepng_decode(out, w, h, &state, in, insize);
4790337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_cleanup(&state);
4791337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4792337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4793337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4794337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)
4795337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4796337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8);
4797337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4798337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4799337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)
4800337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4801337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8);
4802337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4803337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4804337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DISK
4805337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,
4806337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             LodePNGColorType colortype, unsigned bitdepth)
4807337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4808337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer;
4809337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t buffersize;
4810337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error;
4811337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = lodepng_load_file(&buffer, &buffersize, filename);
4812337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth);
4813337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(buffer);
4814337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4815337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4816337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4817337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename)
4818337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4819337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8);
4820337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4821337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4822337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename)
4823337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4824337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8);
4825337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4826337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DISK*/
4827337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4828337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_decoder_settings_init(LodePNGDecoderSettings* settings)
4829337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4830337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->color_convert = 1;
4831337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
4832337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->read_text_chunks = 1;
4833337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->remember_unknown_chunks = 0;
4834337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
4835337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->ignore_crc = 0;
4836337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->fix_png = 0;
4837337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_decompress_settings_init(&settings->zlibsettings);
4838337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4839337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4840337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
4841337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4842337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
4843337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4844337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_state_init(LodePNGState* state)
4845337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4846337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
4847337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_decoder_settings_init(&state->decoder);
4848337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DECODER*/
4849337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
4850337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_encoder_settings_init(&state->encoder);
4851337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
4852337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_init(&state->info_raw);
4853337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_init(&state->info_png);
4854337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state->error = 1;
4855337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4856337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4857337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_state_cleanup(LodePNGState* state)
4858337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4859337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_cleanup(&state->info_raw);
4860337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_cleanup(&state->info_png);
4861337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4862337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4863337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_state_copy(LodePNGState* dest, const LodePNGState* source)
4864337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4865337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_cleanup(dest);
4866337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *dest = *source;
4867337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_color_mode_init(&dest->info_raw);
4868337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_init(&dest->info_png);
4869337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return;
4870337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return;
4871337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4872337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4873337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */
4874337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4875337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
4876337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4877337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
4878337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* / PNG Encoder                                                            / */
4879337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
4880337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4881337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*chunkName must be string of 4 characters*/
4882337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length)
4883337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4884337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data));
4885337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  out->allocsize = out->size; /*fix the allocsize again*/
4886337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
4887337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4888337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4889337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void writeSignature(ucvector* out)
4890337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4891337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*8 bytes PNG signature, aka the magic bytes*/
4892337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 137);
4893337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 80);
4894337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 78);
4895337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 71);
4896337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 13);
4897337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 10);
4898337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 26);
4899337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(out, 10);
4900337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4901337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4902337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,
4903337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method)
4904337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4905337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4906337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector header;
4907337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&header);
4908337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4909337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_add32bitInt(&header, w); /*width*/
4910337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_add32bitInt(&header, h); /*height*/
4911337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/
4912337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&header, (unsigned char)colortype); /*color type*/
4913337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&header, 0); /*compression method*/
4914337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&header, 0); /*filter method*/
4915337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&header, interlace_method); /*interlace method*/
4916337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4917337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "IHDR", header.data, header.size);
4918337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&header);
4919337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4920337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4921337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4922337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4923337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info)
4924337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4925337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4926337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
4927337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector PLTE;
4928337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&PLTE);
4929337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < info->palettesize * 4; i++)
4930337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4931337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*add all channels except alpha channel*/
4932337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]);
4933337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4934337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "PLTE", PLTE.data, PLTE.size);
4935337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&PLTE);
4936337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4937337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4938337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4939337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4940337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info)
4941337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4942337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4943337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
4944337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector tRNS;
4945337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&tRNS);
4946337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->colortype == LCT_PALETTE)
4947337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4948337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t amount = info->palettesize;
4949337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/
4950337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = info->palettesize; i > 0; i--)
4951337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4952337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(info->palette[4 * (i - 1) + 3] == 255) amount--;
4953337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else break;
4954337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4955337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*add only alpha channel*/
4956337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < amount; i++) ucvector_push_back(&tRNS, info->palette[4 * i + 3]);
4957337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4958337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(info->colortype == LCT_GREY)
4959337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4960337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info->key_defined)
4961337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4962337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256));
4963337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256));
4964337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4965337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4966337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(info->colortype == LCT_RGB)
4967337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
4968337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info->key_defined)
4969337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
4970337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256));
4971337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256));
4972337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_g / 256));
4973337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_g % 256));
4974337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_b / 256));
4975337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_push_back(&tRNS, (unsigned char)(info->key_b % 256));
4976337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
4977337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
4978337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4979337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "tRNS", tRNS.data, tRNS.size);
4980337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&tRNS);
4981337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4982337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4983337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4984337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4985337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize,
4986337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              LodePNGCompressSettings* zlibsettings)
4987337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
4988337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector zlibdata;
4989337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
4990337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4991337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*compress with the Zlib compressor*/
4992337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&zlibdata);
4993337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings);
4994337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size);
4995337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&zlibdata);
4996337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
4997337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
4998337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
4999337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5000337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_IEND(ucvector* out)
5001337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5002337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5003337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "IEND", 0, 0);
5004337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5005337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5006337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5007337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5008337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5009337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring)
5010337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5011337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5012337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
5013337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector text;
5014337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&text);
5015337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&text, (unsigned char)keyword[i]);
5016337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
5017337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&text, 0); /*0 termination char*/
5018337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&text, (unsigned char)textstring[i]);
5019337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "tEXt", text.data, text.size);
5020337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&text);
5021337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5022337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5023337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5024337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5025337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring,
5026337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              LodePNGCompressSettings* zlibsettings)
5027337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5028337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5029337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector data, compressed;
5030337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i, textsize = strlen(textstring);
5031337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5032337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&data);
5033337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&compressed);
5034337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&data, (unsigned char)keyword[i]);
5035337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
5036337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, 0); /*0 termination char*/
5037337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, 0); /*compression method: 0*/
5038337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5039337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = zlib_compress(&compressed.data, &compressed.size,
5040337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        (unsigned char*)textstring, textsize, zlibsettings);
5041337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error)
5042337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5043337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < compressed.size; i++) ucvector_push_back(&data, compressed.data[i]);
5044337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = addChunk(out, "zTXt", data.data, data.size);
5045337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5046337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5047337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&compressed);
5048337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&data);
5049337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5050337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5051337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5052337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag,
5053337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                              const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings)
5054337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5055337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5056337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector data;
5057337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i, textsize = strlen(textstring);
5058337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5059337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&data);
5060337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5061337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&data, (unsigned char)keyword[i]);
5062337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
5063337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, 0); /*null termination char*/
5064337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/
5065337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, 0); /*compression method*/
5066337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; langtag[i] != 0; i++) ucvector_push_back(&data, (unsigned char)langtag[i]);
5067337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, 0); /*null termination char*/
5068337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; transkey[i] != 0; i++) ucvector_push_back(&data, (unsigned char)transkey[i]);
5069337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, 0); /*null termination char*/
5070337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5071337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(compressed)
5072337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5073337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector compressed_data;
5074337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_init(&compressed_data);
5075337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    error = zlib_compress(&compressed_data.data, &compressed_data.size,
5076337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                          (unsigned char*)textstring, textsize, zlibsettings);
5077337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error)
5078337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5079337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < compressed_data.size; i++) ucvector_push_back(&data, compressed_data.data[i]);
5080337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5081337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_cleanup(&compressed_data);
5082337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5083337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*not compressed*/
5084337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5085337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&data, (unsigned char)textstring[i]);
5086337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5087337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5088337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) error = addChunk(out, "iTXt", data.data, data.size);
5089337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&data);
5090337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5091337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5092337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5093337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info)
5094337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5095337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5096337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector bKGD;
5097337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&bKGD);
5098337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA)
5099337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256));
5101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256));
5102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA)
5104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256));
5106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256));
5107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_g / 256));
5108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_g % 256));
5109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_b / 256));
5110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_b % 256));
5111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(info->color.colortype == LCT_PALETTE)
5113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); /*palette index*/
5115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "bKGD", bKGD.data, bKGD.size);
5118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&bKGD);
5119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5120337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5122337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time)
5124337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5126337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* data = (unsigned char*)lodepng_malloc(7);
5127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!data) return 83; /*alloc fail*/
5128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[0] = (unsigned char)(time->year / 256);
5129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[1] = (unsigned char)(time->year % 256);
5130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[2] = time->month;
5131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[3] = time->day;
5132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[4] = time->hour;
5133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[5] = time->minute;
5134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  data[6] = time->second;
5135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "tIME", data, 7);
5136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(data);
5137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info)
5141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector data;
5144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&data);
5145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_add32bitInt(&data, info->phys_x);
5147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_add32bitInt(&data, info->phys_y);
5148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_push_back(&data, info->phys_unit);
5149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = addChunk(out, "pHYs", data.data, data.size);
5151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_cleanup(&data);
5152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,
5159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                           size_t length, size_t bytewidth, unsigned char filterType)
5160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i;
5162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  switch(filterType)
5163337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 0: /*None*/
5165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < length; i++) out[i] = scanline[i];
5166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
5167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 1: /*Sub*/
5168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(prevline)
5169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5170337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) out[i] = scanline[i];
5171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth];
5172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
5174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) out[i] = scanline[i];
5176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth];
5177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
5179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 2: /*Up*/
5180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(prevline)
5181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < length; i++) out[i] = scanline[i] - prevline[i];
5183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
5185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < length; i++) out[i] = scanline[i];
5187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
5189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 3: /*Average*/
5190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(prevline)
5191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) out[i] = scanline[i] - prevline[i] / 2;
5193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) / 2);
5194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
5196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) out[i] = scanline[i];
5198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth] / 2;
5199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
5201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 4: /*Paeth*/
5202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(prevline)
5203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/
5205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) out[i] = (scanline[i] - prevline[i]);
5206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++)
5207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth]));
5209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
5212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = 0; i < bytewidth; i++) out[i] = scanline[i];
5214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/
5215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(i = bytewidth; i < length; i++) out[i] = (scanline[i] - scanline[i - bytewidth]);
5216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      break;
5218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    default: return; /*unexisting filter type given*/
5219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* log2 approximation. A slight bit faster than std::log. */
5223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic float flog2(float f)
5224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  float result = 0;
5226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(f > 32) { result += 4; f /= 16; }
5227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(f > 2) { result++; f /= 2; }
5228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f);
5229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
5232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                       const LodePNGColorMode* info, const LodePNGEncoderSettings* settings)
5233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
5235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  For PNG filter method 0
5236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are
5237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  the scanlines with 1 extra byte per scanline
5238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
5239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned bpp = lodepng_get_bpp(info);
5241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*the width of a scanline in bytes, not including the filter type*/
5242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t linebytes = (w * bpp + 7) / 8;
5243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
5244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t bytewidth = (bpp + 7) / 8;
5245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  const unsigned char* prevline = 0;
5246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned x, y;
5247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGFilterStrategy strategy = settings->filter_strategy;
5249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
5251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:
5252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne   *  If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.
5253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      use fixed filtering, with the filter None).
5254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne   * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is
5255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply
5256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     all five filters and select the filter that produces the smallest sum of absolute values per row.
5257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.
5258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,
5260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum
5261337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  heuristic is used.
5262337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
5263337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(settings->filter_palette_zero &&
5264337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO;
5265337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5266337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(bpp == 0) return 31; /*error: invalid color type*/
5267337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5268337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(strategy == LFS_ZERO)
5269337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5270337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(y = 0; y < h; y++)
5271337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5272337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
5273337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t inindex = linebytes * y;
5274337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[outindex] = 0; /*filter type byte*/
5275337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0);
5276337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      prevline = &in[inindex];
5277337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5278337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5279337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(strategy == LFS_MINSUM)
5280337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5281337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*adaptive filtering*/
5282337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t sum[5];
5283337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector attempt[5]; /*five filtering attempts, one for each filter type*/
5284337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t smallest = 0;
5285337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned type, bestType = 0;
5286337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5287337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(type = 0; type < 5; type++)
5288337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5289337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_init(&attempt[type]);
5290337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/
5291337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5292337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5293337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error)
5294337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5295337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(y = 0; y < h; y++)
5296337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5297337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*try the 5 filter types*/
5298337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(type = 0; type < 5; type++)
5299337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5300337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type);
5301337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5302337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*calculate the sum of the result*/
5303337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          sum[type] = 0;
5304337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(type == 0)
5305337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
5306337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            for(x = 0; x < linebytes; x++) sum[type] += (unsigned char)(attempt[type].data[x]);
5307337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
5308337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          else
5309337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
5310337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            for(x = 0; x < linebytes; x++)
5311337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            {
5312337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne              /*For differences, each byte should be treated as signed, values above 127 are negative
5313337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne              (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.
5314337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne              This means filtertype 0 is almost never chosen, but that is justified.*/
5315337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne              signed char s = (signed char)(attempt[type].data[x]);
5316337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne              sum[type] += s < 0 ? -s : s;
5317337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            }
5318337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
5319337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5320337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
5321337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(type == 0 || sum[type] < smallest)
5322337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          {
5323337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            bestType = type;
5324337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne            smallest = sum[type];
5325337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          }
5326337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5327337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5328337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        prevline = &in[y * linebytes];
5329337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5330337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*now fill the out values*/
5331337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
5332337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x];
5333337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5334337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5335337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5336337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]);
5337337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5338337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(strategy == LFS_ENTROPY)
5339337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5340337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    float sum[5];
5341337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector attempt[5]; /*five filtering attempts, one for each filter type*/
5342337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    float smallest = 0;
5343337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned type, bestType = 0;
5344337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned count[256];
5345337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5346337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(type = 0; type < 5; type++)
5347337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5348337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_init(&attempt[type]);
5349337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(!ucvector_resize(&attempt[type], linebytes)) return 83; /*alloc fail*/
5350337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5351337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5352337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(y = 0; y < h; y++)
5353337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5354337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*try the 5 filter types*/
5355337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(type = 0; type < 5; type++)
5356337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5357337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type);
5358337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(x = 0; x < 256; x++) count[x] = 0;
5359337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(x = 0; x < linebytes; x++) count[attempt[type].data[x]]++;
5360337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        count[type]++; /*the filter type itself is part of the scanline*/
5361337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        sum[type] = 0;
5362337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(x = 0; x < 256; x++)
5363337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5364337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          float p = count[x] / (float)(linebytes + 1);
5365337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p;
5366337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5367337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
5368337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(type == 0 || sum[type] < smallest)
5369337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5370337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          bestType = type;
5371337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          smallest = sum[type];
5372337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5373337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5374337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5375337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      prevline = &in[y * linebytes];
5376337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5377337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*now fill the out values*/
5378337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
5379337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x];
5380337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5381337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5382337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]);
5383337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5384337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(strategy == LFS_PREDEFINED)
5385337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5386337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(y = 0; y < h; y++)
5387337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5388337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
5389337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t inindex = linebytes * y;
5390337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned type = settings->predefined_filters[y];
5391337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[outindex] = type; /*filter type byte*/
5392337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
5393337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      prevline = &in[inindex];
5394337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5395337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5396337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else if(strategy == LFS_BRUTE_FORCE)
5397337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5398337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*brute force filter chooser.
5399337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    deflate the scanline after every filter attempt to see which one deflates best.
5400337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    This is very slow and gives only slightly smaller, sometimes even larger, result*/
5401337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t size[5];
5402337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    ucvector attempt[5]; /*five filtering attempts, one for each filter type*/
5403337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t smallest = 0;
5404337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned type = 0, bestType = 0;
5405337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char* dummy;
5406337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    LodePNGCompressSettings zlibsettings = settings->zlibsettings;
5407337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,
5408337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    to simulate the true case where the tree is the same for the whole image. Sometimes it gives
5409337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare
5410337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    cases better compression. It does make this a bit less slow, so it's worth doing this.*/
5411337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    zlibsettings.btype = 1;
5412337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG
5413337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    images only, so disable it*/
5414337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    zlibsettings.custom_zlib = 0;
5415337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    zlibsettings.custom_deflate = 0;
5416337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(type = 0; type < 5; type++)
5417337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5418337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_init(&attempt[type]);
5419337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      ucvector_resize(&attempt[type], linebytes); /*todo: give error if resize failed*/
5420337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5421337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(y = 0; y < h; y++) /*try the 5 filter types*/
5422337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5423337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(type = 0; type < 5; type++)
5424337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5425337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned testsize = attempt[type].size;
5426337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/
5427337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5428337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type);
5429337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        size[type] = 0;
5430337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        dummy = 0;
5431337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        zlib_compress(&dummy, &size[type], attempt[type].data, testsize, &zlibsettings);
5432337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        lodepng_free(dummy);
5433337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/
5434337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(type == 0 || size[type] < smallest)
5435337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5436337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          bestType = type;
5437337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          smallest = size[type];
5438337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5439337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5440337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      prevline = &in[y * linebytes];
5441337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
5442337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x];
5443337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5444337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]);
5445337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5446337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else return 88; /* unknown filter strategy */
5447337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5448337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5449337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5450337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5451337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void addPaddingBits(unsigned char* out, const unsigned char* in,
5452337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                           size_t olinebits, size_t ilinebits, unsigned h)
5453337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5454337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*The opposite of the removePaddingBits function
5455337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  olinebits must be >= ilinebits*/
5456337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned y;
5457337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t diff = olinebits - ilinebits;
5458337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t obp = 0, ibp = 0; /*bit pointers*/
5459337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(y = 0; y < h; y++)
5460337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5461337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t x;
5462337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(x = 0; x < ilinebits; x++)
5463337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5464337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned char bit = readBitFromReversedStream(&ibp, in);
5465337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      setBitOfReversedStream(&obp, out, bit);
5466337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5467337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*obp += diff; --> no, fill in some value in the padding bits too, to avoid
5468337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    "Use of uninitialised value of size ###" warning from valgrind*/
5469337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(x = 0; x < diff; x++) setBitOfReversedStream(&obp, out, 0);
5470337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5471337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5472337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5473337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
5474337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennein: non-interlaced image with size w*h
5475337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneout: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with
5476337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne no padding bits between scanlines, but between reduced images so that each
5477337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne reduced image starts at a byte.
5478337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennebpp: bits per pixel
5479337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethere are no padding bits, not between scanlines, not between reduced images
5480337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennein has the following size in bits: w * h * bpp.
5481337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneout is possibly bigger due to padding bits between reduced images
5482337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneNOTE: comments about padding bits are only relevant if bpp < 8
5483337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
5484337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
5485337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5486337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned passw[7], passh[7];
5487337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t filter_passstart[8], padded_passstart[8], passstart[8];
5488337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned i;
5489337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5490337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
5491337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5492337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(bpp >= 8)
5493337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5494337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < 7; i++)
5495337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5496337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned x, y, b;
5497337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t bytewidth = bpp / 8;
5498337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(y = 0; y < passh[i]; y++)
5499337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(x = 0; x < passw[i]; x++)
5500337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5501337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
5502337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth;
5503337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(b = 0; b < bytewidth; b++)
5504337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5505337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          out[pixeloutstart + b] = in[pixelinstart + b];
5506337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5507337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5508337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5509337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5510337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/
5511337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5512337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < 7; i++)
5513337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5514337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned x, y, b;
5515337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned ilinebits = bpp * passw[i];
5516337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned olinebits = bpp * w;
5517337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      size_t obp, ibp; /*bit pointers (for out and in buffer)*/
5518337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(y = 0; y < passh[i]; y++)
5519337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(x = 0; x < passw[i]; x++)
5520337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5521337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
5522337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        obp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
5523337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        for(b = 0; b < bpp; b++)
5524337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5525337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          unsigned char bit = readBitFromReversedStream(&ibp, in);
5526337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          setBitOfReversedStream(&obp, out, bit);
5527337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5528337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5529337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5530337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5531337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5532337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5533337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image.
5534337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturn value is error**/
5535337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in,
5536337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    unsigned w, unsigned h,
5537337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                                    const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings)
5538337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5539337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*
5540337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps:
5541337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter
5542337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter
5543337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  */
5544337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned bpp = lodepng_get_bpp(&info_png->color);
5545337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = 0;
5546337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5547337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(info_png->interlace_method == 0)
5548337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5549337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/
5550337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *out = (unsigned char*)lodepng_malloc(*outsize);
5551337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!(*out) && (*outsize)) error = 83; /*alloc fail*/
5552337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5553337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error)
5554337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5555337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      /*non multiple of 8 bits per scanline, padding bits needed per scanline*/
5556337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)
5557337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5558337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8));
5559337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!padded) error = 83; /*alloc fail*/
5560337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!error)
5561337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5562337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h);
5563337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          error = filter(*out, padded, w, h, &info_png->color, settings);
5564337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5565337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        lodepng_free(padded);
5566337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5567337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
5568337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5569337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        /*we can immediatly filter into the out buffer, no other steps needed*/
5570337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        error = filter(*out, in, w, h, &info_png->color, settings);
5571337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5572337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5573337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5574337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else /*interlace_method is 1 (Adam7)*/
5575337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5576337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned passw[7], passh[7];
5577337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t filter_passstart[8], padded_passstart[8], passstart[8];
5578337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char* adam7;
5579337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5580337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
5581337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5582337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/
5583337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    *out = (unsigned char*)lodepng_malloc(*outsize);
5584337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!(*out)) error = 83; /*alloc fail*/
5585337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5586337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    adam7 = (unsigned char*)lodepng_malloc(passstart[7]);
5587337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!adam7 && passstart[7]) error = 83; /*alloc fail*/
5588337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5589337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!error)
5590337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5591337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned i;
5592337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5593337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      Adam7_interlace(adam7, in, w, h, bpp);
5594337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < 7; i++)
5595337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5596337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(bpp < 8)
5597337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5598337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]);
5599337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          if(!padded) ERROR_BREAK(83); /*alloc fail*/
5600337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          addPaddingBits(padded, &adam7[passstart[i]],
5601337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]);
5602337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          error = filter(&(*out)[filter_passstart[i]], padded,
5603337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         passw[i], passh[i], &info_png->color, settings);
5604337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          lodepng_free(padded);
5605337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5606337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        else
5607337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5608337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]],
5609337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                         passw[i], passh[i], &info_png->color, settings);
5610337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5611337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5612337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(error) break;
5613337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5614337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5615337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5616337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(adam7);
5617337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5618337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5619337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5620337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5621337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5622337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
5623337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennepalette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA...
5624337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturns 0 if the palette is opaque,
5625337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturns 1 if the palette has a single color with alpha 0 ==> color key
5626337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennereturns 2 if the palette is semi-translucent.
5627337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
5628337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize)
5629337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5630337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t i, key = 0;
5631337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/
5632337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  for(i = 0; i < palettesize; i++)
5633337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5634337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!key && palette[4 * i + 3] == 0)
5635337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5636337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2];
5637337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      key = 1;
5638337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/
5639337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5640337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(palette[4 * i + 3] != 255) return 2;
5641337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*when key, no opaque RGB may have key's RGB*/
5642337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2;
5643337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5644337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return key;
5645337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5646337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5647337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5648337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennestatic unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize)
5649337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5650337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* inchunk = data;
5651337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while((size_t)(inchunk - data) < datasize)
5652337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5653337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));
5654337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out->allocsize = out->size; /*fix the allocsize again*/
5655337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    inchunk = lodepng_chunk_next(inchunk);
5656337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5657337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return 0;
5658337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5659337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5660337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5661337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode(unsigned char** out, size_t* outsize,
5662337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        const unsigned char* image, unsigned w, unsigned h,
5663337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                        LodePNGState* state)
5664337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5665337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGInfo info;
5666337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector outv;
5667337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/
5668337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t datasize = 0;
5669337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5670337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*provide some proper output values if error will happen*/
5671337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = 0;
5672337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = 0;
5673337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state->error = 0;
5674337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5675337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_init(&info);
5676337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_copy(&info, &state->info_png);
5677337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5678337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if((info.color.colortype == LCT_PALETTE || state->encoder.force_palette)
5679337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      && (info.color.palettesize == 0 || info.color.palettesize > 256))
5680337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5681337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/
5682337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    return state->error;
5683337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5684337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5685337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->encoder.auto_convert != LAC_NO)
5686337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
56879ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw,
56889ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne                                             state->encoder.auto_convert);
5689337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5690337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->error) return state->error;
5691337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5692337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->encoder.zlibsettings.btype > 2)
5693337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5694337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/
5695337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5696337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->info_png.interlace_method > 1)
5697337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5698337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    CERROR_RETURN_ERROR(state->error, 71); /*error: unexisting interlace mode*/
5699337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5700337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5701337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state->error = checkColorValidity(info.color.colortype, info.color.bitdepth);
5702337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->error) return state->error; /*error: unexisting color type given*/
5703337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);
5704337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(state->error) return state->error; /*error: unexisting color type given*/
5705337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5706337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!lodepng_color_mode_equal(&state->info_raw, &info.color))
5707337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5708337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    unsigned char* converted;
5709337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t size = (w * h * lodepng_get_bpp(&info.color) + 7) / 8;
5710337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5711337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    converted = (unsigned char*)lodepng_malloc(size);
5712337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!converted && size) state->error = 83; /*alloc fail*/
5713337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!state->error)
5714337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5715337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h, 0 /*fix_png*/);
5716337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5717337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
5718337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(converted);
5719337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5720337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
5721337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5722337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  ucvector_init(&outv);
5723337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  while(!state->error) /*while only executed once, to break on error*/
5724337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5725337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5726337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t i;
5727337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5728337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*write signature and chunks*/
5729337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    writeSignature(&outv);
5730337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*IHDR*/
5731337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method);
5732337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5733337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*unknown chunks between IHDR and PLTE*/
5734337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.unknown_chunks_data[0])
5735337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5736337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]);
5737337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
5738337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5739337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5740337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*PLTE*/
5741337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.color.colortype == LCT_PALETTE)
5742337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5743337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addChunk_PLTE(&outv, &info.color);
5744337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5745337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA))
5746337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5747337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addChunk_PLTE(&outv, &info.color);
5748337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5749337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*tRNS*/
5750337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0)
5751337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5752337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addChunk_tRNS(&outv, &info.color);
5753337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5754337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined)
5755337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5756337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addChunk_tRNS(&outv, &info.color);
5757337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5758337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5759337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*bKGD (must come between PLTE and the IDAt chunks*/
5760337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.background_defined) addChunk_bKGD(&outv, &info);
5761337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*pHYs (must come before the IDAT chunks)*/
5762337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.phys_defined) addChunk_pHYs(&outv, &info);
5763337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5764337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*unknown chunks between PLTE and IDAT*/
5765337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.unknown_chunks_data[1])
5766337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5767337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]);
5768337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
5769337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5770337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5771337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*IDAT (multiple IDAT chunks must be consecutive)*/
5772337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings);
5773337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(state->error) break;
5774337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5775337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*tIME*/
5776337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.time_defined) addChunk_tIME(&outv, &info.time);
5777337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*tEXt and/or zTXt*/
5778337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < info.text_num; i++)
5779337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5780337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(strlen(info.text_keys[i]) > 79)
5781337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5782337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = 66; /*text chunk too large*/
5783337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
5784337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5785337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(strlen(info.text_keys[i]) < 1)
5786337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5787337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = 67; /*text chunk too small*/
5788337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
5789337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5790337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->encoder.text_compression)
57919ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      {
5792337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);
57939ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      }
5794337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      else
57959ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      {
5796337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);
57979ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      }
5798337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5799337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*LodePNG version id in text chunk*/
5800337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(state->encoder.add_id)
5801337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5802337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      unsigned alread_added_id_text = 0;
5803337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      for(i = 0; i < info.text_num; i++)
5804337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5805337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        if(!strcmp(info.text_keys[i], "LodePNG"))
5806337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        {
5807337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          alread_added_id_text = 1;
5808337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne          break;
5809337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        }
5810337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5811337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(alread_added_id_text == 0)
58129ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      {
5813337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        addChunk_tEXt(&outv, "LodePNG", VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/
58149ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne      }
5815337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5816337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*iTXt*/
5817337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    for(i = 0; i < info.itext_num; i++)
5818337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5819337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(strlen(info.itext_keys[i]) > 79)
5820337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5821337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = 66; /*text chunk too large*/
5822337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
5823337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5824337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(strlen(info.itext_keys[i]) < 1)
5825337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      {
5826337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        state->error = 67; /*text chunk too small*/
5827337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne        break;
5828337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      }
5829337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      addChunk_iTXt(&outv, state->encoder.text_compression,
5830337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                    info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i],
5831337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                    &state->encoder.zlibsettings);
5832337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5833337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5834337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*unknown chunks between IDAT and IEND*/
5835337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    if(info.unknown_chunks_data[2])
5836337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    {
5837337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]);
5838337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne      if(state->error) break;
5839337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    }
5840337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5841337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    addChunk_IEND(&outv);
5842337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5843337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    break; /*this isn't really a while loop; no error happened so break out now!*/
5844337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
5845337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5846337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_info_cleanup(&info);
5847337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(data);
5848337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*instead of cleaning the vector up, give it to the output*/
5849337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *out = outv.data;
5850337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  *outsize = outv.size;
5851337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5852337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return state->error;
5853337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5854337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5855337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image,
5856337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                               unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)
5857337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5858337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error;
5859337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  LodePNGState state;
5860337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_init(&state);
5861337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state.info_raw.colortype = colortype;
5862337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state.info_raw.bitdepth = bitdepth;
5863337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state.info_png.color.colortype = colortype;
5864337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  state.info_png.color.bitdepth = bitdepth;
5865337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_encode(out, outsize, image, w, h, &state);
5866337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  error = state.error;
5867337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_cleanup(&state);
5868337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5869337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5870337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5871337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)
5872337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5873337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8);
5874337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5875337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5876337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)
5877337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5878337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8);
5879337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5880337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5881337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DISK
5882337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h,
5883337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                             LodePNGColorType colortype, unsigned bitdepth)
5884337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5885337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer;
5886337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t buffersize;
5887337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth);
5888337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) error = lodepng_save_file(buffer, buffersize, filename);
5889337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_free(buffer);
5890337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
5891337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5892337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5893337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h)
5894337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5895337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8);
5896337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5897337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5898337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h)
5899337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5900337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8);
5901337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5902337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_DISK*/
5903337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5904337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid lodepng_encoder_settings_init(LodePNGEncoderSettings* settings)
5905337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5906337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_compress_settings_init(&settings->zlibsettings);
5907337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->filter_palette_zero = 1;
5908337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->filter_strategy = LFS_MINSUM;
5909337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->auto_convert = LAC_AUTO;
5910337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->force_palette = 0;
5911337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->predefined_filters = 0;
5912337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
5913337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->add_id = 0;
5914337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  settings->text_compression = 1;
5915337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
5916337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
5917337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5918337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ENCODER*/
5919337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_PNG*/
5920337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
5921337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ERROR_TEXT
5922337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*
5923337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneThis returns the description of a numerical error code in English. This is also
5924337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennethe documentation of all the error codes.
5925337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne*/
5926337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneconst char* lodepng_error_text(unsigned code)
5927337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
5928337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  switch(code)
5929337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
5930337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 0: return "no error, everything went ok";
5931337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/
5932337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/
5933337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/
5934337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 13: return "problem while processing dynamic deflate block";
5935337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 14: return "problem while processing dynamic deflate block";
5936337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 15: return "problem while processing dynamic deflate block";
5937337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 16: return "unexisting code while processing dynamic deflate block";
5938337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 17: return "end of out buffer memory reached while inflating";
5939337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 18: return "invalid distance code while inflating";
5940337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 19: return "end of out buffer memory reached while inflating";
5941337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 20: return "invalid deflate block BTYPE encountered while decoding";
5942337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 21: return "NLEN is not ones complement of LEN in a deflate block";
5943337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     /*end of out buffer memory reached while inflating:
5944337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     This can happen if the inflated deflate data is longer than the amount of bytes required to fill up
5945337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     all the pixels of the image, given the color depth and image dimensions. Something that doesn't
5946337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne     happen in a normal, well encoded, PNG image.*/
5947337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 22: return "end of out buffer memory reached while inflating";
5948337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 23: return "end of in buffer memory reached while inflating";
5949337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 24: return "invalid FCHECK in zlib header";
5950337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 25: return "invalid compression method in zlib header";
5951337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 26: return "FDICT encountered in zlib header while it's not used for PNG";
5952337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 27: return "PNG file is smaller than a PNG header";
5953337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Checks the magic file header, the first 8 bytes of the PNG file*/
5954337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 28: return "incorrect PNG signature, it's no PNG or corrupted";
5955337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 29: return "first chunk is not the header chunk";
5956337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 30: return "chunk length too large, chunk broken off at end of file";
5957337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 31: return "illegal PNG color type or bpp";
5958337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 32: return "illegal PNG compression method";
5959337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 33: return "illegal PNG filter method";
5960337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 34: return "illegal PNG interlace method";
5961337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 35: return "chunk length of a chunk is too large or the chunk too small";
5962337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 36: return "illegal PNG filter type encountered";
5963337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 37: return "illegal bit depth for this color type given";
5964337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 38: return "the palette is too big"; /*more than 256 colors*/
5965337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 39: return "more palette alpha values given in tRNS chunk than there are colors in the palette";
5966337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 40: return "tRNS chunk has wrong size for greyscale image";
5967337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 41: return "tRNS chunk has wrong size for RGB image";
5968337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 42: return "tRNS chunk appeared while it was not allowed for this color type";
5969337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 43: return "bKGD chunk has wrong size for palette image";
5970337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 44: return "bKGD chunk has wrong size for greyscale image";
5971337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 45: return "bKGD chunk has wrong size for RGB image";
5972337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Is the palette too small?*/
5973337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 46: return "a value in indexed image is larger than the palette size (bitdepth = 8)";
5974337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*Is the palette too small?*/
5975337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 47: return "a value in indexed image is larger than the palette size (bitdepth < 8)";
5976337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*the input data is empty, maybe a PNG file doesn't exist or is in the wrong path*/
5977337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 48: return "empty input or file doesn't exist";
5978337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 49: return "jumped past memory while generating dynamic huffman tree";
5979337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 50: return "jumped past memory while generating dynamic huffman tree";
5980337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 51: return "jumped past memory while inflating huffman block";
5981337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 52: return "jumped past memory while inflating";
5982337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 53: return "size of zlib data too small";
5983337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 54: return "repeat symbol in tree while there was no value symbol yet";
5984337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*jumped past tree while generating huffman tree, this could be when the
5985337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    tree will have more leaves than symbols after generating it out of the
5986337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/
5987337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 55: return "jumped past tree while generating huffman tree";
5988337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 56: return "given output image colortype or bitdepth not supported for color conversion";
5989337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 57: return "invalid CRC encountered (checking CRC can be disabled)";
5990337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)";
5991337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 59: return "requested color conversion not supported";
5992337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)";
5993337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)";
5994337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*LodePNG leaves the choice of RGB to greyscale conversion formula to the user.*/
5995337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 62: return "conversion from color to greyscale not supported";
5996337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; /*(2^31-1)*/
5997337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/
5998337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 64: return "the length of the END symbol 256 in the Huffman tree is 0";
5999337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes";
6000337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte";
6001337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors";
6002337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 69: return "unknown chunk type with 'critical' flag encountered by the decoder";
6003337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 71: return "unexisting interlace mode given to encoder (must be 0 or 1)";
6004337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 72: return "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)";
6005337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 73: return "invalid tIME chunk size";
6006337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 74: return "invalid pHYs chunk size";
6007337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    /*length could be wrong, or data chopped off*/
6008337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 75: return "no null termination char found while decoding text chunk";
6009337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 76: return "iTXt chunk too short to contain required bytes";
6010337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 77: return "integer overflow in buffer size";
6011337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/
6012337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 79: return "failed to open file for writing";
6013337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 80: return "tried creating a tree of 0 symbols";
6014337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 81: return "lazy matching at pos 0 is impossible";
6015337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 82: return "color conversion to palette requested while a color isn't in palette";
6016337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 83: return "memory allocation failed";
6017337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 84: return "given image too small to contain all pixels to be encoded";
6018337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 85: return "internal color conversion bug";
6019337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 86: return "impossible offset in lz77 encoding (internal bug)";
6020337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined";
6021337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy";
6022337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    case 89: return "text chunk keyword too short or long: must have size 1-79";
60239ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/
60249ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne    case 90: return "windowsize must be a power of two";
6025337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
6026337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return "unknown error code";
6027337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6028337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_ERROR_TEXT*/
6029337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6030337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
6031337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
6032337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* // C++ Wrapper                                                          // */
6033337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
6034337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/* ////////////////////////////////////////////////////////////////////////// */
6035337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6036337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_CPP
6037337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennenamespace lodepng
6038337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6039337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6040337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DISK
6041337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid load_file(std::vector<unsigned char>& buffer, const std::string& filename)
6042337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6043337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
6044337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6045337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*get filesize*/
6046337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::streamsize size = 0;
6047337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(file.seekg(0, std::ios::end).good()) size = file.tellg();
6048337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(file.seekg(0, std::ios::beg).good()) size -= file.tellg();
6049337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6050337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  /*read contents of the file into the vector*/
6051337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  buffer.resize(size_t(size));
6052337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(size > 0) file.read((char*)(&buffer[0]), size);
6053337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6054337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6055337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
6056337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevennevoid save_file(const std::vector<unsigned char>& buffer, const std::string& filename)
6057337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6058337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::ofstream file(filename.c_str(), std::ios::out|std::ios::binary);
6059337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  file.write(buffer.empty() ? 0 : (char*)&buffer[0], std::streamsize(buffer.size()));
6060337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6061337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_DISK
6062337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6063337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ZLIB
6064337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
6065337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
6066337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                    const LodePNGDecompressSettings& settings)
6067337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6068337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer = 0;
6069337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t buffersize = 0;
6070337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings);
6071337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(buffer)
6072337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
6073337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6074337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(buffer);
6075337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
6076337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6077337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6078337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6079337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
6080337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                    const LodePNGDecompressSettings& settings)
6081337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6082337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings);
6083337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6084337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_DECODER
6085337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6086337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
6087337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
6088337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                  const LodePNGCompressSettings& settings)
6089337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6090337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer = 0;
6091337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t buffersize = 0;
6092337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);
6093337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(buffer)
6094337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
6095337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6096337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(buffer);
6097337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
6098337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6099337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6100337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6101337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
6102337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                  const LodePNGCompressSettings& settings)
6103337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6104337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return compress(out, in.empty() ? 0 : &in[0], in.size(), settings);
6105337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6106337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_ENCODER
6107337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_ZLIB
6108337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6109337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6110337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_PNG
6111337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6112337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneState::State()
6113337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6114337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_init(this);
6115337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6116337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6117337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneState::State(const State& other)
6118337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6119337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_init(this);
6120337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_copy(this, &other);
6121337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6122337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6123337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneState::~State()
6124337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6125337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_cleanup(this);
6126337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6127337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6128337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode VandevenneState& State::operator=(const State& other)
6129337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6130337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  lodepng_state_copy(this, &other);
6131337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return *this;
6132337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6133337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6134337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DECODER
6135337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6136337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const unsigned char* in,
6137337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                size_t insize, LodePNGColorType colortype, unsigned bitdepth)
6138337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6139337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer;
6140337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth);
6141337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(buffer && !error)
6142337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
6143337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    State state;
6144337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    state.info_raw.colortype = colortype;
6145337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    state.info_raw.bitdepth = bitdepth;
6146337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
6147337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6148337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(buffer);
6149337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
6150337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6151337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6152337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6153337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
6154337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const std::vector<unsigned char>& in, LodePNGColorType colortype, unsigned bitdepth)
6155337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6156337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth);
6157337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6158337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6159337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
6160337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                State& state,
6161337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const unsigned char* in, size_t insize)
6162337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
61639ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  unsigned char* buffer = NULL;
6164337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);
6165337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(buffer && !error)
6166337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
6167337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
6168337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6169337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
61709ec1023fe7b16c10be9a96b1cd90cf298f7f3d90Lode Vandevenne  lodepng_free(buffer);
6171337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6172337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6173337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6174337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
6175337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                State& state,
6176337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const std::vector<unsigned char>& in)
6177337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6178337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size());
6179337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6180337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6181337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DISK
6182337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const std::string& filename,
6183337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                LodePNGColorType colortype, unsigned bitdepth)
6184337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6185337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::vector<unsigned char> buffer;
6186337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  load_file(buffer, filename);
6187337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return decode(out, w, h, buffer, colortype, bitdepth);
6188337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6189337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_DECODER
6190337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_DISK
6191337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6192337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_ENCODER
6193337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned w, unsigned h,
6194337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                LodePNGColorType colortype, unsigned bitdepth)
6195337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6196337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer;
6197337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t buffersize;
6198337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);
6199337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(buffer)
6200337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
6201337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6202337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(buffer);
6203337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
6204337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6205337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6206337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6207337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned encode(std::vector<unsigned char>& out,
6208337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const std::vector<unsigned char>& in, unsigned w, unsigned h,
6209337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                LodePNGColorType colortype, unsigned bitdepth)
6210337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6211337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
6212337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
6213337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6214337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6215337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned encode(std::vector<unsigned char>& out,
6216337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const unsigned char* in, unsigned w, unsigned h,
6217337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                State& state)
6218337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6219337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned char* buffer;
6220337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  size_t buffersize;
6221337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);
6222337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(buffer)
6223337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  {
6224337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    out.insert(out.end(), &buffer[0], &buffer[buffersize]);
6225337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne    lodepng_free(buffer);
6226337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  }
6227337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6228337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6229337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6230337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned encode(std::vector<unsigned char>& out,
6231337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const std::vector<unsigned char>& in, unsigned w, unsigned h,
6232337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                State& state)
6233337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6234337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84;
6235337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return encode(out, in.empty() ? 0 : &in[0], w, h, state);
6236337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6237337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6238337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#ifdef LODEPNG_COMPILE_DISK
6239337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned encode(const std::string& filename,
6240337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const unsigned char* in, unsigned w, unsigned h,
6241337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                LodePNGColorType colortype, unsigned bitdepth)
6242337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6243337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  std::vector<unsigned char> buffer;
6244337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  unsigned error = encode(buffer, in, w, h, colortype, bitdepth);
6245337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(!error) save_file(buffer, filename);
6246337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return error;
6247337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6248337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne
6249337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenneunsigned encode(const std::string& filename,
6250337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                const std::vector<unsigned char>& in, unsigned w, unsigned h,
6251337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne                LodePNGColorType colortype, unsigned bitdepth)
6252337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne{
6253337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
6254337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne  return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
6255337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne}
6256337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_DISK
6257337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_ENCODER
6258337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif //LODEPNG_COMPILE_PNG
6259337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne} //namespace lodepng
6260337d27f25ef15a6cf34fef2acd0613fddc411cb1Lode Vandevenne#endif /*LODEPNG_COMPILE_CPP*/
6261