我正在尝试使用UIImage
将UIBezierPath
切割成不规则形状。
这就是我掩饰包含我感兴趣的UIImageView
的{{1}}的方式:
UIImage
这是按预期工作的,我得到了正确的屏蔽- (void)maskImageView:(UIImageView *)image
{
UIBezierPath *path = [self getPath];
CGRect rect = CGRectZero;
rect.size = image.image.size;
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = CGRectMake(0, 0,image.frame.size.width, image.frame.size.height);
shapeLayer.path = path.CGPath;
shapeLayer.fillColor = [[UIColor whiteColor] CGColor];
shapeLayer.backgroundColor = [[UIColor clearColor] CGColor];
[image.layer setMask:shapeLayer];
}
。但是,我希望获得基础UIImageView
,以便我可以在另一个图像上绘制它。这就是我得到UIImage
:
UIImage
然后我绘制图像并将其保存到相机胶卷中:
-(UIImage *)getCroppedImageForView:(UIImageView *)view{
CGSize size = view.layer.bounds.size;
UIGraphicsBeginImageContext(size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
当我查看保存的图像时,我可以看到它比原始图像小,即使我在图像边缘周围绘制-(UIImage *)drawImage:(UIImage*)image
{
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(finalImage, nil, nil, nil);
return finalImage;
}
(没有真正裁剪它)。
我使用相同的方法绘制和保存其他图像,它们正确出来,所以我很确定问题出在UIBezierPath
方法。
有人能指出我正确的方向吗?
修改
使用设备的相机拍摄图像,因此对于iPhone 5,尺寸为:3264x2448
包含图片的getCroppedImageForView
的尺寸为:320x568,其UIImageView
为contentMode
。
我想要实现的是获得全尺寸(3264x2448)裁剪后的图像,然后将其绘制在另一个图像(尺寸相同)之上。
答案 0 :(得分:1)
有几点想法:
您注意到图像视图为320x568点,但图像本身为3264x2448像素。关键观察是UIGraphicsBeginImageContext...
函数通过呈现UIImage
来创建UIImageView
,因此,生成的图片的大小将与UIKit
的大小相关联控制并且与实际原始UIImage
的大小关系不大。
在getCroppedImageForView
中,您没有考虑设备的scale
,特别是没有处理视网膜分辨率(生成320x568像素的图像)。通常你会做类似以下的事情:
- (UIImage *)imageForView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
通过UIGraphicsBeginImageContextWithOptions
使用0
作为最后一个选项,它将反映设备的比例,并且在视网膜屏幕上,它将生成640x1136像素的图像。
maskImageView
的一个小简化:默认情况下,添加子图层时,它将使用与图像视图相同的框架,因此您可以完全取消frame
变量的设置,屈服:
- (void)maskImageView:(UIImageView *)imageView
{
UIBezierPath *path = [self getPath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
shapeLayer.fillColor = [[UIColor whiteColor] CGColor];
shapeLayer.backgroundColor = [[UIColor clearColor] CGColor];
[imageView.layer setMask:shapeLayer];
}
在drawImage
中,无需重新渲染图像。您已经拥有image
。所以直接使用UIImage
:
- (void)writeToSavedPhotosAlbum:(UIImage*)image
{
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
但如果你真的想重新渲染图像,你可以使用我在上面第2点中说明的相同UIGraphicsBeginImageContextWithOptions
语法,享受视网膜设备提供的额外分辨率。
虽然上述更改会使图像变大,但仍然比原始图像的3268x2448像素小得多。如果你真的想要创建一个3268x2448像素的最终图像,有两个选项可以跳出来:
一种选择是使图像视图与图像的大小相同(或者更准确地说,相同的大小除以屏幕比例)。您可能希望将此图像视图放在滚动视图上并适当设置缩放比例。
另一种选择是放弃UIKit来渲染图像,然后转移到Core Image(代码的主要重构)。
顺便提一下,请注意这些大图像会慢很多并且消耗更多内存。内部未压缩的尺寸各超过30 mb。