[转自]http://marshal.easymorse.com/archives/3703
在ios开发中,肯定会碰到需要截取部分图片的情况。
最终的效果类似这样:
先看最原始的示例,显示完整的图片
写了个最简单的读取图片并显示的代码,打算以此为开始,逐渐实现截取部分图片的功能。
代码主要是,在控制器代码中:
- (void)loadView {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation: UIStatusBarAnimationSlide];
UIImage *image=[UIImage imageNamed:@"1.jpg"];
UIImageView *contentView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[contentView setImage:image];
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:contentView];
}
另外,应该有一个名为1.jpg的768×1024的图片(我这里是iPad)。
截取整个图片
可以认为截取整个图片是截取部分图片的一个特例。对ios不熟嘛,因此打算很谨慎的推进。截取整个图片可以减少中间的复杂性。
根据API,摸索着写了一个示例,效果出乎意料:
代码:
- (void)loadView {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation: UIStatusBarAnimationSlide];
UIImage *image=[UIImage imageNamed:@"1.jpg"];
UIImageView *contentView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//[contentView setImage:image];
CGRect rect = CGRectMake(0, 0, 768, 1024);//创建矩形框
UIGraphicsBeginImageContext(rect.size);//根据size大小创建一个基于位图的图形上下文
CGContextRef currentContext = UIGraphicsGetCurrentContext();//获取当前quartz 2d绘图环境
CGContextClipToRect( currentContext, rect);//设置当前绘图环境到矩形框
CGContextDrawImage(currentContext, rect, image.CGImage);//绘图
UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();//获得图片
UIGraphicsEndImageContext();//从当前堆栈中删除quartz 2d绘图环境
contentView.image=cropped;
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:contentView];
[cropped release];
}
这个代码说明了两点:
- 好的方面:说明我的代码起作用了,确实截取了所需的图形
- 坏的方面:图形是颠倒的,而且是镜像的。
问题应该出在坐标系上。下面画了一个quartz 2d的坐标系,坐标原点在左下角:
因此以这个坐标系取图形,就会有转向180°的效果。
其实如果是对图片的缩放,而不是剪切部分图片内容,这样写就可以了:
- (void)loadView {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation: UIStatusBarAnimationSlide];
UIImage *image=[UIImage imageNamed:@"1.jpg"];
//[contentView setImage:image];
CGRect rect = CGRectMake(0, 0, 384, 512);//创建矩形框
UIGraphicsBeginImageContext(rect.size);//根据size大小创建一个基于位图的图形上下文
CGContextRef currentContext = UIGraphicsGetCurrentContext();//获取当前quartz 2d绘图环境
CGContextClipToRect(currentContext, rect);//设置当前绘图环境到矩形框
//CGContextRotateCTM(currentContext, 50);
//CGContextDrawImage(currentContext, rect, image.CGImage);//绘图
[image drawInRect:rect];
UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();//获得图片
UIGraphicsEndImageContext();//从当前堆栈中删除quartz 2d绘图环境
UIImageView *contentView = [[UIImageView alloc] initWithFrame:rect];
contentView.image=cropped;
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:contentView];
[cropped release];
}
效果类似这样:
这个方法可以帮助我们在后续开发中实现缩略图。但是不符合现在的需求。
于是想了下面的基本思路:
这样,需要一个能旋转和向下移动的API。ios提供了C++界面的函数调用:
- CGContextRotateCTM,实现角度的转换
- CGContextTranslateCTM,可以重新设置坐标系原点,平移坐标系和移动图片是等效的
代码:
- (void)loadView {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation: UIStatusBarAnimationSlide];
UIImage *image=[UIImage imageNamed:@"1.jpg"];
//[contentView setImage:image];
CGRect rect = CGRectMake(0, 0, 384, 512);//创建矩形框
UIGraphicsBeginImageContext(rect.size);//根据size大小创建一个基于位图的图形上下文
CGContextRef currentContext = UIGraphicsGetCurrentContext();//获取当前quartz 2d绘图环境
CGContextClipToRect(currentContext, rect);//设置当前绘图环境到矩形框
CGContextRotateCTM(currentContext, M_PI);
CGContextTranslateCTM(currentContext, -rect.size.width, -rect.size.height);
CGContextDrawImage(currentContext, rect, image.CGImage);//绘图
//[image drawInRect:rect];
UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();//获得图片
UIGraphicsEndImageContext();//从当前堆栈中删除quartz 2d绘图环境
UIImageView *contentView = [[UIImageView alloc] initWithFrame:rect];
contentView.image=cropped;
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:contentView];
[cropped release];
}
这个结果还有缺陷,可以看到图片是正立的了,但是图片反转了,是个镜像。
解决办法也有,不过不是操作图片了,而是操作图片所在的视图。思路是把视图看作一个位图的矩阵,对它做矩阵变换运算,使视图做镜像反转。写法很简单:
- (void)loadView {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation: UIStatusBarAnimationSlide];
UIImage *image=[UIImage imageNamed:@"1.jpg"];
//[contentView setImage:image];
CGRect rect = CGRectMake(0, 0, 384, 512);//创建矩形框
UIGraphicsBeginImageContext(rect.size);//根据size大小创建一个基于位图的图形上下文
CGContextRef currentContext = UIGraphicsGetCurrentContext();//获取当前quartz 2d绘图环境
CGContextClipToRect(currentContext, rect);//设置当前绘图环境到矩形框
CGContextRotateCTM(currentContext, M_PI);
CGContextTranslateCTM(currentContext, -rect.size.width, -rect.size.height);
//CGContextTranslateCTM(currentContext,0.0,200.0);
CGContextDrawImage(currentContext, rect, image.CGImage);//绘图
//[image drawInRect:rect];
UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();//获得图片
UIGraphicsEndImageContext();//从当前堆栈中删除quartz 2d绘图环境
UIImageView *contentView = [[UIImageView alloc] initWithFrame:rect];
contentView.image=cropped;
contentView.transform = CGAffineTransformIdentity;
contentView.transform = CGAffineTransformMakeScale(-1.0, 1.0);
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:contentView];
[cropped release];
}
这里的转换因子,一个是针对x轴的,一个是针对y轴的。终于可以产生这样的效果了:
这里参考了这个文档:
http://macdevcenter.com/pub/a/mac/2004/11/02/quartz.html
虽然是很古老的文章了,但是说的很清楚。另外,方法名称已经发生变化,需要注意。
截取部分图片
截取部分图片,比如:
截取左边人像部分。
实现后的代码,效果是这样的:
如何实现的呢,这时候才发现,其实根本不需要上面那些转换,如果不使用quartz 2d的话,截取部分图片这么简单:
- (void)loadView {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation: UIStatusBarAnimationSlide];
UIImage *image=[UIImage imageNamed:@"1.jpg"];
CGRect rect = CGRectMake(60, 80, 331, 353);//创建矩形框
UIImageView *contentView = [[UIImageView alloc] initWithFrame:rect];
contentView.image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect([image CGImage], rect)];
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:contentView];
[image release];
}
虽然编写代码的过程是曲折的,但是摸到很多有用的东西,都是以后要用到的。
分享到:
相关推荐
android 框选 图片 截取
.net上传图片并在线截取图片,网页中上传图片并截取图片大小,跟QQ上传头像,并截取大小类似
mfc 显示图片,鼠标截取一部分会显示在另一个控件上
js 截取图片代码
c#截取一张图片的部分 或者缩放图片,教你如何加工原始的图片,变成你想要的效果
html2canvas - 使用JavaScript将整个网页或一部分区域截取成图片并导出
上传图片并在线截取 php上传图片并托动截取
客户端截取页面内容,转为图片并显示。
通过jquery的两个插件实现图片截取效果,上传 后台实现图片根据截取出来的位置坐剪切 压缩 可以配合图片缓存的数据库做的接口实现图片服务器做iframe 跨域上传
在vs2013上win32控制台运用opencv鼠标实时截取图像并显示坐标
jquery 上传图片时截取固定大小的范围图片 类似QQ上传头像截取,17年用的了 当时亲自测试用过还不错
使用java applet开发,指定要截取的屏幕范围,保存成图片到客户端的小应用程序。
jquery图片截取DEMO,jquery图片截取DEMO
高仿微信demo,内含截取本地图片,截取手机拍照图片作为头像
java 拍照 功能,调用链接的摄像头,可以远程访问该拍照页面并且进行拍照
截取图片指定部分
java将视频定时截取图片并保存
JS实现:鼠标操作的,方框截取图片部分内容,只有截图部分,入股有其他功能,可以再叠加
图片截取DEMO...截取图片
jQuery图片等比例缩放截取显示代码基于jquery-1.8.3.min.js和jQThumb.1.9.5制作,应用图片切割平铺显示中避免图片变形。