之前的项目中有个需求:将一个比较长的列表页(用的UITableView)截图然后分享到微信。贴出实现方法:
- (UIImage *)captureScrollView:(UIScrollView *)scrollView {
UIImage* image = nil;
UIGraphicsBeginImageContext(scrollView.contentSize);
{
CGSize s = scrollView.contentSize;
//第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传NO,否则传YES。第三个参数就是屏幕密度了,关键就是第三个参数。
UIGraphicsBeginImageContextWithOptions(s, NO, [UIScreen mainScreen].scale);
CGPoint savedContentOffset = scrollView.contentOffset;
CGRect savedFrame = scrollView.frame;
scrollView.contentOffset = CGPointZero;
scrollView.frame = CGRectMake(0, 0, SCREEN_WIDTH, scrollView.contentSize.height);
[scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
scrollView.contentOffset = savedContentOffset;
scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
if (image != nil) {
return image;
}
return nil;
}
所截的图如下:
这个方法能顺利将tableView截成长图,但是突然有天需求变了:
手续费那一栏不能分享出去,What?
然后我的思路是截两次,第一次把手续费以上的部分截下来,第二次把手续费以下的部分截出来,然后两张图片合成一张图片。思路有了,操起键盘就是一梭子代码:
/**
Description 从图片中按指定的位置大小截取图片的一部分
@param image 原始的图片
@param rect 要截取的区域
@return 截取出的图片
*/
- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect{
CGImageRef sourceImageRef = [image CGImage];//将UIImage转换成CGImageRef
/**以下为错误写法*/
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));//按照给定的矩形区域进行剪裁
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];//将CGImageRef转换成UIImage
return newImage;//返回剪裁后的图片
}
/**
Description 图片上下拼接
@param topImage 上图片
@param bottomImage 下图片
@return 拼接后的图片
*/
- (UIImage *)composeImgWithTopImage:(UIImage *)topImage bottomImage:(UIImage *)bottomImage {
if (bottomImage == nil) {
return topImage;
}
CGFloat topImageH = topImage.size.height;
CGFloat topImageW = topImage.size.width;
CGFloat bottomImageH = bottomImage.size.height;
CGFloat bottomImageW = bottomImage.size.width;
CGFloat totalHeight = SCREEN_WIDTH*topImageH/topImageW + SCREEN_WIDTH*bottomImageH/bottomImageW;
CGSize offScreenSize = CGSizeMake(SCREEN_WIDTH, totalHeight);
UIGraphicsBeginImageContextWithOptions(offScreenSize, NO, [UIScreen mainScreen].scale);
CGRect rectTop = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_WIDTH*topImageH/topImageW);
[topImage drawInRect:rectTop];
CGRect rectBottom = CGRectMake(0, SCREEN_WIDTH*topImageH/topImageW, SCREEN_WIDTH, SCREEN_WIDTH*bottomImageH/bottomImageW);
[bottomImage drawInRect:rectBottom];
UIImage* imagez = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imagez;
}
然后我两次调用截图传的rect是
CGRect headerClipRect = CGRectMake(0, 0, image.size.width, [self.tableView rectForSection:2].origin.y);
CGRect footerClipRect = CGRectMake(0, [self.tableView rectForSection:3].origin.y, image.size.width, self.tableView.contentSize.height - [self.tableView rectForSection:3].origin.y);
准备就绪,来看看截出来的图是什么样子的:
what,我到底哪里错了?一脸惊恐
然后反复查找发现- (UIImage *)captureScrollView:(UIScrollView *)scrollView
这个方法截出的长图的大小并不是传入的scrollView
的contentSize,而是长宽各自乘以手机分辨率[UIScreen mainScreen].scale
,所以对长图进行切割的时候,按照给定的矩形区域进行剪裁应该这样传值
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, CGRectMake(rect.origin.x*[UIScreen mainScreen].scale, rect.origin.y*[UIScreen mainScreen].scale, rect.size.width*[UIScreen mainScreen].scale, rect.size.height*[UIScreen mainScreen].scale));//按照给定的矩形区域进行剪裁
最后的截图合成之后应该是这样的: