更多圖片處理方法見圖片組件 BBWebImagehtml
iOS 圖標一般用 PNG 格式的圖片。PNG 圖片放大到超過自身的大小就會模糊。能夠使用 PDF 格式的矢量圖,優勢是任意改變圖片大小而且保持清晰度。ios
與 PNG 格式的圖片同樣,在 Xcode 中把 PDF 格式的矢量圖拖進 *.xcassets (默認是 Assets.xcassets) 文件夾中,而後用不帶後綴(.pdf)的文件名生成 UIImagegit
imageView.image = [UIImage imageNamed:@"Vector"];
注意,若是以上代碼用 "Vector.pdf",沒法獲得 UIImage。github
這樣作的話,Xcode 會在編譯時根據 PDF 圖的大小生成 @1x、@2x、@3x 的 PNG 圖片,與使用 PNG 圖片的顯示效果相同。若是把圖片放大到超過 PNG 圖片的大小,則會顯示模糊的圖片。沒有發揮矢量圖能夠任意調整大小的優勢。緩存
若是須要改變矢量圖大小而且保持清晰度,那就要解析 PDF 源文件,把矢量圖繪製成所需大小的位圖(Bitmap)。YHPDFImageLoader 庫就實現了這個功能,而且能夠選擇拉伸圖片時是否保持原圖寬高比,還添加了內存和磁盤緩存。解析 PDF 並繪製位圖的代碼在 YHPDFImageDraw.m 文件的 drawImageWithURL:size:canStretched:page: 方法中。可是那些代碼有 bug,在保持原圖寬高比的時候,繪製出的位圖不居中。這裏參照那些代碼,寫了 UIImage 的 Category,用於解析 PDF 源文件,繪製指定大小的位圖;能夠選擇拉伸圖片時是否保持原圖寬高比;拉伸時保持圖片居中。注意,這裏的 PDF 文件放在工程目錄中,與 *.m、*.h 文件同樣,不能放在 *.xcassets 裏。url
#import "UIImage+Vector.h" @implementation UIImage (Vector) + (UIImage *)vectorImageWithName:(NSString *)name size:(CGSize)size { // 默認保持原圖寬高比 return [self vectorImageWithName:name size:size stretch:NO]; } + (UIImage *)vectorImageWithName:(NSString *)name size:(CGSize)size stretch:(BOOL)stretch { // PDF 文件路徑 NSString *path = [NSBundle.mainBundle pathForResource:name ofType:@"pdf"]; NSAssert(path, @"Vector image file path should NOT be nil"); if (!path) return nil; return [self vectorImageWithURL:[NSURL fileURLWithPath:path] size:size stretch:stretch page:1]; } // url: PDF 文件 URL // size: 所需繪製圖片大小;若是須要繪製原圖大小,用 CGSizeZero // stretch: 是否拉伸;YES,拉伸圖片,忽略原圖寬高比;NO,保持原圖寬高比 + (UIImage *)vectorImageWithURL:(NSURL *)url size:(CGSize)size stretch:(BOOL)stretch page:(NSUInteger)page { CGFloat screenScale = UIScreen.mainScreen.scale; // PDF 源文件 CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithURL((__bridge CFURLRef)url); // PDF 中的一頁 CGPDFPageRef imagePage = CGPDFDocumentGetPage(pdfRef, page); // PDF 這一頁顯示出來的 CGRect CGRect pdfRect = CGPDFPageGetBoxRect(imagePage, kCGPDFCropBox); // 傳入的大小若是爲零,使用 PDF 原圖大小 CGSize contextSize = (size.width <= 0 || size.height <= 0) ? pdfRect.size : size; // RGB 顏色空間 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // 位圖上下文 CGContextRef context = CGBitmapContextCreate(NULL, contextSize.width * screenScale, contextSize.height * screenScale, 8, 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); // 座標縮放,增長清晰度 CGContextScaleCTM(context, screenScale, screenScale); if (size.width > 0 && size.height > 0) { // 指定圖片大小,須要縮放圖片 // 計算寬高縮放比 CGFloat widthScale = size.width / pdfRect.size.width; CGFloat heightScale = size.height / pdfRect.size.height; if (!stretch) { // 保持原圖寬高比,使用寬高縮放比中的最小值 heightScale = MIN(widthScale, heightScale); widthScale = heightScale; // 座標平移,使圖片居中 CGFloat currentRatio = size.width / size.height; CGFloat realRatio = pdfRect.size.width / pdfRect.size.height; if (currentRatio < realRatio) { CGContextTranslateCTM(context, 0, (size.height - size.width / realRatio) / 2); } else { CGContextTranslateCTM(context, (size.width - size.height * realRatio) / 2, 0); } } // 用以上寬高縮放比縮放座標 CGContextScaleCTM(context, widthScale, heightScale); } else { // 使用原圖大小 // 獲取原圖座標轉換矩陣,用於位圖上下文 CGAffineTransform drawingTransform = CGPDFPageGetDrawingTransform(imagePage, kCGPDFCropBox, pdfRect, 0, true); CGContextConcatCTM(context, drawingTransform); } // 把 PDF 中的一頁繪製到位圖 CGContextDrawPDFPage(context, imagePage); CGPDFDocumentRelease(pdfRef); // 建立 UIImage CGImageRef image = CGBitmapContextCreateImage(context); UIImage *pdfImage = [[UIImage alloc] initWithCGImage:image scale:screenScale orientation:UIImageOrientationUp]; // 釋放資源 CGImageRelease(image); CGContextRelease(context); CGColorSpaceRelease(colorSpace); return pdfImage; } @end
使用方法code
// 保持原圖寬高比 imageView.image = [UIImage vectorImageWithName:@"Vector" size:CGSizeMake(50, 50)]; // 拉伸圖片,忽略原圖寬高比 imageView.image = [UIImage vectorImageWithName:@"Vector" size:CGSizeMake(50, 50) stretch:YES];
參考orm
http://lugede.cn/ios-use-vector-pdf-imagehtm
https://github.com/jiisd/YHPDFImageLoaderblog
轉載請註明出處:http://www.cnblogs.com/silence-cnblogs/p/7307554.html