.webp ios

2016-10-11 15:25:53 wqt925497045 阅读数 1711

本篇来源于15年双11手淘前端技术巡演 - H5性能最佳实践(点我打开),它们在采用了 webp格式(点我打开) 的图片后,网络数据传输大幅减少.

以及腾讯发布的 webp探寻之路(点我打开)都可以拿出非常漂亮的数据让我们转到 webP 的怀抱(至少部分)

下面是 taobao 的优化对比图


下面是 腾讯的 图片格式对比图


可以看到有非常的实用价值,下面我们看看如何引入到具体项目中

webp 在 iOS中 的应用

本地采用 webP 图片

下载第三方库

很幸运,SDWebImage里面有个webP 框架,可以将webp-->NSData-->UIImage最后变为可识别的图片格式直接给控件调用

但是我在SDWebImage 的 github(点击跳转)上看见了下面这段话

There are 3 subspecs available now: Core, MapKit and WebP (this means you can install only some of the SDWebImage modules. By default, you get just Core, so if you need WebP, you need to specify it).

Podfile example:

$pod 'SDWebImage/WebP'

也就是说我们需要额外下载这个webP库,注意,这个会从 google 下载,如果失败,开 VPN 试试,下载完成后,文件结构如下


使用

SDWebImage 的源码如下,我们直接使用转化出的 UIImage 即可

#ifdef SD_WEBP

#import <UIKit/UIKit.h>

// Fix for issue #416 Undefined symbols for architecture armv7 since WebP introduction when deploying to device
void WebPInitPremultiplyNEON(void);

void WebPInitUpsamplersNEON(void);

void VP8DspInitNEON(void);

@interface UIImage (WebP)

+ (UIImage *)sd_imageWithWebPData:(NSData *)data;

@end

#endif

别的办法

据了解,还有部分三方库也可以...但是我没有进行研究了,我觉得原理应该都差不多,下面重点要说的是和 taobao 一样,如何在 webView 和网络传输中如何使用webp

在 webView 中实用 webP

先给一个 webP 测试 html: http://testing.yongche.org/webp.html

html 的代码如下

