iOS的内存管理非常重要。处理不好会导致页面卡顿,或者App崩溃掉线。基本上,所有应用崩溃都与内存有关。
在平时的开发中,会用到大量的图片。在处理高分辨率图片时,因为画质太高,有时需要对图片进行压缩(目前新iPhone机型拍摄的照片都是高精度的,图片非常大,如果不压缩可能会造成死机)。
Apple提供了五种生成缩略图的方法。
UIKit
UIGraphicsBeginImageContextWithOptions(大小,是,0); [self drawin rect:CGRectMake(0,0,size.width,size . height)]; ui image * image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();画图时,drawInRect会先解码图片,然后生成原始分辨率的位图。此过程会消耗大量内存,因此应避免生成中间位图。
核心显卡
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);CGContextRef context = CGBitmapContextCreate(nil, size.width, size.height, bytePerComponent, bytePerRow, colorSpace, bitmapInfo); //设置插值质量 cgcontextsetinterpolation质量(context,kcginterpolarization高); //drawing cgcontextdrawimage(context,cgrectmake (0,0,size.width,size.height),imageref); //生成imageref cgimageref bitmapimageref = cgbitmapcontextcreateimage(context); ui image * image =[ui image imagewithcigimage:bitmapImageRef scale:self . scale orientation:self . image orientation];CGBitmapContextCreate重新生成一个位图,然后在这个位图上绘制图片,最后得到压缩后的图片。
核心映像
ci image * ci image input =[ci image imageWithCGImage:imageRef]; ci filter * filter =[ci filter filter with name:@ & # 34;CILanczosScaleTransform & # 34]; [filter setValue:ci image input forKey:kCIInputImageKey]; [过滤器设置值:[ns number number with double:scale]forKey:kCIInputScaleKey]; [过滤器设置值:@(1.0)forKey:kciinputasperationkey]; ci image * ci image output =[filter value forkey:kCIOutputImageKey]; 如果(!ciImageOutput) { 返回nil } ci context * ci context =[[ci context alloc]init with options:@ { kcicontextusesoftware renderer:@(NO)}]; CGImageRef ci imageref =[ci context create cgimage:ci image output from rect:CGRectMake(0,0,size.width,size . height)];这种性能比较差,不推荐。
ImageIO
//获取原始图片属性 cfdictionaryef property = cgimagesourcecopyproperties at index(image source,0,nil); ns dictionary * properties = CFBridgingRelease(property); CG float height =[properties[@ & # 34;像素高度& # 34;]integer value];//图片K宽高,12000 CG float width =[Properties[@ & # 34;像素宽度& # 34;]integer value]; //基于较大的边 int image size =(int)max(size。宽度,大小。身高); CFStringRef keys[5]; CFTypeRef值[5]; //创建一个缩放大小相等的缩略图,将根据长度和宽度值中较大的一个进行缩放,作为生成的缩略图大小imageSize /kcgimageresourcenumnaimapixelsize。设置为800时,如果图片本身大于800*600,则生成的图片大小为800*600,如果源图片为700*500,则生成的图片为800 * 500 keys[0]= kcgimageresourcenumnaimapixelsize; CFNumberRef thumbnailSize = CFNumberCreate(NULL,kCFNumberIntType,& imageSize); values[0]=(cf typeref)thumbnail size; keys[1]= kcgimagesourcecreatethumbnailfroimagealways; values[1]=(cf typeref)kcfbooleentrue; keys[2]= kcgimagesourcecreatethumbnailwithstransform; values[2]=(cf typeref)kcfbooleentrue; keys[3]= kcgimagesourcecreatethumbnailfroimageifabsent; values[3]=(cf typeref)kcfbooleentrue; keys[4]= kCGImageSourceShouldCacheImmediately; values[4]=(cf typeref)kcfbooleentrue; CFDictionaryRef options = cfdictionaryrecreate(kCFAllocatorDefault,(const void **)keys,(const void **)values,4,&kCFTypeDictionaryKeyCallBacks,& kCFTypeDictionaryValueCallBacks); CGImageRef thumbnail image = CGImageSourceCreateThumbnailAtIndex(image source,0,options); ui image * result img =[ui image image with gimage:thumbnail image];ImageIO是一个独立的框架,很低级,但是很强大。
VImage
//定义argb 8888
V image _ CG image format格式的结构格式;
format . bitsper component = 8;
format . bitsperpixel = 32;//ARGB四通道4 * 8
format . color space = nil;//Default srgb
format . bitmapinfo = kcgimagalphahfirst | kcgbitmapbyteorderdefault;//表示ARGB
format . version = 0;
format . decode = nil;//默认颜色映射范围[0,1.0]
格式。渲染意图= kcgrenderingingtefault//当
//源图片缓冲区超出[0,1]范围时怎么办,输出图片缓冲区
vimage _ buffersource buffer,输出缓冲区;
vImage _ Error Error = vImage buffer _ initwithcigimage(& source buffer,&format,nil,imageRef,kvImageNoFlags);
if(错误!= kvImageNoError){
return nil;
}
float scale = self . scale;
int width =(int)size . width;
int height =(int)size . height;
int bytes per pixel =(int)CGImageGetBitsPerPixel(imageRef)/8;
//设置输出格式
output buffer . width = width;
output buffer . height = height;
output buffer . row bytes = bytes per pixel * width;
output buffer . data = malloc(output buffer . row bytes * output buffer . height);
//缩放到当前大小
Error = vimagescale _ argb 8888(& source buffer,& outputbuffer,nil,kvagehighquality resampling);
if(错误!= kvImageNoError){
return nil;
}
CGImageRef output imageref = vImageCreateCGImageFromBuffer(& output buffer,&format,nil,nil,kvImageNoFlags,& error);
相比较而言,推荐使用第一种方法获取原图中间部分的缩略图。
-(ui image *)getThumbnailWithTargetSize:(CGSize)targetSize { CGSize imageSize = self . size; if(CGSizeEqualToSize(targetSize,cgsizezezero)){ 返回self } if(targetsize . width & gt;imagesize . width & & targetsize . height & gt;imageSize.height) { 返回自我; } CG float scale = MAX(targetsize . width/imagesize . width,targetsize . height/imagesize . height); CGSize scaleSize = CGSizeMake(imagesize . width * scale,imagesize . height * scale); UIGraphicsBeginImageContextWithOptions(targetSize,false,0); UIBezierPath * bezierPath =[UIBezierPath bezierPathWithRect:CGRectMake(0,0,targetSize.width,targetsize . height)]; [bezier path add clip]; CGRect rect = CGRectMake((targetsize . width-scaleSize.width)/2,(targetsize . height-scalesize . height)/2,scalesize . width,scalesize . height); [self drawin rect:rect]; ui image * new image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 返回newImage }对于用户上传的图片,要做好判断。如果超过一定大小,最好压缩图片;对于列表中显示的图片,如果服务器不返回缩略图,如果是大图,不处理列表滚动就会卡死。