{"action":"created","issue":{"url":"https://api.github.com/repos/facebook/AsyncDisplayKit/issues/955","labels_url":"https://api.github.com/repos/facebook/AsyncDisplayKit/issues/955/labels{/name}","comments_url":"https://api.github.com/repos/facebook/AsyncDisplayKit/issues/955/comments","events_url":"https://api.github.com/repos/facebook/AsyncDisplayKit/issues/955/events","html_url":"https://github.com/facebook/AsyncDisplayKit/issues/955","id":123033778,"number":955,"title":"[ASImageNode] WebP for AsyncDisplayKit image components.","user":{"login":"smyrgl","id":1709178,"avatar_url":"https://avatars.githubusercontent.com/u/1709178?v=3","gravatar_id":"","url":"https://api.github.com/users/smyrgl","html_url":"https://github.com/smyrgl","followers_url":"https://api.github.com/users/smyrgl/followers","following_url":"https://api.github.com/users/smyrgl/following{/other_user}","gists_url":"https://api.github.com/users/smyrgl/gists{/gist_id}","starred_url":"https://api.github.com/users/smyrgl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smyrgl/subscriptions","organizations_url":"https://api.github.com/users/smyrgl/orgs","repos_url":"https://api.github.com/users/smyrgl/repos","events_url":"https://api.github.com/users/smyrgl/events{/privacy}","received_events_url":"https://api.github.com/users/smyrgl/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/facebook/AsyncDisplayKit/labels/feature%20%E2%80%94%20major","name":"feature — major","color":"0052cc"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/facebook/AsyncDisplayKit/milestones/8","html_url":"https://github.com/facebook/AsyncDisplayKit/milestones/2.1","labels_url":"https://api.github.com/repos/facebook/AsyncDisplayKit/milestones/8/labels","id":1387070,"number":8,"title":"2.1","description":null,"creator":{"login":"appleguy","id":565251,"avatar_url":"https://avatars.githubusercontent.com/u/565251?v=3","gravatar_id":"","url":"https://api.github.com/users/appleguy","html_url":"https://github.com/appleguy","followers_url":"https://api.github.com/users/appleguy/followers","following_url":"https://api.github.com/users/appleguy/following{/other_user}","gists_url":"https://api.github.com/users/appleguy/gists{/gist_id}","starred_url":"https://api.github.com/users/appleguy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appleguy/subscriptions","organizations_url":"https://api.github.com/users/appleguy/orgs","repos_url":"https://api.github.com/users/appleguy/repos","events_url":"https://api.github.com/users/appleguy/events{/privacy}","received_events_url":"https://api.github.com/users/appleguy/received_events","type":"User","site_admin":false},"open_issues":21,"closed_issues":2,"state":"open","created_at":"2015-11-01T03:37:28Z","updated_at":"2015-12-19T04:10:28Z","due_on":null,"closed_at":null},"comments":7,"created_at":"2015-12-18T22:02:34Z","updated_at":"2015-12-22T05:13:15Z","closed_at":null,"body":"I have created a sample project to demonstrate this behavior here: https://github.com/smyrgl/adktest\r\n\r\nSo here's what I'm noticing: it seems that in ASCollectionView the memory isn't properly being freed up.  This is very easy to see in the sample project: just play around with clicking on items in the collection view (each will push to another collection view) and scroll and watch the memory usage continue to increase.  Firing memory warnings will not change this behavior, the memory usage just keeps climbing.  \r\n\r\n<img width=\"862\" alt=\"screen shot 2015-12-18 at 1 53 40 pm\" src=\"https://cloud.githubusercontent.com/assets/1709178/11908151/c700d5ec-a58e-11e5-95f1-040907d0c775.png\">\r\n\r\nHowever if in the ASCellNode I manually implement clearContents like this:\r\n```Swift\r\n    override func clearContents() {\r\n        super.clearContents()\r\n        imageNode.image = nil\r\n    }\r\n```\r\nThen memory usage stays under control.  Also if I define a custom subclass of `ASImageNode` that implements `clearContents` I also get the correct memory behavior:\r\n\r\n```Swift\r\nclass ClearImageNode: ASImageNode {\r\n    override func clearContents() {\r\n        super.clearContents()\r\n        image = nil\r\n    }\r\n}\r\n```\r\n<img width=\"641\" alt=\"screen shot 2015-12-18 at 2 02 07 pm\" src=\"https://cloud.githubusercontent.com/assets/1709178/11908326/f300ec58-a58f-11e5-885b-79f192d97eae.png\">\r\n\r\nI'd be glad to create a diff which adds this to ASImageNode but I am uncertain if there is a gotcha to this change.\r\n"},"comment":{"url":"https://api.github.com/repos/facebook/AsyncDisplayKit/issues/comments/166507596","html_url":"https://github.com/facebook/AsyncDisplayKit/issues/955#issuecomment-166507596","issue_url":"https://api.github.com/repos/facebook/AsyncDisplayKit/issues/955","id":166507596,"user":{"login":"appleguy","id":565251,"avatar_url":"https://avatars.githubusercontent.com/u/565251?v=3","gravatar_id":"","url":"https://api.github.com/users/appleguy","html_url":"https://github.com/appleguy","followers_url":"https://api.github.com/users/appleguy/followers","following_url":"https://api.github.com/users/appleguy/following{/other_user}","gists_url":"https://api.github.com/users/appleguy/gists{/gist_id}","starred_url":"https://api.github.com/users/appleguy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appleguy/subscriptions","organizations_url":"https://api.github.com/users/appleguy/orgs","repos_url":"https://api.github.com/users/appleguy/repos","events_url":"https://api.github.com/users/appleguy/events{/privacy}","received_events_url":"https://api.github.com/users/appleguy/received_events","type":"User","site_admin":false},"created_at":"2015-12-22T05:13:15Z","updated_at":"2015-12-22T05:13:15Z","body":"@smyrgl update on my side.  I dove into ImageIO and have been pretty desperately trying to figure out the best way to determine if an image is compressed or not.  The sad news is that I am pretty sure it can't be done in a practical way without access to the original data - you can go down a weird path with CGDataProvider but that doesn't seem to always work either, but better than that is to inspect the actual NSData using CGImageSource.\r\n\r\nI'm thinking of changing the Downloader and Cache protocols to return NSData in their completion blocks rather than CGImageRef.  This could be done as a breaking change for the 2.0 API for anyone who is not using ASBasicImageDownloader, which would certainly be one way to ensure that everyone is using the framework as intended.  We could inspect the NSDatas in DEBUG mode to ensure they are compressed, and if almost all are decompressed, we know something funny is going on (like a user getting the data out of an image after another library decompresses it).\r\n\r\nReally though, I want to get the PINRemoteImage integration accomplished.  PIRI supports WebP, but also Progressive JPEG, GIF, etc...and ASDK absolutely needs a \"1st party\"-quality image downloader and decoding suite.  @Adlai-Holler has done a lot of work on ASMultiplexImageNode recently and might have some further thoughts here.\r\n\r\nOne last thing - the implementation of ASImageNode's async draw method can be significantly improved for the case where a decoded image IS provided.  It was much more efficient for the version used by Paper.  The current version is using UIGraphics contexts regardless of the incoming image, since we can't check if it is decoded.  If it is decoded, we can use the image directly as the contents (potentially setting contentsCenter / contentsRect if necessary) to reduce by approximately half the memory consumed (depends on how much upscaling / downscaling is currently being done by allocating the new buffer of exactly the right size).\r\n\r\nThere's a great deal more that can be done with image handling; for example the Paper version would decode images at native size if they were smaller than the area to be shown in, rather than drawing them at the final size; if they were larger than the ideal size, it would redraw them into the ideal size to save memory.  Very simple and clearly just the beginning compared to using progressive JPEG to its fullest potential, supporting awesome fading transitions (the current placeholderFadesOut option is pretty shady), etc."}}