你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS瘋狂詳解之imageIO完成漸進加載圖片

iOS瘋狂詳解之imageIO完成漸進加載圖片

編輯:IOS開發綜合

一、常見漸進加載圖片模式

目前我們看到的漸進加載主要有以下三種實現方式:

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的,結果是當整幅圖片加載到內存時,內存吃不消,於是就放棄了。現在想想對於這種超大圖片的處理,我們可以采用分片的方式進行,每次只需要處理一小塊圖片即可,這個問題就留給大家思考吧。

今天我們要討論的是CGImageSource實現從web端漸進加載圖片,要達到這個目的我們需要創建一個URLConnnection,然後實現代理,每次接收到數據時更新圖片即可。下面主要的實現源碼:

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

#import "SvIncrementallyImage.h"
#import 
#import 

@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正是幫助我們完成了眾多圖片格式的編解碼,然後一步步構造出最終的圖片。

 

 

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved