{"action":"closed","number":1991,"pull_request":{"url":"https://api.github.com/repos/rs/SDWebImage/pulls/1991","id":134671209,"html_url":"https://github.com/rs/SDWebImage/pull/1991","diff_url":"https://github.com/rs/SDWebImage/pull/1991.diff","patch_url":"https://github.com/rs/SDWebImage/pull/1991.patch","issue_url":"https://api.github.com/repos/rs/SDWebImage/issues/1991","number":1991,"state":"closed","locked":false,"title":"Feature: refactor decoding code and provide decoding plugin","user":{"login":"dreampiggy","id":6919743,"avatar_url":"https://avatars2.githubusercontent.com/u/6919743?v=4","gravatar_id":"","url":"https://api.github.com/users/dreampiggy","html_url":"https://github.com/dreampiggy","followers_url":"https://api.github.com/users/dreampiggy/followers","following_url":"https://api.github.com/users/dreampiggy/following{/other_user}","gists_url":"https://api.github.com/users/dreampiggy/gists{/gist_id}","starred_url":"https://api.github.com/users/dreampiggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dreampiggy/subscriptions","organizations_url":"https://api.github.com/users/dreampiggy/orgs","repos_url":"https://api.github.com/users/dreampiggy/repos","events_url":"https://api.github.com/users/dreampiggy/events{/privacy}","received_events_url":"https://api.github.com/users/dreampiggy/received_events","type":"User","site_admin":false},"body":"### New Pull Request Checklist\r\n\r\n* [x] I have read and understood the [CONTRIBUTING guide](https://github.com/rs/SDWebImage/blob/master/.github/CONTRIBUTING.md)\r\n* [x] I have read the [Documentation](http://cocoadocs.org/docsets/SDWebImage/)\r\n* [x] I have searched for a similar pull request in the [project](https://github.com/rs/SDWebImage/pulls) and found none\r\n\r\n* [x] I have updated this branch with the latest master to avoid conflicts (via merge from master or rebase)\r\n* [x] I have added the required tests to prove the fix/feature I am adding\r\n* [x] I have updated the documentation (if necessary): need further discussion about this feature and I will write some tutorials about this\r\n* [x] I have run the tests and they pass\r\n* [x] I have run the lint and it passes (`pod lib lint`)\r\n\r\nThis merge request fixes / reffers to the following issues: ...\r\n\r\n### Pull Request Description\r\n\r\nThis PR is about one possible implementation to let SDWebImage support user provided decoder plugins. Since our project is become more and more heavy and the decoding code is growing. We face more issues about decoding or new image format support(HEIF APNG WebP). We sometimes do not have enough time to maintain these. So maybe we can open our decoding procedure to the user, who will provide their own decoder/encoder to support more and more image format.\r\n\r\nTo achieve this, I find a solution (can be discussed) that we can use an protocol called `SDWebImageCoder` to defination the decoding/encoding methods we used entirely in our project. User can provide any instance that implement the protocol and set it on `SDImageCache` or `SDWebImageDownloader` to replace our implementation. If you do not provide it or some decoding method do not implement, we will use the default decoder to call the method instead (will call your implementation only when you implement it).The defination of the protocol is under this description.\r\n\r\nThen, we should refactory all our current decoding code to obey this. I seperate the code into 3 main decoder: `SDWebImageImageIOCoder` (support PNG, JPEG, TIFF), `SDWebImageGIFCoder` (support GIF) and `SDWebImageWebPCoder` (support WebP and Animated WebP). Thanks to that protocol, we can combain and use these as a plugin to build the abstract decoder `SDWebImageDecoder`. It just need to dispatch the method call to actual sub-coder depends on image format. And due to this, we can even seperate the decoding code to another cocoapods or write some simple bridges to use some third-party professional decoder.\r\n\r\nAnd not only images, you can even add some decrypt and encrypt feature as you like because of that protocol is open for entire procedure from `NSData` to `UIImage`. There is also a example below to tell you how to build an decoder by yourself with the built-in plugins or even third-party decoder plugins in the future. (Remember, dispatch and just do what you can)\r\n\r\nAfter that, we should also keep the original `UIImage+GIF`, `UIImage+MultiFormat`, `UIImage+WebP` public APIs. These categories just need to call the related coder to get the image. So finally I passed all the tests and keep the refactory code behaves the same as previous version.\r\n\r\nMoreover, I added 4 more tests about check custom decoder/encoder and an new feature about WebP encoding(which can encode an `UIImage` to WebP and even `_UIAnimatedImage` to Animated WebP NSData to save to disk). So that it can be used if you have an `UIImage` not downloaded from SDWebImage and want to use the benefit of `SDImageCache`.\r\n\r\nPlease notes that this may be an future feature and need more discussion. So will not be merged now. I will keep this and any idea about this feature or a better solution is welcome. \r\n\r\n","created_at":"2017-08-08T14:14:24Z","updated_at":"2017-10-17T16:03:13Z","closed_at":"2017-10-17T16:03:13Z","merged_at":"2017-10-17T16:03:13Z","merge_commit_sha":"a0879fc049453c9028e2e1a9755cd9028aecf5f5","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":{"url":"https://api.github.com/repos/rs/SDWebImage/milestones/16","html_url":"https://github.com/rs/SDWebImage/milestone/16","labels_url":"https://api.github.com/repos/rs/SDWebImage/milestones/16/labels","id":2801890,"number":16,"title":"4.2.0","description":"","creator":{"login":"dreampiggy","id":6919743,"avatar_url":"https://avatars2.githubusercontent.com/u/6919743?v=4","gravatar_id":"","url":"https://api.github.com/users/dreampiggy","html_url":"https://github.com/dreampiggy","followers_url":"https://api.github.com/users/dreampiggy/followers","following_url":"https://api.github.com/users/dreampiggy/following{/other_user}","gists_url":"https://api.github.com/users/dreampiggy/gists{/gist_id}","starred_url":"https://api.github.com/users/dreampiggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dreampiggy/subscriptions","organizations_url":"https://api.github.com/users/dreampiggy/orgs","repos_url":"https://api.github.com/users/dreampiggy/repos","events_url":"https://api.github.com/users/dreampiggy/events{/privacy}","received_events_url":"https://api.github.com/users/dreampiggy/received_events","type":"User","site_admin":false},"open_issues":12,"closed_issues":1,"state":"open","created_at":"2017-09-29T02:35:44Z","updated_at":"2017-10-17T16:03:13Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/rs/SDWebImage/pulls/1991/commits","review_comments_url":"https://api.github.com/repos/rs/SDWebImage/pulls/1991/comments","review_comment_url":"https://api.github.com/repos/rs/SDWebImage/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rs/SDWebImage/issues/1991/comments","statuses_url":"https://api.github.com/repos/rs/SDWebImage/statuses/a0879fc049453c9028e2e1a9755cd9028aecf5f5","head":{"label":"dreampiggy:feature_refactor_decoding_with_plugin","ref":"feature_refactor_decoding_with_plugin","sha":"a0879fc049453c9028e2e1a9755cd9028aecf5f5","user":{"login":"dreampiggy","id":6919743,"avatar_url":"https://avatars2.githubusercontent.com/u/6919743?v=4","gravatar_id":"","url":"https://api.github.com/users/dreampiggy","html_url":"https://github.com/dreampiggy","followers_url":"https://api.github.com/users/dreampiggy/followers","following_url":"https://api.github.com/users/dreampiggy/following{/other_user}","gists_url":"https://api.github.com/users/dreampiggy/gists{/gist_id}","starred_url":"https://api.github.com/users/dreampiggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dreampiggy/subscriptions","organizations_url":"https://api.github.com/users/dreampiggy/orgs","repos_url":"https://api.github.com/users/dreampiggy/repos","events_url":"https://api.github.com/users/dreampiggy/events{/privacy}","received_events_url":"https://api.github.com/users/dreampiggy/received_events","type":"User","site_admin":false},"repo":{"id":95782415,"name":"SDWebImage","full_name":"dreampiggy/SDWebImage","owner":{"login":"dreampiggy","id":6919743,"avatar_url":"https://avatars2.githubusercontent.com/u/6919743?v=4","gravatar_id":"","url":"https://api.github.com/users/dreampiggy","html_url":"https://github.com/dreampiggy","followers_url":"https://api.github.com/users/dreampiggy/followers","following_url":"https://api.github.com/users/dreampiggy/following{/other_user}","gists_url":"https://api.github.com/users/dreampiggy/gists{/gist_id}","starred_url":"https://api.github.com/users/dreampiggy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dreampiggy/subscriptions","organizations_url":"https://api.github.com/users/dreampiggy/orgs","repos_url":"https://api.github.com/users/dreampiggy/repos","events_url":"https://api.github.com/users/dreampiggy/events{/privacy}","received_events_url":"https://api.github.com/users/dreampiggy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dreampiggy/SDWebImage","description":"Asynchronous image downloader with cache support as a UIImageView category","fork":true,"url":"https://api.github.com/repos/dreampiggy/SDWebImage","forks_url":"https://api.github.com/repos/dreampiggy/SDWebImage/forks","keys_url":"https://api.github.com/repos/dreampiggy/SDWebImage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dreampiggy/SDWebImage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dreampiggy/SDWebImage/teams","hooks_url":"https://api.github.com/repos/dreampiggy/SDWebImage/hooks","issue_events_url":"https://api.github.com/repos/dreampiggy/SDWebImage/issues/events{/number}","events_url":"https://api.github.com/repos/dreampiggy/SDWebImage/events","assignees_url":"https://api.github.com/repos/dreampiggy/SDWebImage/assignees{/user}","branches_url":"https://api.github.com/repos/dreampiggy/SDWebImage/branches{/branch}","tags_url":"https://api.github.com/repos/dreampiggy/SDWebImage/tags","blobs_url":"https://api.github.com/repos/dreampiggy/SDWebImage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dreampiggy/SDWebImage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dreampiggy/SDWebImage/git/refs{/sha}","trees_url":"https://api.github.com/repos/dreampiggy/SDWebImage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dreampiggy/SDWebImage/statuses/{sha}","languages_url":"https://api.github.com/repos/dreampiggy/SDWebImage/languages","stargazers_url":"https://api.github.com/repos/dreampiggy/SDWebImage/stargazers","contributors_url":"https://api.github.com/repos/dreampiggy/SDWebImage/contributors","subscribers_url":"https://api.github.com/repos/dreampiggy/SDWebImage/subscribers","subscription_url":"https://api.github.com/repos/dreampiggy/SDWebImage/subscription","commits_url":"https://api.github.com/repos/dreampiggy/SDWebImage/commits{/sha}","git_commits_url":"https://api.github.com/repos/dreampiggy/SDWebImage/git/commits{/sha}","comments_url":"https://api.github.com/repos/dreampiggy/SDWebImage/comments{/number}","issue_comment_url":"https://api.github.com/repos/dreampiggy/SDWebImage/issues/comments{/number}","contents_url":"https://api.github.com/repos/dreampiggy/SDWebImage/contents/{+path}","compare_url":"https://api.github.com/repos/dreampiggy/SDWebImage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dreampiggy/SDWebImage/merges","archive_url":"https://api.github.com/repos/dreampiggy/SDWebImage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dreampiggy/SDWebImage/downloads","issues_url":"https://api.github.com/repos/dreampiggy/SDWebImage/issues{/number}","pulls_url":"https://api.github.com/repos/dreampiggy/SDWebImage/pulls{/number}","milestones_url":"https://api.github.com/repos/dreampiggy/SDWebImage/milestones{/number}","notifications_url":"https://api.github.com/repos/dreampiggy/SDWebImage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dreampiggy/SDWebImage/labels{/name}","releases_url":"https://api.github.com/repos/dreampiggy/SDWebImage/releases{/id}","deployments_url":"https://api.github.com/repos/dreampiggy/SDWebImage/deployments","created_at":"2017-06-29T13:48:41Z","updated_at":"2017-06-29T13:48:44Z","pushed_at":"2017-10-17T15:57:30Z","git_url":"git://github.com/dreampiggy/SDWebImage.git","ssh_url":"git@github.com:dreampiggy/SDWebImage.git","clone_url":"https://github.com/dreampiggy/SDWebImage.git","svn_url":"https://github.com/dreampiggy/SDWebImage","homepage":"http://cocoadocs.org/docsets/SDWebImage","size":6343,"stargazers_count":0,"watchers_count":0,"language":"Objective-C","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"rs:master","ref":"master","sha":"c1df782869955cc505a9304637599c606ba04477","user":{"login":"rs","id":68232,"avatar_url":"https://avatars2.githubusercontent.com/u/68232?v=4","gravatar_id":"","url":"https://api.github.com/users/rs","html_url":"https://github.com/rs","followers_url":"https://api.github.com/users/rs/followers","following_url":"https://api.github.com/users/rs/following{/other_user}","gists_url":"https://api.github.com/users/rs/gists{/gist_id}","starred_url":"https://api.github.com/users/rs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rs/subscriptions","organizations_url":"https://api.github.com/users/rs/orgs","repos_url":"https://api.github.com/users/rs/repos","events_url":"https://api.github.com/users/rs/events{/privacy}","received_events_url":"https://api.github.com/users/rs/received_events","type":"User","site_admin":false},"repo":{"id":313419,"name":"SDWebImage","full_name":"rs/SDWebImage","owner":{"login":"rs","id":68232,"avatar_url":"https://avatars2.githubusercontent.com/u/68232?v=4","gravatar_id":"","url":"https://api.github.com/users/rs","html_url":"https://github.com/rs","followers_url":"https://api.github.com/users/rs/followers","following_url":"https://api.github.com/users/rs/following{/other_user}","gists_url":"https://api.github.com/users/rs/gists{/gist_id}","starred_url":"https://api.github.com/users/rs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rs/subscriptions","organizations_url":"https://api.github.com/users/rs/orgs","repos_url":"https://api.github.com/users/rs/repos","events_url":"https://api.github.com/users/rs/events{/privacy}","received_events_url":"https://api.github.com/users/rs/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rs/SDWebImage","description":"Asynchronous image downloader with cache support as a UIImageView category","fork":false,"url":"https://api.github.com/repos/rs/SDWebImage","forks_url":"https://api.github.com/repos/rs/SDWebImage/forks","keys_url":"https://api.github.com/repos/rs/SDWebImage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rs/SDWebImage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rs/SDWebImage/teams","hooks_url":"https://api.github.com/repos/rs/SDWebImage/hooks","issue_events_url":"https://api.github.com/repos/rs/SDWebImage/issues/events{/number}","events_url":"https://api.github.com/repos/rs/SDWebImage/events","assignees_url":"https://api.github.com/repos/rs/SDWebImage/assignees{/user}","branches_url":"https://api.github.com/repos/rs/SDWebImage/branches{/branch}","tags_url":"https://api.github.com/repos/rs/SDWebImage/tags","blobs_url":"https://api.github.com/repos/rs/SDWebImage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rs/SDWebImage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rs/SDWebImage/git/refs{/sha}","trees_url":"https://api.github.com/repos/rs/SDWebImage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rs/SDWebImage/statuses/{sha}","languages_url":"https://api.github.com/repos/rs/SDWebImage/languages","stargazers_url":"https://api.github.com/repos/rs/SDWebImage/stargazers","contributors_url":"https://api.github.com/repos/rs/SDWebImage/contributors","subscribers_url":"https://api.github.com/repos/rs/SDWebImage/subscribers","subscription_url":"https://api.github.com/repos/rs/SDWebImage/subscription","commits_url":"https://api.github.com/repos/rs/SDWebImage/commits{/sha}","git_commits_url":"https://api.github.com/repos/rs/SDWebImage/git/commits{/sha}","comments_url":"https://api.github.com/repos/rs/SDWebImage/comments{/number}","issue_comment_url":"https://api.github.com/repos/rs/SDWebImage/issues/comments{/number}","contents_url":"https://api.github.com/repos/rs/SDWebImage/contents/{+path}","compare_url":"https://api.github.com/repos/rs/SDWebImage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rs/SDWebImage/merges","archive_url":"https://api.github.com/repos/rs/SDWebImage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rs/SDWebImage/downloads","issues_url":"https://api.github.com/repos/rs/SDWebImage/issues{/number}","pulls_url":"https://api.github.com/repos/rs/SDWebImage/pulls{/number}","milestones_url":"https://api.github.com/repos/rs/SDWebImage/milestones{/number}","notifications_url":"https://api.github.com/repos/rs/SDWebImage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rs/SDWebImage/labels{/name}","releases_url":"https://api.github.com/repos/rs/SDWebImage/releases{/id}","deployments_url":"https://api.github.com/repos/rs/SDWebImage/deployments","created_at":"2009-09-21T17:39:19Z","updated_at":"2017-10-17T15:26:45Z","pushed_at":"2017-10-17T16:03:14Z","git_url":"git://github.com/rs/SDWebImage.git","ssh_url":"git@github.com:rs/SDWebImage.git","clone_url":"https://github.com/rs/SDWebImage.git","svn_url":"https://github.com/rs/SDWebImage","homepage":"http://cocoadocs.org/docsets/SDWebImage","size":6193,"stargazers_count":18680,"watchers_count":18680,"language":"Objective-C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4970,"mirror_url":null,"open_issues_count":84,"forks":4970,"open_issues":84,"watchers":18680,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rs/SDWebImage/pulls/1991"},"html":{"href":"https://github.com/rs/SDWebImage/pull/1991"},"issue":{"href":"https://api.github.com/repos/rs/SDWebImage/issues/1991"},"comments":{"href":"https://api.github.com/repos/rs/SDWebImage/issues/1991/comments"},"review_comments":{"href":"https://api.github.com/repos/rs/SDWebImage/pulls/1991/comments"},"review_comment":{"href":"https://api.github.com/repos/rs/SDWebImage/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rs/SDWebImage/pulls/1991/commits"},"statuses":{"href":"https://api.github.com/repos/rs/SDWebImage/statuses/a0879fc049453c9028e2e1a9755cd9028aecf5f5"}},"author_association":"COLLABORATOR","merged":true,"mergeable":null,"rebaseable":null,"mergeable_state":"unknown","merged_by":{"login":"bpoplauschi","id":154913,"avatar_url":"https://avatars2.githubusercontent.com/u/154913?v=4","gravatar_id":"","url":"https://api.github.com/users/bpoplauschi","html_url":"https://github.com/bpoplauschi","followers_url":"https://api.github.com/users/bpoplauschi/followers","following_url":"https://api.github.com/users/bpoplauschi/following{/other_user}","gists_url":"https://api.github.com/users/bpoplauschi/gists{/gist_id}","starred_url":"https://api.github.com/users/bpoplauschi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bpoplauschi/subscriptions","organizations_url":"https://api.github.com/users/bpoplauschi/orgs","repos_url":"https://api.github.com/users/bpoplauschi/repos","events_url":"https://api.github.com/users/bpoplauschi/events{/privacy}","received_events_url":"https://api.github.com/users/bpoplauschi/received_events","type":"User","site_admin":false},"comments":18,"review_comments":18,"maintainer_can_modify":false,"commits":1,"additions":2737,"deletions":1001,"changed_files":38}}
{"actor":{"display_login":"bpoplauschi"}}