UIImage
UIImage派生自NSObject,是用于管理应用程序中图像数据的对象。可以使用image对象来表示各种图像数据,UIImage类能够管理底层平台支持的所有图像格式的数据。图像对象是不可变的,因此总是从现有的图像数据(如磁盘上的图像文件或以编程方式创建的图像数据)创建它们。图像对象可以包含要在动画中使用的单个图像或图像序列。
可以用几种不同的方式使用图像对象:
- 1.将图像分配给UIImageView对象以在界面中显示该图像。
- 2.使用图像可自定义系统控件,如按钮、滑块和分段控件。
- 3.将图像直接绘制到视图或其他图形上下文中。
- 4.将图像传递给可能需要图像数据的其他API。
虽然图像对象支持所有平台原生图像格式,但建议对应用程序中的大多数图像使用PNG或JPEG文件。图像对象针对读取和显示这两种格式进行了优化,这些格式提供了比大多数其他图像格式更好的性能。因为PNG格式是无损的,所以特别推荐在应用程序界面中使用的图像。
常用属性
@property(nonatomic,readonly) CGFloat scale API_AVAILABLE(ios(4.0));
属性描述 : 图像的比例因子。如果从一个名为@2x修饰符的文件中加载图片,比例设置为2.0。还可以在从核心图形图像初始化图像时指定显式的缩放因子。假设所有其他图像的比例因子为1.0。如果将图像的逻辑大小(存储在size属性中)乘以该属性中的值,就会得到图像的尺寸(以像素为单位)。
@property(nonatomic,readonly) CGFloat scale API_AVAILABLE(ios(4.0));
常用函数
+ (nullable UIImage *)imageNamed:(NSString *)name;
函数描述 : 从指定的命名的资源创建一个image对象。在搜索资源目录时,此方法优先选择包含符号图像的资源,而不是包含位图图像的同名资源。因为只有iOS 13及更高版本才支持符号图像,因此可以在同一个资产目录中包含这两种类型的资产。系统会自动恢复到iOS早期版本上的位图图像。不能使用此方法加载系统符号图像,需要使用systemImageNamed:方法代替。此方法检查具有指定名称的图像对象的系统缓存,并返回最适合主屏幕的图像变量。如果匹配的图像对象尚未在缓存中,则此方法从可用的资源目录创建图像或从磁盘加载它。系统可以随时清除缓存的图像数据以释放内存,但仅对缓存中当前未使用的映像进行清除。在iOS9及更高版本中,此方法是线程安全的。
参数 :
name :图像资源或文件的名称。对于资源目录中的图像,指定图像资源的名称。对于PNG图像,可以省略文件扩展名。对于所有其他文件格式,请始终包含文件扩展名。
返回值:包含未配置版本的图像的对象,如果方法找不到指定的图像,则为nil。
+ (nullable UIImage *)imageNamed:(NSString *)name;
+ (UIImage *)imageWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation API_AVAILABLE(ios(4.0));
函数描述 : 创建并返回具有指定缩放因子和方向的图像对象。此方法不缓存图像对象。可以使用CoreGraphics.framework的方法创建一个Quartz图像引用。
参数 :
cgImage :Quartz图像对象。
scale : 解释图像数据时使用的比例因子。将比例因子指定为1.0将得到一个大小与基于像素的图像尺寸匹配的图像。应用不同的比例因子将改变由size属性报告的图像大小。
orientation :图像数据的方向。可以使用此参数指定应用于图像的任何旋转因子。
+ (UIImage *)imageWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation API_AVAILABLE(ios(4.0));
UIImageOrientation的枚举值如下:
typedef NS_ENUM(NSInteger, UIImageOrientation) {
UIImageOrientationUp, // 默认方向
UIImageOrientationDown, // 180度旋转
UIImageOrientationLeft, // 逆时针90度
UIImageOrientationRight, // 顺时针90度
UIImageOrientationUpMirrored, // 同上,但图像沿另一个轴镜像。水平翻转
UIImageOrientationDownMirrored, // 水平翻转
UIImageOrientationLeftMirrored, // 垂直翻转
UIImageOrientationRightMirrored, // 垂直翻转
};
例如 :
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
if(section == 0){
//初始化要显示的标签富文本
NSMutableAttributedString *newAttributedString = [[NSMutableAttributedString alloc]initWithString:@" 好友砍价榜 "];
//创建Image的富文本格式
NSTextAttachment *leftAttach = [[NSTextAttachment alloc] init];
//这个-7.5是为了调整下标签跟文字的位置
leftAttach.bounds = CGRectMake(0, -7.5, 26, 26);
//设置图片
leftAttach.image = [UIImage imageNamed:@"friends_bargaining"];
//添加到富文本对象里
NSAttributedString * leftImageStr = [NSAttributedString attributedStringWithAttachment:leftAttach];
//加入文字前面
[newAttributedString insertAttributedString:leftImageStr atIndex:0];
//创建Image的富文本格式
NSTextAttachment *rightAttach = [[NSTextAttachment alloc] init];
//这个-7.5是为了调整下标签跟文字的位置
rightAttach.bounds = CGRectMake(0, -7.5, 26, 26);
//设置图片
rightAttach.image = [UIImage imageWithCGImage:[UIImage imageNamed:@"friends_bargaining"].CGImage scale:[UIImage imageNamed:@"friends_bargaining"].scale orientation:UIImageOrientationDown];
//添加到富文本对象里
NSAttributedString * rightImageStr = [NSAttributedString attributedStringWithAttachment:rightAttach];
//加入文字前面
[newAttributedString insertAttributedString:rightImageStr atIndex:newAttributedString.length];
//初始化要显示的标签
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectZero];
//设置文本字体
titleLabel.font = [UIFont boldSystemFontOfSize:15];
//设置文本颜色
titleLabel.textColor = HEXCOLOR(0xFB4E09);
//设置文本对齐方式
titleLabel.textAlignment = NSTextAlignmentCenter;
//设置富文本
titleLabel.attributedText = newAttributedString;
//返回标签
return titleLabel;
}
return nil;
}
效果如图:

