作为次要答案,我让它与这段代码一起工作,为了更好地理解,你也可以在 github 上获取工作项目,看看它是否适用于所有情况。
我的 github 项目:
https://github.com/Reza-Abdolahi/HighResMasking
解决问题的部分代码:
-(UIImage*)highResolutionMasking{
NSLog(@"///High quality (Image resolution) masking///////////////////////////////////////////////////");
//1.Rendering the path into an image with the size of _targetBound (which is the size of a device screen sized view in which the path is drawn.)
CGFloat aspectRatioOfImageBasedOnHeight = _highResolutionImage.size.height/ _highResolutionImage.size.width;
CGFloat aspectRatioOfTargetBoundBasedOnHeight = _targetBound.size.height/ _targetBound.size.width;
CGFloat pathScalingFactor = 0;
if ((_highResolutionImage.size.height >= _targetBound.size.height)||
(_highResolutionImage.size.width >= _targetBound.size.width)) {
//Then image is bigger than targetBound
if ((_highResolutionImage.size.height<=_highResolutionImage.size.width)) {
//The image is Horizontal
CGFloat newWidthForTargetBound =_highResolutionImage.size.width;
CGFloat ratioOfHighresImgWidthToTargetBoundWidth = (_highResolutionImage.size.width/_targetBound.size.width);
CGFloat newHeightForTargetBound = _targetBound.size.height* ratioOfHighresImgWidthToTargetBoundWidth;
_bigTargetBound = CGRectMake(0, 0, newWidthForTargetBound, newHeightForTargetBound);
pathScalingFactor = _highResolutionImage.size.width/_targetBound.size.width;
}else if((_highResolutionImage.size.height > _highResolutionImage.size.width)&&
(aspectRatioOfImageBasedOnHeight <= aspectRatioOfTargetBoundBasedOnHeight)){
//The image is Vertical but has smaller aspect ratio (based on height) than targetBound
CGFloat newWidthForTargetBound =_highResolutionImage.size.width;
CGFloat ratioOfHighresImgWidthToTargetBoundWidth = (_highResolutionImage.size.width/_targetBound.size.width);
CGFloat newHeightForTargetBound = _targetBound.size.height* ratioOfHighresImgWidthToTargetBoundWidth;
_bigTargetBound = CGRectMake(0, 0, newWidthForTargetBound, newHeightForTargetBound);
pathScalingFactor = _highResolutionImage.size.width/_targetBound.size.width;
}else if((_highResolutionImage.size.height > _highResolutionImage.size.width)&&
(aspectRatioOfImageBasedOnHeight > aspectRatioOfTargetBoundBasedOnHeight)){
CGFloat newHeightForTargetBound =_highResolutionImage.size.height;
CGFloat ratioOfHighresImgHeightToTargetBoundHeight = (_highResolutionImage.size.height/_targetBound.size.height);
CGFloat newWidthForTargetBound = _targetBound.size.width* ratioOfHighresImgHeightToTargetBoundHeight;
_bigTargetBound = CGRectMake(0, 0, newWidthForTargetBound, newHeightForTargetBound);
pathScalingFactor = _highResolutionImage.size.height/_targetBound.size.height;
}else{
//Do nothing
}
}else{
//Then image is smaller than targetBound
_bigTargetBound = _imageRect;
pathScalingFactor =1;
}
CGSize correctedSize = CGSizeMake(_highResolutionImage.size.width *_scale,
_highResolutionImage.size.height *_scale);
_bigImageRect= AVMakeRectWithAspectRatioInsideRect(correctedSize,_bigTargetBound);
//Scaling path
CGAffineTransform scaleTransform = CGAffineTransformIdentity;
scaleTransform = CGAffineTransformScale(scaleTransform, pathScalingFactor, pathScalingFactor);
CGPathRef scaledCGPath = CGPathCreateCopyByTransformingPath(_examplePath.CGPath,&scaleTransform);
//Render scaled path into image
UIGraphicsBeginImageContextWithOptions(_bigTargetBound.size, NO, 1.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath (context, scaledCGPath);
CGContextSetFillColorWithColor (context, [UIColor redColor].CGColor);
CGContextSetStrokeColorWithColor (context, [UIColor redColor].CGColor);
CGContextDrawPath (context, kCGPathFillStroke);
UIImage * pathImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSLog(@"High res pathImage.size: %@",NSStringFromCGSize(pathImage.size));
//Cropping it from targetBound into imageRect
_maskImage = [self cropThisImage:pathImage toRect:_bigImageRect];
NSLog(@"High res _croppedRenderedPathImage.size: %@",NSStringFromCGSize(_maskImage.size));
//Masking the high res image with my mask image which both have the same size now.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef maskImageRef = [_maskImage CGImage];
CGContextRef myContext = CGBitmapContextCreate (NULL, _highResolutionImage.size.width, _highResolutionImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (myContext==NULL)
return NULL;
CGFloat ratio = 0;
ratio = _maskImage.size.width/ _highResolutionImage.size.width;
if(ratio * _highResolutionImage.size.height < _maskImage.size.height) {
ratio = _maskImage.size.height/ _highResolutionImage.size.height;
}
CGRect rectForMask = {{0, 0}, {_maskImage.size.width, _maskImage.size.height}};
CGRect rectForImageDrawing = {{-((_highResolutionImage.size.width*ratio)-_maskImage.size.width)/2 , -((_highResolutionImage.size.height*ratio)-_maskImage.size.height)/2},
{_highResolutionImage.size.width*ratio, _highResolutionImage.size.height*ratio}};
CGContextClipToMask(myContext, rectForMask, maskImageRef);
CGContextDrawImage(myContext, rectForImageDrawing, _highResolutionImage.CGImage);
CGImageRef newImage = CGBitmapContextCreateImage(myContext);
CGContextRelease(myContext);
UIImage *theImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
return theImage;
}
-(UIImage *)cropThisImage:(UIImage*)image toRect:(CGRect)rect{
CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
CGImageRelease(subImage);
return croppedImage;
}