<head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <title>webp</title>
</head>
<body>
        <img src="http://testing.yongche.org/images/150X1501.webp” width = 50 ,height = 20>
        ![](http://testing.yongche.org/images/150X1501.webp)
</body>

第一个办法 和 JS 协作

webView 等网页上如果用的是 webP 图片,iOS 直接解析的话,会显示?图片.


后来决定这么搞:

A. 在网页加载出后截取到 HTML 及内部的 JS 后,调用 JS 预先准备好的方法获取需要转码的 webP 格式图片下载地址(其实一个一个的遍历也行).
B. 在App 本地开启线程下载图片,下载完成后,将图片转码由 webP—> png—>Base64(因为实验出直接用 png/jpg 的话 没用)
C. 将 Base64及原图片下载地址一一对应调用 JS 准备好的方法进行替换
D. 将下载后的图片进行缓存,并进行管理

注意点:
A. 图片在最终显示成功前会显示成?,此处为了用户体验应该采用占位图片
B. 图片显示成功前应该保持网页布局不调整,需要由 JS 预先设置好布局
C. 图片在本地的缓存需要管理

相应的,HTML需要更改代码,如下

<head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <title>webp</title>
        <script type="text/javascript">
            var YongChe = {};
            YongChe.getAllWebPImg = function() {
                var images = document.getElementsByTagName('img'); 
                var srcList = [];
                var patt1 = new RegExp("\.webp$");
                for(var i = 0; i < images.length; i++) {
                    if(patt1.test(images[i].src)) {
                        srcList.push(images[i].src);
                    }
                }
                console.log(srcList);
                return JSON.stringify(srcList);
            }
            YongChe.replaceWebPImg = function(src, localPath) {
                alert(localPath);
                elementList = document.querySelectorAll('img[src="'+src+'"]');
                console.log(elementList);
                for(element in elementList) {
                    elementList[element].src = localPath;
                }
            }
</script>
</head>
<body>
        <img src="http://testing.yongche.org/images/150X1501.webp” width = 50 ,height = 20>
        ![](http://testing.yongche.org/images/150X1501.webp)
        <script type="text/javascript">
            console.log(YongChe.getAllWebPImg());
            YongChe.replaceWebPImg('http://testing.yongche.org/images/logo.png','http://testing.yongche.org/images/150X1501.webp')
        </script>
</body>

App本地也需要做出相应的措施

//在 `webView` 加载完 `HTML` 后,解析源码,执行相应的 `JS` 方法
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    //获取`HTML`代码
    NSString *lJs = @"document.documentElement.innerHTML";
    NSString *str = [webView stringByEvaluatingJavaScriptFromString:lJs];

    //执行约定好的方法,获取需要下载的 webp 图片
    NSString *imgs = [self.webView stringByEvaluatingJavaScriptFromString:@"YongChe.getAllWebPImg();"];
    NSArray *array = [NSJSONSerialization JSONObjectWithData:[imgs dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];

    //此处,做示范,只转换第一个,将图片下载下来,并且转为 PNG 后,再转成 Base64,传给 JS 脚本执行
    NSString *imgUrl = array.firstObject;

    __weak typeof (self) weakSelf = self;

    [SDWebImageCustomeDownLoad downloadWithURL:[NSURL URLWithString:imgUrl] progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

        NSString *base = [NSString stringWithFormat:@"data:image/png;base64,%@",imgBase];

        NSString *js = [NSString stringWithFormat:@"YongChe.replaceWebPImg('%@','%@')",imageURL,base];

        [weakSelf.webView stringByEvaluatingJavaScriptFromString:js];
    }];

}

下面这个方法是修改 SDWebImage 自带的,本来是属于 UIImage的分类方法,此处只是提取出下载这个操作,并没有深入更改,大家别介意

+ (void)downloadWithURL:(NSURL *)url progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock
{
//    [self sd_cancelCurrentImageLoad];
//    objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    if (url) {
//        __weak __typeof(self)wself = self;
        id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:0 progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
//            if (!wself) return;
            dispatch_main_sync_safe(^{
//                if (!wself) return;
                if (image && completedBlock)
                {
                    completedBlock(image, error, cacheType, url);
                    return;
                }
                else if (image) {   //没有回调,但是图片下载完成了


                } else {    //image 下载失败


                }
                if (completedBlock && finished) {
                    completedBlock(image, error, cacheType, url);
                }
            });
        }];

        //这一步,将这个 View 之前的下载操作全部取消,然后将这次的操作放进去

//        [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
    } else {
        dispatch_main_async_safe(^{
            NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
            if (completedBlock) {
                completedBlock(nil, error, SDImageCacheTypeNone, url);
            }
        });
    }

}

效果


只能说成功了,但是看着效果明显很龊,下面说说其他办法

第二种办法 NSURLProtocol

分析

采用 webP 的目的就是减少网络传输数据量,加快请求整体速度,现在的问题就在于 webView 不识别 webP 这种格式而已,再想想 iOS内的所有网络请求/响应我们都可以控制,那我们获取到数据时,转化成它识别的给它就可以了,而可以帮我们在拿到数据时进行某些操作,操作完以后又正常进行网络流程的,就是接下来的主角了 --- NSURLProtocol,如果大家和我一样平时用的少的话,可以看看 JamesYu 的这篇简书 iOS中的 NSURLProtocol

再看 taobao 前辈们的说法:


估计也是这样做的, OK. 那开撸

NSURLProtocol

自定义一个 YCCustomURLProtocol 继承自 NSURLProtocol
#import <Foundation/Foundation.h>

@interface YCCustomURLProtocol : NSURLProtocol

@end
在 delegate 注册下这个协议
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    //注册protocol
    [NSURLProtocol registerClass:[CustomURLProtocol class]];
    return YES;
}
实现协议内容

有几个注意点:

  1. NSURLConnection 活跃的iOS版本,NSURLSession 可以酌情代替之
  2. 不论 NSURLConnection 还是 NSURLSession,尽量把 URLProtocol didFailWithError URLProtocol DidFinishLoading URLProtocol didLoadData URLProtocol didReceiveResponse 几个方法写全,避免网络请求产生不可预知的 BUG
  3. 暂时就这些
NSURLConnection
#import "YCCustomURLProtocol.h"
#import "UIImage+WebP.h"

static NSString *URLProtocolHandledKey = @"URLHasHandle";

