webp格式圖片是google推出的,相比jpg png有著巨大的優勢,同樣質量的圖片webp格式的圖片占用空間更小,在像電商這樣圖片比較多的App中,使用webp格式圖片會很有優勢。
當前的iOS不支持webp,不知道以後會不會支持,所以從網絡上拿到一個webp格式的圖片後,並不能直接顯示出來,需要把data數據轉化為jpg或者png來顯示。
在podfile中加入
pod 'SDWebImage/WebP'
可以在SDWebImage中加入UIImage的WebP類別,同時會引入libwebp。在使用SD加載圖片時,會判定圖片的格式,如果為webp,調用Google的libwebp庫進行解析。
調用過程如下:
sd_setImageWithURL -> URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error -> sd_imageWithData-> sd_imageWithWebPData 處理成功後會返回一個UIImage。
如果有一些web頁中使用了webp格式的圖片,僅用上述方法是不行的,我推薦的做法是寫一個自定義的URLSession protocol, 繼承自NSURLProtocol, 然後注冊。自定義的協議文件為DMCustomURLSessionProtocol這個類,整個工程的地址如下:Demo地址.
關鍵代碼如下:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error { if (error == nil) { if ([task.currentRequest.URL.absoluteString hasSuffix:@"webp"]) { NSLog(@"webp will changed:%@",task.currentRequest.URL); UIImage *imgData = [UIImage sd_imageWithData:self.imageData]; NSData *transData = UIImageJPEGRepresentation(imgData, 0.8f); self.beginAppendData = NO; self.imageData = nil; [self.client URLProtocol:self didLoadData:transData]; } [self.client URLProtocolDidFinishLoading:self]; } else if ( [[error domain] isEqual:NSURLErrorDomain] && ([error code] == NSURLErrorCancelled) ) { [self.client URLProtocol:self didFailWithError:error]; } else { [[self client] URLProtocol:self didFailWithError:error]; } }
在一個task完成的時候,根據task中的url是否含有webp後綴,做處理,如果有webp後綴,用SD轉化圖片,轉化完成後, 需要把beginAppendData置為NO,imageData置為nil,self.client再load一次data。
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { if ([dataTask.currentRequest.URL.absoluteString hasSuffix:@"webp"]) { self.beginAppendData = YES; [self.imageData appendData:data]; } if (!_beginAppendData) { [self.client URLProtocol:self didLoadData:data]; } }
在didReceiveData裡面要做一些處理,這裡面是每次receive一塊新的data,當一個請求的地址裡面含有webp時,把beginAppendData置為yes,同時imgeData開始append data,而這時self.client不load data,每次有新data來,imageData就append上,止到這一個請求完成, 在完成的裡面 轉化webp後 load data。(請求一個圖片後,可能在did receive data中收到多次才能收全。)
自定義URL Protocol時,一定要實現重定向的代理方法,不然,在webview裡面會出問題。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *))completionHandler { NSMutableURLRequest * redirectRequest; redirectRequest = [newRequest mutableCopy]; [[self class] removePropertyForKey:URLProtocolHandledKey inRequest:redirectRequest]; [[self client] URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:response]; [self.session invalidateAndCancel]; [[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]]; }
最後在appdelegate didFinishLaunchingWithOptions中注冊上
[NSURLProtocol registerClass:[DMCustomURLSessionProtocol class]];
工程地址
webp格式圖片地址
含有webp的網頁地址