对图片操作的方法记录
根据网址获取图片的大小
可以获取路径类似http://timp.oss-cn-beijing.aliyuncs.com/images/746/system/config/bonus/m_bonus_img1.jpg格式的图片大小,编码格式的获取不到。
一般后台直接返回的URL不会有问题,而返回字符串路径的话,有时需要处理一下,如果路径格式不对的话,会报错NSURLConnection finished with error - code -1002。如果路径错误会报错HTTP load failed,NSURLConnection finished with error - code -1003。
例如我遇到的则是请求时未报错,但也没有拿到图片大小,后来发现返回的路径在进行拼接处理后,路径中多出一条/,例如这样也会失败:

- (CGSize)getImageSizeWithURL:(id)URL{
NSURL * url = nil;
if ([URL isKindOfClass:[NSURL class]]) {
url = URL;
}
if ([URL isKindOfClass:[NSString class]]) {
url = [NSURL URLWithString:URL];
}
if (!URL) {
return CGSizeZero;
}
CGImageSourceRef imageSourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
CGFloat width = 0, height = 0;
if (imageSourceRef) {
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef, 0, NULL);
if (imageProperties != NULL) {
CFNumberRef widthNumberRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
if (widthNumberRef != NULL) {
CFNumberGetValue(widthNumberRef, kCFNumberFloat64Type, &width);
}
CFNumberRef heightNumberRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
if (heightNumberRef != NULL) {
CFNumberGetValue(heightNumberRef, kCFNumberFloat64Type, &height);
}
CFRelease(imageProperties);
}
CFRelease(imageSourceRef);
}
return CGSizeMake(width, height);
}
删除URL的多余斜线,例如:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",[self removeExtraSlashOfUrl:@"http://www.baidu.com/images/746//shop/144/images/2019/07/18/15634382435520.png"]);
}
- (NSString *)removeExtraSlashOfUrl:(NSString *)url {
if (!url || url.length == 0) {
return url;
}
NSString *pattern = @"(?<!(http:|https:))/+";
NSRegularExpression *expression = [[NSRegularExpression alloc]initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
return [expression stringByReplacingMatchesInString:url options:0 range:NSMakeRange(0, url.length) withTemplate:@"/"];
}
执行结果:

图片等宽屏幕,高度自适应的计算
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageView1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"test"]];
[self.view addSubview:imageView1];
[imageView1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view);
make.top.equalTo(self.view).offset(44);
}];
UIImageView *imageView2 = [[UIImageView alloc]initWithFrame:CGRectZero];
UIImage *image = [UIImage imageNamed:@"test"];
CGSize newImageSize = resizeForScreen(image.size);
[imageView2 setImage:image];
[self.view addSubview:imageView2];
[imageView2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view);
make.bottom.equalTo(self.view);
make.size.mas_equalTo(newImageSize);
}];
}
//等宽屏幕,高度自适应
CGSize resizeForScreen(CGSize size) {
if (CGSizeEqualToSize(size, CGSizeZero)) {
return CGSizeZero;
}
CGFloat const displayWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat const ratio = size.width / size.height; // 宽高比
CGSize displaySize = CGSizeZero;
if (!isnan(ratio)) {
CGFloat const displayHeight = displayWidth / ratio;
displaySize = CGSizeMake(displayWidth, displayHeight);
}
return displaySize;
}
@end
显示结果:

