亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS開發中用imageIO漸進加載圖片及獲取exif的方法

2020-07-26 03:34:17
字體:
來源:轉載
供稿:網友

imageIO完成漸進加載圖片

一、常見漸進加載圖片模式
 
  目前我們看到的漸進加載主要有以下三種實現方式:
 
  1)  依次從web上加載不同尺寸的圖片,從小到大。最開始先拉取一個小縮略圖做拉伸顯示,然后拉取中等規格的圖,拉取完畢直接覆蓋顯示,最后拉取原圖,拉取完成后顯示原圖。
 
  2)直接從web上拉取最大的圖片,每接受一點兒數據就顯示一點兒圖片,這樣就會實現從上到下一點點刷新出來的效果。
 
  3)結合第1種和第2種,先拉取一個縮略圖做拉伸顯示,然后采用第二種方法直接拉取原圖,這樣即可以實現漸進加載,也可以節省幾次中間的網絡請求。
 
 
 
二、通過imageIO實現圖片的漸進加載
 
  imageIO的guide中原話是這么說的: "If you have a very large image, or are loading image data over the web, you may want to create an incremental image source so that you can draw the image data as you accumulate it. "
 
  翻譯過來就是: "如果你想加載一副特別大的圖片,或者從網絡上加載一副圖片,你可以通過創建一個imageSource實現漸進加載的效果。"翻譯的不是很地道,大概就是這么個意思,以前在做PowerCam的時候,當時為了在iOS上處理超大圖的時候也試過這種方法,當時測試使用的是一副中國地圖,分辨率為10000*8000的,結果是當整幅圖片加載到內存時,內存吃不消,于是就放棄了?,F在想想對于這種超大圖片的處理,我們可以采用分片的方式進行,每次只需要處理一小塊圖片即可,這個問題就留給大家思考吧。
 
  今天我們要討論的是CGImageSource實現從web端漸進加載圖片,要達到這個目的我們需要創建一個URLConnnection,然后實現代理,每次接收到數據時更新圖片即可。下面主要的實現源碼:
 

復制代碼 代碼如下:

//
//  SvIncrementallyImage.m
//  SvIncrementallyImage
//
//  Created by  maple on 6/27/13.
//  Copyright (c) 2013 maple. All rights reserved.
//

#import "SvIncrementallyImage.h"
#import <ImageIO/ImageIO.h>
#import <CoreFoundation/CoreFoundation.h>

@interface SvIncrementallyImage () {
    NSURLRequest    *_request;
    NSURLConnection *_conn;
   
    CGImageSourceRef _incrementallyImgSource;
   
    NSMutableData   *_recieveData;
    long long       _expectedLeght;
    bool            _isLoadFinished;
}

@property (nonatomic, retain) UIImage *image;
@property (nonatomic, retain) UIImage *thumbImage;

@end

@implementation SvIncrementallyImage

@synthesize imageURL = _imageURL;
@synthesize image    = _image;
@synthesize thumbImage = _thumbImage;

- (id)initWithURL:(NSURL *)imageURL
{
    self = [super init];
    if (self) {
        _imageURL = [imageURL retain];
       
        _request = [[NSURLRequest alloc] initWithURL:_imageURL];
        _conn    = [[NSURLConnection alloc] initWithRequest:_request delegate:self];
       
        _incrementallyImgSource = CGImageSourceCreateIncremental(NULL);
       
        _recieveData = [[NSMutableData alloc] init];
        _isLoadFinished = false;
    }
   
    return self;
}

#pragma mark -
#pragma mark NSURLConnectionDataDelegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    _expectedLeght = response.expectedContentLength;
    NSLog(@"expected Length: %lld", _expectedLeght);
   
    NSString *mimeType = response.MIMEType;
    NSLog(@"MIME TYPE %@", mimeType);
   
    NSArray *arr = [mimeType componentsSeparatedByString:@"/"];
    if (arr.count < 1 || ![[arr objectAtIndex:0] isEqual:@"image"]) {
        NSLog(@"not a image url");
        [connection cancel];
        [_conn release]; _conn = nil;
    }
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Connection %@ error, error info: %@", connection, error);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Connection Loading Finished!!!");
   
    // if download image data not complete, create final image
    if (!_isLoadFinished) {
        CGImageSourceUpdateData(_incrementallyImgSource, (CFDataRef)_recieveData, _isLoadFinished);
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_incrementallyImgSource, 0, NULL);
        self.image = [UIImage imageWithCGImage:imageRef];
        CGImageRelease(imageRef);
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [_recieveData appendData:data];
   
    _isLoadFinished = false;
    if (_expectedLeght == _recieveData.length) {
        _isLoadFinished = true;
    }
   
    CGImageSourceUpdateData(_incrementallyImgSource, (CFDataRef)_recieveData, _isLoadFinished);
    CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_incrementallyImgSource, 0, NULL);
    self.image = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
}

