From c4ea259db4debc07401da694f89ebbdc381f2e21 Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Mon, 27 Aug 2012 00:18:48 -0700 Subject: [PATCH 01/17] make VP8DspInitNEON() public this will avoid the "dec_neon.o has no symbol" warning no change in binary size observed on linux. Change-Id: Ifd83dfc6a0c61905481599b06cb5e711f55efa7d --- src/dsp/dec_neon.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/dsp/dec_neon.c b/src/dsp/dec_neon.c index ec824b79..09cafeef 100644 --- a/src/dsp/dec_neon.c +++ b/src/dsp/dec_neon.c @@ -12,14 +12,14 @@ #include "./dsp.h" -#if defined(WEBP_USE_NEON) - -#include "../dec/vp8i.h" - #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif +#if defined(WEBP_USE_NEON) + +#include "../dec/vp8i.h" + #define QRegs "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", \ "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -311,19 +311,24 @@ static void TransformTwoNEON(const int16_t* in, uint8_t* dst, int do_two) { } } +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ +// Entry point + extern void VP8DspInitNEON(void); void VP8DspInitNEON(void) { +#if defined(WEBP_USE_NEON) VP8Transform = TransformTwoNEON; VP8SimpleVFilter16 = SimpleVFilter16NEON; VP8SimpleHFilter16 = SimpleHFilter16NEON; VP8SimpleVFilter16i = SimpleVFilter16iNEON; VP8SimpleHFilter16i = SimpleHFilter16iNEON; +#endif // WEBP_USE_NEON } #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif - -#endif // WEBP_USE_NEON From ef5cc47ee7dc8d0beeac8d9356d75802c710b56d Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Mon, 27 Aug 2012 23:40:47 -0700 Subject: [PATCH 02/17] make *InitSSE2() functions be empty on non-SSE2 platform this avoids the '*.o has no symbols' warning messages Change-Id: I96aad8637fba47fdaa5a12740e3881ed362c805b --- src/dsp/dec_sse2.c | 17 +++++++++++------ src/dsp/enc_sse2.c | 18 ++++++++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/dsp/dec_sse2.c b/src/dsp/dec_sse2.c index 472b68ec..2cb55d01 100644 --- a/src/dsp/dec_sse2.c +++ b/src/dsp/dec_sse2.c @@ -12,15 +12,15 @@ #include "./dsp.h" +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + #if defined(WEBP_USE_SSE2) #include #include "../dec/vp8i.h" -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) @@ -876,9 +876,15 @@ static void HFilter8iSSE2(uint8_t* u, uint8_t* v, int stride, Store16x4(u, v, stride, &p1, &p0, &q0, &q1); } +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ +// Entry point + extern void VP8DspInitSSE2(void); void VP8DspInitSSE2(void) { +#if defined(WEBP_USE_SSE2) VP8Transform = TransformSSE2; VP8VFilter16 = VFilter16SSE2; @@ -894,10 +900,9 @@ void VP8DspInitSSE2(void) { VP8SimpleHFilter16 = SimpleHFilter16SSE2; VP8SimpleVFilter16i = SimpleVFilter16iSSE2; VP8SimpleHFilter16i = SimpleHFilter16iSSE2; +#endif // WEBP_USE_SSE2 } #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif - -#endif // WEBP_USE_SSE2 diff --git a/src/dsp/enc_sse2.c b/src/dsp/enc_sse2.c index b046761d..0986e82e 100644 --- a/src/dsp/enc_sse2.c +++ b/src/dsp/enc_sse2.c @@ -11,16 +11,16 @@ #include "./dsp.h" +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + #if defined(WEBP_USE_SSE2) #include // for abs() #include #include "../enc/vp8enci.h" -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - //------------------------------------------------------------------------------ // Compute susceptibility based on DCT-coeff histograms: // the higher, the "easier" the macroblock is to compress. @@ -819,8 +819,15 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16], } } +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ +// Entry point + extern void VP8EncDspInitSSE2(void); + void VP8EncDspInitSSE2(void) { +#if defined(WEBP_USE_SSE2) VP8CollectHistogram = CollectHistogramSSE2; VP8EncQuantizeBlock = QuantizeBlockSSE2; VP8ITransform = ITransformSSE2; @@ -828,10 +835,9 @@ void VP8EncDspInitSSE2(void) { VP8SSE4x4 = SSE4x4SSE2; VP8TDisto4x4 = Disto4x4SSE2; VP8TDisto16x16 = Disto16x16SSE2; +#endif // WEBP_USE_SSE2 } #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif - -#endif // WEBP_USE_SSE2 From e5970bda8a267209d40853c950eb1e1e0a6b362e Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Tue, 28 Aug 2012 11:02:38 -0700 Subject: [PATCH 03/17] Make *InitSSE2() functions be empty on non-SSE2 platform this avoids the '*.o has no symbols' warning messages Change-Id: Ib47f9faf9073e39293acad6b2f21f21dba8c5378 --- src/dsp/upsampling_sse2.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/dsp/upsampling_sse2.c b/src/dsp/upsampling_sse2.c index 8cb275a0..50076054 100644 --- a/src/dsp/upsampling_sse2.c +++ b/src/dsp/upsampling_sse2.c @@ -11,6 +11,10 @@ #include "./dsp.h" +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + #if defined(WEBP_USE_SSE2) #include @@ -18,10 +22,6 @@ #include #include "./yuv.h" -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - #ifdef FANCY_UPSAMPLING // We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows @@ -184,26 +184,32 @@ SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePairSSE2, VP8YuvToBgra, 4) #undef CONVERT2RGB #undef SSE2_UPSAMPLE_FUNC +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_SSE2 + //------------------------------------------------------------------------------ extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; void WebPInitUpsamplersSSE2(void) { +#if defined(WEBP_USE_SSE2) WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePairSSE2; WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePairSSE2; WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePairSSE2; WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePairSSE2; +#endif // WEBP_USE_SSE2 } void WebPInitPremultiplySSE2(void) { +#if defined(WEBP_USE_SSE2) WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePairSSE2; WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePairSSE2; +#endif // WEBP_USE_SSE2 } -#endif // FANCY_UPSAMPLING - #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif -#endif // WEBP_USE_SSE2 + From 77aa7d50a45dc99daf23d2c3d06374b2d43cf6fe Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Sun, 2 Sep 2012 09:06:44 -0700 Subject: [PATCH 04/17] fix the BITS=8 case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spotted by Måns Rullgård (mans at mansr dot com) Change-Id: I4484b1f00223a0be18cbe924b24a9f5ccffb7ea2 --- src/utils/bit_reader.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/bit_reader.h b/src/utils/bit_reader.h index 36fc13e2..cc7aeece 100644 --- a/src/utils/bit_reader.h +++ b/src/utils/bit_reader.h @@ -93,6 +93,8 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { #elif (BITS == 16) // gcc will recognize a 'rorw $8, ...' here: bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8); +#else // BITS == 8 + bits = (bit_t)in_bits; #endif #else // LITTLE_ENDIAN bits = (bit_t)in_bits; From 3de58d7730189c5ae3b33d0097d640bbfc2f357a Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 3 Oct 2012 15:15:58 +0200 Subject: [PATCH 05/17] fix the -g/O3 discrepancy for 32bit compile in debug mode, some float operations see their intermediate values stored in memory rather than staying in the FPU (which is 80bit precision). Several fixes are possible (breaking long calculations into atomic steps for instance), but simpler of all is just about turning the cost[] array into float* instead of double*. The code is a tad faster, and i didn't see any major output size difference. Change-Id: I053e6d340850f02761687e072b0782c6734d4bf8 --- src/enc/backward_references.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index b8c8ece8..c5474a2d 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -459,8 +459,8 @@ static int BackwardReferencesHashChainDistanceOnly( const int quality = 100; const int pix_count = xsize * ysize; const int use_color_cache = (cache_bits > 0); - double* const cost = - (double*)WebPSafeMalloc((uint64_t)pix_count, sizeof(*cost)); + float* const cost = + (float*)WebPSafeMalloc((uint64_t)pix_count, sizeof(*cost)); CostModel* cost_model = (CostModel*)malloc(sizeof(*cost_model)); HashChain* hash_chain = (HashChain*)malloc(sizeof(*hash_chain)); VP8LColorCache hashers; @@ -481,7 +481,7 @@ static int BackwardReferencesHashChainDistanceOnly( goto Error; } - for (i = 0; i < pix_count; ++i) cost[i] = 1e100; + for (i = 0; i < pix_count; ++i) cost[i] = 1e38f; // We loop one pixel at a time, but store all currently best points to // non-processed locations from this point. @@ -509,10 +509,9 @@ static int BackwardReferencesHashChainDistanceOnly( prev_cost + GetDistanceCost(cost_model, code); int k; for (k = 1; k < len; ++k) { - const double cost_val = - distance_cost + GetLengthCost(cost_model, k); + const double cost_val = distance_cost + GetLengthCost(cost_model, k); if (cost[i + k] > cost_val) { - cost[i + k] = cost_val; + cost[i + k] = (float)cost_val; dist_array[i + k] = k + 1; } } From b30add201700cfdd3188b6a5e18bbbc3c41028ef Mon Sep 17 00:00:00 2001 From: James Zern Date: Wed, 3 Oct 2012 12:06:33 -0700 Subject: [PATCH 06/17] EncodeImageInternal: fix uninitialized free on allocation error refs.refs would be uninitialized and free'd, causing a crash Change-Id: Idb7daec7aec3e5d769d8103595c28a9d0d0b86f4 --- src/enc/vp8l.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 9c202f8d..7abc3b95 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -529,7 +529,12 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, sizeof(*histogram_symbols)); assert(histogram_bits >= MIN_HUFFMAN_BITS); assert(histogram_bits <= MAX_HUFFMAN_BITS); - if (histogram_image == NULL || histogram_symbols == NULL) goto Error; + + if (histogram_image == NULL || histogram_symbols == NULL) { + free(histogram_image); + free(histogram_symbols); + return 0; + } // Calculate backward references from ARGB image. if (!VP8LGetBackwardReferences(width, height, argb, quality, cache_bits, From f9cb58fbcecc8481a090fa7bd8e5e2f163b5dca9 Mon Sep 17 00:00:00 2001 From: James Zern Date: Wed, 3 Oct 2012 12:14:44 -0700 Subject: [PATCH 07/17] GetHistoBits: fix integer overflow huff_image_size was a size_t (=32 bits with 32-bit builds) which could rollover causing an incorrectly sized allocation and a crash in lossless encoding. fixes issue #128 Change-Id: I0f20cee98c29b2b40b02607930b6b7a7ca56996d --- src/enc/vp8l.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 7abc3b95..2abc30f4 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -903,13 +903,13 @@ static int GetHistoBits(const WebPConfig* const config, const WebPPicture* const pic) { const int width = pic->width; const int height = pic->height; - const size_t hist_size = sizeof(VP8LHistogram); + const uint64_t hist_size = sizeof(VP8LHistogram); // Make tile size a function of encoding method (Range: 0 to 6). int histo_bits = 7 - config->method; while (1) { - const size_t huff_image_size = VP8LSubSampleSize(width, histo_bits) * - VP8LSubSampleSize(height, histo_bits) * - hist_size; + const uint64_t huff_image_size = VP8LSubSampleSize(width, histo_bits) * + VP8LSubSampleSize(height, histo_bits) * + hist_size; if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; ++histo_bits; } From 734f762a0814f78e39b1a34f0ff49ea11f51faa2 Mon Sep 17 00:00:00 2001 From: James Zern Date: Wed, 3 Oct 2012 12:09:38 -0700 Subject: [PATCH 08/17] VP8LAllocateHistogramSet: fix overflow in size calculation the multiplications done for total_size would be done with integers, possibly overflowing, before being promoted to 64-bit for the addition Change-Id: I32c3a6400fc2ef120c38e01a8693f4cb1727234d --- src/enc/histogram.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/enc/histogram.c b/src/enc/histogram.c index ca838e06..fb4044bf 100644 --- a/src/enc/histogram.c +++ b/src/enc/histogram.c @@ -55,9 +55,9 @@ VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { int i; VP8LHistogramSet* set; VP8LHistogram* bulk; - const uint64_t total_size = (uint64_t)sizeof(*set) - + size * sizeof(*set->histograms) - + size * sizeof(**set->histograms); + const uint64_t total_size = sizeof(*set) + + (uint64_t)size * sizeof(*set->histograms) + + (uint64_t)size * sizeof(**set->histograms); uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory)); if (memory == NULL) return NULL; From 72b96a6905c9cf51f55ac12fea3dfc5422fca2c1 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 8 Oct 2012 18:15:30 -0700 Subject: [PATCH 09/17] cwebp: fix jpg encodes on XP correct has_alpha check; previously it was controlled by keep_alpha, which overrode the source format check. fixes issue #127 Change-Id: I414cfd9c5ed60b13673ccd2262ee5e4505ed6f6a --- examples/cwebp.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/cwebp.c b/examples/cwebp.c index 8441e94c..7b76c83f 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -179,18 +179,19 @@ static HRESULT ReadPictureWithWIC(const char* filename, IFS(IWICBitmapFrameDecode_GetPixelFormat(pFrame, &srcPixelFormat)); IFS(IWICBitmapDecoder_GetContainerFormat(pDecoder, &srcContainerFormat)); - has_alpha = keep_alpha; - for (i = 0; - has_alpha && i < sizeof(alphaContainers)/sizeof(alphaContainers[0]); - ++i) { - if (IsEqualGUID(MAKE_REFGUID(srcContainerFormat), - MAKE_REFGUID(*alphaContainers[i]))) { - has_alpha = - IsEqualGUID(MAKE_REFGUID(srcPixelFormat), - MAKE_REFGUID(GUID_WICPixelFormat32bppRGBA_)) || - IsEqualGUID(MAKE_REFGUID(srcPixelFormat), - MAKE_REFGUID(GUID_WICPixelFormat32bppBGRA_)); - break; + if (keep_alpha) { + for (i = 0; + i < sizeof(alphaContainers) / sizeof(alphaContainers[0]); + ++i) { + if (IsEqualGUID(MAKE_REFGUID(srcContainerFormat), + MAKE_REFGUID(*alphaContainers[i]))) { + has_alpha = + IsEqualGUID(MAKE_REFGUID(srcPixelFormat), + MAKE_REFGUID(GUID_WICPixelFormat32bppRGBA_)) || + IsEqualGUID(MAKE_REFGUID(srcPixelFormat), + MAKE_REFGUID(GUID_WICPixelFormat32bppBGRA_)); + break; + } } } From d662158010c4eadcc59f2bb96183dbe5acf790f8 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 8 Oct 2012 18:27:27 -0700 Subject: [PATCH 10/17] fix double to float conversion warning introduced in: a792b91 fix the -g/O3 discrepancy for 32bit compile Change-Id: Ic77d6170a5a91cf58ec10c68656ac61a7c0ee41d --- src/enc/backward_references.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index c5474a2d..fd30f307 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -553,7 +553,7 @@ static int BackwardReferencesHashChainDistanceOnly( cost_val += GetLiteralCost(cost_model, argb[i]) * mul1; } if (cost[i] > cost_val) { - cost[i] = cost_val; + cost[i] = (float)cost_val; dist_array[i] = 1; // only one is inserted. } if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); From 4a8fb272238db4d94d2adf51759c0439b35f8f70 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 8 Oct 2012 18:33:18 -0700 Subject: [PATCH 11/17] [cd]webp: always output windows errors don't hide failures with -v. Change-Id: I1578dbb7be67f041f0984bf6696c0c895c1600d9 --- examples/cwebp.c | 14 ++++++-------- examples/dwebp.c | 14 ++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/examples/cwebp.c b/examples/cwebp.c index 7b76c83f..0e5b8206 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -95,14 +95,12 @@ static int ReadYUV(FILE* in_file, WebPPicture* const pic) { #ifdef HAVE_WINCODEC_H -#define IFS(fn) \ - do { \ - if (SUCCEEDED(hr)) \ - { \ - hr = (fn); \ - if (FAILED(hr) && verbose) \ - fprintf(stderr, #fn " failed %08x\n", hr); \ - } \ +#define IFS(fn) \ + do { \ + if (SUCCEEDED(hr)) { \ + hr = (fn); \ + if (FAILED(hr)) fprintf(stderr, #fn " failed %08x\n", hr); \ + } \ } while (0) // modified version of DEFINE_GUID from guiddef.h. diff --git a/examples/dwebp.c b/examples/dwebp.c index 49ff2fa8..12906448 100644 --- a/examples/dwebp.c +++ b/examples/dwebp.c @@ -67,14 +67,12 @@ typedef enum { #ifdef HAVE_WINCODEC_H -#define IFS(fn) \ - do { \ - if (SUCCEEDED(hr)) \ - { \ - hr = (fn); \ - if (FAILED(hr) && verbose) \ - fprintf(stderr, #fn " failed %08x\n", hr); \ - } \ +#define IFS(fn) \ + do { \ + if (SUCCEEDED(hr)) { \ + hr = (fn); \ + if (FAILED(hr)) fprintf(stderr, #fn " failed %08x\n", hr); \ + } \ } while (0) #ifdef __cplusplus From b14fea993a4b70205920abc4e5dfa49fe75beec5 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 8 Oct 2012 22:21:10 -0700 Subject: [PATCH 12/17] autoconf/libwebp: enable dll builds for mingw Change-Id: Ic1ace62aad1d8de95bc370c6729ded83b7b71f0b --- src/Makefile.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 69a09ef1..3979535f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,7 +20,11 @@ libwebp_la_LIBADD += dsp/libwebpdsp.la libwebp_la_LIBADD += enc/libwebpencode.la libwebp_la_LIBADD += utils/libwebputils.la -libwebp_la_LDFLAGS = -version-info 4:0:0 +# Use '-no-undefined' to declare that libwebp does not depend on any libraries +# 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 4:0:0 libwebpincludedir = $(includedir)/webp pkgconfig_DATA = libwebp.pc From 552cd9bce0cc432b786789bf5106ffc8c04614d8 Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 19 Oct 2012 18:34:06 -0700 Subject: [PATCH 13/17] cwebp (windows): fix alpha image import on XP Query the converter to ensure the format is supported; add BGR formats as RGBA was failing for PNG on XP Fixes issue 129 Change-Id: Ib42aaf160a6c18e767e8c7dbe93dec7c45953399 --- examples/cwebp.c | 65 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/examples/cwebp.c b/examples/cwebp.c index 0e5b8206..07616895 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -113,6 +113,12 @@ static int ReadYUV(FILE* in_file, WebPPicture* const pic) { #define MAKE_REFGUID(x) &(x) #endif +typedef struct WICFormatImporter { + const GUID* pixel_format; + int bytes_per_pixel; + int (*import)(WebPPicture* const, const uint8_t* const, int); +} WICFormatImporter; + static HRESULT OpenInputStream(const char* filename, IStream** ppStream) { HRESULT hr = S_OK; IFS(SHCreateStreamOnFileA(filename, STGM_READ, ppStream)); @@ -123,6 +129,31 @@ static HRESULT OpenInputStream(const char* filename, IStream** ppStream) { static HRESULT ReadPictureWithWIC(const char* filename, WebPPicture* const pic, int keep_alpha) { + // From Microsoft SDK 7.0a -- wincodec.h + // Create local copies for compatibility when building against earlier + // versions of the SDK. + WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c); + WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d); + WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_, + 0x6fddc324, 0x4e03, 0x4bfe, + 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f); + WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_, + 0xf5c7ad2d, 0x6a8d, 0x43dd, + 0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9); + const WICFormatImporter alphaFormatImporters[] = { + { &GUID_WICPixelFormat32bppBGRA_, 4, WebPPictureImportBGRA }, + { &GUID_WICPixelFormat32bppRGBA_, 4, WebPPictureImportRGBA }, + { NULL, 0, NULL }, + }; + const WICFormatImporter nonAlphaFormatImporters[] = { + { &GUID_WICPixelFormat24bppBGR_, 3, WebPPictureImportBGR }, + { &GUID_WICPixelFormat24bppRGB_, 3, WebPPictureImportRGB }, + { NULL, 0, NULL }, + }; HRESULT hr = S_OK; IWICBitmapFrameDecode* pFrame = NULL; IWICFormatConverter* pConverter = NULL; @@ -133,6 +164,7 @@ static HRESULT ReadPictureWithWIC(const char* filename, UINT width = 0, height = 0; BYTE* rgb = NULL; WICPixelFormatGUID srcPixelFormat = { 0 }; + const WICFormatImporter* importer = NULL; GUID srcContainerFormat = { 0 }; const GUID* alphaContainers[] = { &GUID_ContainerFormatBmp, @@ -141,18 +173,6 @@ static HRESULT ReadPictureWithWIC(const char* filename, }; int has_alpha = 0; int i, stride; - // From Microsoft SDK 7.0a - // Create local copies for compatibility when building against earlier - // versions of the SDK. - WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_, - 0x6fddc324, 0x4e03, 0x4bfe, - 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d); - WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_, - 0xf5c7ad2d, 0x6a8d, 0x43dd, - 0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9); - WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_, - 0x6fddc324, 0x4e03, 0x4bfe, - 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f); IFS(CoInitialize(NULL)); IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL, @@ -195,15 +215,27 @@ static HRESULT ReadPictureWithWIC(const char* filename, // Prepare for pixel format conversion (if necessary). IFS(IWICImagingFactory_CreateFormatConverter(pFactory, &pConverter)); + + for (importer = has_alpha ? alphaFormatImporters : nonAlphaFormatImporters; + hr == S_OK && importer->import != NULL; ++importer) { + BOOL canConvert; + const HRESULT cchr = IWICFormatConverter_CanConvert( + pConverter, + MAKE_REFGUID(srcPixelFormat), + MAKE_REFGUID(*importer->pixel_format), + &canConvert); + if (SUCCEEDED(cchr) && canConvert) break; + } + if (importer->import == NULL) hr = E_FAIL; + IFS(IWICFormatConverter_Initialize(pConverter, (IWICBitmapSource*)pFrame, - has_alpha ? MAKE_REFGUID(GUID_WICPixelFormat32bppRGBA_) - : MAKE_REFGUID(GUID_WICPixelFormat24bppRGB_), + importer->pixel_format, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom)); // Decode. IFS(IWICFormatConverter_GetSize(pConverter, &width, &height)); - stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); + stride = importer->bytes_per_pixel * width * sizeof(*rgb); if (SUCCEEDED(hr)) { rgb = (BYTE*)malloc(stride * height); if (rgb == NULL) @@ -217,8 +249,7 @@ static HRESULT ReadPictureWithWIC(const char* filename, int ok; pic->width = width; pic->height = height; - ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) - : WebPPictureImportRGB(pic, rgb, stride); + ok = importer->import(pic, rgb, stride); if (!ok) hr = E_FAIL; } From fed7c0485aac753a6c18036510051df80b39894e Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 22 Oct 2012 21:57:59 -0700 Subject: [PATCH 14/17] libwebp: validate chunk size in ParseOptionalChunks the max wasn't checked leading to a rollover case, possibly exploitable. additionally check the RIFF size early, to avoid similar issues. pulled from chromium: http://codereview.chromium.org/11229048/ Change-Id: I4050b13a7e61ec023c0ef50958c45f651cf34c49 --- src/dec/webp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dec/webp.c b/src/dec/webp.c index edd348cb..7455da94 100644 --- a/src/dec/webp.c +++ b/src/dec/webp.c @@ -76,6 +76,9 @@ static VP8StatusCode ParseRIFF(const uint8_t** const data, if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { return VP8_STATUS_BITSTREAM_ERROR; } + if (size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } // We have a RIFF container. Skip it. *riff_size = size; *data += RIFF_HEADER_SIZE; @@ -177,6 +180,9 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, } chunk_size = get_le32(buf + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } // For odd-sized chunk-payload, there's one byte padding at the end. disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; total_size += disk_chunk_size; From 25f585c4f237f7e274f5b54b8c4cba142971dfd3 Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 29 Oct 2012 19:17:17 -0700 Subject: [PATCH 15/17] bump version to 0.2.1 lib - 0.2.1 libtool - 4.1.0 (compatible release) Change-Id: Ib6ca47f2008d5c97d818422816ac60d0d0d8cffa --- README | 2 +- configure.ac | 2 +- src/Makefile.am | 2 +- src/dec/vp8i.h | 2 +- src/enc/vp8enci.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README b/README index a90fda0f..5831311a 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ \__\__/\____/\_____/__/ ____ ___ / _/ / \ \ / _ \/ _/ / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v0.2.0 + \____/____/\_____/_____/____/v0.2.1 Description: ============ diff --git a/configure.ac b/configure.ac index d81c4c98..f6d39bbc 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libwebp], [0.2.0], +AC_INIT([libwebp], [0.2.1], [http://code.google.com/p/webp/issues],, [http://developers.google.com/speed/webp]) AC_CANONICAL_TARGET diff --git a/src/Makefile.am b/src/Makefile.am index 3979535f..99f7f945 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,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 4:0:0 +libwebp_la_LDFLAGS = -no-undefined -version-info 4:1:0 libwebpincludedir = $(includedir)/webp pkgconfig_DATA = libwebp.pc diff --git a/src/dec/vp8i.h b/src/dec/vp8i.h index 4382edfd..6e27456f 100644 --- a/src/dec/vp8i.h +++ b/src/dec/vp8i.h @@ -28,7 +28,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 0 #define DEC_MIN_VERSION 2 -#define DEC_REV_VERSION 0 +#define DEC_REV_VERSION 1 #define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames diff --git a/src/enc/vp8enci.h b/src/enc/vp8enci.h index a77778c0..f660eeec 100644 --- a/src/enc/vp8enci.h +++ b/src/enc/vp8enci.h @@ -27,7 +27,7 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 0 #define ENC_MIN_VERSION 2 -#define ENC_REV_VERSION 0 +#define ENC_REV_VERSION 1 // size of histogram used by CollectHistogram. #define MAX_COEFF_THRESH 64 From 57cf313bba41227d7d36b4c5e1321159df04300d Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 29 Oct 2012 17:05:38 -0700 Subject: [PATCH 16/17] update NEWS Change-Id: Ie225646ba11a6a1d61f5642405c37ed2d20334f8 --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 1431c705..0b40d528 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +- 10/30/12: version 0.2.1 + * Various security related fixes + * cwebp.exe: fix import errors on Windows XP + * enable DLL builds for mingw targets + - 8/3/12: version 0.2.0 * Add support for ARGB -> YUVA conversion for lossless decoder New functions: WebPINewYUVA, WebPIDecGetYUVA From 74fefc8ce8d83946b763345575d6d2c608ba212a Mon Sep 17 00:00:00 2001 From: James Zern Date: Tue, 30 Oct 2012 16:32:36 -0700 Subject: [PATCH 17/17] Update ChangeLog Change-Id: I89a9c8cf6793c38e2b13d6e0557414fb05620eec --- ChangeLog | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0dcf446b..46710c0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +abc0604 Merge "update NEWS" into 0.2.0 +57cf313 update NEWS +25f585c bump version to 0.2.1 +fed7c04 libwebp: validate chunk size in ParseOptionalChunks +552cd9b cwebp (windows): fix alpha image import on XP +b14fea9 autoconf/libwebp: enable dll builds for mingw +4a8fb27 [cd]webp: always output windows errors +d662158 fix double to float conversion warning +72b96a6 cwebp: fix jpg encodes on XP +734f762 VP8LAllocateHistogramSet: fix overflow in size calculation +f9cb58f GetHistoBits: fix integer overflow +b30add2 EncodeImageInternal: fix uninitialized free +3de58d7 fix the -g/O3 discrepancy for 32bit compile +77aa7d5 fix the BITS=8 case +e5970bd Make *InitSSE2() functions be empty on non-SSE2 platform +ef5cc47 make *InitSSE2() functions be empty on non-SSE2 platform +c4ea259 make VP8DspInitNEON() public +4238bc0 Update ChangeLog (v0.2.0) c655380 dec/io.c: cosmetics fe1958f RGBA4444: harmonize lossless/lossy alpha values 681cb30 fix RGBA4444 output w/fancy upsampling