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: orientation:UIImageOrientationLeft];
break;
}
case UIImageOrientationDown:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRight];
break;
}
case UIImageOrientationLeft:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDown];
break;
}
case UIImageOrientationRight:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUp];
break;
}
case UIImageOrientationUpMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRightMirrored];
break;
}
case UIImageOrientationDownMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeftMirrored];
break;
}
case UIImageOrientationLeftMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUpMirrored];
break;
}
case UIImageOrientationRightMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: 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: orientation:UIImageOrientationRight];
break;
}
case UIImageOrientationDown:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeft];
break;
}
case UIImageOrientationLeft:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUp];
break;
}
case UIImageOrientationRight:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDown];
break;
}
case UIImageOrientationUpMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeftMirrored];
break;
}
case UIImageOrientationDownMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRightMirrored];
break;
}
case UIImageOrientationLeftMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDownMirrored];
break;
}
case UIImageOrientationRightMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: 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: orientation:UIImageOrientationDown];
break;
}
case UIImageOrientationDown:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUp];
break;
}
case UIImageOrientationLeft:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRight];
break;
}
case UIImageOrientationRight:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeft];
break;
}
case UIImageOrientationUpMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDownMirrored];
break;
}
case UIImageOrientationDownMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUpMirrored];
break;
}
case UIImageOrientationLeftMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRightMirrored];
break;
}
case UIImageOrientationRightMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: 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(, , size.width, size.height)); [self drawInRect:CGRectMake(, , 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: orientation:UIImageOrientationUpMirrored];
break;
}
case UIImageOrientationDown:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDownMirrored];
break;
}
case UIImageOrientationLeft:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRightMirrored];
break;
}
case UIImageOrientationRight:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeftMirrored];
break;
}
case UIImageOrientationUpMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUp];
break;
}
case UIImageOrientationDownMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDown];
break;
}
case UIImageOrientationLeftMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRight];
break;
}
case UIImageOrientationRightMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: 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: orientation:UIImageOrientationDownMirrored];
break;
}
case UIImageOrientationDown:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUpMirrored];
break;
}
case UIImageOrientationLeft:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeftMirrored];
break;
}
case UIImageOrientationRight:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationRightMirrored];
break;
}
case UIImageOrientationUpMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationDown];
break;
}
case UIImageOrientationDownMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationUp];
break;
}
case UIImageOrientationLeftMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: orientation:UIImageOrientationLeft];
break;
}
case UIImageOrientationRightMirrored:
{
image = [UIImage imageWithCGImage:self.CGImage scale: 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,同时最好能搞懂底层的实现机制。这样我们的程序才会更高效,出了问题才知道去哪里查找。
UIImage的使用的更多相关文章
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- 聊天气泡 button backgroundImage uiimage 拉伸 stretchableImageWithLeftCapWidth: 方法的使用
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCap ...
- github源码学习之UIImage+YYWebImage
UIImage+YYWebImage是YYWebImage(https://github.com/ibireme/YYWebImage)中的一个分类,这个分类封装了一些image常用的变化方法,非常值 ...
- 第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash
1. UIImage imageWithContentsOfFile卡顿 [[UIImage alloc] initWithContentsOfFile 卡顿 2.uitableview scroll ...
- 使用libjpeg.framework压缩UIImage
+(void)writeFile:(NSString *)filePath withQuality:(int)quality { //初始化图片参数 UIImage *image=[UIImage i ...
- iOS开发之功能模块--长方形UIImage截取中间最大正方形区域
这里直接用CoreGraphics的一些处理图片的方法,本身不难,但是有些时候用的不多,就会遗忘掉使用方法的细节.下面就直接展示关键源码,以便下次重复需求,就可以立马找回. 该方法中在UIImage的 ...
- iOS 分析一个支持GIF的UIImage扩展:SwiftGIF
Github:https://github.com/bahlo/SwiftGif 这个extension代码不多,主要通过Apple的ImageIO框架进行解析GIF. 整个扩展最核心还是下面的函数, ...
- UIImage加载本地图片的两种方式
UIImage加载图片方式一般有两种: (1)imagedNamed初始化:默认加载图片成功后会内存中缓存图片,这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象.如果缓存中没有找到相应的图片 ...
- uiimage 上传 数据库
之前我所接触的上传图片都是直接与服务器交互的,即 app端要做的就是上传到服务器 现在这个项目却是app先上传到"数据库",由"数据库"传到服务端 下面说主题 ...
- [IOS 开发代码]UIImage+Blur 网络图片模糊用法
UIImage-Helpers 网络图片模糊用法 float quality = .00001f; float blurred = .5f; NSURL *url = [NSURL URLW ...
随机推荐
- secondarynamenode异常
secondarynamenode异常 -- ::, ERROR org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode: Exception ...
- C# xml2json
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- HDU1395+快速幂
#include<stdio.h> int fast_pow( int a,int b,int mod ){ ; ){ == ){ res = res*a%mod; } a = a*a%m ...
- Java中对List集合排序的两种方法
第一种方法,就是list中对象实现Comparable接口,代码如下: public class Person implements Comparable<Person> { privat ...
- 运行edX Devstack
前一篇文章,我们安装完成了edX Devstack,本文将介绍edX Devstack的常用命令 6.1. 连接到 Devstack Virtual Machine 为了连接到Devstack vir ...
- ANDROID_MARS学习笔记_S02_007_Animation第一种使用方式:代码
一.简介 二.代码1.xml(1)activity_main.xml <?xml version="1.0" encoding="utf-8"?> ...
- delphi中formatFloat代码初探(在qt下实现floatformat的函数)
由于项目需要,需要在qt下实现floatformat的函数.之前写过一个,但是写得不好.决定重新写一个,参考delphi xe2下的实现.把xe2下的相关代码都看了一遍,xe2的代码思路在这里贴出来. ...
- Postman(API & HTTP请求调试插件)和Apizza fiddler
http://blog.csdn.net/u011012932/article/details/51456263#comments
- 139. Word Break
题目: Given a string s and a dictionary of words dict, determine if s can be segmented into a space-se ...
- leetcode面试准备:Implement Trie (Prefix Tree)
leetcode面试准备:Implement Trie (Prefix Tree) 1 题目 Implement a trie withinsert, search, and startsWith m ...