zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    使用eclipse创建maven+动态web的项目
    关于Maven项目build时出现No compiler is provided in this environment的处理
    spark日志输出
    spark并行度加载关系数据库
    【java记录】序列化拷贝
    客户端远程访问高可用(HA)hdfs
    spark算法
    算子的分类和 宽依赖算子、窄依赖算子
    单元测试junit使用
    spark1.x和spark2.x兼容Iterable和Iterator问题【未解决】
  • 原文地址:https://www.cnblogs.com/silence-cnblogs/p/7307554.html
Copyright © 2011-2022 走看看