IOS:聊一聊UIImage几点知识

简介: IOS:聊一聊UIImage几点知识      有一段时间没有写博客了,中间隔了个五一假,算一下差不多20天,这段时间准备组内的一个分享,所以就耽搁了,今天准备写一些UIImage方面的东西。   UIImage是IOS中层级比较高的一个用来加载和绘制图像的一个类,更底层的类还有CGImage,以及IOS5.0以后新增加的CIImage。

IOS:聊一聊UIImage几点知识

  

  有一段时间没有写博客了,中间隔了个五一假,算一下差不多20天,这段时间准备组内的一个分享,所以就耽搁了,今天准备写一些UIImage方面的东西。

  UIImage是IOS中层级比较高的一个用来加载和绘制图像的一个类,更底层的类还有CGImage,以及IOS5.0以后新增加的CIImage。今天我们主要聊一聊UIImage的三个属性: imageOrientation, size, scale,几个初始化的方法: imageNamed,imageWithContentsOfFile,以及绘制Image的几个draw开头的方法。

 

一、UIImage的size,scale属性

  先想一个问题“一个图像的尺寸到底是多大呢?”

  第一反应可能就是image.size,恭喜你答错了,正确的答案是图像的实际的尺寸(像素)等于image.size乘以image.scale。如果做过界面贴图的话你可能经常会需要准备至少两套图,一套1倍图,一套图已@2x命名的二倍图。这样当我们的程序运行在retina屏幕的时候系统就会自动的去加载@2x的图片,它的size将和一倍图加载进来的size相等,但是scale却置为2,这点大家可以做个简单的小测试验证一下。然我们再深入一点儿为什么不直接加载到成二倍的尺寸呢,原因很简单因为我们在界面布局中逻辑坐标系中的(单位是point),而实际的绘制都是在设备坐标系(单位是pixel)进行的,系统会自动帮我们完成从point到pixel之间的转化。其实这个比例也就刚好和UIScreen中的scale对应,这样整条scale的线就可以串通了。

 

二、UIImage的几种初始化方法的对比

  1、imageNamed:方法

    imageNamed:是UIImage的一个类方法,它做的事情比我们看到的要稍微多一些。它的加载流程如下:

    a. 系统回去检查系统缓存中是否存在该名字的图像,如果存在则直接返回。

    b. 如果系统缓存中不存在该名字的图像,则会先加载到缓存中,在返回该对象。

  观察上面的操作我们发现系统会缓存我们使用imageNamed:方法加载的图像时候,系统会自动帮我们缓存。这种机制适合于那种频繁用到界面贴图累的加载,但如果我们需要短时间内频繁的加载一些一次性的图像的话,最好不要使用这种方法。

  2、imageWithContentsOfFile:和initWithContentsOfFile:方法

  这两个方法跟前一个方法一样都是完成从文件加载图像的功能。但是不会经过系统缓存,直接从文件系统中加载并返回。

  顺便提一下,当收到内存警告的时候,系统可能会将UIImage内部的存储图像的内存释放,下一次需要绘制的时候会重新去加载。

  3、imageWithCGImage:scale:orientation:方法

  该方面使用一个CGImageRef创建UIImage,在创建时还可以指定方法倍数以及旋转方向。当scale设置为1的时候,新创建的图像将和原图像尺寸一摸一样,而orientaion则可以指定新的图像的绘制方向。

 

三、UIImage的imageOrientation属性

   UIImage有一个imageOrientation的属性,主要作用是控制image的绘制方向,共有以下8中方向:

typedef NS_ENUM(NSInteger, UIImageOrientation) {
    UIImageOrientationUp,            // default orientation    
    UIImageOrientationDown,          // 180 deg rotation       
    UIImageOrientationLeft,          // 90 deg CCW          (编程发现官方文档中,left和right图像标反了,此处更正过来)
    UIImageOrientationRight,         // 90 deg CW         
    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip   
    UIImageOrientationDownMirrored,  // horizontal flip                             
    UIImageOrientationLeftMirrored,  // vertical flip                              
    UIImageOrientationRightMirrored, // vertical flip                              
};

  默认的方向是UIImageOrientationUp,这8种方向对应的绘制方如上面所示。我们在日常使用中经常会碰到把iPhone相册中的照片导入到windows中,发现方向不对的问题就是与这个属性有关,因为导出照片的时候,写exif中的方向信息时候没有考虑该方向的原因。既然这个属性可以控制image的绘制方向,那我们能不能通过改过这个属性来完成UIImage的旋转和翻转呢?带着这个问题我们继续往下看。

 

