imageIO完成漸進加載圖片
1、罕見漸進加載圖片形式
今朝我們看到的漸進加載重要有以下三種完成方法:
1) 順次從web上加載分歧尺寸的圖片,從小到年夜。最開端先拉取一個小縮略圖做拉伸顯示,然後拉取中等規格的圖,拉取終了直接籠罩顯示,最初拉取原圖,拉取完成後顯示原圖。
2)直接從web上拉取最年夜的圖片,每接收一點兒數據就顯示一點兒圖片,如許就會完成從上到下一點點刷新出來的後果。
3)聯合第1種和第2種,先拉取一個縮略圖做拉伸顯示,然後采取第二種辦法直接拉取原圖,如許便可以完成漸進加載,也能夠節儉幾回中央的收集要求。
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 <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信息完成的。還有許多其他的信息,感興致的可以本身寫個法式研討研討,這裡就不睜開了。
【iOS開辟頂用imageIO漸進加載圖片及獲得exif的辦法】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!