/*
LodePNG version 20120729
Copyright (c) 2005-2012 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
/*
The manual and changelog are in the header file "lodepng.h"
Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.
*/
#include "lodepng.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef LODEPNG_COMPILE_CPP
#include <fstream>
#endif /*LODEPNG_COMPILE_CPP*/
#define VERSION_STRING "20120729"
/*
This source file is built up in the following large parts. The code sections
with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way.
-Tools for C and common code for PNG and Zlib
-C Code for Zlib (huffman, deflate, ...)
-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)
-The C++ wrapper around all of the above
*/
/*The malloc, realloc and free functions defined here with "my" in front of the
name, so that you can easily change them to others related to your platform in
this one location if needed. Everything else in the code calls these.*/
static void* mymalloc(size_t size)
{
return malloc(size);
}
static void* myrealloc(void* ptr, size_t new_size)
{
return realloc(ptr, new_size);
}
static void myfree(void* ptr)
{
free(ptr);
}
/*
Declaration of the custom functions used if LODEPNG_COMPILE_ZLIB isn't defined
or LODEPNG_CUSTOM_ZLIB_DECODER or LODEPNG_CUSTOM_ZLIB_ENCODER are enabled.
In that case, you need to define these yourself (which you can do in one of your
own source files) so that LodePNG can link to it.
By default, this is not needed. If LODEPNG_COMPILE_ZLIB isn't defined, then only
the two zlib related ones are needed.
If needed, the functions must act as follows:
*out must be NULL and *outsize must be 0 initially, and after the function is done,
*out must point to the decompressed data, *outsize must be the size of it, and must
be the size of the useful data in bytes, not the alloc size.
*/
unsigned lodepng_custom_zlib_decompress(unsigned char** out, size_t* outsize,
const unsigned char* in, size_t insize,
const LodePNGDecompressSettings* settings);
unsigned lodepng_custom_zlib_compress(unsigned char** out, size_t* outsize,
const unsigned char* in, size_t insize,
const LodePNGCompressSettings* settings);
unsigned lodepng_custom_inflate(unsigned char** out, size_t* outsize,
const unsigned char* in, size_t insize,
const LodePNGDecompressSettings* settings);
unsigned lodepng_custom_deflate(unsigned char** out, size_t* outsize,
const unsigned char* in, size_t insize,
const LodePNGCompressSettings* settings);
/* ////////////////////////////////////////////////////////////////////////// */
/* ////////////////////////////////////////////////////////////////////////// */
/* // Tools for C, and common code for PNG and Zlib. // */
/* ////////////////////////////////////////////////////////////////////////// */
/* ////////////////////////////////////////////////////////////////////////// */
/*
Often in case of an error a value is assigned to a variable and then it breaks
out of a loop (to go to the cleanup phase of a function). This macro does that.
It makes the error handling code shorter and more readable.
Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);
*/
#define CERROR_BREAK(errorvar, code)\
{\
errorvar = code;\
break;\
}
/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/
#define ERROR_BREAK(code) CERROR_BREAK(error, code)
/*Set error var to the error code, and return it.*/
#define CERROR_RETURN_ERROR(errorvar, code)\
{\
errorvar = code;\
return code;\
}
/*Try the code, if it returns error, also return the error.*/
#define CERROR_TRY_RETURN(call)\
{\
unsigned error = call;\
if(error) return error;\
}
/*
About uivector, ucvector and string:
-All of them wrap dynamic arrays or text strings in a similar way.
-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.
-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.
-They're not used in the interface, only internally in this file as static functions.
-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.
*/
#ifdef LODEPNG_COMPILE_ZLIB
/*dynamic vector of unsigned ints*/
typedef struct uivector
{
unsigned* data;
size_t size; /*size in number of unsigned longs*/
size_t allocsize; /*allocated size in bytes*/
} uivector;
static void uivector_cleanup(void* p)
{
((uivector*)p)->size = ((uivector*)p)->allocsize = 0;
myfree(((uivector*)p)->data);
((uivector*)p)->data = NULL;
}
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned uivector_resize(uivector* p, size_t size)
{
if(size * sizeof(unsigned) > p->allocsize)
{
size_t newsize = size * sizeof(unsigned) * 2;
void* data = myrealloc(p->data, newsize);
if(data)
{
p->allocsize = newsize;
p->data = (unsigned*)data;
p->size = size;
}
else return 0;
}
else p->size = size;
return 1;
}
/*resize and give all new elements the value*/
static unsigned uivector_resizev(uivector* p, size_t size, unsigned value)
{
size_t oldsize = p->size, i;
if(!uivector_resize(p, size)) return 0;
for(i = oldsize; i < size; i++) p->data[i] = value;
return 1;
}
static void uivector_init(uivector* p)
{
p->data = NULL;
p->size = p->allocsize = 0;
}
#ifdef LODEPNG_COMPILE_ENCODER
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned uivector_push_back(uivector* p, unsigned c)
{
if(!uivector_resize(p, p->size + 1)) return 0;
p->data[p->size - 1] = c;
return 1;
}
/*copy q to p, returns 1 if success, 0 if failure ==> nothing done*/
static unsigned uivector_copy(uivector* p, const uivector* q)
{
size_t i;
if(!uivector_resize(p, q->size)) return 0;
for(i = 0; i < q->size; i++) p->data[i] = q->data[i];
return 1;
}
static void uivector_swap(uivector* p, uivector* q)
{
size_t tmp;
unsigned* tmpp;
tmp = p->size; p->size = q->size; q->size = tmp;
tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp;
tmpp = p->data; p->data = q->data; q->data = tmpp;
}
#endif /*LODEPNG_COMPILE_ENCODER*/
#endif /*LODEPNG_COMPILE_ZLIB*/
/* /////////////////////////////////////////////////////////////////////////// */
/*dynamic vector of unsigned chars*/
typedef struct ucvector
{
unsigned char* data;
size_t size; /*used size*/
size_t allocsize; /*allocated size*/
} ucvector;
static void ucvector_cleanup(void* p)
{
((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;
myfree(((ucvector*)p)->data);
((ucvector*)p)->data = NULL;
}
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned ucvector_resize(ucvector* p, size_t size)
{
if(size * sizeof(unsigned char) > p->allocsize)
{
size_t news