@interface YCCustomURLProtocol()<NSURLSessionDelegate,NSURLSessionDataDelegate>

@property (nonatomic,strong) NSURLConnection *connection;

@end

@implementation YCCustomURLProtocol

#pragma mark 初始化请求

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    //只处理http和https请求
    NSString *scheme = [[request URL] scheme];
    if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
          [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame))
    {
        //看看是否已经处理过了,防止无限循环
        if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:request]) {
            return NO;
        }
        return YES;
    }
    return NO;
}

+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

#pragma mark 通信协议内容实现

- (void)startLoading
{
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    //标示改request已经处理过了,防止无限循环
    [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];

    if (![[self.request.URL absoluteString] hasSuffix:@"webp"]) {
        NSLog(@"正常请求,让它 goon ");
    }else{
        NSLog(@"检测到了 webp---%@,拦截它",self.request.URL);
    }

    self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];    
}

- (void)stopLoading
{
    [self.connection cancel];
}

#pragma mark 请求管理 connection

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    if ([connection.currentRequest.URL.absoluteString hasSuffix:@"webp"]) {
        NSLog(@"webp---%@---替换它",connection);
        UIImage *imgData = [UIImage sd_imageWithWebPData:data];
        NSData *jpgData = UIImageJPEGRepresentation(imgData, 1.0f);
        [self.client URLProtocol:self didLoadData:jpgData];
    }else{
        [self.client URLProtocol:self didLoadData:data];
    }
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.client URLProtocol:self didFailWithError:error];
}
NSURLSession
#import "YCCustomURLProtocol.h"
#import "UIImage+WebP.h"

static NSString *URLProtocolHandledKey = @"URLHasHandle";

@interface YCCustomURLProtocol()<NSURLSessionDelegate,NSURLSessionDataDelegate>

@property (nonatomic,strong) NSURLSession *session;

@end

@implementation YCCustomURLProtocol

#pragma mark 初始化请求

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    //只处理http和https请求
    NSString *scheme = [[request URL] scheme];
    if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
          [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame))
    {
        //看看是否已经处理过了,防止无限循环
        if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:request]) {
            return NO;
        }
        return YES;
    }
    return NO;
}

+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

#pragma mark 通信协议内容实现

- (void)startLoading
{
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    //标示改request已经处理过了,防止无限循环
    [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];

    if (![[self.request.URL absoluteString] hasSuffix:@"webp"]) {
       NSLog(@"是一个正常的,%@",self.request.URL);
    }else{
        NSLog(@"检测到了 webp---%@,拦截它",self.request.URL);
    }

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue currentQueue]];
    [[self.session dataTaskWithRequest:mutableReqeust] resume];

}

- (void)stopLoading
{
    [self.session invalidateAndCancel];
}

