Date: Tue, 1 May 2018 23:59:23 +0000 (UTC) From: Olivier Cochard <olivier@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r468805 - in head/graphics: . openfx-arena openfx-arena/files Message-ID: <201805012359.w41NxNJ2039021@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: olivier Date: Tue May 1 23:59:23 2018 New Revision: 468805 URL: https://svnweb.freebsd.org/changeset/ports/468805 Log: New port: graphics/openfx-arena Extra set of OpenFX plugins designed for Natron but also compatible with other hosts. Added: head/graphics/openfx-arena/ head/graphics/openfx-arena/Makefile (contents, props changed) head/graphics/openfx-arena/distinfo (contents, props changed) head/graphics/openfx-arena/files/ head/graphics/openfx-arena/files/patch-Bundle_Makefile (contents, props changed) head/graphics/openfx-arena/files/patch-Bundle_lodepng.cpp (contents, props changed) head/graphics/openfx-arena/files/patch-Bundle_lodepng.h (contents, props changed) head/graphics/openfx-arena/files/patch-Makefile.master (contents, props changed) head/graphics/openfx-arena/pkg-descr (contents, props changed) head/graphics/openfx-arena/pkg-plist (contents, props changed) Modified: head/graphics/Makefile Modified: head/graphics/Makefile ============================================================================== --- head/graphics/Makefile Tue May 1 23:51:34 2018 (r468804) +++ head/graphics/Makefile Tue May 1 23:59:23 2018 (r468805) @@ -658,6 +658,7 @@ SUBDIR += opencv-core SUBDIR += opencv-java SUBDIR += opendx + SUBDIR += openfx-arena SUBDIR += openfx-io SUBDIR += openfx-misc SUBDIR += opengl-man Added: head/graphics/openfx-arena/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/graphics/openfx-arena/Makefile Tue May 1 23:59:23 2018 (r468805) @@ -0,0 +1,67 @@ +# $FreeBSD$ + +PORTNAME= openfx-arena +PORTVERSION= 2.2.1 +CATEGORIES= graphics + +MAINTAINER= olivier@FreeBSD.org +COMMENT= Extra OpenFX plugins for Natron + +LICENSE= GPLv2 + +ONLY_FOR_ARCHS= amd64 +BUILD_DEPENDS= opencl>=0:devel/opencl +LIB_DEPENDS= libOpenColorIO.so:graphics/opencolorio \ + libfontconfig.so:x11-fonts/fontconfig \ + libcdr-0.1.so:graphics/libcdr01 \ + librevenge-0.0.so:textproc/librevenge \ + libpoppler-glib.so:graphics/poppler-glib \ + liblcms2.so:graphics/lcms2 \ + libMagick++-6.so:graphics/ImageMagick \ + libzip.so:archivers/libzip \ + libexpat.so:textproc/expat2 \ + libfreetype.so:print/freetype2 \ + libpcre.so:devel/pcre \ + libffi.so:devel/libffi \ + libdrm.so:graphics/libdrm \ + libpng16.so:graphics/png \ + libharfbuzz.so:print/harfbuzz \ + libgraphite2.so:graphics/graphite2 \ + libicui18n.so:devel/icu \ + liblqr-1.so:graphics/liblqr-1 \ + libfftw3.so:math/fftw3 \ + libltdl.so:devel/libltdl \ + libpoppler.so:graphics/poppler + +USES= gmake iconv +USE_GITHUB= yes +GH_ACCOUNT= olear +GH_PROJECT= openfx-arena +GH_TAGNAME= 95caed1 +GH_TUPLE= devernay:openfx-supportext:90093f7:openfx_supportext/SupportExt \ + devernay:openfx:42463b8:openfx/OpenFX \ + MrKepzie:openfx-io:1148523:OpenFX_IO/OpenFX-IO \ + MrKepzie:SequenceParsing:25112f0:SequenceParsing/OpenFX-IO/IOSupport/SequenceParsing \ + MrKepzie:tinydir:60f0905:tinydir/OpenFX-IO/IOSupport/SequenceParsing/tinydir + +MAKE_ENV+= CONFIG=release +USE_GL= gl +USE_GNOME= libxml2 pango cairo librsvg2 +USE_XORG+= x11 xcb xau xdamage xfixes xxf86vm xrender xext xdmcp pixman sm ice xt +MAKE_ENV+= CONFIG=release + +post-extract: + @${RMDIR} ${WRKSRC}/OpenFX-IO/openfx + ${LN} -s ../OpenFX ${WRKSRC}/OpenFX-IO/openfx + +post-patch: + @${REINPLACE_CMD} -e 's|/usr/OFX/Plugins|${PREFIX}/OFX/Plugins|g' \ + ${WRKSRC}/OpenFX/Examples/Makefile.master \ + ${WRKSRC}/OpenFX/Support/Plugins/Makefile.master \ + ${WRKSRC}/OpenFX/HostSupport/src/ofxhPluginCache.cpp + @${REINPLACE_CMD} -e 's|/Contents/$$(ARCH)|/Contents/FreeBSD-x86-64/|g' \ + ${WRKSRC}/OpenFX/Support/Plugins/Makefile.master +post-install: + ${STRIP_CMD} ${STAGEDIR}${LOCALBASE}/OFX/Plugins/Arena.ofx.bundle/Contents/FreeBSD-x86-64/Arena.ofx + +.include <bsd.port.mk> Added: head/graphics/openfx-arena/distinfo ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/graphics/openfx-arena/distinfo Tue May 1 23:59:23 2018 (r468805) @@ -0,0 +1,13 @@ +TIMESTAMP = 1525130623 +SHA256 (olear-openfx-arena-2.2.1-95caed1_GH0.tar.gz) = 6b945a8fdb93e83af89ef2f2f8b6a69610265ec32257fa5aa5035a84630977c2 +SIZE (olear-openfx-arena-2.2.1-95caed1_GH0.tar.gz) = 564650 +SHA256 (devernay-openfx-supportext-90093f7_GH0.tar.gz) = 3dedf570b60d17e1d6f1c9e0bb2dcb20d3a76f4323f053b20cc35b15efa4956a +SIZE (devernay-openfx-supportext-90093f7_GH0.tar.gz) = 260067 +SHA256 (devernay-openfx-42463b8_GH0.tar.gz) = e914c87aa8902c3f092b432e744e4c9070348efbe5e58c926a05a3664dc7a62b +SIZE (devernay-openfx-42463b8_GH0.tar.gz) = 10319112 +SHA256 (MrKepzie-openfx-io-1148523_GH0.tar.gz) = 5acc203e9de1a24ef18727608abdc2971704906611ee000f8fe604adc2c28a7a +SIZE (MrKepzie-openfx-io-1148523_GH0.tar.gz) = 425189 +SHA256 (MrKepzie-SequenceParsing-25112f0_GH0.tar.gz) = cfc3e6ffff89f978a66e1324e7ec2270618eb8d1133c5281ee8b4507cf1503ec +SIZE (MrKepzie-SequenceParsing-25112f0_GH0.tar.gz) = 15770 +SHA256 (MrKepzie-tinydir-60f0905_GH0.tar.gz) = 9cdedea9e02a97d4539881c06019a2317fa789d8132d914ca9909cba56c3517d +SIZE (MrKepzie-tinydir-60f0905_GH0.tar.gz) = 4479 Added: head/graphics/openfx-arena/files/patch-Bundle_Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/graphics/openfx-arena/files/patch-Bundle_Makefile Tue May 1 23:59:23 2018 (r468805) @@ -0,0 +1,18 @@ +--- Bundle/Makefile.orig 2017-01-03 14:53:38 UTC ++++ Bundle/Makefile +@@ -168,11 +168,11 @@ endif + + PNGVERSION = a70c086077c0eaecbae3845e4da4424de5f43361 + +-lodepng.cpp: +- curl -o $@ https://raw.githubusercontent.com/lvandeve/lodepng/$(PNGVERSION)/lodepng.cpp ++#lodepng.cpp: ++ #curl -o $@ https://raw.githubusercontent.com/lvandeve/lodepng/$(PNGVERSION)/lodepng.cpp + +-lodepng.h: +- curl -o $@ https://raw.githubusercontent.com/lvandeve/lodepng/$(PNGVERSION)/lodepng.h ++#lodepng.h: ++ #curl -o $@ https://raw.githubusercontent.com/lvandeve/lodepng/$(PNGVERSION)/lodepng.h + + $(OBJECTPATH)/lodepng.o: lodepng.cpp lodepng.h + $(OBJECTPATH)/ReadKrita.o: ReadKrita.cpp lodepng.h Added: head/graphics/openfx-arena/files/patch-Bundle_lodepng.cpp ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/graphics/openfx-arena/files/patch-Bundle_lodepng.cpp Tue May 1 23:59:23 2018 (r468805) @@ -0,0 +1,6226 @@ +--- Bundle/lodepng.cpp.orig 2017-10-04 17:18:33 UTC ++++ Bundle/lodepng.cpp +@@ -0,0 +1,6223 @@ ++/* ++LodePNG version 20160418 ++ ++Copyright (c) 2005-2016 Lode Vandevenne ++ ++This software is provided 'as-is', without any express or implied ++warranty. In no event will the authors be held liable for any damages ++arising from the use of this software. ++ ++Permission is granted to anyone to use this software for any purpose, ++including commercial applications, and to alter it and redistribute it ++freely, subject to the following restrictions: ++ ++ 1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++ ++ 2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++ ++ 3. This notice may not be removed or altered from any source ++ distribution. ++*/ ++ ++/* ++The manual and changelog are in the header file "lodepng.h" ++Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. ++*/ ++ ++#include "lodepng.h" ++ ++#include <limits.h> ++#include <stdio.h> ++#include <stdlib.h> ++ ++#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ ++#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ ++#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ ++#endif /*_MSC_VER */ ++ ++const char* LODEPNG_VERSION_STRING = "20160418"; ++ ++/* ++This source file is built up in the following large parts. The code sections ++with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. ++-Tools for C and common code for PNG and Zlib ++-C Code for Zlib (huffman, deflate, ...) ++-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) ++-The C++ wrapper around all of the above ++*/ ++ ++/*The malloc, realloc and free functions defined here with "lodepng_" in front ++of the name, so that you can easily change them to others related to your ++platform if needed. Everything else in the code calls these. Pass ++-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out ++#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and ++define them in your own project's source files without needing to change ++lodepng source code. Don't forget to remove "static" if you copypaste them ++from here.*/ ++ ++#ifdef LODEPNG_COMPILE_ALLOCATORS ++static void* lodepng_malloc(size_t size) ++{ ++ return malloc(size); ++} ++ ++static void* lodepng_realloc(void* ptr, size_t new_size) ++{ ++ return realloc(ptr, new_size); ++} ++ ++static void lodepng_free(void* ptr) ++{ ++ free(ptr); ++} ++#else /*LODEPNG_COMPILE_ALLOCATORS*/ ++void* lodepng_malloc(size_t size); ++void* lodepng_realloc(void* ptr, size_t new_size); ++void lodepng_free(void* ptr); ++#endif /*LODEPNG_COMPILE_ALLOCATORS*/ ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* // Tools for C, and common code for PNG and Zlib. // */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++/* ++Often in case of an error a value is assigned to a variable and then it breaks ++out of a loop (to go to the cleanup phase of a function). This macro does that. ++It makes the error handling code shorter and more readable. ++ ++Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83); ++*/ ++#define CERROR_BREAK(errorvar, code)\ ++{\ ++ errorvar = code;\ ++ break;\ ++} ++ ++/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ ++#define ERROR_BREAK(code) CERROR_BREAK(error, code) ++ ++/*Set error var to the error code, and return it.*/ ++#define CERROR_RETURN_ERROR(errorvar, code)\ ++{\ ++ errorvar = code;\ ++ return code;\ ++} ++ ++/*Try the code, if it returns error, also return the error.*/ ++#define CERROR_TRY_RETURN(call)\ ++{\ ++ unsigned error = call;\ ++ if(error) return error;\ ++} ++ ++/*Set error var to the error code, and return from the void function.*/ ++#define CERROR_RETURN(errorvar, code)\ ++{\ ++ errorvar = code;\ ++ return;\ ++} ++ ++/* ++About uivector, ucvector and string: ++-All of them wrap dynamic arrays or text strings in a similar way. ++-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. ++-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. ++-They're not used in the interface, only internally in this file as static functions. ++-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. ++*/ ++ ++#ifdef LODEPNG_COMPILE_ZLIB ++/*dynamic vector of unsigned ints*/ ++typedef struct uivector ++{ ++ unsigned* data; ++ size_t size; /*size in number of unsigned longs*/ ++ size_t allocsize; /*allocated size in bytes*/ ++} uivector; ++ ++static void uivector_cleanup(void* p) ++{ ++ ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; ++ lodepng_free(((uivector*)p)->data); ++ ((uivector*)p)->data = NULL; ++} ++ ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned uivector_reserve(uivector* p, size_t allocsize) ++{ ++ if(allocsize > p->allocsize) ++ { ++ size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); ++ void* data = lodepng_realloc(p->data, newsize); ++ if(data) ++ { ++ p->allocsize = newsize; ++ p->data = (unsigned*)data; ++ } ++ else return 0; /*error: not enough memory*/ ++ } ++ return 1; ++} ++ ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned uivector_resize(uivector* p, size_t size) ++{ ++ if(!uivector_reserve(p, size * sizeof(unsigned))) return 0; ++ p->size = size; ++ return 1; /*success*/ ++} ++ ++/*resize and give all new elements the value*/ ++static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) ++{ ++ size_t oldsize = p->size, i; ++ if(!uivector_resize(p, size)) return 0; ++ for(i = oldsize; i < size; ++i) p->data[i] = value; ++ return 1; ++} ++ ++static void uivector_init(uivector* p) ++{ ++ p->data = NULL; ++ p->size = p->allocsize = 0; ++} ++ ++#ifdef LODEPNG_COMPILE_ENCODER ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned uivector_push_back(uivector* p, unsigned c) ++{ ++ if(!uivector_resize(p, p->size + 1)) return 0; ++ p->data[p->size - 1] = c; ++ return 1; ++} ++#endif /*LODEPNG_COMPILE_ENCODER*/ ++#endif /*LODEPNG_COMPILE_ZLIB*/ ++ ++/* /////////////////////////////////////////////////////////////////////////// */ ++ ++/*dynamic vector of unsigned chars*/ ++typedef struct ucvector ++{ ++ unsigned char* data; ++ size_t size; /*used size*/ ++ size_t allocsize; /*allocated size*/ ++} ucvector; ++ ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned ucvector_reserve(ucvector* p, size_t allocsize) ++{ ++ if(allocsize > p->allocsize) ++ { ++ size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); ++ void* data = lodepng_realloc(p->data, newsize); ++ if(data) ++ { ++ p->allocsize = newsize; ++ p->data = (unsigned char*)data; ++ } ++ else return 0; /*error: not enough memory*/ ++ } ++ return 1; ++} ++ ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned ucvector_resize(ucvector* p, size_t size) ++{ ++ if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0; ++ p->size = size; ++ return 1; /*success*/ ++} ++ ++#ifdef LODEPNG_COMPILE_PNG ++ ++static void ucvector_cleanup(void* p) ++{ ++ ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; ++ lodepng_free(((ucvector*)p)->data); ++ ((ucvector*)p)->data = NULL; ++} ++ ++static void ucvector_init(ucvector* p) ++{ ++ p->data = NULL; ++ p->size = p->allocsize = 0; ++} ++#endif /*LODEPNG_COMPILE_PNG*/ ++ ++#ifdef LODEPNG_COMPILE_ZLIB ++/*you can both convert from vector to buffer&size and vica versa. If you use ++init_buffer to take over a buffer and size, it is not needed to use cleanup*/ ++static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) ++{ ++ p->data = buffer; ++ p->allocsize = p->size = size; ++} ++#endif /*LODEPNG_COMPILE_ZLIB*/ ++ ++#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER) ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned ucvector_push_back(ucvector* p, unsigned char c) ++{ ++ if(!ucvector_resize(p, p->size + 1)) return 0; ++ p->data[p->size - 1] = c; ++ return 1; ++} ++#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ ++ ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++#ifdef LODEPNG_COMPILE_PNG ++#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS ++/*returns 1 if success, 0 if failure ==> nothing done*/ ++static unsigned string_resize(char** out, size_t size) ++{ ++ char* data = (char*)lodepng_realloc(*out, size + 1); ++ if(data) ++ { ++ data[size] = 0; /*null termination char*/ ++ *out = data; ++ } ++ return data != 0; ++} ++ ++/*init a {char*, size_t} pair for use as string*/ ++static void string_init(char** out) ++{ ++ *out = NULL; ++ string_resize(out, 0); ++} ++ ++/*free the above pair again*/ ++static void string_cleanup(char** out) ++{ ++ lodepng_free(*out); ++ *out = NULL; ++} ++ ++static void string_set(char** out, const char* in) ++{ ++ size_t insize = strlen(in), i; ++ if(string_resize(out, insize)) ++ { ++ for(i = 0; i != insize; ++i) ++ { ++ (*out)[i] = in[i]; ++ } ++ } ++} ++#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ ++#endif /*LODEPNG_COMPILE_PNG*/ ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++unsigned lodepng_read32bitInt(const unsigned char* buffer) ++{ ++ return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); ++} ++ ++#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) ++/*buffer must have at least 4 allocated bytes available*/ ++static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) ++{ ++ buffer[0] = (unsigned char)((value >> 24) & 0xff); ++ buffer[1] = (unsigned char)((value >> 16) & 0xff); ++ buffer[2] = (unsigned char)((value >> 8) & 0xff); ++ buffer[3] = (unsigned char)((value ) & 0xff); ++} ++#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ ++ ++#ifdef LODEPNG_COMPILE_ENCODER ++static void lodepng_add32bitInt(ucvector* buffer, unsigned value) ++{ ++ ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/ ++ lodepng_set32bitInt(&buffer->data[buffer->size - 4], value); ++} ++#endif /*LODEPNG_COMPILE_ENCODER*/ ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* / File IO / */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++#ifdef LODEPNG_COMPILE_DISK ++ ++/* returns negative value on error. This should be pure C compatible, so no fstat. */ ++static long lodepng_filesize(const char* filename) ++{ ++ FILE* file; ++ long size; ++ file = fopen(filename, "rb"); ++ if(!file) return -1; ++ ++ if(fseek(file, 0, SEEK_END) != 0) ++ { ++ fclose(file); ++ return -1; ++ } ++ ++ size = ftell(file); ++ /* It may give LONG_MAX as directory size, this is invalid for us. */ ++ if(size == LONG_MAX) size = -1; ++ ++ fclose(file); ++ return size; ++} ++ ++/* load file into buffer that already has the correct allocated size. Returns error code.*/ ++static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) ++{ ++ FILE* file; ++ size_t readsize; ++ file = fopen(filename, "rb"); ++ if(!file) return 78; ++ ++ readsize = fread(out, 1, size, file); ++ fclose(file); ++ ++ if (readsize != size) return 78; ++ return 0; ++} ++ ++unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) ++{ ++ long size = lodepng_filesize(filename); ++ if (size < 0) return 78; ++ *outsize = (size_t)size; ++ ++ *out = (unsigned char*)lodepng_malloc((size_t)size); ++ if(!(*out) && size > 0) return 83; /*the above malloc failed*/ ++ ++ return lodepng_buffer_file(*out, (size_t)size, filename); ++} ++ ++/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ ++unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) ++{ ++ FILE* file; ++ file = fopen(filename, "wb" ); ++ if(!file) return 79; ++ fwrite((char*)buffer , 1 , buffersize, file); ++ fclose(file); ++ return 0; ++} ++ ++#endif /*LODEPNG_COMPILE_DISK*/ ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* // End of common code and tools. Begin of Zlib related code. // */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++#ifdef LODEPNG_COMPILE_ZLIB ++#ifdef LODEPNG_COMPILE_ENCODER ++/*TODO: this ignores potential out of memory errors*/ ++#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\ ++{\ ++ /*add a new byte at the end*/\ ++ if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\ ++ /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\ ++ (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\ ++ ++(*bitpointer);\ ++} ++ ++static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) ++{ ++ size_t i; ++ for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); ++} ++ ++static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) ++{ ++ size_t i; ++ for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); ++} ++#endif /*LODEPNG_COMPILE_ENCODER*/ ++ ++#ifdef LODEPNG_COMPILE_DECODER ++ ++#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1) ++ ++static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) ++{ ++ unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream)); ++ ++(*bitpointer); ++ return result; ++} ++ ++static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) ++{ ++ unsigned result = 0, i; ++ for(i = 0; i != nbits; ++i) ++ { ++ result += ((unsigned)READBIT(*bitpointer, bitstream)) << i; ++ ++(*bitpointer); ++ } ++ return result; ++} ++#endif /*LODEPNG_COMPILE_DECODER*/ ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++/* / Deflate - Huffman / */ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++#define FIRST_LENGTH_CODE_INDEX 257 ++#define LAST_LENGTH_CODE_INDEX 285 ++/*256 literals, the end code, some length codes, and 2 unused codes*/ ++#define NUM_DEFLATE_CODE_SYMBOLS 288 ++/*the distance codes have their own symbols, 30 used, 2 unused*/ ++#define NUM_DISTANCE_SYMBOLS 32 ++/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ ++#define NUM_CODE_LENGTH_CODES 19 ++ ++/*the base lengths represented by codes 257-285*/ ++static const unsigned LENGTHBASE[29] ++ = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, ++ 67, 83, 99, 115, 131, 163, 195, 227, 258}; ++ ++/*the extra bits used by codes 257-285 (added to base length)*/ ++static const unsigned LENGTHEXTRA[29] ++ = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, ++ 4, 4, 4, 4, 5, 5, 5, 5, 0}; ++ ++/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ ++static const unsigned DISTANCEBASE[30] ++ = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, ++ 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; ++ ++/*the extra bits of backwards distances (added to base)*/ ++static const unsigned DISTANCEEXTRA[30] ++ = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, ++ 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; ++ ++/*the order in which "code length alphabet code lengths" are stored, out of this ++the huffman tree of the dynamic huffman tree lengths is generated*/ ++static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] ++ = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; ++ ++/* ////////////////////////////////////////////////////////////////////////// */ ++ ++/* ++Huffman tree struct, containing multiple representations of the tree ++*/ ++typedef struct HuffmanTree ++{ ++ unsigned* tree2d; ++ unsigned* tree1d; ++ unsigned* lengths; /*the lengths of the codes of the 1d-tree*/ ++ unsigned maxbitlen; /*maximum number of bits a single code can get*/ ++ unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ ++} HuffmanTree; ++ ++/*function used for debug purposes to draw the tree in ascii art with C++*/ ++/* ++static void HuffmanTree_draw(HuffmanTree* tree) ++{ ++ std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; ++ for(size_t i = 0; i != tree->tree1d.size; ++i) ++ { ++ if(tree->lengths.data[i]) ++ std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; ++ } ++ std::cout << std::endl; ++}*/ ++ ++static void HuffmanTree_init(HuffmanTree* tree) ++{ ++ tree->tree2d = 0; ++ tree->tree1d = 0; ++ tree->lengths = 0; ++} ++ ++static void HuffmanTree_cleanup(HuffmanTree* tree) ++{ ++ lodepng_free(tree->tree2d); ++ lodepng_free(tree->tree1d); ++ lodepng_free(tree->lengths); ++} ++ ++/*the tree representation used by the decoder. return value is error*/ ++static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) ++{ ++ unsigned nodefilled = 0; /*up to which node it is filled*/ ++ unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ ++ unsigned n, i; ++ ++ tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned)); ++ if(!tree->tree2d) return 83; /*alloc fail*/ ++ ++ /* ++ convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means ++ uninited, a value >= numcodes is an address to another bit, a value < numcodes ++ is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as ++ many columns as codes - 1. ++ A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. ++ Here, the internal nodes are stored (what their 0 and 1 option point to). ++ There is only memory for such good tree currently, if there are more nodes ++ (due to too long length codes), error 55 will happen ++ */ ++ for(n = 0; n < tree->numcodes * 2; ++n) ++ { ++ tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ ++ } ++ ++ for(n = 0; n < tree->numcodes; ++n) /*the codes*/ ++ { ++ for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/ ++ { ++ unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1); ++ /*oversubscribed, see comment in lodepng_error_text*/ ++ if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55; ++ if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/ ++ { ++ if(i + 1 == tree->lengths[n]) /*last bit*/ ++ { ++ tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/ ++ treepos = 0; ++ } ++ else ++ { ++ /*put address of the next step in here, first that address has to be found of course ++ (it's just nodefilled + 1)...*/ ++ ++nodefilled; ++ /*addresses encoded with numcodes added to it*/ ++ tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes; ++ treepos = nodefilled; ++ } ++ } ++ else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes; ++ } ++ } ++ ++ for(n = 0; n < tree->numcodes * 2; ++n) ++ { ++ if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/ ++ } ++ ++ return 0; ++} ++ ++/* ++Second step for the ...makeFromLengths and ...makeFromFrequencies functions. ++numcodes, lengths and maxbitlen must already be filled in correctly. return ++value is error. ++*/ ++static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) ++{ ++ uivector blcount; ++ uivector nextcode; ++ unsigned error = 0; ++ unsigned bits, n; ++ ++ uivector_init(&blcount); ++ uivector_init(&nextcode); ++ ++ tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); ++ if(!tree->tree1d) error = 83; /*alloc fail*/ ++ ++ if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0) ++ || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) ++ error = 83; /*alloc fail*/ ++ ++ if(!error) ++ { ++ /*step 1: count number of instances of each code length*/ ++ for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]]; ++ /*step 2: generate the nextcode values*/ ++ for(bits = 1; bits <= tree->maxbitlen; ++bits) ++ { ++ nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; ++ } ++ /*step 3: generate all the codes*/ ++ for(n = 0; n != tree->numcodes; ++n) ++ { ++ if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++; ++ } ++ } ++ ++ uivector_cleanup(&blcount); ++ uivector_cleanup(&nextcode); ++ ++ if(!error) return HuffmanTree_make2DTree(tree); ++ else return error; ++} ++ ++/* ++given the code lengths (as stored in the PNG file), generate the tree as defined ++by Deflate. maxbitlen is the maximum bits that a code in the tree can have. ++return value is error. ++*/ ++static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, ++ size_t numcodes, unsigned maxbitlen) ++{ ++ unsigned i; ++ tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); ++ if(!tree->lengths) return 83; /*alloc fail*/ ++ for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; ++ tree->numcodes = (unsigned)numcodes; /*number of symbols*/ ++ tree->maxbitlen = maxbitlen; ++ return HuffmanTree_makeFromLengths2(tree); ++} ++ ++#ifdef LODEPNG_COMPILE_ENCODER ++ ++/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", ++Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ ++ ++/*chain node for boundary package merge*/ ++typedef struct BPMNode ++{ ++ int weight; /*the sum of all weights in this chain*/ ++ unsigned index; /*index of this leaf node (called "count" in the paper)*/ ++ struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ ++ int in_use; ++} BPMNode; ++ ++/*lists of chains*/ ++typedef struct BPMLists ++{ ++ /*memory pool*/ ++ unsigned memsize; ++ BPMNode* memory; ++ unsigned numfree; ++ unsigned nextfree; ++ BPMNode** freelist; ++ /*two heads of lookahead chains per list*/ ++ unsigned listsize; ++ BPMNode** chains0; ++ BPMNode** chains1; ++} BPMLists; ++ ++/*creates a new chain node with the given parameters, from the memory in the lists */ ++static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) ++{ ++ unsigned i; ++ BPMNode* result; ++ ++ /*memory full, so garbage collect*/ ++ if(lists->nextfree >= lists->numfree) ++ { ++ /*mark only those that are in use*/ ++ for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; ++ for(i = 0; i != lists->listsize; ++i) ++ { ++ BPMNode* node; ++ for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; ++ for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; ++ } ++ /*collect those that are free*/ ++ lists->numfree = 0; ++ for(i = 0; i != lists->memsize; ++i) ++ { ++ if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; ++ } ++ lists->nextfree = 0; ++ } ++ ++ result = lists->freelist[lists->nextfree++]; ++ result->weight = weight; ++ result->index = index; ++ result->tail = tail; ++ return result; ++} ++ ++/*sort the leaves with stable mergesort*/ ++static void bpmnode_sort(BPMNode* leaves, size_t num) ++{ ++ BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); ++ size_t width, counter = 0; ++ for(width = 1; width < num; width *= 2) ++ { ++ BPMNode* a = (counter & 1) ? mem : leaves; ++ BPMNode* b = (counter & 1) ? leaves : mem; ++ size_t p; ++ for(p = 0; p < num; p += 2 * width) ++ { ++ size_t q = (p + width > num) ? num : (p + width); ++ size_t r = (p + 2 * width > num) ? num : (p + 2 * width); ++ size_t i = p, j = q, k; ++ for(k = p; k < r; k++) ++ { ++ if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; ++ else b[k] = a[j++]; ++ } ++ } ++ counter++; ++ } ++ if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num); ++ lodepng_free(mem); ++} ++ ++/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ ++static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) ++{ ++ unsigned lastindex = lists->chains1[c]->index; ++ ++ if(c == 0) ++ { ++ if(lastindex >= numpresent) return; ++ lists->chains0[c] = lists->chains1[c]; ++ lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); ++ } ++ else ++ { ++ /*sum of the weights of the head nodes of the previous lookahead chains.*/ ++ int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; ++ lists->chains0[c] = lists->chains1[c]; ++ if(lastindex < numpresent && sum > leaves[lastindex].weight) ++ { ++ lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); ++ return; ++ } ++ lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); ++ /*in the end we are only interested in the chain of the last list, so no ++ need to recurse if we're at the last one (this gives measurable speedup)*/ ++ if(num + 1 < (int)(2 * numpresent - 2)) ++ { ++ boundaryPM(lists, leaves, numpresent, c - 1, num); ++ boundaryPM(lists, leaves, numpresent, c - 1, num); ++ } ++ } ++} ++ ++unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, ++ size_t numcodes, unsigned maxbitlen) ++{ ++ unsigned error = 0; ++ unsigned i; ++ size_t numpresent = 0; /*number of symbols with non-zero frequency*/ ++ BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ ++ ++ if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ ++ if((1u << maxbitlen) < numcodes) return 80; /*error: represent all symbols*/ ++ ++ leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); ++ if(!leaves) return 83; /*alloc fail*/ ++ ++ for(i = 0; i != numcodes; ++i) ++ { ++ if(frequencies[i] > 0) ++ { ++ leaves[numpresent].weight = (int)frequencies[i]; ++ leaves[numpresent].index = i; ++ ++numpresent; ++ } ++ } ++ ++ for(i = 0; i != numcodes; ++i) lengths[i] = 0; ++ ++ /*ensure at least two present symbols. There should be at least one symbol ++ according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To ++ make these work as well ensure there are at least two symbols. The ++ Package-Merge code below also doesn't work correctly if there's only one ++ symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/ ++ if(numpresent == 0) ++ { ++ lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ ++ } ++ else if(numpresent == 1) ++ { ++ lengths[leaves[0].index] = 1; ++ lengths[leaves[0].index == 0 ? 1 : 0] = 1; ++ } ++ else ++ { ++ BPMLists lists; ++ BPMNode* node; ++ ++ bpmnode_sort(leaves, numpresent); ++ ++ lists.listsize = maxbitlen; ++ lists.memsize = 2 * maxbitlen * (maxbitlen + 1); ++ lists.nextfree = 0; ++ lists.numfree = lists.memsize; ++ lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); ++ lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); ++ lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); ++ lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); ++ if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ ++ ++ if(!error) ++ { ++ for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; ++ ++ bpmnode_create(&lists, leaves[0].weight, 1, 0); ++ bpmnode_create(&lists, leaves[1].weight, 2, 0); ++ ++ for(i = 0; i != lists.listsize; ++i) ++ { ++ lists.chains0[i] = &lists.memory[0]; ++ lists.chains1[i] = &lists.memory[1]; ++ } ++ ++ /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ ++ for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); ++ ++ for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) ++ { ++ for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; ++ } ++ } ++ ++ lodepng_free(lists.memory); ++ lodepng_free(lists.freelist); ++ lodepng_free(lists.chains0); ++ lodepng_free(lists.chains1); ++ } ++ ++ lodepng_free(leaves); ++ return error; ++} ++ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805012359.w41NxNJ2039021>