四、UIImage的几个draw方法

  UIImage的几个draw方法是用来绘制图像的利器,为什么这样说呢?因为它们在绘制图像的时候会考虑当前图像的方向,即根据的imageOrientation绘制出不同的方向。由于图像是绘制在当前context中的,它同时还会考虑到当前context的transform的变化。利于这两点我们就可以玩转图像的旋转和翻转了。

  搜索了一些,目前网上大部分图像旋转都是通过创建CGBitmapContext,然后根据图像方向设置context的transform来实现的,这种方法要求对整个矩阵变化的过程都非常清楚,一个参数设置不多,出来的结果就会有问题。

  下面我介绍一种实现起来简单方便的图像旋转方法,这种方法主要就是利用imageWithCGImage:scale:orientation:方法,指定不同的orientation来完成所需要的功能,先举个简单的例子:

  假设一副图片显示为 ,我们要向左旋转90°,那么转过之后应该就会显示为,即将原图从orientationUP转到orientationLeft即可。以此类推为不同的方向旋转,只需要注意看R的显示即可,这样整个旋转和翻转的实现过程中完全可以不用考虑Transform那些东西,是不是很简单。

  下面是图像旋转和翻转的完整代码:

//
//  UIImage+Rotate_Flip.h
//  SvImageEdit
//
//  Created by  maple on 5/14/13.
//  Copyright (c) 2013 smileEvday. All rights reserved.
//
// 

#import <UIKit/UIKit.h>

@interface UIImage (Rotate_Flip)

/*
 * @brief rotate image 90 withClockWise
 */
- (UIImage*)rotate90Clockwise;

/*
 * @brief rotate image 90 counterClockwise
 */
- (UIImage*)rotate90CounterClockwise;

/*
 * @brief rotate image 180 degree
 */
- (UIImage*)rotate180;

/*
 * @brief rotate image to default orientation
 */
- (UIImage*)rotateImageToOrientationUp;

/*
 * @brief flip horizontal
 */
- (UIImage*)flipHorizontal;

/*
 * @brief flip vertical
 */
- (UIImage*)flipVertical;

/*
 * @brief flip horizontal and vertical
 */
- (UIImage*)flipAll;


@end
UIImage+Rotate_Flip.h
//
//  UIImage+Rotate_Flip.m
//  SvImageEdit
//
//  Created by  maple on 5/14/13.
//  Copyright (c) 2013 smileEvday. All rights reserved.
//

#import "UIImage+Rotate_Flip.h"

@implementation UIImage (Rotate_Flip)

/*
 * @brief rotate image 90 with CounterClockWise
 */
- (UIImage*)rotate90CounterClockwise
{
    UIImage *image = nil;
    switch (self.imageOrientation) {
        case UIImageOrientationUp:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeft];
            break;
        }
        case UIImageOrientationDown:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRight];
            break;
        }
        case UIImageOrientationLeft:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDown];
            break;
        }
        case UIImageOrientationRight:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUp];
            break;
        }
        case UIImageOrientationUpMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRightMirrored];
            break;
        }
        case UIImageOrientationDownMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeftMirrored];
            break;
        }
        case UIImageOrientationLeftMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUpMirrored];
            break;
        }
        case UIImageOrientationRightMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDownMirrored];
            break;
        }
        default:
            break;
    }
    
    return image;
}

/*
 * @brief rotate image 90 with Clockwise
 */
- (UIImage*)rotate90Clockwise
{
    UIImage *image = nil;
    switch (self.imageOrientation) {
        case UIImageOrientationUp:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRight];
            break;
        }
        case UIImageOrientationDown:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeft];
            break;
        }
        case UIImageOrientationLeft:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUp];
            break;
        }
        case UIImageOrientationRight:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDown];
            break;
        }
        case UIImageOrientationUpMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeftMirrored];
            break;
        }
        case UIImageOrientationDownMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRightMirrored];
            break;
        }
        case UIImageOrientationLeftMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDownMirrored];
            break;
        }
        case UIImageOrientationRightMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUpMirrored];
            break;
        }
        default:
            break;
    }
    
    return image;
}

/*
 * @brief rotate image 180 degree
 */
- (UIImage*)rotate180
{
    UIImage *image = nil;
    switch (self.imageOrientation) {
        case UIImageOrientationUp:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDown];
            break;
        }
        case UIImageOrientationDown:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUp];
            break;
        }
        case UIImageOrientationLeft:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRight];
            break;
        }
        case UIImageOrientationRight:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeft];
            break;
        }
        case UIImageOrientationUpMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDownMirrored];
            break;
        }
        case UIImageOrientationDownMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUpMirrored];
            break;
        }
        case UIImageOrientationLeftMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRightMirrored];
            break;
        }
        case UIImageOrientationRightMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeftMirrored];
            break;
        }
        default:
            break;
    }
    
    return image;
}

/*
 * @brief rotate image to default orientation
 */
- (UIImage*)rotateImageToOrientationUp
{
    CGSize size = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale);
    UIGraphicsBeginImageContext(size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height));
    
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

/*
 * @brief flip horizontal
 */
