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
};
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
默认的方向是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
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
//
// 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
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
以上只是实现了图像的顺时针90°,逆时针90°,180°旋转,以及水平翻转,数值翻转等。至 于任意角度旋转怎么实现?其实也很简单,留着给大家思考吧。虽然我们可以通过orientation这种方法简单的完成图像旋转,但是如果有时间的话还是 建议大家尽量的看一下那种通过transform来完成旋转的代码,你会彻底搞清楚旋转矩阵是怎么回事儿。当然程序中使用的时候推荐使用我上面提供的这种 方法,因为不涉及真实的旋转操作,速度会快很多。
通过上面的小例子,我们可以看出越高级别的API帮助我们做的事情就越多,越底层的API提 供了更多的灵活性,但同时也带来了很多需要我们处理的东西。再编程的过程中尽量的使用高级别的API,同时***能搞懂底层的实现机制。这样我们的程序才会 更高效,出了问题才知道去哪里查找。
来自www.cnblogs.com/smileEvday/archive/2013/05/14/UIImage.html