更改纯色图片颜色
//UIImage(TintColor).h
//UIImage扩展类
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface UIImage(TintColor)
- (UIImage *)imageWithTintTheColor:(UIColor *)tintColor;
@end
//UIImage(TintColor).m
#import "UIImage(TintColor).h"
@implementation UIImage(TintColor)
- (UIImage *)imageWithTintTheColor:(UIColor *)tintColor {
///UIGraphicsBeginImageContextWithOptions()创建一个临时渲染上下文,在这上面绘制原始图片。第一个参数,size,是缩放图片的尺寸,第二个参数,isOpaque 是用来决定透明通道是否被渲染。对没有透明度的图片设置这个参数为NO,可能导致图片有粉红色调。第三个参数scale是显示缩放系数。当设置成0.0,主屏幕的缩放系数将被使用,对视网膜屏显示是2.0或者更高(在iPhone6 Plus 上是 3.0)
///UIScreen对象定义了基于硬件显示的相关属性,用这个类来获取每一个设备显示屏幕的对象
///UIScreen.mainScreen.scale:计算屏幕分辨率
UIGraphicsBeginImageContextWithOptions(self.size, NO, UIScreen.mainScreen.scale);
///一个不透明类型的Quartz 2D绘画环境,相当于一个画布,你可以在上面任意绘画
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect area = {0, 0, self.size};
CGContextScaleCTM(context, 1.0, -1.0);///坐标系X,Y缩放
CGContextTranslateCTM(context, 0, -area.size.height);///坐标系平移
CGContextSaveGState(context);///压栈操作,保存一份当前图形上下文
///CGImage:是用来重绘图形,它们在应用时是按照图像的像素矩阵来绘制图片的
///CGContextClipToMask:裁剪的区域,第一个参数表示context的指针,第二个参数表示裁剪到context的区域,也就是mask图片映射到context的区域,第三个参数表示mask的图片,对于裁剪区域Rect中的点是否变化取决于mask图中的alpha值,若alpha为0,则对应裁剪Rect中的点为透明,若alpha为1,则对应裁剪Rect中的点无变化
CGContextClipToMask(context, area, self.CGImage);
[tintColor set];
CGContextFillRect(context, area);/// 填充指定的矩形
CGContextRestoreGState(context);///在没有保存之前,用这个函数还原blend mode.
CGContextSetBlendMode(context, kCGBlendModeDestinationOver);///设置blend mode.
///CGContextDrawImage允许在制定的尺寸和位置上画图,允许在特定边缘或者适应一组图片特征比如faces,裁剪图片。
CGContextDrawImage(context, area, self.CGImage);
///从当前环境当中得到重绘的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();///关闭当前环境
///设置图片的渲染模式:始终绘制图片原始状态
return [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
@end
测试代码:
//ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
//ViewController.m
#import "ViewController.h"
#import "UIImage(TintColor).h"
@interface ViewController ()
//@property (nonatomic,strong) UIImage *image;
@property (nonatomic,strong) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect screen = [[UIScreen mainScreen]bounds];
CGFloat oldImageViewWidth = 50;
CGFloat oldImageViewHeigth = 50;
CGFloat oldViewTopSpacing = 200;
UIImageView *oldImageView = [[UIImageView alloc]initWithFrame:CGRectMake((screen.size.width - oldImageViewWidth)/2, oldViewTopSpacing, oldImageViewWidth, oldImageViewHeigth)];
UIImage *oimage = [UIImage imageNamed:@"ic_often_courier"];
[oldImageView setImage:oimage];
[self.view addSubview:oldImageView];
CGFloat newImageViewWidth = 50;
CGFloat newImageViewHeigth = 50;
CGFloat newViewTopSpacing = 400;
UIImageView *newImageView = [[UIImageView alloc]initWithFrame:CGRectMake((screen.size.width - newImageViewWidth)/2, newViewTopSpacing, newImageViewWidth, newImageViewHeigth)];
UIImage *nImage = [UIImage imageNamed:@"ic_often_courier"];
UIImage *newImage = [nImage imageWithTintTheColor:[UIColor greenColor]];
[newImageView setImage:newImage];
[self.view addSubview:newImageView];
}
@end
显示结果:

按大小缩放图片
- (UIImage *)scaleToSize:(UIImage *)img size:(CGSize)size{
UIGraphicsBeginImageContextWithOptions(size, NO, [[UIScreen mainScreen] scale]);
[img drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
测试代码:
- (void)viewDidLoad {
[super viewDidLoad];
self.WeiXinButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.WeiXinButton setImage:[UIImage imageNamed:@"ic_wechat"] forState:UIControlStateNormal];
[self.WeiXinButton setTitle:@"微信支付" forState:UIControlStateNormal];
[self.WeiXinButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
self.WeiXinButton.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10);
self.WeiXinButton.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
self.WeiXinButton.layer.cornerRadius = 22.0f;
self.WeiXinButton.layer.masksToBounds = YES;
self.WeiXinButton.layer.borderColor = [UIColor blackColor].CGColor;
self.WeiXinButton.layer.borderWidth = 0.6;
[self.view addSubview:self.WeiXinButton];
[self.WeiXinButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view).offset(- 44);
make.left.equalTo(self.view.mas_left).offset(10);
make.right.equalTo(self.view.mas_right).offset(- 10);
make.height.mas_equalTo(44);
}];
self.WeiXinButton2 = [UIButton buttonWithType:UIButtonTypeCustom];
[self.WeiXinButton2 setImage:[self scaleToSize:[UIImage imageNamed:@"ic_wechat"] size:CGSizeMake(25, 25)] forState:UIControlStateNormal];
[self.WeiXinButton2 setTitle:@"微信支付" forState:UIControlStateNormal];
[self.WeiXinButton2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
self.WeiXinButton2.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10);
self.WeiXinButton2.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
self.WeiXinButton2.layer.cornerRadius = 22.0f;
self.WeiXinButton2.layer.masksToBounds = YES;
self.WeiXinButton2.layer.borderColor = [UIColor blackColor].CGColor;
self.WeiXinButton2.layer.borderWidth = 0.6;
[self.view addSubview:self.WeiXinButton2];
[self.WeiXinButton2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view).offset(44);
make.left.equalTo(self.view.mas_left).offset(10);
make.right.equalTo(self.view.mas_right).offset(- 10);
make.height.mas_equalTo(44);
}];
}
显示结果:

图片添加圆角
- (UIImage *)createRoundedImageWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius {
CGRect frame = CGRectMake(0, 0, image.size.width, image.size.height);
// 开始一个Image的上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 1.0);
// 添加圆角
[[UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:cornerRadius] addClip];
// 绘制图片
[image drawInRect:frame];
// 接受绘制成功的图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
显示结果:
调用方法前:

返回横向虚线image的方法
- (UIImage *)drawDashLineWithImageView:(UIImageView *)imageView {
UIGraphicsBeginImageContext(CGSizeMake(SCREEN_WIDTH, 4.0)); //开始画线 划线的frame
[imageView.image drawInRect:CGRectMake(0, 0, SCREEN_WIDTH, 4.0)];
//设置线条终点形状
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapSquare);
CGFloat lengths[] = {3.0, 3.0};
CGContextRef line = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(line, [UIColor blackColor].CGColor);
CGContextSetLineDash(line, 4, lengths, 2);
CGContextMoveToPoint(line, 4.0, 4.0); //开始画线
CGContextAddLineToPoint(line, SCREEN_WIDTH, 4.0);
CGContextStrokePath(line);
return UIGraphicsGetImageFromCurrentImageContext();
}
测试代码 :
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectZero];
[imageView setImage:[self drawDashLineWithImageView:imageView]];
[self.view addSubview:imageView];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view);
make.left.equalTo(self.view.mas_left).offset(10);
make.right.equalTo(self.view.mas_right).offset(-10);
make.height.mas_equalTo(1);
}];
}
显示结果 :

网友评论