/*
LodePNG version 20170917
Copyright (c) 2005-2017 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 <limits.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
#endif /*_MSC_VER */
const char* LODEPNG_VERSION_STRING = "20170917";
/*
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 "lodepng_" in front
of the name, so that you can easily change them to others related to your
platform if needed. Everything else in the code calls these. Pass
-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out
#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and
define them in your own project's source files without needing to change
lodepng source code. Don't forget to remove "static" if you copypaste them
from here.*/
#ifdef LODEPNG_COMPILE_ALLOCATORS
static void* lodepng_malloc(size_t size)
{
return malloc(size);
}
static void* lodepng_realloc(void* ptr, size_t new_size)
{
return realloc(ptr, new_size);
}
static void lodepng_free(void* ptr)
{
free(ptr);
}
#else /*LODEPNG_COMPILE_ALLOCATORS*/
void* lodepng_malloc(size_t size);
void* lodepng_realloc(void* ptr, size_t new_size);
void lodepng_free(void* ptr);
#endif /*LODEPNG_COMPILE_ALLOCATORS*/
/* ////////////////////////////////////////////////////////////////////////// */
/* ////////////////////////////////////////////////////////////////////////// */
/* // 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;\
}
/*Set error var to the error code, and return from the void function.*/
#define CERROR_RETURN(errorvar, code)\
{\
errorvar = code;\
return;\
}
/*
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;
lodepng_free(((uivector*)p)->data);
((uivector*)p)->data = NULL;
}
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned uivector_reserve(uivector* p, size_t allocsize)
{
if(allocsize > p->allocsize)
{
size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);
void* data = lodepng_realloc(p->data, newsize);
if(data)
{
p->allocsize = newsize;
p->data = (unsigned*)data;
}
else return 0; /*error: not enough memory*/
}
return 1;
}
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned uivector_resize(uivector* p, size_t size)
{
if(!uivector_reserve(p, size * sizeof(unsigned))) return 0;
p->size = size;
return 1; /*success*/
}
/*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;
}
#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;
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned ucvector_reserve(ucvector* p, size_t allocsize)
{
if(allocsize > p->allocsize)
{
size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);
void* data = lodepng_realloc(p->data, newsize);
if(data)
{
p->allocsize = newsize;
p->data = (unsigned char*)data;
}
else return 0; /*error: not enough memory*/
}
return 1;
}
/*returns 1 if success, 0 if failure ==> nothing done*/
static unsigned ucvector_resize(ucvector* p, size_t size)
{
if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0;
p->size = size;
return 1; /*success*/
}
#ifdef LODEPNG_COMPILE_PNG
static void ucvector_cleanup(void* p)
{
((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;
lodepng_free(((ucvector*)p)->data);
((ucvector*)p)->data = NULL;
}
static void ucvector_init(ucvector* p)
{
p->data = NULL;
p->size = p->allocsize = 0;
}
#endif /*LODEPNG_COMPILE_PNG*/
#ifdef LODEPNG_COMPILE_ZLIB
/*you can both convert from vector to buffer&size and vica versa. If you use
init_buffer to take over a buffer and size, it is not needed to use cleanup*/
static void ucvector_init_buffer(ucvector* p, unsigned