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