zoukankan      html  css  js  c++  java
  • iOS下载图片之前获取网络图片尺寸的失败尝试

    最近一直在找获取网络图片的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怎么可以这么坑

  • 相关阅读:
    Head First设计模式之观察者模式
    Head First设计模式之策略模式
    EF使用Fluent API配置映射关系
    js判断空字符串、null、undefined、空格、中文空格
    从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
    System.Data.SqlClient.SqlException: 数据类型 text 和 varchar 在 equal to 运算符中不兼容。
    Content-Type的几种常用数据编码格式
    如何通过Git GUI将自己本地的项目上传至Github
    微信小程序开发之模板
    获取图片的EXIF信息
  • 原文地址:https://www.cnblogs.com/chebaodaren/p/5111423.html
Copyright © 2011-2022 走看看