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的網頁地址