将图像裁剪为叠加层的形状 - iOS
Posted
技术标签:
【中文标题】将图像裁剪为叠加层的形状 - iOS【英文标题】:Cropping an Image to the shape of an Overlay - iOS 【发布时间】:2014-09-09 22:42:01 【问题描述】:我正在使用 pickerController 的视图和 uinavigationcontrollerdelegate 添加叠加层,如下所示。
-(void)navigationController:(UINavigationController *)navigationController didShowViewController: (UIViewController *)viewController animated:(BOOL)animated
if ([navigationController.viewControllers count] == 3)
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
UIView *plCropOverlay = [[[viewController.view.subviews objectAtIndex:1]subviews] objectAtIndex:0];
plCropOverlay.hidden = YES;
int position = 0;
if (screenHeight == 568)
position = 124;
else
position = 80;
CAShapeLayer *circleLayer = [CAShapeLayer layer];
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, position, 320.0f, 320.0f)];
[path2 setUsesEvenOddFillRule:YES];
[circleLayer setPath:[path2 CGPath]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-72) cornerRadius:0];
[path appendPath:path2];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.8;
[viewController.view.layer addSublayer:fillLayer];
当添加上面定义的叠加层时,我倾向于得到这个视图:
我可以使用定义的 CGRect 将图像精确地裁剪为正方形。
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
如果存在圆形叠加层且 imagePickers 编辑属性为 YES,如何解决此问题?我可以放大和缩小图片。我如何在这里使用 BezierPath?
【问题讨论】:
目标到底是什么?您不能以圆形图像结束,所以您只想将覆盖层下的图像擦除为白色?缩放与叠加层有何关系?您已经可以自己处理缩放了吗? UIImage 位于缩放比例为 2.0 的滚动视图之上。当图像被缩放并预计被裁剪时,该覆盖清晰视图内的缩放图像应该被裁剪掉。 是的,要正确缩放非常非常困难。我已经在下面给了你你需要的所有代码! 你好@DesperateLearner 还有什么问题吗?!运气好吗? 【参考方案1】:您的问题addClip
的简短回答,但您提到您是初学者,所以这里是从A 到Z 的所有步骤!!
首先,试试这个类别,看看它是否有帮助。 (如果您不熟悉类别,请使用 google 或在评论中询问。)
-(UIImage *)doMask
UIImage *maskImage = [UIImage imageNamed:@"yourMask.png"];
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef maskedImageRef = CGImageCreateWithMask([self CGImage], mask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
CGImageRelease(mask);
CGImageRelease(maskedImageRef);
return maskedImage;
只需创建(我的意思是在 Photoshop 中)一个 png 蒙版,然后熟悉该过程。
我鼓励你先掌握这个过程......
这里有一些重要的类别会有所帮助...
-(UIImage *)becomeSquare
CGSize imageSize = self.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
UIImage *result = self;
if (width != height)
CGFloat newDimension = MIN(width, height);
CGFloat widthOffset = (width - newDimension) / 2;
CGFloat heightOffset = (height - newDimension) / 2;
UIGraphicsBeginImageContextWithOptions(
CGSizeMake(newDimension, newDimension), NO, 0. );
[result drawAtPoint:CGPointMake(-widthOffset, -heightOffset)
blendMode:kCGBlendModeCopy alpha:1. ];
result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
还有更多...
-(UIImage *)doScale
UIImage *result = self;
CGSize size = CGSizeMake(320,320);
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
[result drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];
result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
-(UIImage *)scaled640AnyShape
if ( self.size.height < 5.0 ) return nil;
if ( self.size.width < 5.0 ) return nil;
UIImage *result = self;
float widthShouldBe = 640.0;
float heightShouldBe = widthShouldBe * ( self.size.height / self.size.width );
CGSize size = CGSizeMake( widthShouldBe ,heightShouldBe );
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
[result drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];
result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
(显然可以根据需要更改硬编码的输出大小。)
请注意,您的最终结果将通过按适当顺序组合来实现,例如:
yourImage = [yourImage doSquare];
yourImage = [yourImage doMask];
一旦你得到它的工作......
然后....
从字面上看,有很多关于 .. 的示例代码,例如 https://***.com/a/13870097/294884 呢
如你所见,你从根本上...
UIGraphicsBeginImageContextWithOptions(...);
UIBezierPath * path = [UIBezierPath
bezierPathWithRoundedRect:imageRect cornerRadius:10.f];
[path addClip];
[yourImage drawInRect:imageRect];
... then ... UIGraphicsGetImageFromCurrentImageContext();
.. see the extensive code above for how to save it and so on.
您只需使用上面的缩放示例正确缩放即可。
还要注意这一点,当您更改“裁剪区域”时...https://***.com/a/17884863/294884
这是该关键技术的一个示例...
-(UIImage *)squareAndSmall
// genius credits: https://***.com/a/17884863/294884
CGSize finalsize = CGSizeMake(640,640);
CGFloat scale = MAX(
finalsize.width/self.size.width,
finalsize.height/self.size.height);
CGFloat width = self.size.width * scale;
CGFloat height = self.size.height * scale;
// for example, the central area....
CGRect imageRect = CGRectMake(
(finalsize.width - width)/2.0f,
(finalsize.height - height)/2.0f,
width, height);
// or, the top area... CGRect imageRect = CGRectMake( 0, 0, width, height);
UIGraphicsBeginImageContextWithOptions(finalsize, NO, 0);
[self drawInRect:imageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
希望对您有所帮助!
【讨论】:
【参考方案2】:发现这个 blog post 条目非常有趣、简洁且易于 Nimit Parekh 关注。
以下代码复制/粘贴到您的“viewcontroller.h”文件中:
#import <UIKit/UIKit.h>
@interface UIImagePickerDemoViewController : UIViewController< UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property(nonatomic,retain) UIImagePickerController *imgPicker;
@property(nonatomic,retain) IBOutlet UIImageView *image_view;
//- (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect;
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage;
@end
以下代码复制/粘贴到“viewcontroller.m”文件中:
// Following method is use for the mask the image.
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
return [UIImage imageWithCGImage:masked];
// Following method is use for Cropping the image for a perticular size.
- (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
UIGraphicsBeginImageContext(rect.size);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(currentContext, 0.0, rect.size.height);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGRect clippedRect = CGRectMake(0, 0, rect.size.width, rect.size.height);
CGContextClipToRect( currentContext, clippedRect);
CGRect drawRect = CGRectMake(rect.origin.x * -1,rect.origin.y * -1,imageToCrop.size.width,imageToCrop.size.height);
CGContextDrawImage(currentContext, drawRect, imageToCrop.CGImage);
CGContextScaleCTM(currentContext, 1.0, -1.0);
UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return cropped;
// Calling the method of maskimage.
//=============================Camera Enable(display)============================================
-(IBAction)next:(id)sender
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
self.imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:self.imgPicker animated:YES];
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
[picker dismissModalViewControllerAnimated:YES];
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
[picker dismissModalViewControllerAnimated:YES];
UIImage *img = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
self.image_view.image=[self maskImage:img withMask:[UIImage imageNamed:@"frame.png"]];
//===============================================================================================
// Calling the method of cropping the image.
//=============================Camera Enable(display)============================================
-(IBAction)next:(id)sender
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
self.imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:self.imgPicker animated:YES];
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
[picker dismissModalViewControllerAnimated:YES];
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
[picker dismissModalViewControllerAnimated:YES];
UIImage *img = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
self.image_view.image = [self imageByCropping:img toRect:CGRectMake(0, 0, 420, 40)];
//===============================================================================================
输出:
Grab the source code here.
【讨论】:
【参考方案3】:我拥有与您完全相同的个人资料图像选择器控制器。这是我的委托代码。我认为你不需要所有东西,但你可以在这里找到一些有用的信息
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
NSString *mediaType = info[UIImagePickerControllerMediaType];
if([mediaType isEqualToString:(NSString *) kUTTypeImage])
UIImage *image = info[UIImagePickerControllerOriginalImage];
UIImage *editedImage = (UIImage *) [info objectForKey:UIImagePickerControllerEditedImage];
CGRect croppingRect = [info[UIImagePickerControllerCropRect] CGRectValue];
if (editedImage)
image = editedImage;
else
CGFloat smaller = 1;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
smaller = 0.9;
CGFloat width = MIN(image.size.width * smaller, image.size.height * (smaller * 0.95));
croppingRect = CGRectMake(0 + (image.size.width - width) / 2,
0 + (image.size.height - width) / 2,
width, width);
UIImage *finalImage = nil;
if (editedImage)
finalImage = [UIImage image:editedImage byScalingAndCroppingForSize:kCroppedImageSize];
else
finalImage = [UIImage image:image byScalingAndCroppingForSize:kCroppedImageSize];
if ([self.imagePickerDelegate respondsToSelector:@selector(profileImagePicker:didSelectImage:)])
[self.imagePickerDelegate profileImagePicker:self didSelectImage:finalImage];
else
NSAssert(nil, @"Delegate should confirm ProfileImagePickerControllerDelegate protocol");
else if ([mediaType isEqualToString:(NSString *) kUTTypeVideo])
NSAssert(nil, @"Movie is not supported");
【讨论】:
以上是关于将图像裁剪为叠加层的形状 - iOS的主要内容,如果未能解决你的问题,请参考以下文章