diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..bcf8e6ca4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Vendors/libwebp"] + path = Vendors/libwebp + url = http://git.chromium.org/webm/libwebp.git diff --git a/Examples/SDWebImage Demo/MasterViewController.m b/Examples/SDWebImage Demo/MasterViewController.m index 7faae7387..2eab33643 100644 --- a/Examples/SDWebImage Demo/MasterViewController.m +++ b/Examples/SDWebImage Demo/MasterViewController.m @@ -31,6 +31,8 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil action:@selector(flushCache)]; _objects = [NSArray arrayWithObjects: @"http://assets.sbnation.com/assets/2512203/dogflops.gif", + @"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp", + @"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp", @"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.jpg?20120509154705", @"http://static2.dmcdn.net/static/video/629/228/44822926:jpeg_preview_small.jpg?20120509181018", @"http://static2.dmcdn.net/static/video/116/367/44763611:jpeg_preview_small.jpg?20120509101749", diff --git a/README.md b/README.md index cc68c4226..5fb444681 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ It provides: - An asynchronous image downloader - An asynchronous memory + disk image caching with automatic cache expiration handling - Animated GIF support +- WebP format support - A background image decompression - A guarantee that the same URL won't be downloaded several times - A guarantee that bogus URLs won't be retried again and again diff --git a/SDWebImage.xcodeproj/project.pbxproj b/SDWebImage.xcodeproj/project.pbxproj index 97ea8a4c9..830dc3b55 100644 --- a/SDWebImage.xcodeproj/project.pbxproj +++ b/SDWebImage.xcodeproj/project.pbxproj @@ -71,6 +71,86 @@ 53EDFB8B17623F7C00698166 /* UIImage+MultiFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFB8817623F7C00698166 /* UIImage+MultiFormat.h */; }; 53EDFB8C17623F7C00698166 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB8917623F7C00698166 /* UIImage+MultiFormat.m */; }; 53EDFB8D17623F7C00698166 /* UIImage+MultiFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB8917623F7C00698166 /* UIImage+MultiFormat.m */; }; + 53EDFB931762547D00698166 /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFB911762547C00698166 /* UIImage+WebP.h */; }; + 53EDFB941762547D00698166 /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFB911762547C00698166 /* UIImage+WebP.h */; }; + 53EDFB951762547D00698166 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; }; + 53EDFB961762547D00698166 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; }; + 53EDFC9217625BE300698166 /* webpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFC9017625BE300698166 /* webpi.h */; }; + 53EDFC9317625BE300698166 /* webpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFC9017625BE300698166 /* webpi.h */; }; + 53EDFC9417625BE300698166 /* webp.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFC9117625BE300698166 /* webp.c */; }; + 53EDFC9517625BE300698166 /* webp.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFC9117625BE300698166 /* webp.c */; }; + 53EDFC9A17625C1100698166 /* vp8li.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFC9617625C1100698166 /* vp8li.h */; }; + 53EDFC9B17625C1100698166 /* vp8li.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFC9617625C1100698166 /* vp8li.h */; }; + 53EDFC9C17625C1100698166 /* vp8l.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFC9717625C1100698166 /* vp8l.c */; }; + 53EDFC9D17625C1100698166 /* vp8l.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFC9717625C1100698166 /* vp8l.c */; }; + 53EDFC9E17625C1100698166 /* vp8i.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFC9817625C1100698166 /* vp8i.h */; }; + 53EDFC9F17625C1100698166 /* vp8i.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFC9817625C1100698166 /* vp8i.h */; }; + 53EDFCA017625C1100698166 /* vp8.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFC9917625C1100698166 /* vp8.c */; }; + 53EDFCA117625C1100698166 /* vp8.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFC9917625C1100698166 /* vp8.c */; }; + 53EDFCA617625C5B00698166 /* huffman.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCA417625C5B00698166 /* huffman.h */; }; + 53EDFCA717625C5B00698166 /* huffman.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCA417625C5B00698166 /* huffman.h */; }; + 53EDFCA817625C5B00698166 /* huffman.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCA517625C5B00698166 /* huffman.c */; }; + 53EDFCA917625C5B00698166 /* huffman.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCA517625C5B00698166 /* huffman.c */; }; + 53EDFCAB17625C8700698166 /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCAA17625C8700698166 /* frame.c */; }; + 53EDFCAC17625C8700698166 /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCAA17625C8700698166 /* frame.c */; }; + 53EDFCAE17625CA600698166 /* alpha.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCAD17625CA600698166 /* alpha.c */; }; + 53EDFCAF17625CA600698166 /* alpha.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCAD17625CA600698166 /* alpha.c */; }; + 53EDFCB217625CD800698166 /* quant_levels_dec.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCB017625CD800698166 /* quant_levels_dec.h */; }; + 53EDFCB317625CD800698166 /* quant_levels_dec.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCB017625CD800698166 /* quant_levels_dec.h */; }; + 53EDFCB417625CD800698166 /* quant_levels_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCB117625CD800698166 /* quant_levels_dec.c */; }; + 53EDFCB517625CD800698166 /* quant_levels_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCB117625CD800698166 /* quant_levels_dec.c */; }; + 53EDFCB917625D1900698166 /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCB717625D1900698166 /* dsp.h */; }; + 53EDFCBA17625D1900698166 /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCB717625D1900698166 /* dsp.h */; }; + 53EDFCBB17625D1900698166 /* dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCB817625D1900698166 /* dec.c */; }; + 53EDFCBC17625D1900698166 /* dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCB817625D1900698166 /* dec.c */; }; + 53EDFCBE17625D3F00698166 /* dec_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCBD17625D3F00698166 /* dec_sse2.c */; }; + 53EDFCBF17625D3F00698166 /* dec_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCBD17625D3F00698166 /* dec_sse2.c */; }; + 53EDFCC117625D8400698166 /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCC017625D8400698166 /* cpu.c */; }; + 53EDFCC217625D8400698166 /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCC017625D8400698166 /* cpu.c */; }; + 53EDFCC517625DB200698166 /* bit_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCC317625DB200698166 /* bit_reader.h */; }; + 53EDFCC617625DB200698166 /* bit_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCC317625DB200698166 /* bit_reader.h */; }; + 53EDFCC717625DB200698166 /* bit_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCC417625DB200698166 /* bit_reader.c */; }; + 53EDFCC817625DB200698166 /* bit_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCC417625DB200698166 /* bit_reader.c */; }; + 53EDFCCB17625DD700698166 /* color_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCC917625DD700698166 /* color_cache.h */; }; + 53EDFCCC17625DD700698166 /* color_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCC917625DD700698166 /* color_cache.h */; }; + 53EDFCCD17625DD700698166 /* color_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCCA17625DD700698166 /* color_cache.c */; }; + 53EDFCCE17625DD700698166 /* color_cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCCA17625DD700698166 /* color_cache.c */; }; + 53EDFCD117625DFA00698166 /* lossless.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCCF17625DFA00698166 /* lossless.h */; }; + 53EDFCD217625DFA00698166 /* lossless.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCCF17625DFA00698166 /* lossless.h */; }; + 53EDFCD317625DFA00698166 /* lossless.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCD017625DFA00698166 /* lossless.c */; }; + 53EDFCD417625DFA00698166 /* lossless.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCD017625DFA00698166 /* lossless.c */; }; + 53EDFCD617625E1A00698166 /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCD517625E1A00698166 /* tree.c */; }; + 53EDFCD717625E1A00698166 /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCD517625E1A00698166 /* tree.c */; }; + 53EDFCD917625E3000698166 /* quant.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCD817625E3000698166 /* quant.c */; }; + 53EDFCDA17625E3000698166 /* quant.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCD817625E3000698166 /* quant.c */; }; + 53EDFCDC17625E6000698166 /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCDB17625E6000698166 /* buffer.c */; }; + 53EDFCDD17625E6000698166 /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCDB17625E6000698166 /* buffer.c */; }; + 53EDFCDF17625E8D00698166 /* upsampling.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCDE17625E8D00698166 /* upsampling.c */; }; + 53EDFCE017625E8D00698166 /* upsampling.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCDE17625E8D00698166 /* upsampling.c */; }; + 53EDFCE317625EB100698166 /* yuv.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCE117625EB100698166 /* yuv.h */; }; + 53EDFCE417625EB100698166 /* yuv.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCE117625EB100698166 /* yuv.h */; }; + 53EDFCE517625EB100698166 /* yuv.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCE217625EB100698166 /* yuv.c */; }; + 53EDFCE617625EB100698166 /* yuv.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCE217625EB100698166 /* yuv.c */; }; + 53EDFCE817625EC800698166 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCE717625EC800698166 /* io.c */; }; + 53EDFCE917625EC800698166 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCE717625EC800698166 /* io.c */; }; + 53EDFCEB17625EE200698166 /* upsampling_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCEA17625EE200698166 /* upsampling_sse2.c */; }; + 53EDFCEC17625EE200698166 /* upsampling_sse2.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCEA17625EE200698166 /* upsampling_sse2.c */; }; + 53EDFCEF17625F1D00698166 /* rescaler.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCED17625F1D00698166 /* rescaler.h */; }; + 53EDFCF017625F1D00698166 /* rescaler.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCED17625F1D00698166 /* rescaler.h */; }; + 53EDFCF117625F1D00698166 /* rescaler.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCEE17625F1D00698166 /* rescaler.c */; }; + 53EDFCF217625F1D00698166 /* rescaler.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCEE17625F1D00698166 /* rescaler.c */; }; + 53EDFCF517625F4100698166 /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCF317625F4100698166 /* utils.h */; }; + 53EDFCF617625F4100698166 /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCF317625F4100698166 /* utils.h */; }; + 53EDFCF717625F4100698166 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCF417625F4100698166 /* utils.c */; }; + 53EDFCF817625F4100698166 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCF417625F4100698166 /* utils.c */; }; + 53EDFCFB17625F5F00698166 /* filters.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCF917625F5F00698166 /* filters.h */; }; + 53EDFCFC17625F5F00698166 /* filters.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCF917625F5F00698166 /* filters.h */; }; + 53EDFCFD17625F5F00698166 /* filters.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCFA17625F5F00698166 /* filters.c */; }; + 53EDFCFE17625F5F00698166 /* filters.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFCFA17625F5F00698166 /* filters.c */; }; + 53EDFD0117625F7900698166 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCFF17625F7900698166 /* thread.h */; }; + 53EDFD0217625F7900698166 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFCFF17625F7900698166 /* thread.h */; }; + 53EDFD0317625F7900698166 /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFD0017625F7900698166 /* thread.c */; }; + 53EDFD0417625F7900698166 /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFD0017625F7900698166 /* thread.c */; }; A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = A18A6CC5172DC28500419892 /* UIImage+GIF.h */; }; A18A6CC8172DC28500419892 /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = A18A6CC5172DC28500419892 /* UIImage+GIF.h */; }; A18A6CC9172DC28500419892 /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = A18A6CC6172DC28500419892 /* UIImage+GIF.m */; }; @@ -118,6 +198,46 @@ 53922D96148C56230056699D /* UIImageView+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/UIImageView+WebCache.m"; sourceTree = SOURCE_ROOT; }; 53EDFB8817623F7C00698166 /* UIImage+MultiFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+MultiFormat.h"; sourceTree = ""; }; 53EDFB8917623F7C00698166 /* UIImage+MultiFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+MultiFormat.m"; sourceTree = ""; }; + 53EDFB911762547C00698166 /* UIImage+WebP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+WebP.h"; sourceTree = ""; }; + 53EDFB921762547C00698166 /* UIImage+WebP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+WebP.m"; sourceTree = ""; }; + 53EDFC9017625BE300698166 /* webpi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = webpi.h; path = Vendors/libwebp/src/dec/webpi.h; sourceTree = ""; }; + 53EDFC9117625BE300698166 /* webp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = webp.c; path = Vendors/libwebp/src/dec/webp.c; sourceTree = ""; }; + 53EDFC9617625C1100698166 /* vp8li.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vp8li.h; path = Vendors/libwebp/src/dec/vp8li.h; sourceTree = ""; }; + 53EDFC9717625C1100698166 /* vp8l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vp8l.c; path = Vendors/libwebp/src/dec/vp8l.c; sourceTree = ""; }; + 53EDFC9817625C1100698166 /* vp8i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vp8i.h; path = Vendors/libwebp/src/dec/vp8i.h; sourceTree = ""; }; + 53EDFC9917625C1100698166 /* vp8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vp8.c; path = Vendors/libwebp/src/dec/vp8.c; sourceTree = ""; }; + 53EDFCA417625C5B00698166 /* huffman.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = huffman.h; path = Vendors/libwebp/src/utils/huffman.h; sourceTree = ""; }; + 53EDFCA517625C5B00698166 /* huffman.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = huffman.c; path = Vendors/libwebp/src/utils/huffman.c; sourceTree = ""; }; + 53EDFCAA17625C8700698166 /* frame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = frame.c; path = Vendors/libwebp/src/dec/frame.c; sourceTree = ""; }; + 53EDFCAD17625CA600698166 /* alpha.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = alpha.c; path = Vendors/libwebp/src/dec/alpha.c; sourceTree = ""; }; + 53EDFCB017625CD800698166 /* quant_levels_dec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = quant_levels_dec.h; path = Vendors/libwebp/src/utils/quant_levels_dec.h; sourceTree = ""; }; + 53EDFCB117625CD800698166 /* quant_levels_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quant_levels_dec.c; path = Vendors/libwebp/src/utils/quant_levels_dec.c; sourceTree = ""; }; + 53EDFCB717625D1900698166 /* dsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dsp.h; path = Vendors/libwebp/src/dsp/dsp.h; sourceTree = ""; }; + 53EDFCB817625D1900698166 /* dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dec.c; path = Vendors/libwebp/src/dsp/dec.c; sourceTree = ""; }; + 53EDFCBD17625D3F00698166 /* dec_sse2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dec_sse2.c; path = Vendors/libwebp/src/dsp/dec_sse2.c; sourceTree = ""; }; + 53EDFCC017625D8400698166 /* cpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cpu.c; path = Vendors/libwebp/src/dsp/cpu.c; sourceTree = ""; }; + 53EDFCC317625DB200698166 /* bit_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bit_reader.h; path = Vendors/libwebp/src/utils/bit_reader.h; sourceTree = ""; }; + 53EDFCC417625DB200698166 /* bit_reader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bit_reader.c; path = Vendors/libwebp/src/utils/bit_reader.c; sourceTree = ""; }; + 53EDFCC917625DD700698166 /* color_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = color_cache.h; path = Vendors/libwebp/src/utils/color_cache.h; sourceTree = ""; }; + 53EDFCCA17625DD700698166 /* color_cache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = color_cache.c; path = Vendors/libwebp/src/utils/color_cache.c; sourceTree = ""; }; + 53EDFCCF17625DFA00698166 /* lossless.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lossless.h; path = Vendors/libwebp/src/dsp/lossless.h; sourceTree = ""; }; + 53EDFCD017625DFA00698166 /* lossless.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lossless.c; path = Vendors/libwebp/src/dsp/lossless.c; sourceTree = ""; }; + 53EDFCD517625E1A00698166 /* tree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tree.c; path = Vendors/libwebp/src/dec/tree.c; sourceTree = ""; }; + 53EDFCD817625E3000698166 /* quant.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quant.c; path = Vendors/libwebp/src/dec/quant.c; sourceTree = ""; }; + 53EDFCDB17625E6000698166 /* buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = buffer.c; path = Vendors/libwebp/src/dec/buffer.c; sourceTree = ""; }; + 53EDFCDE17625E8D00698166 /* upsampling.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = upsampling.c; path = Vendors/libwebp/src/dsp/upsampling.c; sourceTree = ""; }; + 53EDFCE117625EB100698166 /* yuv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yuv.h; path = Vendors/libwebp/src/dsp/yuv.h; sourceTree = ""; }; + 53EDFCE217625EB100698166 /* yuv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yuv.c; path = Vendors/libwebp/src/dsp/yuv.c; sourceTree = ""; }; + 53EDFCE717625EC800698166 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = io.c; path = Vendors/libwebp/src/dec/io.c; sourceTree = ""; }; + 53EDFCEA17625EE200698166 /* upsampling_sse2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = upsampling_sse2.c; path = Vendors/libwebp/src/dsp/upsampling_sse2.c; sourceTree = ""; }; + 53EDFCED17625F1D00698166 /* rescaler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rescaler.h; path = Vendors/libwebp/src/utils/rescaler.h; sourceTree = ""; }; + 53EDFCEE17625F1D00698166 /* rescaler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rescaler.c; path = Vendors/libwebp/src/utils/rescaler.c; sourceTree = ""; }; + 53EDFCF317625F4100698166 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = Vendors/libwebp/src/utils/utils.h; sourceTree = ""; }; + 53EDFCF417625F4100698166 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utils.c; path = Vendors/libwebp/src/utils/utils.c; sourceTree = ""; }; + 53EDFCF917625F5F00698166 /* filters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = filters.h; path = Vendors/libwebp/src/utils/filters.h; sourceTree = ""; }; + 53EDFCFA17625F5F00698166 /* filters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filters.c; path = Vendors/libwebp/src/utils/filters.c; sourceTree = ""; }; + 53EDFCFF17625F7900698166 /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = thread.h; path = Vendors/libwebp/src/utils/thread.h; sourceTree = ""; }; + 53EDFD0017625F7900698166 /* thread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = thread.c; path = Vendors/libwebp/src/utils/thread.c; sourceTree = ""; }; 53FB893F14D35D1A0020B787 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 53FB894814D35E9E0020B787 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; A18A6CC5172DC28500419892 /* UIImage+GIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+GIF.h"; sourceTree = ""; }; @@ -172,6 +292,7 @@ 53922D71148C55820056699D /* Frameworks */ = { isa = PBXGroup; children = ( + 53EDFBE417625A2800698166 /* WebP */, 53FB893F14D35D1A0020B787 /* CoreGraphics.framework */, 53922D72148C55820056699D /* Foundation.framework */, 53FB894814D35E9E0020B787 /* UIKit.framework */, @@ -202,6 +323,8 @@ A18A6CCC172DC33A00419892 /* NSData+GIF.m */, A18A6CC5172DC28500419892 /* UIImage+GIF.h */, A18A6CC6172DC28500419892 /* UIImage+GIF.m */, + 53EDFB911762547C00698166 /* UIImage+WebP.h */, + 53EDFB921762547C00698166 /* UIImage+WebP.m */, 535699B415113E7300A4C397 /* MKAnnotationView+WebCache.h */, 535699B515113E7300A4C397 /* MKAnnotationView+WebCache.m */, 53922D93148C56230056699D /* UIButton+WebCache.h */, @@ -245,6 +368,75 @@ name = Utils; sourceTree = ""; }; + 53EDFBE417625A2800698166 /* WebP */ = { + isa = PBXGroup; + children = ( + 53EDFCB617625D1200698166 /* dsp */, + 53EDFCA317625C4600698166 /* util */, + 53EDFCA217625C3C00698166 /* dec */, + ); + name = WebP; + sourceTree = ""; + }; + 53EDFCA217625C3C00698166 /* dec */ = { + isa = PBXGroup; + children = ( + 53EDFCE717625EC800698166 /* io.c */, + 53EDFCDB17625E6000698166 /* buffer.c */, + 53EDFCD817625E3000698166 /* quant.c */, + 53EDFCD517625E1A00698166 /* tree.c */, + 53EDFCAD17625CA600698166 /* alpha.c */, + 53EDFCAA17625C8700698166 /* frame.c */, + 53EDFC9017625BE300698166 /* webpi.h */, + 53EDFC9117625BE300698166 /* webp.c */, + 53EDFC9617625C1100698166 /* vp8li.h */, + 53EDFC9717625C1100698166 /* vp8l.c */, + 53EDFC9817625C1100698166 /* vp8i.h */, + 53EDFC9917625C1100698166 /* vp8.c */, + ); + name = dec; + sourceTree = ""; + }; + 53EDFCA317625C4600698166 /* util */ = { + isa = PBXGroup; + children = ( + 53EDFCFF17625F7900698166 /* thread.h */, + 53EDFD0017625F7900698166 /* thread.c */, + 53EDFCF917625F5F00698166 /* filters.h */, + 53EDFCFA17625F5F00698166 /* filters.c */, + 53EDFCF317625F4100698166 /* utils.h */, + 53EDFCF417625F4100698166 /* utils.c */, + 53EDFCED17625F1D00698166 /* rescaler.h */, + 53EDFCEE17625F1D00698166 /* rescaler.c */, + 53EDFCC917625DD700698166 /* color_cache.h */, + 53EDFCCA17625DD700698166 /* color_cache.c */, + 53EDFCC317625DB200698166 /* bit_reader.h */, + 53EDFCC417625DB200698166 /* bit_reader.c */, + 53EDFCB017625CD800698166 /* quant_levels_dec.h */, + 53EDFCB117625CD800698166 /* quant_levels_dec.c */, + 53EDFCA417625C5B00698166 /* huffman.h */, + 53EDFCA517625C5B00698166 /* huffman.c */, + ); + name = util; + sourceTree = ""; + }; + 53EDFCB617625D1200698166 /* dsp */ = { + isa = PBXGroup; + children = ( + 53EDFCEA17625EE200698166 /* upsampling_sse2.c */, + 53EDFCE117625EB100698166 /* yuv.h */, + 53EDFCE217625EB100698166 /* yuv.c */, + 53EDFCDE17625E8D00698166 /* upsampling.c */, + 53EDFCCF17625DFA00698166 /* lossless.h */, + 53EDFCD017625DFA00698166 /* lossless.c */, + 53EDFCB717625D1900698166 /* dsp.h */, + 53EDFCB817625D1900698166 /* dec.c */, + 53EDFCBD17625D3F00698166 /* dec_sse2.c */, + 53EDFCC017625D8400698166 /* cpu.c */, + ); + name = dsp; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -266,6 +458,21 @@ A18A6CC8172DC28500419892 /* UIImage+GIF.h in Headers */, A18A6CCE172DC33A00419892 /* NSData+GIF.h in Headers */, 53EDFB8B17623F7C00698166 /* UIImage+MultiFormat.h in Headers */, + 53EDFB941762547D00698166 /* UIImage+WebP.h in Headers */, + 53EDFC9317625BE300698166 /* webpi.h in Headers */, + 53EDFC9B17625C1100698166 /* vp8li.h in Headers */, + 53EDFC9F17625C1100698166 /* vp8i.h in Headers */, + 53EDFCA717625C5B00698166 /* huffman.h in Headers */, + 53EDFCB317625CD800698166 /* quant_levels_dec.h in Headers */, + 53EDFCBA17625D1900698166 /* dsp.h in Headers */, + 53EDFCC617625DB200698166 /* bit_reader.h in Headers */, + 53EDFCCC17625DD700698166 /* color_cache.h in Headers */, + 53EDFCD217625DFA00698166 /* lossless.h in Headers */, + 53EDFCE417625EB100698166 /* yuv.h in Headers */, + 53EDFCF017625F1D00698166 /* rescaler.h in Headers */, + 53EDFCF617625F4100698166 /* utils.h in Headers */, + 53EDFCFC17625F5F00698166 /* filters.h in Headers */, + 53EDFD0217625F7900698166 /* thread.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -286,6 +493,21 @@ A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */, A18A6CCD172DC33A00419892 /* NSData+GIF.h in Headers */, 53EDFB8A17623F7C00698166 /* UIImage+MultiFormat.h in Headers */, + 53EDFB931762547D00698166 /* UIImage+WebP.h in Headers */, + 53EDFC9217625BE300698166 /* webpi.h in Headers */, + 53EDFC9A17625C1100698166 /* vp8li.h in Headers */, + 53EDFC9E17625C1100698166 /* vp8i.h in Headers */, + 53EDFCA617625C5B00698166 /* huffman.h in Headers */, + 53EDFCB217625CD800698166 /* quant_levels_dec.h in Headers */, + 53EDFCB917625D1900698166 /* dsp.h in Headers */, + 53EDFCC517625DB200698166 /* bit_reader.h in Headers */, + 53EDFCCB17625DD700698166 /* color_cache.h in Headers */, + 53EDFCD117625DFA00698166 /* lossless.h in Headers */, + 53EDFCE317625EB100698166 /* yuv.h in Headers */, + 53EDFCEF17625F1D00698166 /* rescaler.h in Headers */, + 53EDFCF517625F4100698166 /* utils.h in Headers */, + 53EDFCFB17625F5F00698166 /* filters.h in Headers */, + 53EDFD0117625F7900698166 /* thread.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -403,6 +625,31 @@ A18A6CCA172DC28500419892 /* UIImage+GIF.m in Sources */, A18A6CD0172DC33A00419892 /* NSData+GIF.m in Sources */, 53EDFB8D17623F7C00698166 /* UIImage+MultiFormat.m in Sources */, + 53EDFB961762547D00698166 /* UIImage+WebP.m in Sources */, + 53EDFC9517625BE300698166 /* webp.c in Sources */, + 53EDFC9D17625C1100698166 /* vp8l.c in Sources */, + 53EDFCA117625C1100698166 /* vp8.c in Sources */, + 53EDFCA917625C5B00698166 /* huffman.c in Sources */, + 53EDFCAC17625C8700698166 /* frame.c in Sources */, + 53EDFCAF17625CA600698166 /* alpha.c in Sources */, + 53EDFCB517625CD800698166 /* quant_levels_dec.c in Sources */, + 53EDFCBC17625D1900698166 /* dec.c in Sources */, + 53EDFCBF17625D3F00698166 /* dec_sse2.c in Sources */, + 53EDFCC217625D8400698166 /* cpu.c in Sources */, + 53EDFCC817625DB200698166 /* bit_reader.c in Sources */, + 53EDFCCE17625DD700698166 /* color_cache.c in Sources */, + 53EDFCD417625DFA00698166 /* lossless.c in Sources */, + 53EDFCD717625E1A00698166 /* tree.c in Sources */, + 53EDFCDA17625E3000698166 /* quant.c in Sources */, + 53EDFCDD17625E6000698166 /* buffer.c in Sources */, + 53EDFCE017625E8D00698166 /* upsampling.c in Sources */, + 53EDFCE617625EB100698166 /* yuv.c in Sources */, + 53EDFCE917625EC800698166 /* io.c in Sources */, + 53EDFCEC17625EE200698166 /* upsampling_sse2.c in Sources */, + 53EDFCF217625F1D00698166 /* rescaler.c in Sources */, + 53EDFCF817625F4100698166 /* utils.c in Sources */, + 53EDFCFE17625F5F00698166 /* filters.c in Sources */, + 53EDFD0417625F7900698166 /* thread.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -422,6 +669,31 @@ A18A6CC9172DC28500419892 /* UIImage+GIF.m in Sources */, A18A6CCF172DC33A00419892 /* NSData+GIF.m in Sources */, 53EDFB8C17623F7C00698166 /* UIImage+MultiFormat.m in Sources */, + 53EDFB951762547D00698166 /* UIImage+WebP.m in Sources */, + 53EDFC9417625BE300698166 /* webp.c in Sources */, + 53EDFC9C17625C1100698166 /* vp8l.c in Sources */, + 53EDFCA017625C1100698166 /* vp8.c in Sources */, + 53EDFCA817625C5B00698166 /* huffman.c in Sources */, + 53EDFCAB17625C8700698166 /* frame.c in Sources */, + 53EDFCAE17625CA600698166 /* alpha.c in Sources */, + 53EDFCB417625CD800698166 /* quant_levels_dec.c in Sources */, + 53EDFCBB17625D1900698166 /* dec.c in Sources */, + 53EDFCBE17625D3F00698166 /* dec_sse2.c in Sources */, + 53EDFCC117625D8400698166 /* cpu.c in Sources */, + 53EDFCC717625DB200698166 /* bit_reader.c in Sources */, + 53EDFCCD17625DD700698166 /* color_cache.c in Sources */, + 53EDFCD317625DFA00698166 /* lossless.c in Sources */, + 53EDFCD617625E1A00698166 /* tree.c in Sources */, + 53EDFCD917625E3000698166 /* quant.c in Sources */, + 53EDFCDC17625E6000698166 /* buffer.c in Sources */, + 53EDFCDF17625E8D00698166 /* upsampling.c in Sources */, + 53EDFCE517625EB100698166 /* yuv.c in Sources */, + 53EDFCE817625EC800698166 /* io.c in Sources */, + 53EDFCEB17625EE200698166 /* upsampling_sse2.c in Sources */, + 53EDFCF117625F1D00698166 /* rescaler.c in Sources */, + 53EDFCF717625F4100698166 /* utils.c in Sources */, + 53EDFCFD17625F5F00698166 /* filters.c in Sources */, + 53EDFD0317625F7900698166 /* thread.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -443,6 +715,10 @@ COPY_PHASE_STRIP = NO; DEAD_CODE_STRIPPING = NO; DSTROOT = /tmp/SDWebImage.dst; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; @@ -461,6 +737,10 @@ COPY_PHASE_STRIP = NO; DEAD_CODE_STRIPPING = NO; DSTROOT = /tmp/SDWebImage.dst; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; @@ -479,6 +759,10 @@ COPY_PHASE_STRIP = NO; DEAD_CODE_STRIPPING = NO; DSTROOT = /tmp/SDWebImage.dst; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; @@ -497,6 +781,10 @@ COPY_PHASE_STRIP = NO; DEAD_CODE_STRIPPING = NO; DSTROOT = /tmp/SDWebImage.dst; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; @@ -535,6 +823,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = Vendors/libwebp/src; IPHONEOS_DEPLOYMENT_TARGET = 5.0; PUBLIC_HEADERS_FOLDER_PATH = include/SDWebImage; RUN_CLANG_STATIC_ANALYZER = YES; @@ -562,6 +851,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = Vendors/libwebp/src; IPHONEOS_DEPLOYMENT_TARGET = 5.0; PUBLIC_HEADERS_FOLDER_PATH = include/SDWebImage; RUN_CLANG_STATIC_ANALYZER = YES; diff --git a/SDWebImage/SDWebImageDownloader.m b/SDWebImage/SDWebImageDownloader.m index 932b3e0a2..1caf0380b 100644 --- a/SDWebImage/SDWebImageDownloader.m +++ b/SDWebImage/SDWebImageDownloader.m @@ -70,7 +70,7 @@ - (id)init _downloadQueue = NSOperationQueue.new; _downloadQueue.maxConcurrentOperationCount = 2; _URLCallbacks = NSMutableDictionary.new; - _HTTPHeaders = [NSMutableDictionary dictionaryWithObject:@"image/*" forKey:@"Accept"]; + _HTTPHeaders = [NSMutableDictionary dictionaryWithObject:@"image/webp,image/*;q=0.8" forKey:@"Accept"]; _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); } return self; diff --git a/SDWebImage/UIImage+MultiFormat.m b/SDWebImage/UIImage+MultiFormat.m index 1863f1c1d..a3fb44373 100644 --- a/SDWebImage/UIImage+MultiFormat.m +++ b/SDWebImage/UIImage+MultiFormat.m @@ -8,6 +8,7 @@ #import "UIImage+MultiFormat.h" #import "UIImage+GIF.h" +#import "UIImage+WebP.h" @implementation UIImage (MultiFormat) @@ -24,6 +25,11 @@ + (UIImage *)sd_imageWithData:(NSData *)data image = [[UIImage alloc] initWithData:data]; } + if (!image) // TODO: detect webp signature + { + image = [UIImage sd_imageWithWebPData:data]; + } + return image; } diff --git a/SDWebImage/UIImage+WebP.h b/SDWebImage/UIImage+WebP.h new file mode 100644 index 000000000..871e41e6e --- /dev/null +++ b/SDWebImage/UIImage+WebP.h @@ -0,0 +1,15 @@ +// +// UIImage+WebP.h +// SDWebImage +// +// Created by Olivier Poitrey on 07/06/13. +// Copyright (c) 2013 Dailymotion. All rights reserved. +// + +#import + +@interface UIImage (WebP) + ++ (UIImage *)sd_imageWithWebPData:(NSData *)data; + +@end diff --git a/SDWebImage/UIImage+WebP.m b/SDWebImage/UIImage+WebP.m new file mode 100644 index 000000000..066de527f --- /dev/null +++ b/SDWebImage/UIImage+WebP.m @@ -0,0 +1,62 @@ +// +// UIImage+WebP.m +// SDWebImage +// +// Created by Olivier Poitrey on 07/06/13. +// Copyright (c) 2013 Dailymotion. All rights reserved. +// + +#import "UIImage+WebP.h" +#import "webp/decode.h" + +// Callback for CGDataProviderRelease +static void FreeImageData(void *info, const void *data, size_t size) +{ + free((void *)data); +} + +@implementation UIImage (WebP) + ++ (UIImage *)sd_imageWithWebPData:(NSData *)data +{ + WebPDecoderConfig config; + if (!WebPInitDecoderConfig(&config)) + { + return nil; + } + + config.output.colorspace = MODE_rgbA; + config.options.use_threads = 1; + + // Decode the WebP image data into a RGBA value array. + if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK) + { + return nil; + } + + int width = config.input.width; + int height = config.input.height; + if (config.options.use_scaling) + { + width = config.options.scaled_width; + height = config.options.scaled_height; + } + + // Construct a UIImage from the decoded RGBA value array. + CGDataProviderRef provider = + CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData); + CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); + CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast; + CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; + CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); + + CGColorSpaceRelease(colorSpaceRef); + CGDataProviderRelease(provider); + + UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; + CGImageRelease(imageRef); + + return image; +} + +@end diff --git a/Vendors/libwebp b/Vendors/libwebp new file mode 160000 index 000000000..c2113ad4f --- /dev/null +++ b/Vendors/libwebp @@ -0,0 +1 @@ +Subproject commit c2113ad4f955e042a47a681dd6a5beb6cdd46099