UIKit

UIKit - UIImage

2020-04-20  本文已影响0人  ienos

通过颜色获取图片

extension UIColor {
    
    /// 通过颜色获取纯色图片
    func convertImage(withSize size: CGSize, cornerRadius: CGFloat?) -> UIImage? {
        
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        guard let context: CGContext = UIGraphicsGetCurrentContext() else { return nil }

        /// 添加圆角
        if let radius = cornerRadius {
            let path = UIBezierPath(roundedRect: rect, cornerRadius: radius)
            path.addClip()
        }
        
        context.setFillColor(self.cgColor)
        context.fill(rect)
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        
        UIGraphicsEndImageContext()
        
        return image
    }
    
}

图片处理获取图片的一部分

UIImage *image = [UIImage imageNamed:filename];
CGImageRef imageRef = image.CGImage;
CGRect rect = CGRectMake(origin.x, origin.y ,size.width, size.height);
//这里的宽高是相对于图片的真实大小
//比如你的图片是400x400的那么(0,0,400,400)就是图片的全尺寸,想取哪一部分就设置相应坐标即可
CGImageRef imageRefRect = CGImageCreateWithImageInRect(imageRef, rect);
return [[UIImage alloc] initWithCGImage:imageRefRect];

改变图片大小不影响质量

- (UIImage*)scaleToSize:(CGSize)size {

    //Determine whether the screen is retina
    if([[UIScreen mainScreen] scale] == 2.0){
        UIGraphicsBeginImageContextWithOptions(size, NO, 2.0);
    }else{
        UIGraphicsBeginImageContext(size);
    }
    // 绘制改变大小的图片
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();        // 返回新的改变大小后的图片

    return scaledImage;
}

UIImage 两种加载方式的区别

imageNamed: 这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象。因此 imageNamed: 的优点是当加载时会缓存图片。所以当图片会频繁的使用时,那么用 imageNamed:的方法会比较好。

例如:你需要在一个 TableView 里的 TableViewCell 里都加载同样一个图标,那么用 imageNamed:加载图像效率很高。系统会把那个图标 Cache 到内存,在 TableViewCell 里每次利用那个图像的时候,只会把图片指针指向同一块内存。正是因此使用 imageNamed: 会缓存图片,即将图片的数据放在内存中,iOS 的内存非常珍贵并且在内存消耗过大时,会强制释放内存,即会遇到 memory warnings。而在 iOS 系统里面释放图像的内存是一件比较麻烦的事情,有可能会造成内存泄漏。

例如:当一个 UIView 对象的 animationImages 是一个装有 UIImage 对象动态数组 NSMutableArray,并进行逐帧动画。当使用 imageNamed: 的方式加载图像到一个动态数组 NSMutableArray,这将会很有可能造成内存泄露。原因很显然的。imageWithContentsOfFile: 仅加载图片,图像数据不会缓存。因此对于较大的图片以及使用情况较少时,那就可以用该方法,降低内存消耗。下面列举出两种方法的详细用法:

NSString *path = [[NSBundle mainBundle] pathForResource:@”icon” ofType:@”png”];
UIImage *image = [UIImage imageWithContentsOfFile:path];
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:“png”];
NSData *image = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [UIImage imageWithData:image]; //or = [UIImage imageWithContentsOfFile:filePath];关键,在于imageWithContentsOfFile:仅加载图片,图像数据不会缓存, 而imageNamed:先将图片缓存到内存中,然后在显示。

注意: Images.xcassets 中的图片资源只能通过 imageNamed: 方法加载,无法通过 NSBundlepathForResource:ofType: 获取。因此,Images.xcassets 只适合存放系统常用的,占用内存小的图片资源。
imageNamed: 方法同样可以加载根目录中的图片资源。要想利用 imageWithContentsOfFile: 方法以不缓存的形式加载图片,必须将图片资源放置在根目录中。

图片抗锯齿

抗锯齿: 也称边缘化,它是一种消除显示器输出的画面中图物边缘出现凹凸锯齿的技术

采用抗锯齿技术会降低动画帧数

方法1: 添加透明边,抗锯齿能力一般,用于iOS6及6以前,帧数一般。

- (UIImage *)antiAlias
{
    CGFloat border = 1.0f;
    CGRect rect = CGRectMake(border, border, self.size.width-2*border, self.size.height-2*border);
    UIImage *img = nil;

    UIGraphicsBeginImageContext(CGSizeMake(rect.size.width,rect.size.height));
    [self drawInRect:CGRectMake(-1, -1, self.size.width, self.size.height)];
    img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIGraphicsBeginImageContext(self.size);
    [img drawInRect:rect];
    UIImage* antiImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return antiImage;
}

方法2: 直接修改属性,抗锯齿能力好,用于 iOS 7及7之后,帧数较差。

layer.allowsEdgeAntialiasing = true
上一篇 下一篇

猜你喜欢

热点阅读