网站首页 > 精选教程 正文
在进行iOS开发时,经常会遇到这种情况:
常常想不下载图片,根据网络图片URL获取图片的尺寸。根据得到尺寸或者比例显示占位图片与轮廓预览区域。当完全下载下来图片后,替换上去。
TableView显示的时候要动态的设置Cell的高度,因为大量的图片不会一口气下载完成,所以想先拿到图片的高度把Cell的高度提前设置好。
根据图片尺寸或比例动态创建控件
方法
1.服务端返回的JSON等等数据的时候不仅仅返回一个URL,额外返回一个字段描述图片大小。
{
"object": {
"image_url": "images/pic.jpg",
"image_size": "222x255"
}
}
2.返回图片URL时拼接该图片的宽高
比如
http://xxx.com/images/pic_215x500.jpg,http://xxx.com/images/pic.jpg@215x500,http://xxx.com/images/pic_215_500.jpg,格式与服务器端约定好即可。
最好是上传图片的时候直接把尺寸拼接将要存储的图片文件,这样正常访问图片的url解析尺寸就行了。
3.HTTP响应头中写入图片的宽高
4.完全下载下来图片后获的宽高
这种方式,耗费性能与流量。完全不建议。是有没办法的办法。
5.图片数据头中写入图片的宽高
此方法需要服务器支持Range分段请求,整个图片虽然很大,可能只需要很少的字节就能得到图片的大小
curl判断服务器是否支持Range请求
mac的终端下执行:
curl -i --rang 0-9 https://sqimg.qq.com/qq_product_operations/im/qqlogo/imlogo_b.png
返回
HTTP/1.1 206 Partial Content
Server: Qnginx/1.3.2
Date: Tue, 28 Mar 2017 05:19:13 GMT
Content-Type: image/png
Content-Length: 10
Connection: keep-alive
Cache-Control: max-age=2592000
Expires: Thu, 27 Apr 2017 05:19:13 GMT
Last-Modified: Tue, 29 Mar 2016 11:07:42 GMT
Content-Range: bytes 0-9/2148
Access-Control-Allow-Origin: *
X-Cache-Lookup: Hit From Disktank
X-NWS-LOG-UUID: bd8d7f0d-010c-4482-b535-6abefd2e893e
?PNG
输出结果 Accept-Ranges: bytes 或者statuscode等于206,说明服务器支持按字节下载。我们看到标准的返回中Content-Type就可以判断图片类型了。
iOS代码检测
+(BOOL)checkSupportResume:(NSURL*)url{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"HEAD";//0-9 range
//[request setValue:@"bytes=0-9" forHTTPHeaderField:@"Range"];
NSURLResponse *response;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
NSHTTPURLResponse *resp = (NSHTTPURLResponse*)response;
// NSLog(@"resp%@", [resp allHeaderFields]);
// NSLog(@"文件长度-%lld",response.expectedContentLength);
BOOL support = resp.statusCode ==206?YES:NO;
return support;
}
iOS从图片数据头请求尺寸
常见图片的range
PngRange = @"bytes=16-23";
JPGRange = @"bytes=0-209";
GIFRange = @"bytes=6-9";
请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imgURL];
[request setValue:PngRange forHTTPHeaderField:@"Range"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//data 即是图片的数据头
}];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imgURL];
[request setValue:PngRange forHTTPHeaderField:@"Range"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//data 即是图片的数据头
}];
尺寸解析
从数据头中解析图片的尺寸大同小异,也许每个人的方法具体算法不同,但是核心还是一样的。当然这么多代码肯定不是我写的。来自互联网。
PNG,png尺寸在16-23字节中,所以请求的时候只需要请求8字节即可解析出具体尺寸:
+ (CGSize)PNGImageSizeWithRangeHeader:(NSData *)data{
int w1 = 0, w2 = 0, w3 = 0, w4 = 0;
[data getBytes:&w1 range:NSMakeRange(0, 1)];
[data getBytes:&w2 range:NSMakeRange(1, 1)];
[data getBytes:&w3 range:NSMakeRange(2, 1)];
[data getBytes:&w4 range:NSMakeRange(3, 1)];
int w = (w1 << 24) + (w2 << 16) + (w3 << 8) + w4;
int h1 = 0, h2 = 0, h3 = 0, h4 = 0;
[data getBytes:&h1 range:NSMakeRange(4, 1)];
[data getBytes:&h2 range:NSMakeRange(5, 1)];
[data getBytes:&h3 range:NSMakeRange(6, 1)];
[data getBytes:&h4 range:NSMakeRange(7, 1)];
int h = (h1 << 24) + (h2 << 16) + (h3 << 8) + h4;
return CGSizeMake(w, h);
}
GIF
+(CGSize)GIFImageSizeWithRangeHeader:(NSData *)data{
short w1 = 0, w2 = 0;
[data getBytes:&w1 range:NSMakeRange(0, 1)];
[data getBytes:&w2 range:NSMakeRange(1, 1)];
short w = w1 + (w2 << 8);
short h1 = 0, h2 = 0;
[data getBytes:&h1 range:NSMakeRange(2, 1)];
[data getBytes:&h2 range:NSMakeRange(3, 1)];
short h = h1 + (h2 << 8);
return CGSizeMake(w, h);
}
JPG
+(CGSize)JPGImageSizeWithRangeHeader:(NSData *)data{
if ([data length] <= 0x58) {
return CGSizeZero;
}
if ([data length] < 210) {// 肯定只有一个DQT字段
short w1 = 0, w2 = 0;
[data getBytes:&w1 range:NSMakeRange(0x60, 0x1)];
[data getBytes:&w2 range:NSMakeRange(0x61, 0x1)];
short w = (w1 << 8) + w2;
short h1 = 0, h2 = 0;
[data getBytes:&h1 range:NSMakeRange(0x5e, 0x1)];
[data getBytes:&h2 range:NSMakeRange(0x5f, 0x1)];
short h = (h1 << 8) + h2;
return CGSizeMake(w, h);
} else {
short word = 0x0;
[data getBytes:&word range:NSMakeRange(0x15, 0x1)];
if (word == 0xdb) {
[data getBytes:&word range:NSMakeRange(0x5a, 0x1)];
if (word == 0xdb) {// 两个DQT字段
short w1 = 0, w2 = 0;
[data getBytes:&w1 range:NSMakeRange(0xa5, 0x1)];
[data getBytes:&w2 range:NSMakeRange(0xa6, 0x1)];
short w = (w1 << 8) + w2;
short h1 = 0, h2 = 0;
[data getBytes:&h1 range:NSMakeRange(0xa3, 0x1)];
[data getBytes:&h2 range:NSMakeRange(0xa4, 0x1)];
short h = (h1 << 8) + h2;
return CGSizeMake(w, h);
} else {// 一个DQT字段
short w1 = 0, w2 = 0;
[data getBytes:&w1 range:NSMakeRange(0x60, 0x1)];
[data getBytes:&w2 range:NSMakeRange(0x61, 0x1)];
short w = (w1 << 8) + w2;
short h1 = 0, h2 = 0;
[data getBytes:&h1 range:NSMakeRange(0x5e, 0x1)];
[data getBytes:&h2 range:NSMakeRange(0x5f, 0x1)];
short h = (h1 << 8) + h2;
return CGSizeMake(w, h);
}
} else {
return CGSizeZero;
}
}
}
总结
从图片头中获取尺寸并不是一个高效的方法,耗费服务器性能,增加服务端负担。
其实如果是自己服务器的图片,采用url附带尺寸是非常好的选择。最好是上传图片的时候直接把尺寸拼接将要存储的图片文件名中。
猜你喜欢
- 2024-10-24 ansible 运维使用(一) ansible自动化运维工具
- 2024-10-24 HTTP,HTTP2.0,SPDY,HTTPS你应该知道的一些事
- 2024-10-24 「mysql优化专题」高可用性、负载均衡的mysql集群解决方案(12)
- 2024-10-24 k8s网络calico之ipip数据流 k8s pod ip会变吗
- 2024-10-24 linux工作中常用之必备基础命令(二)
- 2024-10-24 高可用性、负载均衡的mysql集群解决方案
- 2024-10-24 搭建分发平台需要什么配置的服务器
- 2024-10-24 k8s 理解Service工作原理 k8s service 原理
- 2024-10-24 《MySQL主从不一致情形与解决方法》
- 2024-10-24 关于HTTP,我们需要知道哪些? 外贸需要知道的认证有哪些
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)