Cropping an Image to the shape of an Overlay - iOS

前端 未结 3 554
悲哀的现实
悲哀的现实 2021-02-14 17:27

I\'m adding the overlay using pickerController\'s view and the uinavigationcontrollerdelegate as below.

-(void)navigationController:(UINavigationController *)nav         


        
3条回答
  •  失恋的感觉
    2021-02-14 17:59

    the short answer to your question addClip , but you mention you're a beginner, so here's all the steps from A to Z!!

    Firstly, try this category, see if it helps. (If you're not familiar w/ categories have a google or just ask here in a comment.)

    -(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;
        }
    

    just create (I mean in photoshop) a png mask, and get familiar with that process.

    I encourage you to master that process first...

    Here are critical categories that will help...

    -(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;
        }
    

    and a couple more ...

    -(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;
        }
    

    (obviously change the hard-coded output sizes as you wish.)

    Note that your final result, will be achieved, by a combination in the appropriate order, such as:

    yourImage = [yourImage doSquare];
    yourImage = [yourImage doMask];
    

    once you've got that working ...

    Then ....

    for LITERALLY what you ask, there are many example codes about .. e.g., what about https://stackoverflow.com/a/13870097/294884

    As you can see, you fundamentally...

    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.
    

    You just have to get the zoom right with the scaling examples above.

    Also note this, when you are changing the "area cropped"... https://stackoverflow.com/a/17884863/294884

    here's an example of that critical technique...

    -(UIImage *)squareAndSmall
        {
        // genius credits: https://stackoverflow.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;
        }
    

    Hope it all helps!

提交回复
热议问题