@end


  從上面代碼中我們可以看到,一開始我們根據傳入的URL創建一個URLConnection,同時創建一個空的CGImageSource,然后在每次收到數據的時候調用CGImageSourceUpdateData更新imageSource的數據,接著調用CGImageSourceCreateImageAtIndex獲取最新的圖片即可。
 
  怎么樣,看到上面的實現是不是感覺實現從web上漸進加載圖片很簡單,雖然imageIO幫我們做了很多事情,但是我們也應該了解它的原理。我們知道文件都是有格式的,一般文件的頭部會記錄一些關于文件格式的數據,后面就是實際的文件數據。
 
  拿最簡單的BMP圖片文件舉例:
 
  1)  最開始的BITMAPFILEHEADER,這部分主要記錄文件的大小,以及實際的圖像數據離文件頭的距離。
 
  2)  接著是BITMAPINFOHEADER,這部分主要記錄圖片的寬,高,位深等信息
 
  3)可選的調色板信息
 
  4)最后一部分就是實際的圖片數據。
 
  前三部分的信息很小,一般加起來不會超過100個字節,獲取到這寫信息以后,我們就可以很輕松的根據后面的數據構建出圖片,當數據獲取的越來越完整的時候,我們構造出的圖片就會越完整,直至全部加載完成。
 
  BMP格式是簡單的圖片格式,其他的JPG,PNG雖然結果更加復雜,但是總體構成都差不多。imageIO正是幫助我們完成了眾多圖片格式的編解碼,然后一步步構造出最終的圖片。


使用imageIO獲取圖片的exif信息
一幅圖片除了包含我們能看見的像素信息,背后還包含了拍攝時間,光圈大小,曝光等信息。UIImage類將這些細節信息都隱藏了起來,只提供我們關心的圖片尺寸,圖片方向等。我們可以通過imageIO框架獲取到圖片背后的所有信息,下面就讓我們一起看看。
 
  imageIO框架是iOS中偏底層一點兒的框架,它內部提供的接口都是C風格的,關鍵數據也都是使用CoreFoundation進行存儲。慶幸的是CoreFoundation中有很多數據類型都可以上層的數據Foundation框架中的數據類型進行無縫橋接。這也就大大方便了我們對圖片信息的操作。
 
  CGImageSourceRef是整個imageIO的入口,通過它我們可以完成從文件的加載圖片。加載完成以后我們就得到一個CGImageSourceRef,通過CGImageSourceRef我們就可以獲取圖片文件的大小,UTI(uniform type identifier),內部包含幾張圖片,訪問每一張圖片以及獲取每張圖片對應的exif信息等。
 
  你可能會有一個疑問,為什么會有幾張圖片呢?
 
  這塊兒我解釋一下,imageSourceRef和文件是一一對應的,通常我們見到的圖片文件(例如jpg,png)內部都只有一張圖片,這種情況我們通過CGImageSourceGetCount方法得到的就會是1。但是不能排除一個圖片文件中會有多種圖片的情況,例如gif文件,這個時候一個文件中就可能包含幾張甚至幾十張圖片。前面我寫的一片博客《IOS中如何解析并顯示Gif》就是通過imageSource實現加載和解析gif的功能。
 
  下面是系統相機拍的照片的exif信息:

復制代碼 代碼如下:

