iOS 使用矢量圖


更多圖片處理方法見圖片組件 BBWebImage

iOS 使用矢量圖

iOS 圖標通常用 PNG 格式的圖片。PNG 圖片放大到超過自身的大小就會模糊。可以使用 PDF 格式的矢量圖,優點是任意改變圖片大小並且保持清晰度。

簡單使用

與 PNG 格式的圖片一樣,在 Xcode 中把 PDF 格式的矢量圖拖進 *.xcassets (默認是 Assets.xcassets) 文件夾中,然后用不帶后綴(.pdf)的文件名生成 UIImage

imageView.image = [UIImage imageNamed:@"Vector"];

注意,如果以上代碼用 "Vector.pdf",無法得到 UIImage。

這樣做的話,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 里。

#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

使用方法

// 保持原圖寬高比
imageView.image = [UIImage vectorImageWithName:@"Vector" size:CGSizeMake(50, 50)];
// 拉伸圖片,忽略原圖寬高比
imageView.image = [UIImage vectorImageWithName:@"Vector"
										  size:CGSizeMake(50, 50)
									   stretch:YES];

參考

http://lugede.cn/ios-use-vector-pdf-image

https://github.com/jiisd/YHPDFImageLoader

轉載請注明出處:http://www.cnblogs.com/silence-cnblogs/p/7307554.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM