Add image transformer protocol and class. Add UIImage+Transformer category including common image geometry, tinting, blur effect processor.
This commit is contained in:
parent
5ff999f3d1
commit
b4ea87f6c5
|
@ -388,6 +388,30 @@
|
|||
32CF1C101FA496B000004BD1 /* SDWebImageCoderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CF1C061FA496B000004BD1 /* SDWebImageCoderHelper.m */; };
|
||||
32CF1C111FA496B000004BD1 /* SDWebImageCoderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CF1C061FA496B000004BD1 /* SDWebImageCoderHelper.m */; };
|
||||
32CF1C121FA496B000004BD1 /* SDWebImageCoderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CF1C061FA496B000004BD1 /* SDWebImageCoderHelper.m */; };
|
||||
32F7C06F2030114C00873181 /* SDWebImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C06D2030114C00873181 /* SDWebImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
32F7C0702030114C00873181 /* SDWebImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C06D2030114C00873181 /* SDWebImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
32F7C0712030114C00873181 /* SDWebImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C06D2030114C00873181 /* SDWebImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
32F7C0722030114C00873181 /* SDWebImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C06D2030114C00873181 /* SDWebImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
32F7C0732030114C00873181 /* SDWebImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C06D2030114C00873181 /* SDWebImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
32F7C0742030114C00873181 /* SDWebImageTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C06D2030114C00873181 /* SDWebImageTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
32F7C0752030114C00873181 /* SDWebImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C06E2030114C00873181 /* SDWebImageTransformer.m */; };
|
||||
32F7C0762030114C00873181 /* SDWebImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C06E2030114C00873181 /* SDWebImageTransformer.m */; };
|
||||
32F7C0772030114C00873181 /* SDWebImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C06E2030114C00873181 /* SDWebImageTransformer.m */; };
|
||||
32F7C0782030114C00873181 /* SDWebImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C06E2030114C00873181 /* SDWebImageTransformer.m */; };
|
||||
32F7C0792030114C00873181 /* SDWebImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C06E2030114C00873181 /* SDWebImageTransformer.m */; };
|
||||
32F7C07A2030114C00873181 /* SDWebImageTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C06E2030114C00873181 /* SDWebImageTransformer.m */; };
|
||||
32F7C07E2030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
|
||||
32F7C07F2030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
|
||||
32F7C0802030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
|
||||
32F7C0812030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
|
||||
32F7C0822030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
|
||||
32F7C0832030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
|
||||
32F7C0842030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
|
||||
32F7C0852030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
|
||||
32F7C0862030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
|
||||
32F7C0872030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
|
||||
32F7C0882030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
|
||||
32F7C0892030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
|
||||
4314D1231D0E0E3B004B36C9 /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 53922D86148C56230056699D /* SDImageCache.m */; };
|
||||
4314D1311D0E0E3B004B36C9 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 53922D8C148C56230056699D /* SDWebImageDownloader.m */; };
|
||||
4314D1341D0E0E3B004B36C9 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; };
|
||||
|
@ -1391,6 +1415,10 @@
|
|||
32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageIndicator.m; sourceTree = "<group>"; };
|
||||
32CF1C051FA496B000004BD1 /* SDWebImageCoderHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageCoderHelper.h; sourceTree = "<group>"; };
|
||||
32CF1C061FA496B000004BD1 /* SDWebImageCoderHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageCoderHelper.m; sourceTree = "<group>"; };
|
||||
32F7C06D2030114C00873181 /* SDWebImageTransformer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTransformer.h; sourceTree = "<group>"; };
|
||||
32F7C06E2030114C00873181 /* SDWebImageTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTransformer.m; sourceTree = "<group>"; };
|
||||
32F7C07C2030719600873181 /* UIImage+Transform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Transform.m"; sourceTree = "<group>"; };
|
||||
32F7C07D2030719600873181 /* UIImage+Transform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Transform.h"; sourceTree = "<group>"; };
|
||||
4314D1991D0E0E3B004B36C9 /* libSDWebImage watchOS static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libSDWebImage watchOS static.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
431BB7031D06D2C1006A3455 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4369C2751D9807EC007E863A /* UIView+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+WebCache.h"; path = "SDWebImage/UIView+WebCache.h"; sourceTree = "<group>"; };
|
||||
|
@ -1835,6 +1863,8 @@
|
|||
53EDFB921762547C00698166 /* UIImage+WebP.m */,
|
||||
321E60BC1F38E91700405457 /* UIImage+ForceDecode.h */,
|
||||
321E60BD1F38E91700405457 /* UIImage+ForceDecode.m */,
|
||||
32F7C07D2030719600873181 /* UIImage+Transform.h */,
|
||||
32F7C07C2030719600873181 /* UIImage+Transform.m */,
|
||||
4397D2F41D0DE2DF00BB2784 /* NSImage+Additions.h */,
|
||||
4397D2F51D0DE2DF00BB2784 /* NSImage+Additions.m */,
|
||||
AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */,
|
||||
|
@ -1878,6 +1908,8 @@
|
|||
325312C7200F09910046BF1E /* SDWebImageTransition.m */,
|
||||
32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */,
|
||||
32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */,
|
||||
32F7C06D2030114C00873181 /* SDWebImageTransformer.h */,
|
||||
32F7C06E2030114C00873181 /* SDWebImageTransformer.m */,
|
||||
);
|
||||
name = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2125,11 +2157,13 @@
|
|||
80377C5F1F2F666300F89830 /* utils.h in Headers */,
|
||||
80377C5B1F2F666300F89830 /* rescaler_utils.h in Headers */,
|
||||
323F8BF91F38EF770092B609 /* animi.h in Headers */,
|
||||
32F7C0872030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
80377C4F1F2F666300F89830 /* filters_utils.h in Headers */,
|
||||
80377C4C1F2F666300F89830 /* color_cache_utils.h in Headers */,
|
||||
32C0FDE42013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
|
||||
321E60C11F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
|
||||
80377DBE1F2F66A700F89830 /* dsp.h in Headers */,
|
||||
32F7C0722030114C00873181 /* SDWebImageTransformer.h in Headers */,
|
||||
80377EB81F2F66D400F89830 /* alphai_dec.h in Headers */,
|
||||
00733A6D1BC4880E00A5A117 /* UIImage+GIF.h in Headers */,
|
||||
80377C551F2F666300F89830 /* quant_levels_dec_utils.h in Headers */,
|
||||
|
@ -2152,8 +2186,10 @@
|
|||
321E60BF1F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
|
||||
80377EA61F2F66D400F89830 /* webpi_dec.h in Headers */,
|
||||
807A12291F89636300EC2A9B /* SDWebImageCodersManager.h in Headers */,
|
||||
32F7C0852030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
80377C141F2F666300F89830 /* bit_reader_utils.h in Headers */,
|
||||
323F8C0F1F38EF770092B609 /* muxi.h in Headers */,
|
||||
32F7C0702030114C00873181 /* SDWebImageTransformer.h in Headers */,
|
||||
80377C2B1F2F666300F89830 /* utils.h in Headers */,
|
||||
4314D1621D0E0E3B004B36C9 /* mux_types.h in Headers */,
|
||||
4314D1631D0E0E3B004B36C9 /* demux.h in Headers */,
|
||||
|
@ -2255,6 +2291,7 @@
|
|||
80377E211F2F66A800F89830 /* neon.h in Headers */,
|
||||
80377C711F2F666400F89830 /* quant_levels_utils.h in Headers */,
|
||||
323F8B541F38EF770092B609 /* backward_references_enc.h in Headers */,
|
||||
32F7C0882030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
43A62A1F1D0E0A800089D7DD /* mux.h in Headers */,
|
||||
431BB6E91D06D2C1006A3455 /* SDWebImageDownloaderOperation.h in Headers */,
|
||||
80377ED41F2F66D500F89830 /* vp8li_dec.h in Headers */,
|
||||
|
@ -2289,6 +2326,7 @@
|
|||
323F8BFA1F38EF770092B609 /* animi.h in Headers */,
|
||||
431BB6F91D06D2C1006A3455 /* UIImage+GIF.h in Headers */,
|
||||
321E60B41F38E90100405457 /* SDWebImageWebPCoder.h in Headers */,
|
||||
32F7C0732030114C00873181 /* SDWebImageTransformer.h in Headers */,
|
||||
431BB6FA1D06D2C1006A3455 /* SDWebImageDownloader.h in Headers */,
|
||||
80377DF51F2F66A800F89830 /* common_sse2.h in Headers */,
|
||||
323F8BDC1F38EF770092B609 /* vp8i_enc.h in Headers */,
|
||||
|
@ -2305,6 +2343,7 @@
|
|||
80377ED81F2F66D500F89830 /* alphai_dec.h in Headers */,
|
||||
321E60A71F38E8F600405457 /* SDWebImageGIFCoder.h in Headers */,
|
||||
324DF4B9200A14DC008A84CC /* SDWebImageDefine.h in Headers */,
|
||||
32F7C0892030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
80377EDA1F2F66D500F89830 /* common_dec.h in Headers */,
|
||||
80377EE61F2F66D500F89830 /* webpi_dec.h in Headers */,
|
||||
4397D2BA1D0DDD8C00BB2784 /* demux.h in Headers */,
|
||||
|
@ -2340,6 +2379,7 @@
|
|||
32CF1C0C1FA496B000004BD1 /* SDWebImageCoderHelper.h in Headers */,
|
||||
43A918691D8308FE00B3925F /* SDImageCacheConfig.h in Headers */,
|
||||
4397D2D81D0DDD8C00BB2784 /* UIButton+WebCache.h in Headers */,
|
||||
32F7C0742030114C00873181 /* SDWebImageTransformer.h in Headers */,
|
||||
80377E641F2F66A800F89830 /* mips_macro.h in Headers */,
|
||||
323F8BDD1F38EF770092B609 /* vp8i_enc.h in Headers */,
|
||||
323F8B671F38EF770092B609 /* cost_enc.h in Headers */,
|
||||
|
@ -2452,11 +2492,13 @@
|
|||
4A2CAE311AB4BB7500B6BC39 /* UIImage+WebP.h in Headers */,
|
||||
323F8BF81F38EF770092B609 /* animi.h in Headers */,
|
||||
80377C351F2F666300F89830 /* filters_utils.h in Headers */,
|
||||
32F7C0862030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
80377C321F2F666300F89830 /* color_cache_utils.h in Headers */,
|
||||
321E60C01F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
|
||||
32C0FDE32013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
|
||||
80377D791F2F66A700F89830 /* dsp.h in Headers */,
|
||||
80377EA81F2F66D400F89830 /* alphai_dec.h in Headers */,
|
||||
32F7C0712030114C00873181 /* SDWebImageTransformer.h in Headers */,
|
||||
4A2CAE2D1AB4BB7500B6BC39 /* UIImage+GIF.h in Headers */,
|
||||
80377C3B1F2F666300F89830 /* quant_levels_dec_utils.h in Headers */,
|
||||
80377EB11F2F66D400F89830 /* vp8_dec.h in Headers */,
|
||||
|
@ -2473,6 +2515,7 @@
|
|||
431738BE1CDFC2660008FEB9 /* demux.h in Headers */,
|
||||
80377BFC1F2F665300F89830 /* bit_writer_utils.h in Headers */,
|
||||
32CF1C071FA496B000004BD1 /* SDWebImageCoderHelper.h in Headers */,
|
||||
32F7C0842030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
431738BF1CDFC2660008FEB9 /* encode.h in Headers */,
|
||||
53761316155AD0D5005750A4 /* SDImageCache.h in Headers */,
|
||||
323F8C0E1F38EF770092B609 /* muxi.h in Headers */,
|
||||
|
@ -2507,6 +2550,7 @@
|
|||
80377C0F1F2F665300F89830 /* thread_utils.h in Headers */,
|
||||
321E60BE1F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
|
||||
5376131E155AD0D5005750A4 /* SDWebImagePrefetcher.h in Headers */,
|
||||
32F7C06F2030114C00873181 /* SDWebImageTransformer.h in Headers */,
|
||||
324DF4B4200A14DC008A84CC /* SDWebImageDefine.h in Headers */,
|
||||
80377CE11F2F66A100F89830 /* common_sse2.h in Headers */,
|
||||
80377C0B1F2F665300F89830 /* random_utils.h in Headers */,
|
||||
|
@ -2796,6 +2840,7 @@
|
|||
80377DAE1F2F66A700F89830 /* argb_sse2.c in Sources */,
|
||||
323F8B7D1F38EF770092B609 /* frame_enc.c in Sources */,
|
||||
80377EBB1F2F66D500F89830 /* frame_dec.c in Sources */,
|
||||
32F7C0782030114C00873181 /* SDWebImageTransformer.m in Sources */,
|
||||
80377DAF1F2F66A700F89830 /* argb.c in Sources */,
|
||||
323F8B6B1F38EF770092B609 /* delta_palettization_enc.c in Sources */,
|
||||
00733A5B1BC4880000A5A117 /* NSData+ImageContentType.m in Sources */,
|
||||
|
@ -2828,6 +2873,7 @@
|
|||
80377DE31F2F66A700F89830 /* upsampling_mips_dsp_r2.c in Sources */,
|
||||
80377EBD1F2F66D500F89830 /* io_dec.c in Sources */,
|
||||
80377EBC1F2F66D500F89830 /* idec_dec.c in Sources */,
|
||||
32F7C0812030719600873181 /* UIImage+Transform.m in Sources */,
|
||||
323F8B991F38EF770092B609 /* near_lossless_enc.c in Sources */,
|
||||
80377DE81F2F66A700F89830 /* yuv_mips_dsp_r2.c in Sources */,
|
||||
80377EC31F2F66D500F89830 /* vp8l_dec.c in Sources */,
|
||||
|
@ -3016,6 +3062,7 @@
|
|||
3237F9EC20161AE000A88143 /* NSImage+Additions.m in Sources */,
|
||||
4314D1411D0E0E3B004B36C9 /* SDWebImageDownloaderOperation.m in Sources */,
|
||||
80377D561F2F66A700F89830 /* rescaler_neon.c in Sources */,
|
||||
32F7C0762030114C00873181 /* SDWebImageTransformer.m in Sources */,
|
||||
80377D551F2F66A700F89830 /* rescaler_msa.c in Sources */,
|
||||
80377D5E1F2F66A700F89830 /* yuv_mips_dsp_r2.c in Sources */,
|
||||
80377D611F2F66A700F89830 /* yuv.c in Sources */,
|
||||
|
@ -3056,6 +3103,7 @@
|
|||
4314D1551D0E0E3B004B36C9 /* UIImageView+HighlightedWebCache.m in Sources */,
|
||||
80377E991F2F66D400F89830 /* buffer_dec.c in Sources */,
|
||||
80377C201F2F666300F89830 /* quant_levels_dec_utils.c in Sources */,
|
||||
32F7C07F2030719600873181 /* UIImage+Transform.m in Sources */,
|
||||
80377D471F2F66A700F89830 /* lossless_enc_sse2.c in Sources */,
|
||||
80377C1E1F2F666300F89830 /* huffman_utils.c in Sources */,
|
||||
);
|
||||
|
@ -3164,6 +3212,7 @@
|
|||
3237F9EA20161AE000A88143 /* NSImage+Additions.m in Sources */,
|
||||
431BB6B61D06D2C1006A3455 /* UIImage+WebP.m in Sources */,
|
||||
80377E251F2F66A800F89830 /* rescaler_neon.c in Sources */,
|
||||
32F7C0792030114C00873181 /* SDWebImageTransformer.m in Sources */,
|
||||
80377E241F2F66A800F89830 /* rescaler_msa.c in Sources */,
|
||||
80377E2D1F2F66A800F89830 /* yuv_mips_dsp_r2.c in Sources */,
|
||||
431BB6B91D06D2C1006A3455 /* UIButton+WebCache.m in Sources */,
|
||||
|
@ -3204,6 +3253,7 @@
|
|||
80377C6E1F2F666400F89830 /* quant_levels_dec_utils.c in Sources */,
|
||||
80377EC91F2F66D500F89830 /* buffer_dec.c in Sources */,
|
||||
80377C6C1F2F666400F89830 /* huffman_utils.c in Sources */,
|
||||
32F7C0822030719600873181 /* UIImage+Transform.m in Sources */,
|
||||
80377E161F2F66A800F89830 /* lossless_enc_sse2.c in Sources */,
|
||||
431BB6C71D06D2C1006A3455 /* UIImageView+HighlightedWebCache.m in Sources */,
|
||||
);
|
||||
|
@ -3348,6 +3398,7 @@
|
|||
32C0FDEC2013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
|
||||
80377E5E1F2F66A800F89830 /* lossless_mips_dsp_r2.c in Sources */,
|
||||
80377E3D1F2F66A800F89830 /* cost_sse2.c in Sources */,
|
||||
32F7C0832030719600873181 /* UIImage+Transform.m in Sources */,
|
||||
321E60BB1F38E90100405457 /* SDWebImageWebPCoder.m in Sources */,
|
||||
80377E3C1F2F66A800F89830 /* cost_mips32.c in Sources */,
|
||||
80377E421F2F66A800F89830 /* dec_mips32.c in Sources */,
|
||||
|
@ -3355,6 +3406,7 @@
|
|||
323F8B851F38EF770092B609 /* histogram_enc.c in Sources */,
|
||||
80377EE51F2F66D500F89830 /* webp_dec.c in Sources */,
|
||||
4397D2B01D0DDD8C00BB2784 /* SDImageCache.m in Sources */,
|
||||
32F7C07A2030114C00873181 /* SDWebImageTransformer.m in Sources */,
|
||||
80377E4F1F2F66A800F89830 /* enc_sse41.c in Sources */,
|
||||
80377E701F2F66A800F89830 /* upsampling_sse2.c in Sources */,
|
||||
);
|
||||
|
@ -3395,6 +3447,7 @@
|
|||
80377D6A1F2F66A700F89830 /* argb.c in Sources */,
|
||||
323F8B7C1F38EF770092B609 /* frame_enc.c in Sources */,
|
||||
80377EAB1F2F66D400F89830 /* frame_dec.c in Sources */,
|
||||
32F7C0772030114C00873181 /* SDWebImageTransformer.m in Sources */,
|
||||
43C8929D1D9D6DD90022038D /* anim_decode.c in Sources */,
|
||||
323F8B6A1F38EF770092B609 /* delta_palettization_enc.c in Sources */,
|
||||
43CE75D41CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
|
||||
|
@ -3427,6 +3480,7 @@
|
|||
4A2CAE1E1AB4BB6800B6BC39 /* SDWebImageDownloaderOperation.m in Sources */,
|
||||
80377EAD1F2F66D400F89830 /* io_dec.c in Sources */,
|
||||
80377EAC1F2F66D400F89830 /* idec_dec.c in Sources */,
|
||||
32F7C0802030719600873181 /* UIImage+Transform.m in Sources */,
|
||||
323F8B981F38EF770092B609 /* near_lossless_enc.c in Sources */,
|
||||
80377D6F1F2F66A700F89830 /* cost.c in Sources */,
|
||||
80377EB31F2F66D400F89830 /* vp8l_dec.c in Sources */,
|
||||
|
@ -3547,6 +3601,7 @@
|
|||
323F8B7A1F38EF770092B609 /* frame_enc.c in Sources */,
|
||||
80377E8B1F2F66D000F89830 /* frame_dec.c in Sources */,
|
||||
43C8929A1D9D6DD70022038D /* anim_decode.c in Sources */,
|
||||
32F7C0752030114C00873181 /* SDWebImageTransformer.m in Sources */,
|
||||
323F8B681F38EF770092B609 /* delta_palettization_enc.c in Sources */,
|
||||
43CE75D31CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
|
||||
323F8B5C1F38EF770092B609 /* cost_enc.c in Sources */,
|
||||
|
@ -3579,6 +3634,7 @@
|
|||
80377E8D1F2F66D000F89830 /* io_dec.c in Sources */,
|
||||
80377E8C1F2F66D000F89830 /* idec_dec.c in Sources */,
|
||||
323F8B961F38EF770092B609 /* near_lossless_enc.c in Sources */,
|
||||
32F7C07E2030719600873181 /* UIImage+Transform.m in Sources */,
|
||||
80377CE51F2F66A100F89830 /* cost.c in Sources */,
|
||||
80377E931F2F66D000F89830 /* vp8l_dec.c in Sources */,
|
||||
321E609A1F38E8ED00405457 /* SDWebImageImageIOCoder.m in Sources */,
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
#ifndef UIView
|
||||
#define UIView NSView
|
||||
#endif
|
||||
#ifndef UIColor
|
||||
#define UIColor NSColor
|
||||
#endif
|
||||
#else
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0
|
||||
#error SDWebImage doesn't support Deployment Target version < 5.0
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
#import "UIImage+Transform.h"
|
||||
|
||||
/**
|
||||
A transformer protocol to transform the image load from cache or from download.
|
||||
For cache, it store the transformed image to memory cache if the memory cache missed (Default).
|
||||
For download, it store the transformed image to disk cache and memory cache if the download finished (Default).
|
||||
|
||||
@note The transform process is called from a global queue in order to not to block the main queue.
|
||||
*/
|
||||
@protocol SDWebImageTransformer <NSObject>
|
||||
|
||||
@required
|
||||
/**
|
||||
For each transformer, it must contains its cache key to used to store the image cache or query from the cache. This key will be appened after the original cache key generated by URL or from user.
|
||||
|
||||
@return The cache key to appended after the original cache key. Should not be nil.
|
||||
*/
|
||||
- (nonnull NSString *)transformerKey;
|
||||
|
||||
/**
|
||||
Transform the image to another image.
|
||||
|
||||
@param image The image to be transformed
|
||||
@param key The cache key associated to the image
|
||||
@return The transformed image, or nil if transform failed
|
||||
*/
|
||||
- (nullable UIImage *)transformedImageWithImage:(nonnull UIImage *)image forKey:(nonnull NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Pipeline
|
||||
|
||||
// Pipeline transformer. Which you can bind multiple transformers together to let the image to be transformed one by one and generate the final image.
|
||||
@interface SDWebImagePipelineTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, copy, readonly, nonnull) NSArray<id<SDWebImageTransformer>> *transformers;
|
||||
|
||||
- (nonnull instancetype)initWithTransformers:(nonnull NSArray<id<SDWebImageTransformer>> *)transformers;
|
||||
|
||||
- (void)addTransformer:(nonnull id<SDWebImageTransformer>)transformer;
|
||||
- (void)removeTransformer:(nonnull id<SDWebImageTransformer>)transformer;
|
||||
|
||||
@end
|
||||
|
||||
// There are some build-in transformer based on the `UIImage+Transformer` category to provide the common image geometry, image blending and image effect process. Those transform are useful for static image only but you can create your own to support animated image as well.
|
||||
#pragma mark - Image Geometry
|
||||
|
||||
// Image round corner transformer
|
||||
@interface SDWebImageRoundCornerTransformer: NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, assign, readonly) CGFloat cornerRadius;
|
||||
@property (nonatomic, assign, readonly) SDRectCorner corners;
|
||||
@property (nonatomic, assign, readonly) CGFloat borderWidth;
|
||||
@property (nonatomic, strong, readonly, nullable) UIColor *borderColor;
|
||||
|
||||
- (nonnull instancetype)initWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(nullable UIColor *)borderColor;
|
||||
|
||||
@end
|
||||
|
||||
// Image resizing transformer
|
||||
@interface SDWebImageResizingTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, assign, readonly) CGSize size;
|
||||
@property (nonatomic, assign, readonly) SDImageScaleMode scaleMode;
|
||||
|
||||
- (nonnull instancetype)initWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode;
|
||||
|
||||
@end
|
||||
|
||||
// Image cropping transformer
|
||||
@interface SDWebImageCroppingTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, assign, readonly) CGRect rect;
|
||||
|
||||
- (nonnull instancetype)initWithRect:(CGRect)rect;
|
||||
|
||||
@end
|
||||
|
||||
// Image flipping transformer
|
||||
@interface SDWebImageFlippingTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, assign, readonly) BOOL horizontal;
|
||||
@property (nonatomic, assign, readonly) BOOL vertical;
|
||||
|
||||
- (nonnull instancetype)initWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical;
|
||||
|
||||
@end
|
||||
|
||||
// Image rotation transformer
|
||||
@interface SDWebImageRotationTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, assign, readonly) CGFloat angle;
|
||||
@property (nonatomic, assign, readonly) BOOL fitSize;
|
||||
|
||||
- (nonnull instancetype)initWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Image Blending
|
||||
|
||||
// Image tint color transformer
|
||||
@interface SDWebImageTintTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, strong, readonly, nonnull) UIColor *tintColor;
|
||||
|
||||
- (nonnull instancetype)initWithColor:(nonnull UIColor *)tintColor;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Image Effect
|
||||
|
||||
// Image blur effect transformer
|
||||
@interface SDWebImageBlurTransformer : NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, assign, readonly) CGFloat blurRadius;
|
||||
|
||||
- (nonnull instancetype)initWithRadius:(CGFloat)blurRadius;
|
||||
|
||||
@end
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
// Core Image filter transformer
|
||||
@interface SDWebImageFilterTransformer: NSObject <SDWebImageTransformer>
|
||||
|
||||
@property (nonatomic, strong, readonly, nonnull) CIFilter *filter;
|
||||
|
||||
- (nonnull instancetype)initWithFilter:(nonnull CIFilter *)filter;
|
||||
|
||||
@end
|
||||
#endif
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageTransformer.h"
|
||||
#if SD_UIKIT || SD_MAC
|
||||
#import <CoreImage/CoreImage.h>
|
||||
#endif
|
||||
|
||||
@interface UIColor (Additions)
|
||||
|
||||
@property (nonatomic, copy, readonly, nonnull) NSString *sd_hexString;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIColor (Additions)
|
||||
|
||||
- (NSString *)sd_hexString {
|
||||
CGFloat red, green, blue, alpha;
|
||||
#if SD_UIKIT
|
||||
if (![self getRed:&red green:&green blue:&blue alpha:&alpha]) {
|
||||
[self getWhite:&red alpha:&alpha];
|
||||
green = red;
|
||||
blue = red;
|
||||
}
|
||||
#else
|
||||
@try {
|
||||
[self getRed:&red green:&green blue:&blue alpha:&alpha];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[self getWhite:&red alpha:&alpha];
|
||||
green = red;
|
||||
blue = red;
|
||||
}
|
||||
#endif
|
||||
|
||||
red = roundf(red * 255.f);
|
||||
green = roundf(green * 255.f);
|
||||
blue = roundf(blue * 255.f);
|
||||
alpha = roundf(alpha * 255.f);
|
||||
|
||||
uint hex = ((uint)alpha << 24) | ((uint)red << 16) | ((uint)green << 8) | ((uint)blue);
|
||||
|
||||
return [NSString stringWithFormat:@"0x%08x", hex];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface SDWebImagePipelineTransformer ()
|
||||
|
||||
@property (nonatomic, copy, readwrite, nonnull) NSArray<id<SDWebImageTransformer>> *transformers;
|
||||
@property (nonatomic, copy, readwrite) NSString *transformerKey;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImagePipelineTransformer
|
||||
|
||||
- (instancetype)initWithTransformers:(NSArray<id<SDWebImageTransformer>> *)transformers {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_transformers = [transformers copy];
|
||||
_transformerKey = [[self class] cacheKeyForTransformers:transformers];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSString *)cacheKeyForTransformers:(NSArray<id<SDWebImageTransformer>> *)transformers {
|
||||
if (transformers.count == 0) {
|
||||
return @"";
|
||||
}
|
||||
NSMutableArray<NSString *> *cacheKeys = [NSMutableArray arrayWithCapacity:transformers.count];
|
||||
[transformers enumerateObjectsUsingBlock:^(id<SDWebImageTransformer> _Nonnull transformer, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
NSString *cacheKey = transformer.transformerKey;
|
||||
[cacheKeys addObject:cacheKey];
|
||||
}];
|
||||
|
||||
return [cacheKeys componentsJoinedByString:@"@"];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
UIImage *transformedImage = image;
|
||||
for (id<SDWebImageTransformer> transformer in self.transformers) {
|
||||
transformedImage = [transformer transformedImageWithImage:transformedImage forKey:key];
|
||||
}
|
||||
return transformedImage;
|
||||
}
|
||||
|
||||
- (void)addTransformer:(id<SDWebImageTransformer>)transformer {
|
||||
if (!transformer) {
|
||||
return;
|
||||
}
|
||||
self.transformers = [self.transformers arrayByAddingObject:transformer];
|
||||
}
|
||||
|
||||
- (void)removeTransformer:(id<SDWebImageTransformer>)transformer {
|
||||
if (!transformer) {
|
||||
return;
|
||||
}
|
||||
NSMutableArray<id<SDWebImageTransformer>> *transformers = [self.transformers mutableCopy];
|
||||
[transformers removeObject:transformer];
|
||||
self.transformers = [transformers copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageRoundCornerTransformer
|
||||
|
||||
- (instancetype)initWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(nullable UIColor *)borderColor {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_cornerRadius = cornerRadius;
|
||||
_corners = corners;
|
||||
_borderWidth = borderWidth;
|
||||
_borderColor = borderColor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
return [NSString stringWithFormat:@"SDWebImageRoundCornerTransformer(%f,%lu,%f,%@)", self.cornerRadius, (unsigned long)self.corners, self.borderWidth, self.borderColor.sd_hexString];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_roundedCornerImageWithRadius:self.cornerRadius corners:self.corners borderWidth:self.borderWidth borderColor:self.borderColor];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageResizingTransformer
|
||||
|
||||
- (instancetype)initWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_size = size;
|
||||
_scaleMode = scaleMode;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
CGSize size = self.size;
|
||||
return [NSString stringWithFormat:@"SDWebImageResizingTransformer({%f,%f},%lu)", size.width, size.height, (unsigned long)self.scaleMode];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_resizedImageWithSize:self.size scaleMode:self.scaleMode];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageCroppingTransformer
|
||||
|
||||
- (instancetype)initWithRect:(CGRect)rect {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_rect = rect;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
CGRect rect = self.rect;
|
||||
return [NSString stringWithFormat:@"SDWebImageCroppingTransformer({%f,%f,%f,%f})", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_croppedImageWithRect:self.rect];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageFlippingTransformer
|
||||
|
||||
- (instancetype)initWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_horizontal = horizontal;
|
||||
_vertical = vertical;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
return [NSString stringWithFormat:@"SDWebImageFlippingTransformer(%d,%d)", self.horizontal, self.vertical];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_flippedImageWithHorizontal:self.horizontal vertical:self.vertical];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageRotationTransformer
|
||||
|
||||
- (instancetype)initWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_angle = angle;
|
||||
_fitSize = fitSize;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
return [NSString stringWithFormat:@"SDWebImageRotationTransformer(%f,%d)", self.angle, self.fitSize];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_rotatedImageWithAngle:self.angle fitSize:self.fitSize];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Image Blending
|
||||
|
||||
@implementation SDWebImageTintTransformer
|
||||
|
||||
- (instancetype)initWithColor:(UIColor *)tintColor {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_tintColor = tintColor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
return [NSString stringWithFormat:@"SDWebImageTintTransformer(%@)", self.tintColor.sd_hexString];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_tintedImageWithColor:self.tintColor];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Image Effect
|
||||
|
||||
@implementation SDWebImageBlurTransformer
|
||||
|
||||
- (instancetype)initWithRadius:(CGFloat)blurRadius {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_blurRadius = blurRadius;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
return [NSString stringWithFormat:@"SDWebImageBlurTransformer(%f)", self.blurRadius];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_blurredImageWithRadius:self.blurRadius];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
@implementation SDWebImageFilterTransformer
|
||||
|
||||
- (instancetype)initWithFilter:(CIFilter *)filter {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_filter = filter;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)transformerKey {
|
||||
return [NSString stringWithFormat:@"SDWebImageFilterTransformer(%@)", self.filter.name];
|
||||
}
|
||||
|
||||
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
return [image sd_filteredImageWithFilter:self.filter];
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, SDImageScaleMode) {
|
||||
SDImageScaleModeFill = 0,
|
||||
SDImageScaleModeAspectFit = 1,
|
||||
SDImageScaleModeAspectFill = 2
|
||||
};
|
||||
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
typedef UIRectCorner SDRectCorner;
|
||||
#else
|
||||
typedef NS_OPTIONS(NSUInteger, SDRectCorner) {
|
||||
SDRectCornerTopLeft = 1 << 0,
|
||||
SDRectCornerTopRight = 1 << 1,
|
||||
SDRectCornerBottomLeft = 1 << 2,
|
||||
SDRectCornerBottomRight = 1 << 3,
|
||||
SDRectCornerAllCorners = ~0UL
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
Provide some commen method for `UIImage`.
|
||||
Image process is based on Core Graphics and vImage.
|
||||
*/
|
||||
@interface UIImage (Transform)
|
||||
|
||||
#pragma mark - Image Geometry
|
||||
|
||||
/**
|
||||
Returns a new image which is scaled from this image.
|
||||
The image content will be changed with the scale mode.
|
||||
|
||||
@param size The new size to be scaled, values should be positive.
|
||||
@param contentMode The scale mode for image content.
|
||||
@return The new image with the given size.
|
||||
*/
|
||||
- (nullable UIImage *)sd_resizedImageWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode;
|
||||
|
||||
/**
|
||||
Returns a new image which is cropped from this image.
|
||||
|
||||
@param cropRect Image's inner rect.
|
||||
@return The new image with the cropping rect.
|
||||
*/
|
||||
- (nullable UIImage *)sd_croppedImageWithRect:(CGRect)rect;
|
||||
|
||||
/**
|
||||
Rounds a new image with a given corner radius and corners.
|
||||
|
||||
@param cornerRadius The radius of each corner oval. Values larger than half the
|
||||
rectangle's width or height are clamped appropriately to
|
||||
half the width or height.
|
||||
@param corners A bitmask value that identifies the corners that you want
|
||||
rounded. You can use this parameter to round only a subset
|
||||
of the corners of the rectangle.
|
||||
@param borderWidth The inset border line width. Values larger than half the rectangle's
|
||||
width or height are clamped appropriately to half the width
|
||||
or height.
|
||||
@param borderColor The border stroke color. nil means clear color.
|
||||
@return The new image with the round corner.
|
||||
*/
|
||||
- (nullable UIImage *)sd_roundedCornerImageWithRadius:(CGFloat)cornerRadius
|
||||
corners:(SDRectCorner)corners
|
||||
borderWidth:(CGFloat)borderWidth
|
||||
borderColor:(nullable UIColor *)borderColor;
|
||||
|
||||
/**
|
||||
Returns a new rotated image (relative to the center).
|
||||
|
||||
@param radians Rotated radians in counterclockwise.⟲
|
||||
@param fitSize YES: new image's size is extend to fit all content.
|
||||
NO: image's size will not change, content may be clipped.
|
||||
@return The new image with the rotation.
|
||||
*/
|
||||
- (nullable UIImage *)sd_rotatedImageWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize;
|
||||
|
||||
/**
|
||||
Returns a new horizontally(vertically) flipped image.
|
||||
|
||||
@param horizontal YES to flip the image horizontally. ⇋
|
||||
@param vertical YES to flip the image vertically. ⥯
|
||||
@return The new image with the flipping.
|
||||
*/
|
||||
- (nullable UIImage *)sd_flippedImageWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical;
|
||||
|
||||
#pragma mark - Image Blending
|
||||
|
||||
/**
|
||||
Return a tinted image in alpha channel with the given color.
|
||||
|
||||
@param tintColor The color.
|
||||
@return The new image with the tint color.
|
||||
*/
|
||||
- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor;
|
||||
|
||||
#pragma mark - Image Effect
|
||||
|
||||
/**
|
||||
Return a new image applied a blur effect.
|
||||
|
||||
@param blurRadius The radius of the blur in points, 0 means no blur effect.
|
||||
|
||||
@return The new image with blur effect, or nil if an error occurs (e.g. no enough memory).
|
||||
*/
|
||||
- (nullable UIImage *)sd_blurredImageWithRadius:(CGFloat)blurRadius;
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
/**
|
||||
Return a new image applied a CIFilter.
|
||||
|
||||
@param filter The CIFilter to be applied to the image.
|
||||
@return The new image with the CIFilter, or nil if an error occurs (e.g. no
|
||||
enough memory).
|
||||
*/
|
||||
- (nullable UIImage *)sd_filteredImageWithFilter:(nonnull CIFilter *)filter;
|
||||
#endif
|
||||
|
||||
@end
|
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "UIImage+Transform.h"
|
||||
#import "NSImage+Additions.h"
|
||||
#import <Accelerate/Accelerate.h>
|
||||
#if SD_UIKIT || SD_MAC
|
||||
#import <CoreImage/CoreImage.h>
|
||||
#endif
|
||||
|
||||
#ifndef SD_SWAP // swap two value
|
||||
#define SD_SWAP(_a_, _b_) do { __typeof__(_a_) _tmp_ = (_a_); (_a_) = (_b_); (_b_) = _tmp_; } while (0)
|
||||
#endif
|
||||
|
||||
#if SD_MAC
|
||||
static CGContextRef SDCGContextCreateARGBBitmapContext(CGSize size, BOOL opaque, CGFloat scale) {
|
||||
size_t width = ceil(size.width * scale);
|
||||
size_t height = ceil(size.height * scale);
|
||||
if (width < 1 || height < 1) return NULL;
|
||||
|
||||
//pre-multiplied ARGB, 8-bits per component
|
||||
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
|
||||
CGImageAlphaInfo alphaInfo = (opaque ? kCGImageAlphaNoneSkipFirst : kCGImageAlphaPremultipliedFirst);
|
||||
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, kCGBitmapByteOrderDefault | alphaInfo);
|
||||
CGColorSpaceRelease(space);
|
||||
return context;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SDGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIGraphicsBeginImageContextWithOptions(size, opaque, scale);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextTranslateCTM(context, 0, -size.height);
|
||||
CGContextScaleCTM(context, scale, -scale);
|
||||
#else
|
||||
CGContextRef context = SDCGContextCreateARGBBitmapContext(size, opaque, scale);
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
NSGraphicsContext *graphicsContext = [NSGraphicsContext graphicsContextWithCGContext:context flipped:NO];
|
||||
CGContextRelease(context);
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
NSGraphicsContext.currentContext = graphicsContext;
|
||||
#endif
|
||||
}
|
||||
|
||||
static CGContextRef SDGraphicsGetCurrentContext(void) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
return UIGraphicsGetCurrentContext();
|
||||
#else
|
||||
return NSGraphicsContext.currentContext.CGContext;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SDGraphicsEndImageContext(void) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIGraphicsEndImageContext();
|
||||
#else
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
#endif
|
||||
}
|
||||
|
||||
static UIImage * SDGraphicsGetImageFromCurrentImageContext(void) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
return UIGraphicsGetImageFromCurrentImageContext();
|
||||
#else
|
||||
CGContextRef context = SDGraphicsGetCurrentContext();
|
||||
if (!context) {
|
||||
return nil;
|
||||
}
|
||||
CGImageRef imageRef = CGBitmapContextCreateImage(context);
|
||||
if (!imageRef) {
|
||||
return nil;
|
||||
}
|
||||
NSImage *image = [[NSImage alloc] initWithCGImage:imageRef size:NSZeroSize];
|
||||
CGImageRelease(imageRef);
|
||||
return image;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDRectCorner SDRectCornerConvertCounterClockwise(SDRectCorner corners) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
if (corners != UIRectCornerAllCorners) {
|
||||
UIRectCorner tmp = 0;
|
||||
if (corners & UIRectCornerTopLeft) tmp |= UIRectCornerBottomLeft;
|
||||
if (corners & UIRectCornerTopRight) tmp |= UIRectCornerBottomRight;
|
||||
if (corners & UIRectCornerBottomLeft) tmp |= UIRectCornerTopLeft;
|
||||
if (corners & UIRectCornerBottomRight) tmp |= UIRectCornerTopRight;
|
||||
corners = tmp;
|
||||
}
|
||||
#else
|
||||
if (corners != SDRectCornerAllCorners) {
|
||||
SDRectCorner tmp = 0;
|
||||
if (corners & SDRectCornerTopLeft) tmp |= SDRectCornerBottomLeft;
|
||||
if (corners & SDRectCornerTopRight) tmp |= SDRectCornerBottomRight;
|
||||
if (corners & SDRectCornerBottomLeft) tmp |= SDRectCornerTopLeft;
|
||||
if (corners & SDRectCornerBottomRight) tmp |= SDRectCornerTopRight;
|
||||
corners = tmp;
|
||||
}
|
||||
#endif
|
||||
return corners;
|
||||
}
|
||||
|
||||
static CGRect SDCGRectFitWithScaleMode(CGRect rect, CGSize size, SDImageScaleMode scaleMode) {
|
||||
rect = CGRectStandardize(rect);
|
||||
size.width = size.width < 0 ? -size.width : size.width;
|
||||
size.height = size.height < 0 ? -size.height : size.height;
|
||||
CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
|
||||
switch (scaleMode) {
|
||||
case SDImageScaleModeAspectFit:
|
||||
case SDImageScaleModeAspectFill: {
|
||||
if (rect.size.width < 0.01 || rect.size.height < 0.01 ||
|
||||
size.width < 0.01 || size.height < 0.01) {
|
||||
rect.origin = center;
|
||||
rect.size = CGSizeZero;
|
||||
} else {
|
||||
CGFloat scale;
|
||||
if (scaleMode == SDImageScaleModeAspectFit) {
|
||||
if (size.width / size.height < rect.size.width / rect.size.height) {
|
||||
scale = rect.size.height / size.height;
|
||||
} else {
|
||||
scale = rect.size.width / size.width;
|
||||
}
|
||||
} else {
|
||||
if (size.width / size.height < rect.size.width / rect.size.height) {
|
||||
scale = rect.size.width / size.width;
|
||||
} else {
|
||||
scale = rect.size.height / size.height;
|
||||
}
|
||||
}
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
rect.size = size;
|
||||
rect.origin = CGPointMake(center.x - size.width * 0.5, center.y - size.height * 0.5);
|
||||
}
|
||||
} break;
|
||||
case SDImageScaleModeFill:
|
||||
default: {
|
||||
rect = rect;
|
||||
}
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
#if SD_MAC
|
||||
@interface NSBezierPath (Compatibility)
|
||||
|
||||
+ (instancetype)bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSBezierPath (Compatibility)
|
||||
|
||||
+ (instancetype)bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius {
|
||||
NSBezierPath *path = [NSBezierPath bezierPath];
|
||||
|
||||
CGFloat maxCorner = MIN(NSWidth(rect), NSHeight(rect)) / 2;
|
||||
|
||||
CGFloat topLeftRadius = MIN(maxCorner, (corners & SDRectCornerTopLeft) ? cornerRadius : 0);
|
||||
CGFloat topRightRadius = MIN(maxCorner, (corners & SDRectCornerTopRight) ? cornerRadius : 0);
|
||||
CGFloat bottomLeftRadius = MIN(maxCorner, (corners & SDRectCornerBottomLeft) ? cornerRadius : 0);
|
||||
CGFloat bottomRightRadius = MIN(maxCorner, (corners & SDRectCornerBottomRight) ? cornerRadius : 0);
|
||||
|
||||
NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
|
||||
NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
|
||||
NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect));
|
||||
NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect));
|
||||
|
||||
[path moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))];
|
||||
[path appendBezierPathWithArcFromPoint:topLeft toPoint:bottomLeft radius:topLeftRadius];
|
||||
[path appendBezierPathWithArcFromPoint:bottomLeft toPoint:bottomRight radius:bottomLeftRadius];
|
||||
[path appendBezierPathWithArcFromPoint:bottomRight toPoint:topRight radius:bottomRightRadius];
|
||||
[path appendBezierPathWithArcFromPoint:topRight toPoint:topLeft radius:topRightRadius];
|
||||
[path closePath];
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@implementation UIImage (Transform)
|
||||
|
||||
- (void)sd_drawInRect:(CGRect)rect withScaleMode:(SDImageScaleMode)scaleMode clipsToBounds:(BOOL)clips {
|
||||
CGRect drawRect = SDCGRectFitWithScaleMode(rect, self.size, scaleMode);
|
||||
if (drawRect.size.width == 0 || drawRect.size.height == 0) return;
|
||||
if (clips) {
|
||||
CGContextRef context = SDGraphicsGetCurrentContext();
|
||||
if (context) {
|
||||
CGContextSaveGState(context);
|
||||
CGContextAddRect(context, rect);
|
||||
CGContextClip(context);
|
||||
[self drawInRect:drawRect];
|
||||
CGContextRestoreGState(context);
|
||||
}
|
||||
} else {
|
||||
[self drawInRect:drawRect];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImage *)sd_resizedImageWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode {
|
||||
if (size.width <= 0 || size.height <= 0) return nil;
|
||||
SDGraphicsBeginImageContextWithOptions(size, NO, self.scale);
|
||||
[self sd_drawInRect:CGRectMake(0, 0, size.width, size.height) withScaleMode:scaleMode clipsToBounds:NO];
|
||||
UIImage *image = SDGraphicsGetImageFromCurrentImageContext();
|
||||
SDGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
- (UIImage *)sd_croppedImageWithRect:(CGRect)rect {
|
||||
if (!self.CGImage) return nil;
|
||||
rect.origin.x *= self.scale;
|
||||
rect.origin.y *= self.scale;
|
||||
rect.size.width *= self.scale;
|
||||
rect.size.height *= self.scale;
|
||||
if (rect.size.width <= 0 || rect.size.height <= 0) return nil;
|
||||
CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, rect);
|
||||
if (!imageRef) {
|
||||
return nil;
|
||||
}
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
|
||||
#else
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:self.scale];
|
||||
#endif
|
||||
CGImageRelease(imageRef);
|
||||
return image;
|
||||
}
|
||||
|
||||
- (UIImage *)sd_roundedCornerImageWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor {
|
||||
if (!self.CGImage) return nil;
|
||||
corners = SDRectCornerConvertCounterClockwise(corners);
|
||||
SDGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
|
||||
CGContextRef context = SDGraphicsGetCurrentContext();
|
||||
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
|
||||
|
||||
CGFloat minSize = MIN(self.size.width, self.size.height);
|
||||
if (borderWidth < minSize / 2) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];
|
||||
#else
|
||||
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadius:cornerRadius];
|
||||
#endif
|
||||
[path closePath];
|
||||
|
||||
CGContextSaveGState(context);
|
||||
[path addClip];
|
||||
CGContextDrawImage(context, rect, self.CGImage);
|
||||
CGContextRestoreGState(context);
|
||||
}
|
||||
|
||||
if (borderColor && borderWidth < minSize / 2 && borderWidth > 0) {
|
||||
CGFloat strokeInset = (floor(borderWidth * self.scale) + 0.5) / self.scale;
|
||||
CGRect strokeRect = CGRectInset(rect, strokeInset, strokeInset);
|
||||
CGFloat strokeRadius = cornerRadius > self.scale / 2 ? cornerRadius - self.scale / 2 : 0;
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:strokeRect byRoundingCorners:corners cornerRadii:CGSizeMake(strokeRadius, strokeRadius)];
|
||||
#else
|
||||
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:strokeRect byRoundingCorners:corners cornerRadius:strokeRadius];
|
||||
#endif
|
||||
[path closePath];
|
||||
|
||||
path.lineWidth = borderWidth;
|
||||
[borderColor setStroke];
|
||||
[path stroke];
|
||||
}
|
||||
|
||||
UIImage *image = SDGraphicsGetImageFromCurrentImageContext();
|
||||
SDGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
- (UIImage *)sd_rotatedImageWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize {
|
||||
if (!self.CGImage) return nil;
|
||||
size_t width = (size_t)CGImageGetWidth(self.CGImage);
|
||||
size_t height = (size_t)CGImageGetHeight(self.CGImage);
|
||||
CGRect newRect = CGRectApplyAffineTransform(CGRectMake(0., 0., width, height),
|
||||
fitSize ? CGAffineTransformMakeRotation(angle) : CGAffineTransformIdentity);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef context = CGBitmapContextCreate(NULL,
|
||||
(size_t)newRect.size.width,
|
||||
(size_t)newRect.size.height,
|
||||
8,
|
||||
(size_t)newRect.size.width * 4,
|
||||
colorSpace,
|
||||
kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
if (!context) return nil;
|
||||
|
||||
CGContextSetShouldAntialias(context, true);
|
||||
CGContextSetAllowsAntialiasing(context, true);
|
||||
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
|
||||
|
||||
CGContextTranslateCTM(context, +(newRect.size.width * 0.5), +(newRect.size.height * 0.5));
|
||||
CGContextRotateCTM(context, angle);
|
||||
|
||||
CGContextDrawImage(context, CGRectMake(-(width * 0.5), -(height * 0.5), width, height), self.CGImage);
|
||||
CGImageRef imgRef = CGBitmapContextCreateImage(context);
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImage *img = [UIImage imageWithCGImage:imgRef scale:self.scale orientation:self.imageOrientation];
|
||||
#else
|
||||
UIImage *img = [[UIImage alloc] initWithCGImage:imgRef scale:self.scale];
|
||||
#endif
|
||||
CGImageRelease(imgRef);
|
||||
CGContextRelease(context);
|
||||
return img;
|
||||
}
|
||||
|
||||
- (UIImage *)sd_flippedImageWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical {
|
||||
if (!self.CGImage) return nil;
|
||||
size_t width = (size_t)CGImageGetWidth(self.CGImage);
|
||||
size_t height = (size_t)CGImageGetHeight(self.CGImage);
|
||||
size_t bytesPerRow = width * 4;
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
if (!context) return nil;
|
||||
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, width, height), self.CGImage);
|
||||
UInt8 *data = (UInt8 *)CGBitmapContextGetData(context);
|
||||
if (!data) {
|
||||
CGContextRelease(context);
|
||||
return nil;
|
||||
}
|
||||
vImage_Buffer src = { data, height, width, bytesPerRow };
|
||||
vImage_Buffer dest = { data, height, width, bytesPerRow };
|
||||
if (vertical) {
|
||||
vImageVerticalReflect_ARGB8888(&src, &dest, kvImageBackgroundColorFill);
|
||||
}
|
||||
if (horizontal) {
|
||||
vImageHorizontalReflect_ARGB8888(&src, &dest, kvImageBackgroundColorFill);
|
||||
}
|
||||
CGImageRef imgRef = CGBitmapContextCreateImage(context);
|
||||
CGContextRelease(context);
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImage *img = [UIImage imageWithCGImage:imgRef scale:self.scale orientation:self.imageOrientation];
|
||||
#else
|
||||
UIImage *img = [[UIImage alloc] initWithCGImage:imgRef scale:self.scale];
|
||||
#endif
|
||||
CGImageRelease(imgRef);
|
||||
return img;
|
||||
}
|
||||
|
||||
#pragma mark - Image Blending
|
||||
|
||||
- (UIImage *)sd_tintedImageWithColor:(UIColor *)tintColor {
|
||||
if (!self.CGImage) return nil;
|
||||
if (!tintColor.CGColor) return nil;
|
||||
|
||||
BOOL hasTint = CGColorGetAlpha(tintColor.CGColor) > __FLT_EPSILON__;
|
||||
if (!hasTint) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
return [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:self.imageOrientation];
|
||||
#else
|
||||
return [[UIImage alloc] initWithCGImage:self.CGImage scale:self.scale];
|
||||
#endif
|
||||
}
|
||||
|
||||
CGSize size = self.size;
|
||||
CGRect rect = { CGPointZero, size };
|
||||
CGFloat scale = self.scale;
|
||||
|
||||
// blend mode, see https://en.wikipedia.org/wiki/Alpha_compositing
|
||||
CGBlendMode blendMode = kCGBlendModeSourceAtop;
|
||||
|
||||
SDGraphicsBeginImageContextWithOptions(size, NO, scale);
|
||||
CGContextRef context = SDGraphicsGetCurrentContext();
|
||||
CGContextDrawImage(context, rect, self.CGImage);
|
||||
CGContextSetBlendMode(context, blendMode);
|
||||
CGContextSetFillColorWithColor(context, tintColor.CGColor);
|
||||
CGContextFillRect(context, rect);
|
||||
UIImage *image = SDGraphicsGetImageFromCurrentImageContext();
|
||||
SDGraphicsEndImageContext();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#pragma mark - Image Effect
|
||||
|
||||
- (UIImage *)sd_blurredImageWithRadius:(CGFloat)blurRadius {
|
||||
if (self.size.width < 1 || self.size.height < 1) {
|
||||
return nil;
|
||||
}
|
||||
if (!self.CGImage) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL hasBlur = blurRadius > __FLT_EPSILON__;
|
||||
if (!hasBlur) {
|
||||
return self;
|
||||
}
|
||||
|
||||
CGFloat scale = self.scale;
|
||||
CGImageRef imageRef = self.CGImage;
|
||||
|
||||
vImage_Buffer effect = {}, scratch = {};
|
||||
vImage_Buffer *input = NULL, *output = NULL;
|
||||
|
||||
vImage_CGImageFormat format = {
|
||||
.bitsPerComponent = 8,
|
||||
.bitsPerPixel = 32,
|
||||
.colorSpace = NULL,
|
||||
.bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little, //requests a BGRA buffer.
|
||||
.version = 0,
|
||||
.decode = NULL,
|
||||
.renderingIntent = kCGRenderingIntentDefault
|
||||
};
|
||||
|
||||
vImage_Error err;
|
||||
err = vImageBuffer_InitWithCGImage(&effect, &format, NULL, imageRef, kvImagePrintDiagnosticsToConsole);
|
||||
if (err != kvImageNoError) {
|
||||
NSLog(@"UIImage+Transform error: vImageBuffer_InitWithCGImage returned error code %zi for inputImage: %@", err, self);
|
||||
return nil;
|
||||
}
|
||||
err = vImageBuffer_Init(&scratch, effect.height, effect.width, format.bitsPerPixel, kvImageNoFlags);
|
||||
if (err != kvImageNoError) {
|
||||
NSLog(@"UIImage+Transform error: vImageBuffer_Init returned error code %zi for inputImage: %@", err, self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
input = &effect;
|
||||
output = &scratch;
|
||||
|
||||
if (hasBlur) {
|
||||
// A description of how to compute the box kernel width from the Gaussian
|
||||
// radius (aka standard deviation) appears in the SVG spec:
|
||||
// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
|
||||
//
|
||||
// For larger values of 's' (s >= 2.0), an approximation can be used: Three
|
||||
// successive box-blurs build a piece-wise quadratic convolution kernel, which
|
||||
// approximates the Gaussian kernel to within roughly 3%.
|
||||
//
|
||||
// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
|
||||
//
|
||||
// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
|
||||
//
|
||||
CGFloat inputRadius = blurRadius * scale;
|
||||
if (inputRadius - 2.0 < __FLT_EPSILON__) inputRadius = 2.0;
|
||||
uint32_t radius = floor((inputRadius * 3.0 * sqrt(2 * M_PI) / 4 + 0.5) / 2);
|
||||
radius |= 1; // force radius to be odd so that the three box-blur methodology works.
|
||||
int iterations;
|
||||
if (blurRadius * scale < 0.5) iterations = 1;
|
||||
else if (blurRadius * scale < 1.5) iterations = 2;
|
||||
else iterations = 3;
|
||||
NSInteger tempSize = vImageBoxConvolve_ARGB8888(input, output, NULL, 0, 0, radius, radius, NULL, kvImageGetTempBufferSize | kvImageEdgeExtend);
|
||||
void *temp = malloc(tempSize);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
vImageBoxConvolve_ARGB8888(input, output, temp, 0, 0, radius, radius, NULL, kvImageEdgeExtend);
|
||||
SD_SWAP(input, output);
|
||||
}
|
||||
free(temp);
|
||||
}
|
||||
|
||||
CGImageRef effectCGImage = NULL;
|
||||
effectCGImage = vImageCreateCGImageFromBuffer(input, &format, NULL, NULL, kvImageNoAllocate, NULL);
|
||||
if (effectCGImage == NULL) {
|
||||
effectCGImage = vImageCreateCGImageFromBuffer(input, &format, NULL, NULL, kvImageNoFlags, NULL);
|
||||
free(input->data);
|
||||
}
|
||||
free(output->data);
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImage *outputImage = [UIImage imageWithCGImage:effectCGImage scale:self.scale orientation:self.imageOrientation];
|
||||
#else
|
||||
UIImage *outputImage = [[UIImage alloc] initWithCGImage:effectCGImage scale:self.scale];
|
||||
#endif
|
||||
CGImageRelease(effectCGImage);
|
||||
|
||||
return outputImage;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
- (UIImage *)sd_filteredImageWithFilter:(CIFilter *)filter {
|
||||
if (!self.CGImage) return nil;
|
||||
|
||||
CIContext *context = [CIContext context];
|
||||
CIImage *inputImage = [CIImage imageWithCGImage:self.CGImage];
|
||||
if (!inputImage) return nil;
|
||||
|
||||
[filter setValue:inputImage forKey:kCIInputImageKey];
|
||||
CIImage *outputImage = filter.outputImage;
|
||||
if (!outputImage) return nil;
|
||||
|
||||
CGImageRef imageRef = [context createCGImage:outputImage fromRect:outputImage.extent];
|
||||
if (!imageRef) return nil;
|
||||
|
||||
#if SD_UIKIT
|
||||
UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
|
||||
#else
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:self.scale];
|
||||
#endif
|
||||
CGImageRelease(imageRef);
|
||||
|
||||
return image;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
Loading…
Reference in New Issue