image property: {
    ColorModel = RGB;
    DPIHeight = 72;
    DPIWidth = 72;
    Depth = 8;
    Orientation = 6;
    PixelHeight = 2448;
    PixelWidth = 3264;
    "{Exif}" =     {
        ApertureValue = "2.526069";
        BrightnessValue = "-0.5140446";
        ColorSpace = 1;
        ComponentsConfiguration =         (
            1,
            2,
            3,
            0
        );
        DateTimeDigitized = "2013:06:24 22:11:30";
        DateTimeOriginal = "2013:06:24 22:11:30";
        ExifVersion =         (
            2,
            2,
            1
        );
        ExposureMode = 0;
        ExposureProgram = 2;
        ExposureTime = "0.06666667";
        FNumber = "2.4";
        Flash = 16;
        FlashPixVersion =         (
            1,
            0
        );
        FocalLenIn35mmFilm = 33;
        FocalLength = "4.13";
        ISOSpeedRatings =         (
            400
        );
        MeteringMode = 3;
        PixelXDimension = 3264;
        PixelYDimension = 2448;
        SceneCaptureType = 0;
        SensingMethod = 2;
        ShutterSpeedValue = "3.906905";
        SubjectArea =         (
            2815,
            1187,
            610,
            612
        );
        WhiteBalance = 0;
    };
    "{GPS}" =     {
        Altitude = "27.77328";
        AltitudeRef = 0;
        Latitude = "22.5645";
        LatitudeRef = N;
        Longitude = "113.8886666666667";
        LongitudeRef = E;
        TimeStamp = "14:11:23.36";
    };
    "{TIFF}" =     {
        DateTime = "2013:06:24 22:11:30";
        Make = Apple;
        Model = "iPhone 5";
        Orientation = 6;
        ResolutionUnit = 2;
        Software = "6.1.4";
        XResolution = 72;
        YResolution = 72;
        "_YCbCrPositioning" = 1;
    };
}

  從中我們可以看出最開始的幾項分別顯示了當前圖片的顏色模式,色深,x,y方向的DPI,實際像素以及圖片的方向。我最開始看到這個方向時,心中一喜這不是UIImage中的imageOrientation,但是實驗發現這個方向和UIImage中的imageOrientation并不相等,此處的方向是exif標準定義的方向,從1到8分別對應這UIImage中的8個方向,只是順序不一樣,它們對應關系如下:
 

復制代碼 代碼如下:

enum {
    exifOrientationUp = 1,      // UIImageOrientationUp
    exifOrientationDown = 3,    // UIImageOrientationDown
    exifOrientationLeft = 6,    // UIImageOrientationLeft
    exifOrientationRight = 8,   // UIImageOrientationRight
   