#pragma mark dataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{    
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];

    if (completionHandler) {
        completionHandler(NSURLSessionResponseAllow);
    }

}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{

    NSData *transData = data;

    if ([dataTask.currentRequest.URL.absoluteString hasSuffix:@"webp"]) {
        NSLog(@"webp---%@---替换它",dataTask.currentRequest.URL);
        //采用 SDWebImage 的转换方法
        UIImage *imgData = [UIImage sd_imageWithWebPData:data];
        transData = UIImageJPEGRepresentation(imgData, 1.0f);
    }

    [self.client URLProtocol:self didLoadData:transData];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error{

    if (error) {

        [self.client URLProtocol:self didFailWithError:error];
    }else{

        [self.client URLProtocolDidFinishLoading:self];
    }

}
实际效果

结尾语

ok, 至此已经全部成功,不过 NSURLProtocol 会影响 App 内所有请求,稍有遗漏的话后果比较严重,大家一定要慎重.不过相比效果,电商类 App 采用大量图片的话还是值得转换到 webP 阵营的

谢谢观看,个人水平有限,如有遗漏/不妥,请指出

PS:原创文章,转载请注明地址: https://kevinmky.github.io



文/KevinMK(简书作者)
原文链接:http://www.jianshu.com/p/ed7562a34af1
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
2015-01-20 14:16:11 ChSaDiN 阅读数 6248

什么是webp?这里我就不多说了,直接在官网黏一段描述过来:


WebP is a new image format that provides lossless and lossy compression for images on the web. WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller in size compared to JPEG images at equivalent SSIM index. WebP supports lossless transparency (also known as alpha channel) with just 22% additional bytes. Transparency is also supported with lossy compression and typically provides 3x smaller file sizes compared to PNG when lossy compression is acceptable for the red/green/blue color channels.

Webmasters and web developers can use the WebP image format to create smaller and richer images that can help make the web faster.



中文的意思大概是:

WebP是提供无损和有损压缩在网络上图像的新图像格式。的WebP无损图像小26%的规模相比,PNG格式。的WebP有损图像是小25-34%的规模相比,相当于SSIM指数JPEG图像。的WebP支持无损透明性(也称为阿尔法通道)只用22%的附加 ​​字节。透明度也支持与有损压缩和典型地提供3倍较小的文件大小相比,PNG当有损压缩是可以接受的红/绿/蓝颜色通道。网站管理员和Web开发人员可以使用的WebP图像格式,以创建更小和更丰富的图像,可以帮助使网络更快。


Google WebP官网 你可以下载到webp的源码,你可以点击downloads repository 到下载列表页面,可以选择下载任意的版本以及任意的平台的webp源代码。或者你可以点击Download直接下载当前最新版的。如下图



点击Dwonload 直接下载Mac OSX 平台最新的源码。有空的同学可以看一下README文件,有指导说明。生成framework就很简单了,直接执行iosbuild.sh脚本即。会生成一个WebP.framwork文件。



用lipo命令看一下framework支持的指令集,可以看的出来有i386、armv7、armv7s、arm64 可以支持iphone4及以上的设备了。

Mac-mini:libwebp-0.4-2.2 ios$ lipo -info /Users/efun_ios/Desktop/webp/webp源码/libwebp-0.4.2/WebP.framework/Web  
Architectures in the fat file: /Users/efun_ios/Desktop/webp/webp源码/libwebp-0.4.2/WebP.framework/WebP are: i386 armv7 armv7s arm64 


PS:官网上关于webp的文档,说个实话,没有一定很深的图像知识基础的同学,就算看懂了也不知道怎么用!例如就像我这样,看大半天还要去找图像相关的知识来补脑,不然没法搞下去!%>_<%

幸好,网上已有大神给出易用的demo了,大家可以在github上下载.如有疑问,欢迎留言拍砖等等等


PS:其实,一开始把源码下下来我都不知道怎么弄,看了readme文件,说了一大堆,只知道通过configure可以生成framework文件,但是我最初尝试了几次是失败了,后来又尝试好多种方法,把文件的各种脚本文件以及makefile文件都稍稍看过了。最终发现一个iosbuild.sh文件。这个脚本的功能就是针对不同的archive (arm7 arm64 i386  x86_64等)来生成makefile 文件,然后通过makefile文件来生成对应的.a文件的。最后会通过lipo 命令来合成framework 的。最初,我执行这个脚本的时候是由问题的,搞的我把这个脚本完完整整的看了一遍...发现是脚本生成的makefile文件中指定的编译器有问题,重新制定一个编译器就OK了。后来在写文章的时候又没法重现这个问题,不知道是官方修复了这个问题,还是我之前的配置弄乱了。。不过我发现官方更新真的很快3两天就会有一个新的版本(*^__^*) 嘻嘻……


2016-09-08 10:38:54 wf96390 阅读数 2460

下载webp支持包

google官网中 webp下载地址
https://developers.google.com/speed/webp/download

其中包括iOS的SDK,可以直接下载使用,也可以参照下面的方法
http://blog.csdn.net/chsadin/article/details/42917271
在客户端中使用 framework 进行导入

iOS-WebP中增加了Category来解析webp图片 http://seanooi.github.io/iOS-WebP/
但是只支持静态的 webp 显示,如果需要显示动态的 webp 图片,则需要对每一帧进行解析,再展示每帧动画
解析动态图片可以按照 YYKit 中的方法 https://github.com/ibireme/YYKit

YYKit

使用到的主要的类
YYImageCoder(图片解码,包括所有的图片类型)
里面包括帧信息 YYImageFrame ,YYImageDecoder 解码 和 YYImageEncoder 编码等操作

YYImage(包括的所有的图片类型)
UIImage 的子类,增加了很多属性比如 coder,初始化方法同 UIImage 一样

YYAnimatedImageView(展示动态图片的View)
UIImageView 的子类,用于播放 webp 动画

UIImageView 并不支持播放 gif 以及 webp 的动图,但是提供了展示动态图片的方法

属性

property (nullable, nonatomic, copy) NSArray<UIImage *> *animationImages; // The array must contain UIImages. Setting hides the single image. default is nil
@property (nullable, nonatomic, copy) NSArray<UIImage *> *highlightedAnimationImages NS_AVAILABLE_IOS(3_0); // The array must contain UIImages. Setting hides the single image. default is nil

@property (nonatomic) NSTimeInterval animationDuration;         // for one cycle of images. default is number of images * 1/30th of a second (i.e. 30 fps)
@property (nonatomic) NSInteger      animationRepeatCount;      // 0 means infinite (default is 0)

以及方法

- (void)startAnimating;
- (void)stopAnimating;
- (BOOL)isAnimating;

Runloop

最后不得不提一下 YYAnimatedImageView 的一个属性 runloopMode ,即设置 runloop 的 mode
The animation timer’s runloop mode, default is NSRunLoopCommonModes. Set this property to NSDefaultRunLoopMode will make the animation pause during UIScrollView scrolling.
设置 NSDefaultRunLoopMode 时,滚动屏幕的时候暂停动画
设置 NSRunLoopCommonModes 仍播放动画

需要了解 RunLoop 的 mode 才能解释这个问题
RunLoop只能运行在一种mode下,如果要换mode当前的loop也需要停下重启成新的。利用这个机制,ScrollView过程中NSDefaultRunLoopMode的mode会切换UITrackingRunLoopMode来保证ScrollView的流畅滑动不受只能在NSDefaultRunLoopMode时处理的事件影响滑动。同时mode还是可定制的。

NSDefaultRunLoopMode:默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时
UIInitializationRunLoopMode:启动时
NSRunLoopCommonModes:Mode集合 Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModes来解决。
参考:http://www.starming.com/index.php?v=index&view=74

2018-09-20 11:10:03 jia12216 阅读数 15026

iOS不支持WebP格式图片解决方案:在阿里云的图片下载规则里配置为把WebP格式图片转换成png或 jpeg格式的图片。
今天我们遇到我们的苹果app和苹果上的微信端在加载有个用户的商品时,商品图片显示不出来,安卓app上可以显示。后来定位,那个用户传递的图片文件名后缀虽然是jpeg,但时其实是WebP格式的图片,safari也显示不了对应页面的图片,iOS不支持该格式的图片。这个是一张WebP格式的图片
我们首先想到的是让苹果app支持WebP格式的图片。于是我们就遇到下面的新问题:想让WKWebView支持WebP格式的图片,最关键的问题时需要通过NSURLProtocol 协议截获WebP图片的请求(参考文章《iOS加载WebP格式图片小结》),若图片地址是以https:或http:开头,想拦截该图片地址的下载请求,就要注册http(s) scheme 来拦截。但是一旦注册 http(s) scheme 后,post 请求 body 数据被清空。咱们的页面有很多post请求需要传递参数。如增加收货地地址,图片上传。产生的新问题解决方案,参考文章WKWebView采用HybridNSURLProtocol协议拦截图片等资源预加载。想实现WKWebView支持WebP格式的图片。只能像图片上传时的图片预览那样,WebP图片地址是以yxLocalFile://开头。
具体解决方案是:注册自定义scheme,通过canInitWithRequest函数拦截指定图片资源下载地址,通过代理函数startLoading进一步识别图片资源下载地址,判断出是WebP格式的图片,可以文件后缀来识别,若上传时乱填文件后缀那就麻烦了。然后下载图片到本地,然后把WebP格式的图片转换成png或jpeg格式(为了保持图片质量和文件大小,压缩参数可以设置为0.7)的图片数据流(NSData对象)给页面显示。不过采用这种方法,就需要图像转换时间,该图片的缓存机制失效。
另一种解决方案是,在所有上传图片的时候(安卓app,苹果app,电脑端),判断是否是WebP,若是统一转换成png或 jpeg格式的图片再上传。
后来服务器后台进行了研究。发现我们图片的存储在阿里云上,可以通过设置图片下载时的配置规则实现把下载的WebP格式图片统一转换成png或 jpeg格式的图片。问题终于完满解决了。看来一个问题有很多解决方案,总有一个最解决完美的。是该谁解决就让谁解决,不是有解决方案就上,不考虑实现的复杂度和所产生的新问题及完美程度。

WebP简介
WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器宽带资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式。
WebP既支持有损压缩也支持无损压缩。相较编码JPEG文件,编码同样质量的WebP文件需要占用更多的计算资源。
桌面版Chrome可打开WebP格式。
去年10月份Google宣布了一种新的图片格式WebP,它可以将图片大小减少40%,目的是替代当前的图片标准JPEG,今天Google开发者宣布了WebP图片格式的一些改进,加入了透明格式支持,所以它同样也想取代掉PNG格式。
第一个版本的WebP采用有损压缩,所以用户想要图片体积小必须牺牲一些图片质量,今天的升级引进了“无损压缩”,意味着用户不需要牺牲图片质量就能够获得小体积的图片。Google开发团队说WebP比JPEG的压缩率高25%-34%,相比于PNG图片(需要透明时会使用这种格式),即便是最高的压缩,WebP也比它小28%,并且大部分网站不会采用这种压缩方式。下面的例子中,WebP图片比PNG图片小45%,就是说从网页中加载图片时,WebP比PNG快45%。然而,目前只有Chrome、Opera浏览器和Android 4.0默认浏览器本地原生支持WebP图片格式,所以要想成为标准Google还有很长的路要走。对于Google开发团队来说,想把它打造成新的Web标准的路很艰难,但是它的优势也很明显:图片体积小 = 互联网速度更快。
在这里插入图片描述
HEIC是iOS 11更新后,iPhone 7及其后硬件,在拍摄照片时的默认图像存储格式。
HEIC是一种图像格式,上线时间还比较短,只有4年左右。自iOS 11和macOS High Sierra(10.13)内测开始,苹果将HEIC设置为图片存储的默认格式。
与JPG相比,它占用的空间更小,画质更加无损。
HEIC格式照片支持iOS11及macOS High Sierra(10.13)及更新版本。
但是此种格式是无法在Windows 中直接使用看图软件打开的(Windows10 RS4开始支持该格式)。
所以如果想要在电脑中查看HEIC图片,最好使用在线免费HEIC图片转换应用,将HEIC转JPG,这样就可以在PC上打开iPhone HEIC照片了。HEIC可是连iphone4,5,6都不支持的图片格式,不知道苹果为何推出连自己的产品都不完全支持的图片格式干什么,徒给我们码农添麻烦。落下一地的鸡毛,现在还要给他们擦屁股。看来想推广一种图片格式没有那么容易,可能开源图片压缩算法并且承诺永久免费可能好些。现在缺的不是图片压缩的技术,而是没有革命性的改进,不得不使用的技术,谁会劳民伤财的迁就你按你的来采用你的新格式。怎么让iPhone 7及其后手机拍照不变成HEIC格式 HEIC格式改回JPG格式在线把HEIC和WebP格式图片转换成JPG格式图片,不过你别自己乱修改文件后缀,防止它识别不出来源图片文件。

2019-03-11 19:34:02 u013107634 阅读数 2491

前提条件:图片服务器是阿里云OSS

问题原因: 安卓端上传了一张webp 格式图片,格式是webp(安卓特有的格式) , 安卓手机/ chrome 等访问都没问题,

但是 IOS,Safari 确访问不了。

 

解决办法:

1. 在阿里云上传图片完成后,图片URL拼接参数  ?x-oss-process=image/info

类似:http://图片路径?x-oss-process=image/info  用于获取图片大小格式等信息

{
    "FileSize": {
        "value": "18610"
    },
    "Format": {
        "value": "webp"
    },
    "ImageHeight": {
        "value": "593"
    },
    "ImageWidth": {
        "value": "600"
    }
}

Format 返回了图片格式为 webp ,

代码中可在处理完上传图片后加上如下代码:

Map map = restTemplate.getForObject(path + "?x-oss-process=image/info", Map.class);

判断返回的图片格式是webp 时, 图片URL拼接上字符串   ?x-oss-process=image/format,jpg

就可以访问了。

IIS 对webp的支持

阅读数 123