1 圖片處理
1.1 編輯圖片的幾個(gè)方法
第一種
????先用UIImage對(duì)象加載一張圖片
????然后轉(zhuǎn)化成CGImageRef放到CGContext中去編輯
第二種
????用CGImageCreate函數(shù)創(chuàng)建CGImageRef
????然后把CGImageRef放到CGContext中去編輯
第三種
????用CGImageCreateCopy 或者CGImageCreateCopyWithColorSpace函數(shù)拷貝
CGImageRefCGImageCreate (
????size_t width, //圖片的寬度
????size_t height, //圖片的高度
????size_t bitsPerComponent,? //圖片每個(gè)顏色的bits檩奠,比如rgb顏色空間辅斟,有可能是5 或者8 ==
????size_t bitsPerPixel,? //每一個(gè)像素占用的buts内地,15 位24位 32位等等
????size_t bytesPerRow, //每一行占用多少bytes 注意是bytes不是bits ?1byte =8bit
????CGColorSpaceRef colorspace,? //顏色空間茁肠,比如rgb
????CGBitmapInfo bitmapInfo,? //layout,像素中bit的布局, 是rgba還是 argb,==
????CGDataProviderRef provider,? //數(shù)據(jù)源提供者,url或者內(nèi)存==
????const CGFloat decode[],? //一個(gè)解碼數(shù)組
????bool shouldInterpolate,? //抗鋸齒參數(shù)
????CGColorRenderingIntent intent
????//圖片渲染相關(guān)參數(shù)
);
1.2 示例代碼
CGImageRef CGImageCreate(size_t width, size_theight, size_tbitsPerComponent, size_t bitsPerPixel, size_tbytesPerRow, CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRefprovider, const CGFloat decode[], boolshouldInterpolate, CGColorRenderingIntent intent);
????通過這個(gè)方法雏掠,我們可以創(chuàng)建出一個(gè)CGImageRef類型的對(duì)象,下面分別對(duì)參數(shù)進(jìn)行解釋:
????sizt_t是定義的一個(gè)可移植性的單位劣像,在64位機(jī)器中為8字節(jié)乡话,32位位4字節(jié)。
????width:圖片寬度像素
????height:圖片高度像素
????bitsPerComponent:每個(gè)顏色的比特?cái)?shù)驾讲,例如在rgba-32模式下為8
????bitsPerPixel:每個(gè)像素的總比特?cái)?shù)
????bytesPerRow:每一行占用的字節(jié)數(shù)蚊伞,注意這里的單位是字節(jié)
????space:顏色空間模式席赂,例如const CFStringRef kCGColorSpaceGenericRGB 這個(gè)函數(shù)可以返回一個(gè)顏色空間對(duì)象。
????bitmapInfo:位圖像素布局时迫,枚舉如下:
typedef?CF_OPTIONS(uint32_t,?CGBitmapInfo)?{
??kCGBitmapAlphaInfoMask?=?0x1F,
??kCGBitmapFloatComponents?=?(1?<<?8),
??kCGBitmapByteOrderMask?=?0x7000,
??kCGBitmapByteOrderDefault?=?(0?<<?12),
??kCGBitmapByteOrder16Little?=?(1?<<?12),
??kCGBitmapByteOrder32Little?=?(2?<<?12),
??kCGBitmapByteOrder16Big?=?(3?<<?12),
??kCGBitmapByteOrder32Big?=?(4?<<?12)
}
????provider:數(shù)據(jù)源提供者
????decode[]:解碼渲染數(shù)組
????shouldInterpolate:是否抗鋸齒
????intent:圖片相關(guān)參數(shù)
CGImageRef CGImageMaskCreate(size_t width, size_theight, size_t bitsPerComponent, size_t bitsPerPixel, size_tbytesPerRow, CGDataProviderRef provider, const CGFloat decode[], boolshouldInterpolate)
????這個(gè)方法用于創(chuàng)建mask圖片圖層颅停,可以設(shè)置其顯示部分與不顯示部分達(dá)到特殊的效果,參數(shù)意義同上掠拳。
CGImageRef CGImageCreateCopy(CGImageRefimage)
????這個(gè)方法可以復(fù)制一個(gè)CGImageRef對(duì)象
CGImageRef CGImageCreateWithJPEGDataProvider(CGDataProviderRef source, const CGFloat decode[], boolshouldInterpolate, CGColorRenderingIntent intent)
????通過JPEG數(shù)據(jù)源獲取圖像
CGImageRef CGImageCreateWithPNGDataProvider(CGDataProviderRefsource, const CGFloat decode[], boolshouldInterpolate, CGColorRenderingIntent intent)
????通過PNG數(shù)據(jù)源獲取圖像
CGImageRef CGImageCreateWithImageInRect(CGImageRefimage, CGRectrect)
????截取圖像的一個(gè)區(qū)域重繪圖像
CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRefmask)
????截取mask圖像的某一區(qū)域重繪
CGImageRef CGImageCreateWithMaskingColors(CGImageRefimage, const CGFloatcomponents[])
????通過顏色分量數(shù)組創(chuàng)建位圖
CGImageRef CGImageCreateCopyWithColorSpace(CGImageRefimage, CGColorSpaceRef space)
????通過顏色空間模式復(fù)制位圖
CGImageRef CGImageRetain(CGImageRefimage)
????引用+1
void CGImageRelease(CGImageRefimage)
????引用-1
bool CGImageIsMask(CGImageRefimage)
????返回是否為Mask圖層
size_t CGImageGetWidth(CGImageRefimage)
????獲取寬度像素
size_t CGImageGetHeight(CGImageRefimage)
獲取高度像素
下面這些方法分別獲取相應(yīng)屬性
size_t CGImageGetBitsPerComponent(CGImageRefimage)
size_t CGImageGetBitsPerPixel(CGImageRefimage)
size_t CGImageGetBytesPerRow(CGImageRefimage)
CGColorSpaceRef CGImageGetColorSpace(CGImageRef image)CG_EXTERN CGImageAlphaInfo CGImageGetAlphaInfo(CGImageRefimage)
CGDataProviderRef CGImageGetDataProvider(CGImageRefimage)
const CGFloat *CGImageGetDecode(CGImageRefimage)
bool CGImageGetShouldInterpolate(CGImageRefimage)
CGColorRenderingIntent CGImageGetRenderingIntent(CGImageRefimage)
CGBitmapInfo CGImageGetBitmapInfo(CGImageRefimage)
1.3 PNG與JPEG優(yōu)劣比較
????存儲(chǔ)速度:JPG更快
????壓縮比:JPG更大癞揉;
????圖片質(zhì)量:JPG更好
????JPG不支持透明效果;????
????UIImageJPEGRepresentation方法在耗時(shí)上比較少 而UIImagePNGRepresentation耗時(shí)操作時(shí)間比較長(zhǎng)溺欧;
????UIImageJPEGRepresentation函數(shù)需要兩個(gè)參數(shù):圖片的引用和壓縮系數(shù).而UIImagePNGRepresentation只需要圖片引用作為參數(shù).通過在實(shí)際使用過程中,比較發(fā)現(xiàn): UIImagePNGRepresentation(UIImage* image) 要比UIImageJPEGRepresentation(UIImage* image, 1.0) 返回的圖片數(shù)據(jù)量大很多.譬如,同樣是讀取攝像頭拍攝的同樣景色的照片, UIImagePNGRepresentation()返回的數(shù)據(jù)量大小為199K ,而 UIImageJPEGRepresentation(UIImage* image, 1.0)返回的數(shù)據(jù)量大小只為140KB,比前者少了50多KB.如果對(duì)圖片的清晰度要求不高,還可以通過設(shè)置 UIImageJPEGRepresentation函數(shù)的第二個(gè)參數(shù),大幅度降低圖片數(shù)據(jù)量.譬如,剛才拍攝的圖片, 通過調(diào)用UIImageJPEGRepresentation(UIImage* image, 1.0)讀取數(shù)據(jù)時(shí),返回的數(shù)據(jù)大小為140KB,但更改壓縮系數(shù)后,通過調(diào)用UIImageJPEGRepresentation(UIImage* image, 0.5)讀取數(shù)據(jù)時(shí),返回的數(shù)據(jù)大小只有11KB多,大大壓縮了圖片的數(shù)據(jù)量 ,而且從視角角度看,圖片的質(zhì)量并沒有明顯的降低.因此,在讀取圖片數(shù)據(jù)內(nèi)容時(shí),建議優(yōu)先使用UIImageJPEGRepresentation,并可根據(jù)自己的實(shí)際使用場(chǎng)景,設(shè)置壓縮系數(shù),進(jìn)一步降低圖片數(shù)據(jù)量大小.
1.4 圖片縮放
圖片縮放的三個(gè)函數(shù)
http://www.cnblogs.com/pengyingh/articles/2355052.html
????????程序中一個(gè)界面用到了好多張大圖喊熟,內(nèi)存報(bào)警告了,所以做了一下圖片縮放姐刁,在網(wǎng)上找了別人寫的代碼
//把圖片做等比縮放芥牌,生成一個(gè)新圖片
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize sourceImage:(UIImage*)sourceImage {
//????UIGraphicsBeginImageContext(targetSize);
//? ? [sourceImage drawInRect:CGRectMake(0,0, targetSize.width, targetSize.height)];
//? ? UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext();
//????UIGraphicsEndImageContext();
//????return scaledImage;
? ? UIImage*newImage = nil;
? ?CGSize imageSize = sourceImage.size;
? ?CGFloat width = imageSize.width;
? ?CGFloat height = imageSize.height;
? ?CGFloat targetWidth = targetSize.width;
? ?CGFloat targetHeight = targetSize.height;
? ?CGFloat scaleFactor =0.0;
? ?CGFloat scaledWidth = targetWidth;
? ?CGFloat scaledHeight = targetHeight;
? ?CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
? ?UIGraphicsBeginImageContext(targetSize);// this will crop
? ?CGRect thumbnailRect = CGRectZero;
? ?thumbnailRect.origin = thumbnailPoint;
? ?thumbnailRect.size.width? = scaledWidth;
? ?thumbnailRect.size.height = scaledHeight;
? ?[sourceImage drawInRect:thumbnailRect];
? ?newImage =UIGraphicsGetImageFromCurrentImageContext();
? ?if(newImage== nil)
? ? ? ? NSLog(@"could not scale image");
? ? ? ?//pop thecontext to get back to the default
? ? ? ?UIGraphicsEndImageContext();
? ? ? ?return newImage;
}
//把圖片按照新大小進(jìn)行裁剪,生成一個(gè)新圖片
- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize image:(UIImage *)sourceImage
{
? ? //??? UIImage*sourceImage = self;
? ? UIImage*newImage = nil;
? ?CGSizeimageSize = sourceImage.size;
? ?CGFloat width= imageSize.width;
? ?CGFloat height= imageSize.height;
? ?CGFloattargetWidth = targetSize.width;
? ?CGFloattargetHeight = targetSize.height;
? ?CGFloat scaleFactor =0.0;
? ?CGFloat scaledWidth = targetWidth;
? ?CGFloat scaledHeight = targetHeight;
? ?CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
? ?if(CGSizeEqualToSize(imageSize, targetSize) == NO)
? ?{
? ? ? ?CGFloat widthFactor = targetWidth /width;
? ? ? ?CGFloat heightFactor = targetHeight / height;
? ? ? ?if(widthFactor > heightFactor)
? ? ? ? ? ?scaleFactor = widthFactor;// scale to fit height
? ? ? ?else
? ? ? ? ? ?scaleFactor = heightFactor;// scale to fit width
? ? ? ?scaledWidth? = width * scaleFactor;
? ? ? ?scaledHeight = height * scaleFactor;
? ? ? ?// centerthe image
? ? ? ?if (widthFactor > heightFactor)
? ? ? ?{
? ? ? ? ? ?thumbnailPoint.y = (targetHeight -scaledHeight) *0.5;
? ? ? ?}
? ? ? ?else
? ? ? ? ? ?if(widthFactor < heightFactor)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?thumbnailPoint.x =(targetWidth - scaledWidth) *0.5;
? ? ? ? ? ?}
? ?}??????
? ?UIGraphicsBeginImageContext(targetSize);// this will crop
? ?CGRect thumbnailRect = CGRectZero;
? ?thumbnailRect.origin = thumbnailPoint;
? ?thumbnailRect.size.width? = scaledWidth;
? ?thumbnailRect.size.height = scaledHeight;
? ?[sourceImage drawInRect:thumbnailRect];
? ?newImage =UIGraphicsGetImageFromCurrentImageContext();
? ?if (newImage== nil)
? ? ? ?NSLog(@"could not scale image");
? ?//pop thecontext to get back to the default
? ?UIGraphicsEndImageContext();
? ?return newImage;
}
- (UIImage*)generatePhotoThumbnail:(UIImage *)image
{
? ? // Create a thumbnail version of the image for the eventobject.
? ? CGSize size =image.size;
? ? CGSize croppedSize;
? ? CGFloat ratio=64.0;//這個(gè)是設(shè)置轉(zhuǎn)換后圖片的尺寸大小
? ? ?CGFloat offsetX =0.0;
? ? ?CGFloat offsetY =0.0;
? ? // check the size of the image, we want to make it
????// a square with sides the size of the smallest dimension
? ?if(size.width > size.height) {
? ? ? ?offsetX = (size.height - size.width) /2;
? ? ? ?croppedSize = CGSizeMake(size.height, size.height);
? ?}else{
? ? ? ?offsetY = (size.width - size.height) /2;
? ? ? ?croppedSize = CGSizeMake(size.width, size.width);
? ?}
? ?// Crop the image before resize
? ?CGRect clippedRect = CGRectMake(offsetX *-1, offsetY * -1, croppedSize.width, croppedSize.height);
????//裁剪圖片
????CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
? ?// Donecropping
????// Resize the image
? ? CGRect rect = CGRectMake(0.0,0.0,ratio, ratio);
? ? UIGraphicsBeginImageContext(rect.size);
? ? [[UIImage imageWithCGImage: imageRef] drawInRect: rect];
? ? UIImage *thumbnail =UIGraphicsGetImageFromCurrentImageContext();
? ? UIGraphicsEndImageContext();
? ? // DoneResizing
? ? return thumbnail;
}
實(shí)際應(yīng)用簡(jiǎn)化
-(UIImage *)generatePhotoThumbnail:(UIImage *)image
{
??? CGRect rect=CGRectMake(0,0,60,78);
????//裁剪圖片
??? CGImageRefimageRef=CGImageCreateWithImageInRect([image CGImage], CGRectMake(0,0,140,182));
??? UIGraphicsBeginImageContext(rect.size);
??? [[UIImage imageWithCGImage:imageRef]drawInRect:rect];
????//如果不裁剪圖片可以直接畫
??? //[image drawInRect:CGRectMake(0, 0,theSize.width, theSize.height)];
??? UIImage*thumbnail=UIGraphicsGetImageFromCurrentImageContext();
??? UIGraphicsEndImageContext();
??? returnthumbnail;
}
附:
UIImage類并沒有提供縮放圖片需要用到的API聂使,是不是覺得很吃驚壁拉?沒關(guān)系,我們自己來添加一個(gè)柏靶。
定義縮放圖片的Category
//? UIImage+Scale.h
@interfaceUIImage (scale)
-(UIImage*)scaleToSize:(CGSize)size;
@end
實(shí)現(xiàn)這個(gè)Category的定義
// UIImage+Scale.m?
#import"UIImage+Scale.h"
@implementation UIImage (scale)
-(UIImage*)scaleToSize:(CGSize)size
{
????// 創(chuàng)建一個(gè)bitmap的context
????// 并把它設(shè)置成為當(dāng)前正在使用的context
? ? UIGraphicsBeginImageContext(size);
? ? // 繪制改變大小的圖片
????[self drawInRect: CGRectMake(0,0, size.width, size.height)];
? ? ?// 從當(dāng)前context中創(chuàng)建一個(gè)改變大小后的圖片
? ? ?UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext();
? ????// 使當(dāng)前的context出堆棧
? ????UIGraphicsEndImageContext();
? ????// 返回新的改變大小后的圖片
????return scaledImage;
}
@end
如何使用
// 創(chuàng)建圖片
UIImage*image =[UIImage imageNamed:@"myImage.png"];
// 更改圖片大小
UIImage *scaledImage=[image scaleToSize:CGSizeMake(25.0f,35.0f)]
1.5 參考鏈接
IOS-圖片操作集合
http://blog.csdn.net/ch_soft/article/details/7685753
UIImagePNGRepresentation存在緩慢問題
http://blog.sina.com.cn/s/blog_95a3991f010162ws.html
UIImage變?yōu)镹SData并進(jìn)行壓縮
http://www.cnblogs.com/robinkey/archive/2013/01/21/2869930.html
UIImageJPEGRepresentation和UIImagePNGRepresentation
http://blog.csdn.net/mideveloper/article/details/11473627
png有透明通道弃理,JPEG無
http://blog.163.com/chentong1115@126/blog/static/45314732200972323921819/
透明PNG圖片有黑邊的解決方法
用UIImage和UIButton畫出的按鈕,使用透明的png圖片屎蜓,為什么會(huì)出現(xiàn)白邊
http://segmentfault.com/q/1010000000095447
JPG痘昌、PNG和GIF圖片的基本原理及優(yōu)化方法
http://www.mahaixiang.cn/Photoshop/400.html
JPEG原理詳細(xì)
http://blog.chinaunix.net/uid-27002868-id-3220554.html
IOS開發(fā)中圖片資源使用png還是jpg格式
http://www.cnblogs.com/wengzilin/p/3485298.html
(good)ios開發(fā)圖片格式的選擇:png和jpg
http://m.blog.csdn.net/blog/awaylin113/22712317
IOS開發(fā)之保存圖片到Documents目錄及PNG,JPEG格式相互轉(zhuǎn)換
http://blog.csdn.net/sanpintian/article/details/7418755
iOS過濾png圖片透明部分點(diǎn)擊事件
http://www.cocoachina.com/industry/20121127/5192.html
JPEG壓縮原理
http://blog.csdn.net/xfortius/article/details/8904012
png壓縮原理
http://blog.csdn.net/zykun/article/details/1825086
iOS開發(fā)炬转,圖片使用png好還是jpg好辆苔?
http://www.cocoachina.com/bbs/read.php?tid=110115
2 繪制文本
2.1 NSMutableAttributedString繪制
CGRect textViewRect = CGRectMake(ICON_SPACE, _imageHeight + ICON_SPACE, _postContentTextView.frame.size.width, _labelSize);
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString: vm.contentText];
[str addAttribute:NSForegroundColorAttributeName value: kContentTextColor range:NSMakeRange(0,[vm.contentText length])];
[str addAttribute: NSFontAttributeName value: kContentTextFont range:NSMakeRange(0,[vm.contentText length])];
[str addAttribute: NSBackgroundColorDocumentAttribute value: [UIColor whiteColor] range: NSMakeRange(0, [vm.contentText length])];
[str drawInRect: textViewRect];
2.2 參考資料
IOS開發(fā)(78)之繪制文本
http://www.2cto.com/kf/201305/212045.html
iOS界面上繪制不同字體 顏色 大小的字符串
http://blog.csdn.net/wsk_123_123/article/details/23277457
初探NSAttributedString和NSMutableAttributedString的使用-LiuWJ
http://www.tuicool.com/articles/Fvqia2
iOS字符屬性NSAttributedString描述
http://my.oschina.net/lanrenbar/blog/395909
NSAttributedString詳解
http://www.cnblogs.com/zhw511006/archive/2012/09/21/2696700.html
3 異步繪制
3.1 異步繪制示例
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
???????CGRect drawRect = _bgImageView.frame;
???????UIGraphicsBeginImageContextWithOptions(drawRect.size, YES, 0);
???????CGContextRef context = UIGraphicsGetCurrentContext();
???????if(!context) {
???????????return;
???????}
???????[[UIColor whiteColor] set];
???????CGContextFillRect(context, drawRect);
???????CGRect imgRect = CGRectZero;
???????if ([vm.contentImgPath length] > 0) {
???????????imgRect =CGRectMake(0, 0, BODY_HEIGTH, _imageHeight);
???????????[vm.contentImage drawInRect:? contentImageView.frame blendMode: kCGBlendModeNormal alpha:1];
???????}
???????CGRect textViewRect = CGRectZero;
?????? ?if ([vm.contentText length] > 0) {
??????????? NSMutableAttributedString*str;
??????????? if (!isContentDisplayCompletly) {
??????????????? if (vm.digestText) {
??????????????????? str = [[NSMutableAttributedString alloc] initWithString: vm.digestText attributes: contentTextView.typingAttributes];
??????????????? }else
??????????????????? str = [[NSMutableAttributedString alloc] initWithString: vm.contentText attributes: contentTextView.typingAttributes];
??????????? }else
??????????????? str = [[NSMutableAttributedString alloc] initWithString: vm.contentText attributes: contentTextView.typingAttributes];
??????????? [strdrawInRect: contentTextView.frame];
??????? }
??????? if (_subjectTitleHeight> 0) {
??????? ????CGRect subjectIconFrame = CGRectMake(_subjectButton.frame.origin.x, _subjectButton.frame.origin.y, 16, 16);
??????????? UIImage*iconImg = [UIImage imageNamed:@"FlagIcon"];
??????????? subjectIconFrame.size = iconImg.size;
??????????? [iconImg drawInRect: subjectIconFrame blendMode: kCGBlendModeNormal alpha:1];
??????????? CGRect subjectTitleFrame = CGRectMake(subjectIconFrame.origin.x + subjectIconFrame.size.width, subjectIconFrame.origin.y, 100, _subjectTitleHeight);
??????????? [_subjectButton.titleLabel.attributedText drawInRect: subjectTitleFrame];
??????? }
??????? UIImage*temp = UIGraphicsGetImageFromCurrentImageContext();
??????? UIGraphicsEndImageContext();
??????? dispatch_async(dispatch_get_main_queue(),^{
??????????? _bgImageView.image = nil;
??????????? _bgImageView.image=temp;
??????????? [self setHidden:NO];
??????? });
??? });
3.2 DrawRect之后注意用hitTest:withEvent:方法處理事件接收
//用戶觸摸時(shí)第一時(shí)間加載內(nèi)容
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{
??? UIView*result = [super hitTest: point withEvent: event];
??? CGPoint buttonPoint = [_subjectButton convertPoint: point fromView: self];
??? if ([_subjectButton pointInside:buttonPointwithEvent:event]){
??????? return _subjectButton;
??? }
??? returnresult;
}
3.3 參考鏈接
[iOS Animation]-CALayer繪圖效率-異步繪制
http://my.oschina.net/u/2438875/blog/507545?fromerr=R4LnEaJ5
CGDataProviderCreateWithData對(duì)內(nèi)存數(shù)據(jù)的釋放
http://www.taofengping.com/2012/11/04/cgdataprovidercreatewithdata_memory_release/#.VnJQ6jaitZF
IOS中使用像素位圖(CGImageRef)對(duì)圖片進(jìn)行處理
http://my.oschina.net/u/2340880/blog/406437?p={{currentPage-1}}
4 Asyncdisplaykit
4.1 參考鏈接
Asyncdisplaykit指南(一)
http://www.th7.cn/Program/IOS/201410/302413.shtml
AsyncDisplayKit教程:達(dá)到60FPS的滾動(dòng)幀率
http://www.cocoachina.com/swift/20141124/10298.html
http://asyncdisplaykit.org/guide/
AsyncDisplayKit入門指南
http://www.cocoachina.com/ios/20141020/9975.html
5 開發(fā)技巧
5.1 常見問題
5.1.1 CGBitmapContextCreateImage繪制后內(nèi)存泄露導(dǎo)致內(nèi)存告警
????????CGBitmapContextCreateImage繪制的圖片會(huì)造成內(nèi)存無法釋放,應(yīng)該換用CGDataProviderCreateWithCFData扼劈。
5.1.1.1 方案一:修改源代碼姑子,入緩存前壓縮
http://my.oschina.net/u/1244672/blog/510379
SDWebImage有一個(gè)SDWebImageDownloaderOperation類來執(zhí)行下載操作的。里面有個(gè)下載完成的方法:
- (void)connectionDidFinishLoading:(NSURLConnection*)aConnection {
????SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock;
????@synchronized(self) {
????????CFRunLoopStop(CFRunLoopGetCurrent());
????????self.thread =?nil;
????????self.connection= nil;
????????[[NSNotificationCenter defaultCenter] postNotificationName: SDWebImageDownloadStopNotificati onobject: nil];
????}
????if (![[NSURLCache sharedURLCache] cachedResponseForRequest:_request]) {
????????responseFromCached= NO;
????}
? ? if(completionBlock)
????{
????if(self.options & SDWebImageDownloaderIgnoreCachedResponse &&responseFromCached) {
????????completionBlock(nil, nil, nil, YES);
????}
????else {
????????UIImage *image= [UIImage sd_imageWithData: self.imageData];
????????NSString *key= [[SDWebImageManager sharedManager] cacheKeyForURL: self.request.URL];
????????image = [self scaledImageForKey: key image: image];
????????// Do notforce decoding animated GIFs
????????if (!image.images) {
????????????image = [UIImage decodedImageWithImage: image];
????????}
????????if (CGSizeEqualToSize(image.size, CGSizeZero)) {
????????????completionBlock(nil, nil, [NSError errorWithDomain:@"SDWebImageErrorDomain" code:0userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0pixels"}], YES);
????????}
????????else {
????????????completionBlock(image, self.imageData, nil, YES);
????????}
????}
}
self.completionBlock= nil;
[self done];
}
其中测僵,UIImage*image = [UIImage sd_imageWithData:self.imageData];就是將data轉(zhuǎn)換成image。
再看看sd_imageWithData:這個(gè)方法:
+ (UIImage*)sd_imageWithData:(NSData *)data {
????UIImage*image;
????NSString*imageContentType = [NSData sd_contentTypeForImageData: data];
????if ([imageContentType isEqualToString:@"image/gif"]) {
????????image =[UIImage sd_animatedGIFWithData: data];
????}
#ifdefSD_WEBP
????else if([imageContentType isEqualToString:@"image/webp"])
????{
????????image =[UIImage sd_imageWithWebPData: data];
????}
#endif
????else {
????????image =[[UIImage alloc] initWithData: data];
????????UIImageOrientation orientation = [self sd_imageOrientationFromImageData: data];
????????if(orientation != UIImageOrientationUp) {
????????????image =[UIImage imageWithCGImage: image.CGImage scale: image.scale orientation: orientation];
????????}
????}
????return image;
}
????????這個(gè)方法在UIImage+MultiFormat里面谢翎,是UIImage的一個(gè)類別處理捍靠。這句話很重要image =[[UIImage alloc] initWithData: data]; SDWebImage把下載下來的data直接轉(zhuǎn)成image,然后沒做等比縮放直接存起來使用森逮。所以榨婆,我們只需要在這邊做處理即可:
UIImage+MultiFormat添加一個(gè)方法:
+(UIImage*)compressImageWith:(UIImage *)image
{
????float imageWidth = image.size.width;
????float imageHeight = image.size.height;
????float width =640;
????float height =image.size.height/(image.size.width/width);
????float widthScale = imageWidth /width;
????float heightScale = imageHeight /height;
????// 創(chuàng)建一個(gè)bitmap的context
????// 并把它設(shè)置成為當(dāng)前正在使用的context
????UIGraphicsBeginImageContext(CGSizeMake(width, height));
????if (widthScale> heightScale) {
????????[image drawInRect: CGRectMake(0, 0, imageWidth /heightScale , height)];
????}
????else {
????????[image drawInRect: CGRectMake(0, 0, width , imageHeight /widthScale)];
????}
????// 從當(dāng)前context中創(chuàng)建一個(gè)改變大小后的圖片
????UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
????// 使當(dāng)前的context出堆棧
????UIGraphicsEndImageContext();
????return newImage;
}
????然后在:image =[[UIImage alloc] initWithData: data];下面調(diào)用以下:
if (data.length/1024 > 1024) {
????image = [self compressImageWith: image];
}
????當(dāng)data大于1M的時(shí)候做壓縮處理。革命尚未成功褒侧,還需要一步處理良风。在SDWebImageDownloaderOperation的connectionDidFinishLoading方法里面的:
UIImage *image= [UIImage sd_imageWithData: self.imageData];
//將等比壓縮過的image在賦在轉(zhuǎn)成data賦給self.imageData
NSData *data =UIImageJPEGRepresentation(image, 1);
self.imageData = [NSMutableData dataWithData: data];
5.1.1.2 方案二:設(shè)置全局緩存大小
http://www.myexception.cn/swift/2033029.html
1谊迄、首先在appdelegate方法didFinishLaunchingWithOptions
SDImageCache.sharedImageCache().maxCacheSize=1024*1024*8設(shè)置一下最大的緩存大小。
2烟央、在appdelegate?applicationDidReceiveMemoryWarning里加入
SDImageCache.sharedImageCache().clearMemory()
SDWebImageManager.sharedManager().cancelAll()
5.1.1.3 方案三:定時(shí)清理內(nèi)存緩存
http://www.bubuko.com/infodetail-956863.html
????經(jīng)過嘗試统诺,發(fā)現(xiàn)了一個(gè)最簡(jiǎn)單的完美解決該問題的方法
????在使用SDWebImage加載較多圖片造成內(nèi)存警告時(shí),定期調(diào)用
?[[SDImageCache sharedImageCache] setValue:nilforKey:@"memCache"];
5.1.1.4 方案四(不推薦):修復(fù)SD庫代碼疑俭,不做解壓粮呢,直接返回壓縮的原圖
5.1.1.5 方案五(推薦):使用CGDataProviderRef進(jìn)行圖形解壓重繪
iOS開發(fā)中界面展示大圖片時(shí)UIImage的性能有關(guān)問題
http://www.myexception.cn/operating-system/578931.html
#import "SDWebImageDecoder.h"
@implementationUIImage (ForceDecode)
+ (UIImage*)decodedImageWithImage:(UIImage*)image {
??? if (image.images) {
???????// Do not decode animated images
???????return image;
??? }
??? UIImage *decompressedImage;
????@autoreleasepool{
????????//核心代碼,可以解決內(nèi)存未釋放問題
??????? NSData *data = UIImageJPEGRepresentation(image, 1);
??????? CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
??????? CGImageRef imageRef = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO, kCGRenderingIntentDefault);
????//??? CGImageRef imageRef = image.CGImage;
??? ????CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
??? ????CGRect imageRect = (CGRect){.origin = CGPointZero, .size=imageSize};
??? ????CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
??? ????CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
??????? int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
??? ????BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone || infoMask == kCGImageAlphaNoneSkipFirst || infoMask ==kCGImageAlphaNoneSkipLast);
??? ????// CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
??? ????//https://developer.apple.com/library/mac/#qa/qa1037/_index.html
??? ????if (infoMask == kCGImageAlphaNone&& CGColorSpaceGetNumberOfComponents(colorSpace)
> 1) {
??????? ????// Unset the old alpha info.
??????? ????bitmapInfo &= ~kCGBitmapAlphaInfoMask;
?? ?????????// Set noneSkipFirst.
??????? ????bitmapInfo |= kCGImageAlphaNoneSkipFirst;
??? ????}
??????????? // Some PNGs tell us they have alpha but only 3 components. Odd.
??? ????else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace)
== 3) {
??????? ????????// Unset the old alpha info.
??????? ????????bitmapInfo &= ~kCGBitmapAlphaInfoMask;
??????? ????????bitmapInfo |=kCGImageAlphaPremultipliedFirst;
??? ????????}
??? // It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
??? ????????CGContextRef context = CGBitmapContextCreate(NULL,
??????????? imageSize.width,
??????????? imageSize.height,
??????????? CGImageGetBitsPerComponent(imageRef), 0, colorSpace, bitmapInfo);
??? ????????CGColorSpaceRelease(colorSpace);
??? ????????// If failed, return undecompressed image
??? ????????if (!context) return image;
??? ????????CGContextDrawImage(context, imageRect, imageRef);
??? ????????CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
??????????? CGContextRelease(context);
??? ????????decompressedImage = [UIImage imageWithCGImage: decompressedImageRef scale: image.scale orientation: image.imageOrientation];
??? ????????CGImageRelease(decompressedImageRef);
? ? ? ?}
????????//??? CVPixelBufferRef pixelBuffer;? ?
????????//???CreateCGImageFromCVPixelBuffer(pixelBuffer,&decompressedImageRef);
????????//??? CGImage *cgImage =CGBitmapContextCreateImage(context);
????????//??? CFDataRef dataRef =CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
????????//??? CGImageRelease(cgImage);
????????//??? image->imageRef = dataRef;
????????//??? image->image = CFDataGetBytePtr(dataRef);
??? return decompressedImage;
}
5.1.2 UIImage自定義繪制的四種方法
///方法中會(huì)自動(dòng)做縮放處理
+(void) getBitmapImage: (UIImage *)image Size: (CGSize)imageSize WithCompletionBlock:(HJCallbackBlock)block
{
? ? ? ?dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
??????? ????UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0);
??????? ????CGContextRef context = UIGraphicsGetCurrentContext();
??????? ????if(!context) {
??????????? ????dispatch_async(dispatch_get_main_queue(), ^{
??????????????? ????block(image);
??????????? ????});
??????? ????}
??????? ????CGRect rect = CGRectMake(0, 0, imageSize.width, imageSize.height);
??????? ????//坐標(biāo)系統(tǒng)已經(jīng)自動(dòng)考慮了縮放因素钞艇,不需要額外處理
??????? ????[image drawInRect: rect blendMode: kCGBlendModeNormal alpha:1];
??????? ????UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();
??????? ????NSData *tempData = UIImageJPEGRepresentation(temp, 1);
??????? ????UIGraphicsEndImageContext();
??????? ????//設(shè)置SDWebImage庫的緩存
??????? ????NSString *device = [HJUtility getCurDeviceModel];
??????? ????if ([device rangeOfString:@"iPhone 4"].length > 0) {
??????????? ????if (tempData.length > 500000) {
??????????????? ????tempData =UIImageJPEGRepresentation(temp, 0.4);
??????????????? }
??????????? ????temp = [UIImage imageWithData: tempData];
??????? }
??????? dispatch_async(dispatch_get_main_queue(), ^{
??????????? if(block) {
??????????????? block(temp);
??????????? }
??????? });
??? });
??? //方案二啄寡,內(nèi)存有釋放,掛機(jī)
??? //???UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
??? //
??? //???CGContextRef context = UIGraphicsGetCurrentContext();
??? //???CGRect rect = CGRectMake(0, 0, imageSize.width * [UIScreenmainScreen].scale, imageSize.height * [UIScreen mainScreen].scale);
??? //???// draw alpha-mask
??? ////???CGContextSetBlendMode(context, kCGBlendModeNormal);
??? //???CGContextDrawImage(context, rect, image.CGImage);
??? //???// draw tint color, preserving alpha values of original image
??? ////???CGContextSetBlendMode(context, kCGBlendModeSourceIn);
??? //
??? //???CGContextFillRect(context, rect);
??? //
??? //???//Set the original greyscale template as the overlay of the new image
??? //???UIImage *imgData = [self verticallyFlipImage:image];
??? //???[imgData drawInRect:imageRect];
??? //???UIImage *colouredImage = UIGraphicsGetImageFromCurrentImageContext();
??? //???UIGraphicsEndImageContext();
??? //???colouredImage = [self verticallyFlipImage:colouredImage];
??? //?? ?CGContextRelease(context);
??? //???return colouredImage;
??? //方案三哩照,CGBitmapContextCreate方案挺物,內(nèi)存沒釋放
??? //???CGFloat targetWidth = imageSize.width * [UIScreen mainScreen].scale;
??? //???CGFloat targetHeight = imageSize.height * [UIScreen mainScreen].scale;
??? //???CGImageRef imageRef = [image CGImage];
??? //???CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
??? //???CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
??? //???CGContextRef bitmapContext;
??? //???bitmapContext = CGBitmapContextCreate(NULL, targetWidth,targetHeight,CGImageGetBitsPerComponent(imageRef),CGImageGetBytesPerRow(imageRef),colorSpaceInfo, bitmapInfo);
??? //???CGContextDrawImage(bitmapContext, CGRectMake(0, 0, targetWidth,targetHeight), imageRef);
??? //
??? //???CGImageRef imgref = CGBitmapContextCreateImage(bitmapContext);
??? //???UIImage* newImage = [UIImage imageWithCGImage:imgref];
??? //
??? //???CGColorSpaceRelease(colorSpaceInfo);
??? //???CGContextRelease(bitmapContext);
??? //???CGImageRelease(imgref);
??? //
??? //???return newImage;
??? //方案四,CGBitmapContextCreate方案飘弧,但是采用CGDataProviderCreateWithCFData方案解決內(nèi)存占用問題
??? //???NSData *data = UIImageJPEGRepresentation(image, 1);
??? //???CGDataProviderRef dataProvider =CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
??? //???CGImageRef imageRef = CGImageCreateWithJPEGDataProvider(dataProvider,
??? //??????????????????????????????????????????????????????????NULL, NO,
??? //??????????????? ???????????????????????????????????????????kCGRenderingIntentDefault);
??? //
??? //???CGFloat targetWidth = imageSize.width * [UIScreen mainScreen].scale;
??? //???CGFloat targetHeight = imageSize.height * [UIScreen mainScreen].scale;
??? //???//????? ??CGImageRef imageRef = [image CGImage];
??? //
??? //???CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
??? //
??? //???CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
??? //???CGContextRef bitmapContext;
??? //???bitmapContext = CGBitmapContextCreate(NULL, targetWidth,targetHeight,CGImageGetBitsPerComponent(imageRef),0, colorSpaceInfo,bitmapInfo);
??? //???CGContextDrawImage(bitmapContext, CGRectMake(0, 0, targetWidth,targetHeight), imageRef);
??? //
??? //???// If failed, return undecompressed image
??? //???if (!bitmapContext) return image;
??? //
??? //???CGImageRef imgref = CGBitmapContextCreateImage(bitmapContext);
??? //???UIImage* newImage = [UIImage imageWithCGImage:imgref];//[UIImageimageWithCGImage:decompressedImageRef scale:image.scaleorientation:image.imageOrientation];
??? //???
??? //???CGColorSpaceRelease(colorSpaceInfo);
??? //???CGContextRelease(bitmapContext);
??? //???CGImageRelease(imgref);
??? //???
??? //???return newImage;
}
5.1.3 繪制時(shí)單元格底部出現(xiàn)高度不定的細(xì)微黑線
問題原因:
?????? 將Text做寬高計(jì)算時(shí)识藤,高度值容易得出小數(shù)數(shù)值,而頁面繪制均是基于整數(shù)像素點(diǎn)繪制眯牧,對(duì)于小數(shù)點(diǎn)部分蹋岩,系統(tǒng)會(huì)做舍去處理(即便有縮放),固留下高度不定的未繪制區(qū)域(為黑色)学少。
解決方案:
?????? 將計(jì)算出來的高度值做向下取整處理即可剪个。
CGRect labelFrame = [content boundingRectWithSize: size options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:_postContentTextView.typingAttributes context: nil];
labelSize = labelFrame.size;
labelSize.height = ceilf(labelSize.height);
6 參考鏈接
(GOOD)iOS開發(fā)中界面展示大圖片時(shí)UIImage的性能有關(guān)問題
http://www.myexception.cn/operating-system/578931.html
(Good)iPhone - UIImage Leak, CGBitmapContextCreateImage Leak
http://stackoverflow.com/questions/1427478/iphone-uiimage-leak-cgbitmapcontextcreateimage-leak
Another iPhone - CGBitmapContextCreateImage Leak
http://stackoverflow.com/questions/1434714/another-iphone-cgbitmapcontextcreateimage-leak
UIGraphicsBeginImageContext vs CGBitmapContextCreate
http://stackoverflow.com/questions/4683448/uigraphicsbeginimagecontext-vs-cgbitmapcontextcreate
iPhone - CGBitmapContextCreateImage Leak, Anyone else withthis problem?
Build and Analyze false positive on leak detection?
http://stackoverflow.com/questions/8438249/build-and-analyze-false-positive-on-leak-detection
iPhone - Multiple CGBitmapContextCreateImage Calls -ObjectAlloc climbing
(Good)ios開發(fā)圖片處理,內(nèi)存泄露
http://www.oschina.net/question/736524_69802
主題:CGBitmapContextCreateImage(bitmap)內(nèi)存泄露問題處理
http://www.cocoachina.com/bbs/read.php?tid=31835
iOS異步圖片加載優(yōu)化與常用開源庫分析
http://luoyibu.com/2015/05/12/iOS異步圖片加載優(yōu)化與常用開源庫分析/
主題:圖片處理開源函數(shù)ImageProcessing? CGDataProviderCreateWithData Bug修復(fù)
http://www.cocoachina.com/bbs/read.php?tid=116149
CGDataProviderCreateWithData對(duì)內(nèi)存數(shù)據(jù)的釋放
http://www.taofengping.com/2012/11/04/cgdataprovidercreatewithdata_memory_release/#.VmpqgoSitZE
IOS7.x下UIGraphicsGetImageFromCurrentImageContext引發(fā)內(nèi)存暴漲版确,導(dǎo)致應(yīng)用被結(jié)束掉
http://blog.163.com/l1_jun/blog/static/1438638820155593641529/
在iOS中與CGContextRef的內(nèi)存泄漏
http://www.itstrike.cn/Question/55b86ce7-dfba-4548-a103-22dc5317420a.html
使用AFNetworking, SDWebimage和OHHTTPStubs
http://blog.shiqichan.com/using-afnetworking-sdwebimage-and-ohhttpstubs/
SDWebImage緩存圖片的機(jī)制(轉(zhuǎn))
http://blog.csdn.net/zhun36/article/details/8900327
近來一個(gè)swift項(xiàng)目用uicollectionview 用sdwebimage 加載圖片扣囊,發(fā)生內(nèi)存猛增,直接閃退的情況绒疗,簡(jiǎn)單說一下解決方案
http://www.myexception.cn/swift/2033029.html
關(guān)于SDWebImage加載高清圖片導(dǎo)致app崩潰的問題
http://www.bubuko.com/infodetail-956863.html
SDWebImage加載大圖導(dǎo)致的內(nèi)存警告問題
http://blog.csdn.net/richer1997/article/details/43481959
解決MWPhotoBrowser中的SDWebImage加載大圖導(dǎo)致的內(nèi)存警告問題
http://my.oschina.net/u/1244672/blog/510379
使用SDWebImage加載大量圖片后造成內(nèi)存泄露的解決辦法
http://www.bubuko.com/infodetail-985746.html
UIGraphicsBeginImageContext系列知識(shí)
http://blog.sina.com.cn/s/blog_5fb39f9101017n1v.html
iOS繪圖教程
http://blog.csdn.net/nogodoss/article/details/18660153
CGBitmapContextCreate函數(shù)
http://blog.csdn.net/thanklife/article/details/25790433
UIGraphicsBeginImageContext創(chuàng)建的映像停留在內(nèi)存中永恒
多次在cell中加載網(wǎng)絡(luò)圖片后侵歇,內(nèi)存增長(zhǎng),以前資源未釋放
http://bbs.csdn.net/topics/390891681
請(qǐng)問下面的代碼有潛在的內(nèi)存泄漏吓蘑?
[ios]UIGraphicsGetImageFromCurrentImageContext()-內(nèi)存泄漏
http://www.itstrike.cn/Question/88ada9bd-911c-44a7-874b-e04c1a1c2bca.html
[轉(zhuǎn)載]ios開發(fā)之View屬性hidden, opaque, alpha的區(qū)別
http://blog.sina.com.cn/s/blog_7da2c9030101ev8n.html
利用預(yù)渲染加速iOS設(shè)備的圖像顯示
http://www.keakon.net/2011/07/26/利用預(yù)渲染加速iOS設(shè)備的圖像顯示
iOS使用CGContextRef繪制各種圖形
http://www.devstore.cn/essay/essayInfo/116.html
iOS CGContextRef畫圖小結(jié)
http://blog.sina.com.cn/s/blog_9693f61a0101deko.html
IOS用CGContextRef畫各種圖形(文字惕虑、圓、直線磨镶、弧線溃蔫、矩形、扇形琳猫、橢圓伟叛、三角形、圓角矩形脐嫂、貝塞爾曲線统刮、圖片)
http://blog.csdn.net/rhljiayou/article/details/9919713
iOS畫圖 以及清空
http://blog.csdn.net/woshidaniu/article/details/46683409
7 Quartz 2D
7.1 參考鏈接
iOS通過Quartz畫矩形紊遵、文字、線
http://blog.csdn.net/onlyou930/article/details/7726399
Quartz 2D參考-文本
http://blog.csdn.net/kmyhy/article/details/7258338
Quartz 2D (ProgrammingWithQuartz) note