最近一直在找获取网络图片的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头文件的部分解析

iOS 计算图片的内存大小 ios 查看图片尺寸_头文件

iOS 计算图片的内存大小 ios 查看图片尺寸_iOS 计算图片的内存大小_02

iOS 计算图片的内存大小 ios 查看图片尺寸_宽高_03

iOS 计算图片的内存大小 ios 查看图片尺寸_头文件_04

这些都还正常,放一段我获取到的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

然后后面就奇葩起来了

iOS 计算图片的内存大小 ios 查看图片尺寸_头文件_05

 

然后我发现了我截取的data数据里各种appn标记码,然后这玩意儿是不知道有多长,有多少的,然后那个存着图片尺寸的标记码

iOS 计算图片的内存大小 ios 查看图片尺寸_宽高_06

ffc0被埋在data的汪洋大海里,我使用搜索找到了它,但是已经毛用没有了

iOS 计算图片的内存大小 ios 查看图片尺寸_头文件_07

 

瞬间,心都碎了

能获取png,gif格式的图片大小,因为png和gif格式的图片头文件固定,可以准确找到宽高所在字节,只需要极少流量就可以获得图片大小
但是jpeg的头文件很混乱,我真的想说它根本就不分header和body,绘图软件编辑一次保存一次就添加一个标记码,然后存放宽高的标记码就消失在数据流的某个地方了,因为不知道有多少个绘图软件编辑过,也不知道绘图软件标记码里面的内容格式,所以手动获取jpeg图片的宽高基本不可能了

我这么多天都白玩儿了

还是去捣鼓一下分线程吧,要不去搞一下webView,都比这个靠谱啊,,,

jpeg怎么可以这么坑