最近一直在找获取网络图片的size的方式,最后得出两个结论:
1 使用分线程下载下来,然后获得图片的size
2 使用网络请求图片的头文件,然后从头文件中找到图片大小的信息
第一种方法需要主线程分线程切换,因为在使用tableView来reloadData的时候,刷表老是出问题,先放着不管
然后我重点是想搞一下第二个方法:
在网上找到了一个博客:http://cxjwin.github.io/2013/11/05/preview_image_size/
大神写的很不错
主要思路就是先在网上找一个图片头文件的格式,然后对照着请求回来的data数据来进行查找,找到图片宽高的地方,解析出来
以png格式为例,先放一段代码:
case PngImage: { NSString *URLString = @"http://pic12.nipic.com/20110118/1295091_171039317000_2.png"; NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:2.0f]; NSString *range=[NSString stringWithFormat:@"Bytes=16-23"]; [request setValue:range forHTTPHeaderField:@"Range"]; NSURLResponse *response=nil; NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL]; CGSize size = pngImageSizeWithHeaderData(data); NSLog(@"png image size : %@", NSStringFromCGSize(size)); }
或者这样的
NSString *URLString = @"http://pic12.nipic.com/20110118/1295091_171039317000_2.png"; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URLString]]; [request setValue:kPngRangeValue forHTTPHeaderField:@"Range"]; [[NSURLConnection connectionWithRequest:request delegate:self] start];
请求方式不同,原理是一样的
然后就是对获取到的data进行解析
CGSize pngImageSizeWithHeaderData(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); }
在我的试验中,获取到的data数值为<00000400 000002ad>,只有八字节,前四位是width,后四位是height
这是他看过png的格式,所以在获取数据的时候只需要16-23位
data数据是以16进制数展示的,其实应该是 <00 00 04 00 00 00 02 ad>,每两个数代表8位,二进制中8位一个字节,这里换算一下,四个数可以表示一个字节
这个清楚了之后就可以照着网上的头文件解析来解析这些16进制数
下面放上网上的对jpeg头文件的部分解析
这些都还正常,放一段我获取到的data的分析记录
ff d8(soi) ff e0(appo) 00 10(数据长度) 4a 46 49 46 00(标示符) 01 02(版本号) 01(密度单位) 00 48(x密度) 00 48 (y密度)00(缩略图水平像素数目)00(缩略图垂直像素数目) ffed002c 50686f74
然后后面就奇葩起来了
然后我发现了我截取的data数据里各种appn标记码,然后这玩意儿是不知道有多长,有多少的,然后那个存着图片尺寸的标记码
ffc0被埋在data的汪洋大海里,我使用搜索找到了它,但是已经毛用没有了
瞬间,心都碎了
能获取png,gif格式的图片大小,因为png和gif格式的图片头文件固定,可以准确找到宽高所在字节,只需要极少流量就可以获得图片大小
但是jpeg的头文件很混乱,我真的想说它根本就不分header和body,绘图软件编辑一次保存一次就添加一个标记码,然后存放宽高的标记码就消失在数据流的某个地方了,因为不知道有多少个绘图软件编辑过,也不知道绘图软件标记码里面的内容格式,所以手动获取jpeg图片的宽高基本不可能了
我这么多天都白玩儿了
还是去捣鼓一下分线程吧,要不去搞一下webView,都比这个靠谱啊,,,
jpeg怎么可以这么坑