    // these four exifOrientation does not support by all camera, but IOS support these orientation
    exifOrientationUpMirrored = 2,          // UIImageOrientationUpMirrored
    exifOrientationDownMirrored = 4,        // UIImageOrientationDownMirrored
    exifOrientationLeftMirrored = 5,        // UIImageOrientationLeftMirrored
    exifOrientationRightMirrored = 7,       // UIImageOrientationRightMirrored
};
typedef NSInteger ExifOrientation;

  目前市面上的大部分數碼相機和手機都會內置一個方向感應器,拍出的照片中會寫如方向信息,但是通常都只會有前四種方向。這幾種Mirrored方向通常都是手機前置攝像頭自拍的時候才會設置。
 
  exif為什么要搞這么一個方向呢?
 
  幾乎所有的攝像頭在出場的時候成相芯片都是有方向的,拍出來的照片的像素都是默認方向的。如果每拍一張照片就對這些像素進行旋轉,如果數碼相機每秒連拍20張來算,旋轉操作將會非常耗時。更聰明的做法是拍照時只記錄一個方向,然后顯示的時候按方向顯示出來即可。因此exif定義了一個標準的方向參數,只要讀圖的軟件都來遵守規則,加載時候讀取圖片方向,然后做相應的旋轉即可。這樣既可以達到快速成像的目的,又能達到正確的顯示,何樂而不為呢。
 
  常見的圖片瀏覽和編輯軟件都遵守這個規則,但是有一個我們最常用的看圖軟件(windows自帶的看圖程序)不會去讀這個方向,因此我們將數碼相機和手機拍出來的圖片導入windows上時,會經常遇到方向錯誤的問題。不知道windows帝國是怎么想的,或許和定義exif的組織有什么過節吧。
 
  圖片信息中除了上面看提到的那些,還有拍攝的GPS信息,iOS自帶的相冊軟件中的地點tab就是按照GPS信息實現的。還有很多其他的信息,感興趣的可以自己寫個程序研究研究,這里就不展開了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色悠悠国产精品| 91精品国产综合久久香蕉的用户体验| 亚洲福利视频网| 久久久久北条麻妃免费看| 欧美日韩在线观看视频| 精品国产区一区二区三区在线观看| 日韩av在线一区| 欧洲成人午夜免费大片| 中文字幕综合在线| 成人乱人伦精品视频在线观看| 国产亚洲aⅴaaaaaa毛片| 亚洲欧美国产制服动漫| 亚洲专区国产精品| 欧美高清电影在线看| 91国偷自产一区二区三区的观看方式| www.日韩视频| 亚洲精选一区二区| 国产视频综合在线| 91在线无精精品一区二区| 九色精品美女在线| 77777少妇光屁股久久一区| 91牛牛免费视频| 国产97在线亚洲| 亚洲图片欧美午夜| 亚洲毛片在线观看.| 亚洲xxx自由成熟| 欧美精品电影在线| 日韩av综合网| 91av在线免费观看视频| 97香蕉久久超级碰碰高清版| 亚洲国产成人精品久久| 一个人看的www欧美| 国模gogo一区二区大胆私拍| 一区二区亚洲欧洲国产日韩| 欧美精品做受xxx性少妇| 欧美国产第二页| 亲子乱一区二区三区电影| 欧美高清无遮挡| 国产欧美精品xxxx另类| 97视频在线播放| 91精品视频在线免费观看| 亚洲精品成人免费| 国产精品久久色| 国产在线视频2019最新视频| 欧美在线视频网站| 九色精品免费永久在线| 久久久免费在线观看| 欧美黄色片免费观看| 曰本色欧美视频在线| 亚洲精品美女久久| 国产精品一二三视频| 亚洲精品美女免费| 国产亚洲综合久久| 夜夜躁日日躁狠狠久久88av| 亚洲精品乱码久久久久久金桔影视| 亚洲精品中文字幕av| 4p变态网欧美系列| 深夜福利国产精品| 久久精品91久久香蕉加勒比| 精品中文字幕在线| 色噜噜狠狠狠综合曰曰曰88av| 国产精品免费在线免费| 亚洲精品一区中文| 久久中文精品视频| 在线观看亚洲视频| 亚洲欧洲一区二区三区在线观看| 亚洲国产欧美一区二区三区同亚洲| 亚洲国产精品成人一区二区| 91国内产香蕉| 国产成人精品一区二区在线| 在线看片第一页欧美| 国内精品小视频在线观看| 亚洲欧美日韩网| 日韩在线观看免费网站| 情事1991在线| 成人网在线免费观看| 欧美一级片久久久久久久| 日韩美女视频在线观看| 色噜噜久久综合伊人一本| 亚洲最大成人网色| 伊人成人开心激情综合网| www.精品av.com| 日韩在线视频网| 成人a免费视频| 日av在线播放中文不卡| 亚洲成年网站在线观看| 久久九九国产精品怡红院| 国产精品夜色7777狼人| 欧美福利视频网站| 国内外成人免费激情在线视频| 亚洲有声小说3d| 秋霞午夜一区二区| 欧美大胆在线视频| 亚洲网站在线看| 成人亚洲激情网| 精品久久久视频| 亚洲娇小xxxx欧美娇小| 日韩电影大片中文字幕| 日韩av电影在线免费播放| 91禁外国网站| 日韩精品中文字幕在线| 亚洲欧洲国产伦综合| 91久久嫩草影院一区二区| 欧亚精品中文字幕| 亚洲qvod图片区电影| 九九九久久久久久| 国色天香2019中文字幕在线观看| 国产丝袜一区二区三区免费视频| 亚洲一区二区三区视频播放| 国产精品免费久久久久久| 国产精品夫妻激情| 久久久www成人免费精品张筱雨| 中日韩美女免费视频网址在线观看| 欧美午夜精品久久久久久浪潮| 欧美精品电影免费在线观看| 欧美激情中文字幕在线| 国产精品尤物福利片在线观看| 久久香蕉国产线看观看av| 亚洲免费一在线| 韩国欧美亚洲国产| 97超碰蝌蚪网人人做人人爽| 中文字幕亚洲一区| 欧美老妇交乱视频| 97视频在线观看免费高清完整版在线观看| 91亚洲精品一区二区| 欧美伊久线香蕉线新在线| 亚洲最大成人在线| 国外成人性视频| 视频在线观看一区二区| 自拍偷拍亚洲一区| 亚洲国产成人av在线| 96精品视频在线| 97超视频免费观看| 欧美成人午夜激情在线| 久久久久国产精品免费网站| 国产日韩欧美成人| 97高清免费视频| 国产日韩欧美中文在线播放| 亚洲欧美国产精品va在线观看| 国产精品www| 精品久久久国产精品999| 亚洲精品v天堂中文字幕| 黑人巨大精品欧美一区二区一视频| 成人免费视频97| 在线播放日韩欧美| 欧美国产乱视频| 精品亚洲aⅴ在线观看| 欧美性猛交xxxx黑人猛交| 亚洲欧美成人一区二区在线电影| 成人xxxxx| 国产一区二区三区丝袜| 亚洲偷欧美偷国内偷| 在线电影欧美日韩一区二区私密| 欧美亚洲日本网站| 亚洲人成电影在线| 欧美激情a∨在线视频播放| 欧美麻豆久久久久久中文| 欧美尺度大的性做爰视频| 91精品国产自产在线观看永久| 国产精品va在线| 欧美激情xxxxx| 国产suv精品一区二区三区88区| 最新国产精品拍自在线播放| 欧美精品在线免费|