- (UIImage*)flipHorizontal
{
    UIImage *image = nil;
    switch (self.imageOrientation) {
        case UIImageOrientationUp:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUpMirrored];
            break;
        }
        case UIImageOrientationDown:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDownMirrored];
            break;
        }
        case UIImageOrientationLeft:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRightMirrored];
            break;
        }
        case UIImageOrientationRight:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeftMirrored];
            break;
        }
        case UIImageOrientationUpMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUp];
            break;
        }
        case UIImageOrientationDownMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDown];
            break;
        }
        case UIImageOrientationLeftMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRight];
            break;
        }
        case UIImageOrientationRightMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeft];
            break;
        }
        default:
            break;
    }
    
    return image;
}

/*
 * @brief flip vertical
 */
- (UIImage*)flipVertical
{
    UIImage *image = nil;
    switch (self.imageOrientation) {
        case UIImageOrientationUp:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDownMirrored];
            break;
        }
        case UIImageOrientationDown:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUpMirrored];
            break;
        }
        case UIImageOrientationLeft:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeftMirrored];
            break;
        }
        case UIImageOrientationRight:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRightMirrored];
            break;
        }
        case UIImageOrientationUpMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationDown];
            break;
        }
        case UIImageOrientationDownMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationUp];
            break;
        }
        case UIImageOrientationLeftMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationLeft];
            break;
        }
        case UIImageOrientationRightMirrored:
        {
            image = [UIImage imageWithCGImage:self.CGImage scale:1 orientation:UIImageOrientationRight];
            break;
        }
        default:
            break;
    }
    
    return image;
}

/*
 * @brief flip horizontal and vertical
 */
- (UIImage*)flipAll
{
    return [self rotate180];
}

@end
UIImage+Rotate_Flip.m

  以上只是实现了图像的顺时针90°,逆时针90°,180°旋转,以及水平翻转,数值翻转等。至于任意角度旋转怎么实现?其实也很简单,留着给大家思考吧。虽然我们可以通过orientation这种方法简单的完成图像旋转,但是如果有时间的话还是建议大家尽量的看一下那种通过transform来完成旋转的代码,你会彻底搞清楚旋转矩阵是怎么回事儿。当然程序中使用的时候推荐使用我上面提供的这种方法,因为不涉及真实的旋转操作,速度会快很多。

  通过上面的小例子,我们可以看出越高级别的API帮助我们做的事情就越多,越底层的API提供了更多的灵活性,但同时也带来了很多需要我们处理的东西。再编程的过程中尽量的使用高级别的API,同时最好能搞懂底层的实现机制。这样我们的程序才会更高效,出了问题才知道去哪里查找。

 

注:转载请注明出处!欢迎大家一起讨论,共同进步。

 


部门招人: 高级iOS、Android、前端开发,有意私聊,博主请你喝️
如果觉得本文帮到了你,记得点赞哦,当然也可以请博主喝一杯豆浆
微信二维码 QQ二维码
目录
相关文章
|
编解码 iOS开发
iOS中图片(UIImage)拉伸技巧
iOS中图片(UIImage)拉伸技巧
344 0
iOS中图片(UIImage)拉伸技巧
|
1月前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
110 1
|
1月前
|
设计模式 安全 Swift
探索iOS开发:打造你的第一个天气应用
【9月更文挑战第36天】在这篇文章中,我们将一起踏上iOS开发的旅程,从零开始构建一个简单的天气应用。文章将通过通俗易懂的语言,引导你理解iOS开发的基本概念,掌握Swift语言的核心语法,并逐步实现一个具有实际功能的天气应用。我们将遵循“学中做,做中学”的原则,让理论知识和实践操作紧密结合,确保学习过程既高效又有趣。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你打开一扇通往iOS开发世界的大门。
|
1月前
|
搜索推荐 IDE API
打造个性化天气应用:iOS开发之旅
【9月更文挑战第35天】在这篇文章中,我们将一起踏上iOS开发的旅程,通过创建一个个性化的天气应用来探索Swift编程语言的魅力和iOS平台的强大功能。无论你是编程新手还是希望扩展你的技能集,这个项目都将为你提供实战经验,帮助你理解从构思到实现一个应用的全过程。让我们开始吧,构建你自己的天气应用,探索更多可能!
63 1
|
7天前
|
安全 数据处理 Swift
深入探索iOS开发中的Swift语言特性
本文旨在为开发者提供对Swift语言在iOS平台开发的深度理解,涵盖从基础语法到高级特性的全面分析。通过具体案例和代码示例,揭示Swift如何简化编程过程、提高代码效率,并促进iOS应用的创新。文章不仅适合初学者作为入门指南,也适合有经验的开发者深化对Swift语言的认识。
25 9
|
7天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
5天前
|
iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第39天】在苹果的生态系统中,SwiftUI框架以其声明式语法和易用性成为开发者的新宠。本文将深入SwiftUI的核心概念,通过实际案例展示如何利用这一框架快速构建用户界面,并探讨其对iOS应用开发流程的影响。