diff --git a/.mailmap b/.mailmap index 3674696e..a82a2ca4 100644 --- a/.mailmap +++ b/.mailmap @@ -8,3 +8,4 @@ Vikas Arora Tamar Levy + diff --git a/AUTHORS b/AUTHORS index ea6e21fc..0f382dab 100644 --- a/AUTHORS +++ b/AUTHORS @@ -10,10 +10,13 @@ Contributors: - Lode Vandevenne (lode at google dot com) - Lou Quillio (louquillio at google dot com) - Mans Rullgard (mans at mansr dot com) +- Marcin Kowalczyk (qrczak at google dot com) - Martin Olsson (mnemo at minimum dot se) - Mikołaj Zalewski (mikolajz at google dot com) - Mislav Bradac (mislavm at google dot com) +- Nico Weber (thakis at chromium dot org) - Noel Chromium (noel at chromium dot org) +- Parag Salasakar (img dot mips1 at gmail dot com) - Pascal Massimino (pascal dot massimino at gmail dot com) - Paweł Hajdan, Jr (phajdan dot jr at chromium dot org) - Pierre Joye (pierre dot php at gmail dot com) diff --git a/ChangeLog b/ChangeLog index 2f8def20..99fb3c02 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,179 @@ +deb54d9 Clarify the expected 'config' lifespan in WebPIDecode() +c7e2d24 update ChangeLog (tag: v0.5.1-rc5) +c7eb06f Fix corner case in CostManagerInit. +ab7937a gif2webp: normalize the number of .'s in the help message +3cdec84 vwebp: normalize the number of .'s in the help message +bdf6241 cwebp: normalize the number of .'s in the help message +06a38c7 fix rescaling bug: alpha plane wasn't filled with 0xff +319e37b Improve lossless compression. +447adbc 'our bug tracker' -> 'the bug tracker' +97b9e64 normalize the number of .'s in the help message +bb50bf4 pngdec,ReadFunc: throw an error on invalid read +38063af decode.h,WebPGetInfo: normalize function comment +9e8e1b7 Inline GetResidual for speed. +7d58d1b Speed-up uniform-region processing. +23e29cb Merge "Fix a boundary case in BackwardReferencesHashChainDistanceOnly." into 0.5.1 +0bb23b2 free -> WebPSafeFree() +e7b9177 Merge "DecodeImageData(): change the incorrect assert" into 0.5.1 +2abfa54 DecodeImageData(): change the incorrect assert +5a48fcd Merge "configure: test for -Wfloat-conversion" +0174d18 Fix a boundary case in BackwardReferencesHashChainDistanceOnly. +6a9c262 Merge "Added MSA optimized transform functions" +cfbcc5e Make sure to consider small distances in LZ77. +5e60c42 Added MSA optimized transform functions +3dc28d7 configure: test for -Wfloat-conversion +f2a0946 add some asserts to delimit the perimeter of CostManager's operation +9a583c6 fix invalid-write bug for alpha-decoding +f66512d make gradlew executable +6fda58f backward_references: quiet double->int warning +a48cc9d Merge "Fix a compression regression for images with long uniform regions." into 0.5.1 +cc2720c Merge "Revert an LZ77 boundary constant." into 0.5.1 +059aab4 Fix a compression regression for images with long uniform regions. +b0c7e49 Check more backward matches with higher quality. +a361151 Revert an LZ77 boundary constant. +8190374 README: fix typo +7551db4 update NEWS +0fb2269 bump version to 0.5.1 +f453761 update AUTHORS & .mailmap +3259571 Refactor GetColorPalette method. +1df5e26 avoid using tmp histogram in PreparePair() +7685123 fix comment typos +a246b92 Speedup backward references. +76d73f1 Merge "CostManager: introduce a free-list of ~10 intervals" +eab39d8 CostManager: introduce a free-list of ~10 intervals +4c59aac Merge "mips msa webp configuration" +043c33f Merge "Improve speed and compression in backward reference for lossless." +71be9b8 Merge "clarify variable names in HistogramRemap()" +0ba7fd7 Improve speed and compression in backward reference for lossless. +0481d42 CostManager: cache one interval and re-use it when possible +41b7e6b Merge "histogram: fix bin calculation" +96c3d62 histogram: fix bin calculation +fe9e31e clarify variable names in HistogramRemap() +ce3c824 disable near-lossless quantization if palette is used +e11da08 mips msa webp configuration +5f8f998 mux: Presence of unknown chunks should trigger VP8X chunk output. +cadec0b Merge "Sync mips32 and dsp_r2 YUV->RGB code with C verison" +d963775 Compute the hash chain once and for all for lossless compression. +50a4866 Sync mips32 and dsp_r2 YUV->RGB code with C verison +eee788e Merge "introduce a common signature for all image reader function" +d77b877 introduce a common signature for all image reader function +ca8d951 remove some obsolete TODOs +ae2a722 collect all decoding utilities from examples/ in libexampledec.a +0b8ae85 Merge "Move DitherCombine8x8 to dsp/dec.c" +77cad88 Merge "ReadWebP: avoid conversion to ARGB if final format is YUVA" +ab8d669 ReadWebP: avoid conversion to ARGB if final format is YUVA +f8b7ce9 Merge "test pointer to NULL explicitly" +5df6f21 test pointer to NULL explicitly +77f21c9 Move DitherCombine8x8 to dsp/dec.c +c9e6d86 Add gradle support +c65f41e Revert "Add gradle support" +bf731ed Add gradle support +08333b8 WebPAnimEncoder: Detect when canvas is modified, restore only when needed. +0209d7e Merge "speed-up MapToPalette() with binary search" +fdd29a3 speed-up MapToPalette() with binary search +cf4a651 Revert "Refactor GetColorPalette method." +0a27aca Merge changes Idfa8ce83,I19adc9c4 +f25c440 WebPAnimEncoder: Restore original canvas between multiple encodes. +169004b Refactor GetColorPalette method. +576362a VP8LDoFillBitWindow: support big-endian in fast path +ac49e4e bit_reader.c: s/VP8L_USE_UNALIGNED_LOAD/VP8L_USE_FAST_LOAD/ +d39ceb5 VP8LDoFillBitWindow: remove stale TODO +2ec2de1 Merge "Speed-up BackwardReferencesHashChainDistanceOnly." +3e023c1 Speed-up BackwardReferencesHashChainDistanceOnly. +f2e1efb Improve near lossless compression when a prediction filter is used. +e15afbc dsp.h: fix ubsan macro name +e53c9cc dsp.h: add WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW +af81fdb utils.h: quiet -fsanitize=undefined warnings +ea0be35 dsp.h: remove utils.h include +cd276ae utils/*.c: ../utils/utils.h -> ./utils.h +c892713 utils/Makefile.am: add some missing headers +ea24e02 Merge "dsp.h: add WEBP_UBSAN_IGNORE_UNDEF" +369e264 dsp.h: add WEBP_UBSAN_IGNORE_UNDEF +0d020a7 Merge "add runtime NEON detection" +5ee2136 Merge "add VP8LAddPixels() to lossless.h" +47435a6 add VP8LAddPixels() to lossless.h +8fa6ac6 remove two ubsan warnings +74fb56f add runtime NEON detection +4154a83 MIPS update to new Unfilter API +c80b9fc Merge "cherry-pick decoder fix for 64-bit android devices" +6235147 cherry-pick decoder fix for 64-bit android devices +d41b8c4 configure: test for -Wformat-* w/-Wformat present +5f95589 Fix WEBP_ALIGN in case the argument is a pointer to a type larger than a byte. +2309fd5 replace num_parts_ by num_parts_minus_one_ (unsigned) +9629f4b SimplifySegments: quiet -Warray-bounds warning +de47492 Merge "update the Unfilter API in dsp to process one row independently" +2102ccd update the Unfilter API in dsp to process one row independently +e3912d5 WebPAnimEncoder: Restore canvas before evaluating blending possibility. +6e12e1e WebPAnimEncoder: Fix for single-frame optimization. +602f344 Merge changes I1d03acac,Ifcb64219 +95ecccf only apply color-mapping for alpha on the cropped area +47dd070 anim_diff: Add an experimental option for max inter-frame diff. +aa809cf only allocate alpha_plane_ up to crop_bottom row +31f2b8d WebPAnimEncoder: FlattenSimilarPixels(): look for similar +774dfbd perform alpha filtering within the decoding loop +a4cae68 lossless decoding: only process decoded row up to last_row +238cdcd Only call WebPDequantizeLevels() on cropped area +cf6c713 alpha: preparatory cleanup +b95ac0a Merge "VP8GetHeaders(): initialize VP8Io with sane value for crop/scale dimensions" +8923139 VP8GetHeaders(): initialize VP8Io with sane value for crop/scale dimensions +5828e19 use_8b_decode -> use_8b_decode_ +8dca024 fix bug in alpha.c that was triggering a memory error in incremental mode +9a950c5 WebPAnimEncoder: Disable filtering when blending is used with lossy encoding. +eb42390 WebPAnimEncoder: choose max diff for framerect based on quality. +ff0a94b WebPAnimEncoder lossy: ignore small pixel differences for frame rectangles. +f804008 gif2webp: Remove the 'prev_to_prev_canvas' buffer. +6d8c07d Merge "WebPDequantizeLevels(): use stride in CountLevels()" +d96fe5e WebPDequantizeLevels(): use stride in CountLevels() +ec1b240 WebPPictureImport*: check output pointer +c076876 Merge "Revert "Re-enable encoding of alpha plane with color cache for next release."" +41f14bc WebPPictureImport*: check src pointer +64eed38 Pass stride parameter to WebPDequantizeLevels() +97934e2 Revert "Re-enable encoding of alpha plane with color cache for next release." +e88c4ca fix -m 2 mode-cost evaluation (causing partition0 overflow) +4562e83 Merge "add extra meaning to WebPDecBuffer::is_external_memory" +abdb109 add extra meaning to WebPDecBuffer::is_external_memory +875aec7 enc_neon,cosmetics: break long comment +71e856c GetMBSSIM,cosmetics: fix alignment +a90edff fix missing 'extern' for SSIM function in dsp/ +423ecaf move some SSIM-accumulation function for dsp/ +f08e662 Merge "Fix FindClosestDiscretized in near lossless:" +0d40cc5 enc_neon,Disto4x4: remove an unnecessary transpose +e8feb20 Fix FindClosestDiscretized in near lossless: +8200643 anim_util: quiet static analysis warning +a6f23c4 Merge "AnimEncoder: Support progress hook and user data." +a519377 Merge "Near lossless feature: fix some comments." +da98d31 AnimEncoder: Support progress hook and user data. +3335713 Near lossless feature: fix some comments. +0beed01 cosmetics: fix indent after 2f5e898 +6753f35 Merge "FTransformWHT optimization." +6583bb1 Improve SSE4.1 implementation of TTransform. +7561d0c FTransformWHT optimization. +7ccdb73 fix indentation after patch #328220 +6ec0d2a clarify the logic of the error path when decoding fails. +8aa352b Merge "Remove an unnecessary transposition in TTransform." +db86088 Merge "remove useless #include" +9960c31 Remove an unnecessary transposition in TTransform. +6e36b51 Small speedup in FTransform. +9dbd4aa Merge "fix C and SIMD flags completion." +e60853e Add missing common_sse2.h file to makefile.unix +696eb2b fix C and SIMD flags completion. +2b4fe33 Merge "fix multiple allocation for transform buffer" +2f5e898 fix multiple allocation for transform buffer +bf2b4f1 Regroup common SSE code + optimization. +4ed650a force "-pass 6" if -psnr or -size is used but -pass isn't. +3ef1ce9 yuv_sse2: fix -Wconstant-conversion warning +a7a03e9 Merge changes I4852d18f,I51ccb85d +5e122bd gif2webp: set enc_options.verbose = 0 w/-quiet +ab3c258 anim_encode,DefaultEncoderOptions: init verbose +8f0dee7 Merge "configure: fix builtin detection w/-Werror" +4a7b85a cmake: fix builtin detection w/-Werror +b74657f configure: fix builtin detection w/-Werror +3661b98 Add a CMakeLists.txt +75f4af4 remove useless #include +6c1d763 avoid Yoda style for comparison +8ce975a SSE optimization for vector mismatch. +7db5383 Merge tag 'v0.5.0' +37f0494 update ChangeLog (tag: v0.5.0-rc1, tag: v0.5.0, origin/0.5.0, 0.5.0) 7e7b6cc faster rgb565/rgb4444/argb output 4c7f565 update NEWS 1f62b6b update AUTHORS @@ -140,7 +316,7 @@ f7c507a Merge "remove unnecessary #include "yuv.h"" 7861578 for ReadXXXX() image-readers, use the value of pic->use_argb 14e4043 remove unnecessary #include "yuv.h" 469ba2c vwebp: fix incorrect clipping w/NO_BLEND -4b9186b update issue tracker url (master) +4b9186b update issue tracker url d64d376 change WEBP_ALIGN_CST value to 31 f717b82 vp8l.c, cosmetics: fix indent after 95509f9 927ccdc Merge "fix alignment of allocated memory in AllocateTransformBuffer" diff --git a/NEWS b/NEWS index a72f1796..30554bf6 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,17 @@ +- 6/14/2016: version 0.5.1 + This is a binary compatible release. + * miscellaneous bug fixes (issues #280, #289) + * reverted alpha plane encoding with color cache for compatibility with + libwebp 0.4.0->0.4.3 (issues #291, #298) + * lossless encoding performance improvements + * memory reduction in both lossless encoding and decoding + * force mux output to be in the extended format (VP8X) when undefined chunks + are present (issue #294) + * gradle, cmake build support + * workaround for compiler bug causing 64-bit decode failures on android + devices using clang-3.8 in the r11c NDK + * various WebPAnimEncoder improvements + - 12/17/2015: version 0.5.0 * miscellaneous bug & build fixes (issues #234, #258, #274, #275, #278) * encoder & decoder speed-ups on x86/ARM/MIPS for lossy & lossless diff --git a/README b/README index 07c0aeae..90f8f10f 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ \__\__/\____/\_____/__/ ____ ___ / _/ / \ \ / _ \/ _/ / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v0.5.0 + \____/____/\_____/_____/____/v0.5.1 Description: ============ @@ -20,7 +20,7 @@ https://chromium.googlesource.com/webm/libwebp It is released under the same license as the WebM project. See http://www.webmproject.org/license/software/ or the -file "COPYING" file for details. An additional intellectual +"COPYING" file for details. An additional intellectual property rights grant can be found in the file PATENTS. Building: @@ -218,8 +218,8 @@ If input size (-s) for an image is not specified, it is assumed to be a PNG, JPEG, TIFF or WebP file. Options: - -h / -help ............ short help - -H / -longhelp ........ long help + -h / -help ............. short help + -H / -longhelp ......... long help -q ............. quality factor (0:small..100:big) -alpha_q ......... transparency-compression quality (0..100) -preset ....... preset setting, one of: @@ -341,7 +341,7 @@ Use following options to convert into alternate image formats: -yuv ......... save the raw YUV samples in flat layout Other options are: - -version .... print version number and exit + -version ..... print version number and exit -nofancy ..... don't use the fancy YUV420 upscaler -nofilter .... disable in-loop filtering -nodither .... disable dithering @@ -353,8 +353,8 @@ Use following options to convert into alternate image formats: -flip ........ flip the output vertically -alpha ....... only save the alpha plane -incremental . use incremental decoding (useful for tests) - -h ....... this help message - -v ....... verbose (e.g. print encoding/decoding times) + -h ........... this help message + -v ........... verbose (e.g. print encoding/decoding times) -quiet ....... quiet mode, don't print anything -noasm ....... disable all assembly optimizations @@ -370,7 +370,7 @@ Usage: vwebp in_file [options] Decodes the WebP image file and visualize it using OpenGL Options are: - -version .... print version number and exit + -version ..... print version number and exit -noicc ....... don't use the icc profile if present -nofancy ..... don't use the fancy YUV420 upscaler -nofilter .... disable in-loop filtering @@ -378,7 +378,7 @@ Options are: -noalphadither disable alpha plane dithering -mt .......... use multi-threading -info ........ print info - -h ....... this help message + -h ........... this help message Keyboard shortcuts: 'c' ................ toggle use of color profile @@ -420,7 +420,7 @@ vwebp. Usage: gif2webp [options] gif_file -o webp_file Options: - -h / -help ............ this help + -h / -help ............. this help -lossy ................. encode image using lossy compression -mixed ................. for each frame in the image, pick lossy or lossless compression heuristically @@ -704,7 +704,7 @@ an otherwise too-large picture. Some CPU can be saved too, incidentally. Bugs: ===== -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp Patches welcome! See this page to get started: http://www.webmproject.org/code/contribute/submitting-patches/ diff --git a/README.mux b/README.mux index aa077e8d..1380c914 100644 --- a/README.mux +++ b/README.mux @@ -1,7 +1,7 @@  __ __ ____ ____ ____ __ __ _ __ __ / \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\ \ / __/ _ \ __/ / / (_/ /__ - \__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.3.0 + \__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.3.1 Description: @@ -198,7 +198,7 @@ For a detailed AnimEncoder API reference, please refer to the header file Bugs: ===== -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp Patches welcome! See this page to get started: http://www.webmproject.org/code/contribute/submitting-patches/ diff --git a/configure.ac b/configure.ac index 36f79b8d..8c22fddb 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libwebp], [0.5.0], +AC_INIT([libwebp], [0.5.1], [https://bugs.chromium.org/p/webp],, [http://developers.google.com/speed/webp]) AC_CANONICAL_HOST diff --git a/examples/cwebp.c b/examples/cwebp.c index b538ae21..df45aa9b 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -514,8 +514,8 @@ static void HelpLong(void) { printf("Windows builds can take as input any of the files handled by WIC.\n"); #endif printf("\nOptions:\n"); - printf(" -h / -help ............ short help\n"); - printf(" -H / -longhelp ........ long help\n"); + printf(" -h / -help ............. short help\n"); + printf(" -H / -longhelp ......... long help\n"); printf(" -q ............. quality factor (0:small..100:big)\n"); printf(" -alpha_q ......... transparency-compression quality " "(0..100)\n"); diff --git a/examples/dwebp.c b/examples/dwebp.c index f3d15c32..384987ba 100644 --- a/examples/dwebp.c +++ b/examples/dwebp.c @@ -572,7 +572,7 @@ static void Help(void) { " -yuv ......... save the raw YUV samples in flat layout\n" "\n" " Other options are:\n" - " -version .... print version number and exit\n" + " -version ..... print version number and exit\n" " -nofancy ..... don't use the fancy YUV420 upscaler\n" " -nofilter .... disable in-loop filtering\n" " -nodither .... disable dithering\n" @@ -584,8 +584,8 @@ static void Help(void) { " -flip ........ flip the output vertically\n" " -alpha ....... only save the alpha plane\n" " -incremental . use incremental decoding (useful for tests)\n" - " -h ....... this help message\n" - " -v ....... verbose (e.g. print encoding/decoding times)\n" + " -h ........... this help message\n" + " -v ........... verbose (e.g. print encoding/decoding times)\n" " -quiet ....... quiet mode, don't print anything\n" #ifndef WEBP_DLL " -noasm ....... disable all assembly optimizations\n" diff --git a/examples/gif2webp.c b/examples/gif2webp.c index daf3d69e..b6a9964b 100644 --- a/examples/gif2webp.c +++ b/examples/gif2webp.c @@ -55,7 +55,7 @@ static void Help(void) { printf("Usage:\n"); printf(" gif2webp [options] gif_file -o webp_file\n"); printf("Options:\n"); - printf(" -h / -help ............ this help\n"); + printf(" -h / -help ............. this help\n"); printf(" -lossy ................. encode image using lossy compression\n"); printf(" -mixed ................. for each frame in the image, pick lossy\n" " or lossless compression heuristically\n"); diff --git a/examples/pngdec.c b/examples/pngdec.c index 85183621..c75a6dec 100644 --- a/examples/pngdec.c +++ b/examples/pngdec.c @@ -18,7 +18,6 @@ #include #ifdef WEBP_HAVE_PNG -#include #include #include // note: this must be included *after* png.h #include @@ -198,7 +197,9 @@ typedef struct { static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) { PNGReadContext* const ctx = (PNGReadContext*)png_get_io_ptr(png_ptr); - assert(ctx->offset + length <= ctx->data_size); + if (ctx->data_size - ctx->offset < length) { + png_error(png_ptr, "ReadFunc: invalid read length (overflow)!"); + } memcpy(data, ctx->data + ctx->offset, length); ctx->offset += length; } diff --git a/examples/vwebp.c b/examples/vwebp.c index f09aec43..4b3fcf62 100644 --- a/examples/vwebp.c +++ b/examples/vwebp.c @@ -387,7 +387,7 @@ static void Help(void) { printf("Usage: vwebp in_file [options]\n\n" "Decodes the WebP image file and visualize it using OpenGL\n" "Options are:\n" - " -version .... print version number and exit\n" + " -version ..... print version number and exit\n" " -noicc ....... don't use the icc profile if present\n" " -nofancy ..... don't use the fancy YUV420 upscaler\n" " -nofilter .... disable in-loop filtering\n" @@ -395,7 +395,7 @@ static void Help(void) { " -noalphadither disable alpha plane dithering\n" " -mt .......... use multi-threading\n" " -info ........ print info\n" - " -h ....... this help message\n" + " -h ........... this help message\n" "\n" "Keyboard shortcuts:\n" " 'c' ................ toggle use of color profile\n" diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/man/cwebp.1 b/man/cwebp.1 index dc460512..a89ee7a8 100644 --- a/man/cwebp.1 +++ b/man/cwebp.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH CWEBP 1 "February 11, 2016" +.TH CWEBP 1 "June 23, 2016" .SH NAME cwebp \- compress an image file to a WebP file .SH SYNOPSIS @@ -281,7 +281,7 @@ Note: each input format may not support all combinations. Disable all assembly optimizations. .SH BUGS -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp .br Patches welcome! See this page to get started: diff --git a/man/dwebp.1 b/man/dwebp.1 index b3b23cb7..d4b60ed8 100644 --- a/man/dwebp.1 +++ b/man/dwebp.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH DWEBP 1 "December 11, 2015" +.TH DWEBP 1 "June 23, 2016" .SH NAME dwebp \- decompress a WebP file to an image file .SH SYNOPSIS @@ -108,7 +108,7 @@ Print extra information (decoding time in particular). Disable all assembly optimizations. .SH BUGS -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp .br Patches welcome! See this page to get started: diff --git a/man/gif2webp.1 b/man/gif2webp.1 index ceb36080..91e24fae 100644 --- a/man/gif2webp.1 +++ b/man/gif2webp.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH GIF2WEBP 1 "December 11, 2015" +.TH GIF2WEBP 1 "June 23, 2016" .SH NAME gif2webp \- Convert a GIF image to WebP .SH SYNOPSIS @@ -117,7 +117,7 @@ Print extra information. Do not print anything. .SH BUGS -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp .br Patches welcome! See this page to get started: diff --git a/man/vwebp.1 b/man/vwebp.1 index 90c2d63e..a7d5181f 100644 --- a/man/vwebp.1 +++ b/man/vwebp.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH VWEBP 1 "December 11, 2015" +.TH VWEBP 1 "June 23, 2016" .SH NAME vwebp \- decompress a WebP file and display it in a window .SH SYNOPSIS @@ -63,7 +63,7 @@ Overlay file information. Quit. .SH BUGS -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp .br Patches welcome! See this page to get started: diff --git a/man/webpmux.1 b/man/webpmux.1 index 932c747e..0407ef4a 100644 --- a/man/webpmux.1 +++ b/man/webpmux.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH WEBPMUX 1 "December 11, 2015" +.TH WEBPMUX 1 "June 23, 2016" .SH NAME webpmux \- create animated WebP files from non\-animated WebP images, extract frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile. @@ -128,7 +128,7 @@ Output file in WebP format. The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid. .SH BUGS -Please report all bugs to our issue tracker: +Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp .br Patches welcome! See this page to get started: diff --git a/src/Makefile.am b/src/Makefile.am index 23c5b491..8567c6f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,7 +38,7 @@ libwebp_la_LIBADD += utils/libwebputils.la # other than the ones listed on the command line, i.e., after linking, it will # not have unresolved symbols. Some platforms (Windows among them) require all # symbols in shared libraries to be resolved at library creation. -libwebp_la_LDFLAGS = -no-undefined -version-info 6:0:0 +libwebp_la_LDFLAGS = -no-undefined -version-info 6:1:0 libwebpincludedir = $(includedir)/webp pkgconfig_DATA = libwebp.pc @@ -50,7 +50,7 @@ if BUILD_LIBWEBPDECODER libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la - libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 2:0:0 + libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 2:1:0 pkgconfig_DATA += libwebpdecoder.pc endif diff --git a/src/dec/vp8l.c b/src/dec/vp8l.c index 164d2d03..cb2e3176 100644 --- a/src/dec/vp8l.c +++ b/src/dec/vp8l.c @@ -721,6 +721,9 @@ static void ProcessRows(VP8LDecoder* const dec, int row) { const int num_rows = row - dec->last_row_; assert(row <= dec->io_->crop_bottom); + // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size + // of argb_cache_), but we currently don't need more than that. + assert(num_rows <= NUM_ARGB_CACHE_ROWS); if (num_rows > 0) { // Emit output. VP8Io* const io = dec->io_; uint8_t* rows_data = (uint8_t*)dec->argb_cache_; @@ -1055,7 +1058,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, const int mask = hdr->huffman_mask_; const HTreeGroup* htree_group = (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; - assert(src < src_end); + assert(dec->last_row_ < last_row); assert(src_last <= src_end); while (src < src_last) { @@ -1464,23 +1467,31 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { // Special row-processing that only stores the alpha data. static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) { - const int num_rows = last_row - dec->last_row_; - const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; + int cur_row = dec->last_row_; + int num_rows = last_row - cur_row; + const uint32_t* in = dec->pixels_ + dec->width_ * cur_row; assert(last_row <= dec->io_->crop_bottom); - if (num_rows > 0) { + while (num_rows > 0) { + const int num_rows_to_process = + (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows; // Extract alpha (which is stored in the green plane). ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; uint8_t* const output = alph_dec->output_; const int width = dec->io_->width; // the final width (!= dec->width_) - const int cache_pixs = width * num_rows; - uint8_t* dst = output + width * dec->last_row_; + const int cache_pixs = width * num_rows_to_process; + uint8_t* const dst = output + width * cur_row; const uint32_t* const src = dec->argb_cache_; int i; - ApplyInverseTransforms(dec, num_rows, in); + ApplyInverseTransforms(dec, num_rows_to_process, in); for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; - AlphaApplyFilter(alph_dec, dec->last_row_, last_row, dst, width); + AlphaApplyFilter(alph_dec, + cur_row, cur_row + num_rows_to_process, dst, width); + num_rows -= num_rows_to_process; + in += num_rows_to_process * dec->width_; + cur_row += num_rows_to_process; } + assert(cur_row == last_row); dec->last_row_ = dec->last_out_row_ = last_row; } diff --git a/src/dsp/lossless_enc.c b/src/dsp/lossless_enc.c index 0c7bd403..256f6f5f 100644 --- a/src/dsp/lossless_enc.c +++ b/src/dsp/lossless_enc.c @@ -684,14 +684,13 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict, // Returns the difference between the pixel and its prediction. In case of a // lossy encoding, updates the source image to avoid propagating the deviation // further to pixels which depend on the current pixel for their predictions. -static uint32_t GetResidual(int width, int height, - uint32_t* const upper_row, - uint32_t* const current_row, - const uint8_t* const max_diffs, - int mode, VP8LPredictorFunc pred_func, - int x, int y, - int max_quantization, - int exact, int used_subtract_green) { +static WEBP_INLINE uint32_t GetResidual(int width, int height, + uint32_t* const upper_row, + uint32_t* const current_row, + const uint8_t* const max_diffs, + int mode, VP8LPredictorFunc pred_func, + int x, int y, int max_quantization, + int exact, int used_subtract_green) { const uint32_t predict = Predict(pred_func, x, y, current_row, upper_row); uint32_t residual; if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 || diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index 27886f30..136a24a8 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -245,6 +245,7 @@ int VP8LHashChainFill(VP8LHashChain* const p, int quality, const uint32_t* const argb, int xsize, int ysize) { const int size = xsize * ysize; const int iter_max = GetMaxItersForQuality(quality); + const int iter_min = iter_max - quality / 10; const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize); int pos; uint32_t base_position; @@ -296,7 +297,11 @@ int VP8LHashChainFill(VP8LHashChain* const p, int quality, if (best_length < curr_length) { best_length = curr_length; best_distance = base_position - pos; - if (curr_length >= length_max) { + // Stop if we have reached the maximum length. Otherwise, make sure + // we have executed a minimum number of iterations depending on the + // quality. + if ((best_length == MAX_LENGTH) || + (curr_length >= length_max && iter < iter_min)) { break; } } @@ -437,7 +442,6 @@ static int BackwardReferencesLz77(int xsize, int ysize, int len = 0; int j; HashChainFindCopy(hash_chain, i, &offset, &len); - // MIN_LENGTH+1 is empirically better than MIN_LENGTH. if (len > MIN_LENGTH + 1) { const int len_ini = len; int max_reach = 0; @@ -648,9 +652,8 @@ typedef struct { CostCacheInterval* cache_intervals_; size_t cache_intervals_size_; double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k). - // cost_cache_min_dist_[i] contains the index of the minimum in - // cost_cache_[1:i]. cost_cache_min_dist_[0] is unused. - uint16_t cost_cache_min_dist_[MAX_LENGTH]; + double min_cost_cache_; // The minimum value in cost_cache_[1:]. + double max_cost_cache_; // The maximum value in cost_cache_[1:]. float* costs_; uint16_t* dist_array_; // Most of the time, we only need few intervals -> use a free-list, to avoid @@ -660,6 +663,10 @@ typedef struct { // These are regularly malloc'd remains. This list can't grow larger than than // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note. CostInterval* recycled_intervals_; + // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends + // of the intervals that can have impacted the cost at a pixel. + int* interval_ends_; + int interval_ends_size_; } CostManager; static int IsCostCacheIntervalWritable(int start, int end) { @@ -708,6 +715,7 @@ static void CostManagerClear(CostManager* const manager) { WebPSafeFree(manager->costs_); WebPSafeFree(manager->cache_intervals_); + WebPSafeFree(manager->interval_ends_); // Clear the interval lists. DeleteIntervalList(manager, manager->head_); @@ -720,22 +728,6 @@ static void CostManagerClear(CostManager* const manager) { CostManagerInitFreeList(manager); } -static void CostManagerMinDistCacheInit(CostManager* const manager) { - int min_idx = 1; - double min = manager->cost_cache_[1]; - int i; - - // cost_cache_min_dist_[i] contains the index of the minimum in - // cost_cache_[1:i]. - for (i = 1; i < MAX_LENGTH; ++i) { - manager->cost_cache_min_dist_[i] = min_idx; - if (manager->cost_cache_[i] < min) { - min_idx = i; - min = manager->cost_cache_[i]; - } - } -} - static int CostManagerInit(CostManager* const manager, uint16_t* const dist_array, int pix_count, const CostModel* const cost_model) { @@ -745,6 +737,9 @@ static int CostManagerInit(CostManager* const manager, // Empirically, differences between intervals is usually of more than 1. const double min_cost_diff = 0.1; + manager->costs_ = NULL; + manager->cache_intervals_ = NULL; + manager->interval_ends_ = NULL; manager->head_ = NULL; manager->recycled_intervals_ = NULL; manager->count_ = 0; @@ -761,10 +756,17 @@ static int CostManagerInit(CostManager* const manager, min_cost_diff) { ++manager->cache_intervals_size_; } + // Compute the minimum of cost_cache_. + if (i == 1) { + manager->min_cost_cache_ = manager->cost_cache_[1]; + manager->max_cost_cache_ = manager->cost_cache_[1]; + } else if (manager->cost_cache_[i] < manager->min_cost_cache_) { + manager->min_cost_cache_ = manager->cost_cache_[i]; + } else if (manager->cost_cache_[i] > manager->max_cost_cache_) { + manager->max_cost_cache_ = manager->cost_cache_[i]; + } } - CostManagerMinDistCacheInit(manager); - // With the current cost models, we have 15 intervals, so we are safe by // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX. if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) { @@ -789,7 +791,8 @@ static int CostManagerInit(CostManager* const manager, // difference is found, a new interval is created and bounded. for (i = 0; i < cost_cache_size; ++i) { const double cost_val = manager->cost_cache_[i]; - if (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end) { + if (i == 0 || + (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) { if (i > 1) { const int is_writable = IsCostCacheIntervalWritable(cur->start_, cur->end_); @@ -833,25 +836,67 @@ static int CostManagerInit(CostManager* const manager, CostManagerClear(manager); return 0; } - // Set the initial costs_ high for every pixel as we wil lkeep the minimum. + // Set the initial costs_ high for every pixel as we will keep the minimum. for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f; + // The cost at pixel is influenced by the cost intervals from previous pixels. + // Let us take the specific case where the offset is the same (which actually + // happens a lot in case of uniform regions). + // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i] + // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1] + // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2] + // and so on. + // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is + // the value of j such that pixel i + j cannot influence any of those pixels? + // This value is such that: + // max of cost_cache_ < j*offset cost + min of cost_cache_ + // (pixel i + j 's cost cannot beat the worst cost given by pixel i). + // This value will be used to optimize the cost computation in + // BackwardReferencesHashChainDistanceOnly. + { + // The offset cost is computed in GetDistanceCost and has a minimum value of + // the minimum in cost_model->distance_. The case where the offset cost is 0 + // will be dealt with differently later so we are only interested in the + // minimum non-zero offset cost. + double offset_cost_min = 0.; + int size; + for (i = 0; i < NUM_DISTANCE_CODES; ++i) { + if (cost_model->distance_[i] != 0) { + if (offset_cost_min == 0.) { + offset_cost_min = cost_model->distance_[i]; + } else if (cost_model->distance_[i] < offset_cost_min) { + offset_cost_min = cost_model->distance_[i]; + } + } + } + // In case all the cost_model->distance_ is 0, the next non-zero cost we + // can have is from the extra bit in GetDistanceCost, hence 1. + if (offset_cost_min < 1.) offset_cost_min = 1.; + + size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) / + offset_cost_min); + // Empirically, we usually end up with a value below 100. + if (size > MAX_LENGTH) size = MAX_LENGTH; + + manager->interval_ends_ = + (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_)); + if (manager->interval_ends_ == NULL) { + CostManagerClear(manager); + return 0; + } + manager->interval_ends_size_ = size; + } + return 1; } // Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it // is smaller than the previously computed value. -// If index is negative, the distance is computed using -// manager->cost_cache_min_dist_[-index] instead. static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index, double distance_cost) { - int k; + int k = i - index; double cost_tmp; - if (index < 0) { - k = manager->cost_cache_min_dist_[-index]; - } else { - k = i - index; - } + assert(k >= 0 && k < MAX_LENGTH); cost_tmp = distance_cost + manager->cost_cache_[k]; if (manager->costs_[i] > cost_tmp) { @@ -1173,41 +1218,63 @@ static int BackwardReferencesHashChainDistanceOnly( if (len >= MIN_LENGTH) { const int code = DistanceToPlaneCode(xsize, offset); const double offset_cost = GetDistanceCost(cost_model, code); - double distance_cost = prev_cost + offset_cost; const int first_i = i; + int j_max = 0, interval_ends_index = 0; + const int is_offset_zero = (offset_cost == 0.); - PushInterval(cost_manager, distance_cost, i, len); - - // The cost to get to pixel i+k is: - // prev_cost + best weight of path going from i to l. - // For the last cost, if the path were composed of several segments - // (like [i,j), [j,k), [k,l) ), its cost would be: - // offset cost + manager->cost_cache_[j-i] + - // offset cost + manager->cost_cache_[k-j] + - // offset cost + manager->cost_cache_[l-j] - // As the offset_cost is close to the values in cost_cache_ (both are the - // cost to store a number, whether it's an offset or a length), the best - // paths are therefore the ones involving one hop. - for (; i + 1 < pix_count - 1; ++i) { - int offset_next, len_next, diff; + if (!is_offset_zero) { + j_max = (int)ceil( + (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) / + offset_cost); + if (j_max < 1) { + j_max = 1; + } else if (j_max > cost_manager->interval_ends_size_ - 1) { + // This could only happen in the case of MAX_LENGTH. + j_max = cost_manager->interval_ends_size_ - 1; + } + } // else j_max is unused anyway. + // Instead of considering all contributions from a pixel i by calling: + // PushInterval(cost_manager, prev_cost + offset_cost, i, len); + // we optimize these contributions in case offset_cost stays the same for + // consecutive pixels. This describes a set of pixels similar to a + // previous set (e.g. constant color regions). + for (; i < pix_count - 1; ++i) { + int offset_next, len_next; prev_cost = cost_manager->costs_[i - 1]; - distance_cost = prev_cost + offset_cost; + + if (is_offset_zero) { + // No optimization can be made so we just push all of the + // contributions from i. + PushInterval(cost_manager, prev_cost, i, len); + } else { + // j_max is chosen as the smallest j such that: + // max of cost_cache_ < j*offset cost + min of cost_cache_ + // Therefore, the pixel influenced by i-j_max, cannot be influenced + // by i. Only the costs after the end of what i contributed need to be + // updated. cost_manager->interval_ends_ is a circular buffer that + // stores those ends. + const double distance_cost = prev_cost + offset_cost; + int j = cost_manager->interval_ends_[interval_ends_index]; + if (i - first_i <= j_max || + !IsCostCacheIntervalWritable(j, i + len)) { + PushInterval(cost_manager, distance_cost, i, len); + } else { + for (; j < i + len; ++j) { + UpdateCost(cost_manager, j, i, distance_cost); + } + } + // Store the new end in the circular buffer. + assert(interval_ends_index < cost_manager->interval_ends_size_); + cost_manager->interval_ends_[interval_ends_index] = i + len; + if (++interval_ends_index > j_max) interval_ends_index = 0; + } // Check whether i is the last pixel to consider, as it is handled // differently. + if (i + 1 >= pix_count - 1) break; HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next); if (offset_next != offset) break; - - diff = i - first_i; - if (diff > 0) { - assert(len > 1); - if (diff >= len) diff = len - 1; - // The best path going to pixel i is the one starting in a pixel - // within diff hence at the pixel: - // i - manager->cost_cache_min_dist_[diff]. - UpdateCost(cost_manager, i, -diff, distance_cost); - } len = len_next; UpdateCostPerIndex(cost_manager, i); AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i, @@ -1215,7 +1282,6 @@ static int BackwardReferencesHashChainDistanceOnly( cost_manager->costs_, dist_array); } // Submit the last pixel. - if (first_i != i) PushInterval(cost_manager, distance_cost, i, len); UpdateCostPerIndex(cost_manager, i + 1); // This if is for speedup only. It roughly doubles the speed, and @@ -1238,7 +1304,7 @@ static int BackwardReferencesHashChainDistanceOnly( } goto next_symbol; } - if (len != MIN_LENGTH) { + if (len > MIN_LENGTH) { int code_min_length; double cost_total; offset = HashChainFindOffset(hash_chain, i); diff --git a/src/enc/vp8enci.h b/src/enc/vp8enci.h index d3b588b7..c1fbd764 100644 --- a/src/enc/vp8enci.h +++ b/src/enc/vp8enci.h @@ -32,7 +32,7 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 0 #define ENC_MIN_VERSION 5 -#define ENC_REV_VERSION 0 +#define ENC_REV_VERSION 1 enum { MAX_LF_LEVELS = 64, // Maximum loop filter level MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index d98a360b..c16e2560 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -290,7 +290,7 @@ static int AnalyzeEntropy(const uint32_t* argb, } } } - free(histo); + WebPSafeFree(histo); return 1; } else { return 0; diff --git a/src/mux/Makefile.am b/src/mux/Makefile.am index a25bf286..042a14ba 100644 --- a/src/mux/Makefile.am +++ b/src/mux/Makefile.am @@ -13,6 +13,6 @@ libwebpmuxinclude_HEADERS += ../webp/mux_types.h libwebpmuxinclude_HEADERS += ../webp/types.h libwebpmux_la_LIBADD = ../libwebp.la -libwebpmux_la_LDFLAGS = -no-undefined -version-info 2:0:0 +libwebpmux_la_LDFLAGS = -no-undefined -version-info 2:1:0 libwebpmuxincludedir = $(includedir)/webp pkgconfig_DATA = libwebpmux.pc diff --git a/src/mux/muxi.h b/src/mux/muxi.h index 5e8ba2e8..d4d5cbad 100644 --- a/src/mux/muxi.h +++ b/src/mux/muxi.h @@ -28,7 +28,7 @@ extern "C" { #define MUX_MAJ_VERSION 0 #define MUX_MIN_VERSION 3 -#define MUX_REV_VERSION 0 +#define MUX_REV_VERSION 1 // Chunk object. typedef struct WebPChunk WebPChunk; diff --git a/src/webp/decode.h b/src/webp/decode.h index b00d15b3..7a3bed93 100644 --- a/src/webp/decode.h +++ b/src/webp/decode.h @@ -39,8 +39,8 @@ typedef struct WebPDecoderConfig WebPDecoderConfig; WEBP_EXTERN(int) WebPGetDecoderVersion(void); // Retrieve basic header information: width, height. -// This function will also validate the header and return 0 in -// case of formatting error. +// This function will also validate the header, returning true on success, +// false otherwise. '*width' and '*height' are only valid on successful return. // Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height); @@ -471,16 +471,18 @@ static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { // parameter, in which case the features will be parsed and stored into // config->input. Otherwise, 'data' can be NULL and no parsing will occur. // Note that 'config' can be NULL too, in which case a default configuration -// is used. +// is used. If 'config' is not NULL, it must outlive the WebPIDecoder object +// as some references to its fields will be used. No internal copy of 'config' +// is made. // The return WebPIDecoder object must always be deleted calling WebPIDelete(). // Returns NULL in case of error (and config->status will then reflect -// the error condition). +// the error condition, if available). WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size, WebPDecoderConfig* config); // Non-incremental version. This version decodes the full data at once, taking // 'config' into account. Returns decoding status (which should be VP8_STATUS_OK -// if the decoding was successful). +// if the decoding was successful). Note that 'config' cannot be NULL. WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size, WebPDecoderConfig* config);