Search code examples
iphoneiosipadquartz-2dmasking

CGContextAddEllipseInRect to CGImageRef to CGImageMaskCreate to CGContextClipToMask


I haven't been able to find one single example on the internets that teaches me how to create a circle on the fly and then use this circle to clip an UIImage.

Here's my code, unfortunately it doesn't give me desired results.

//create a graphics context
UIGraphicsBeginImageContext(CGSizeMake(243, 243));
CGContextRef context = UIGraphicsGetCurrentContext();

//create my object in this context
CGContextAddEllipseInRect(context, CGRectMake(0, 0, 243, 243));
CGContextSetFillColor(context, CGColorGetComponents([[UIColor whiteColor] CGColor]));
CGContextFillPath(context);

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//create an uiimage from the ellipse


//Get the drawing image
CGImageRef maskImage = [image CGImage];

// Get the mask from the image
CGImageRef maskRef = CGImageMaskCreate(CGImageGetWidth(maskImage)
                                    , CGImageGetHeight(maskImage)
                                    , CGImageGetBitsPerComponent(maskImage)
                                    , CGImageGetBitsPerPixel(maskImage)
                                    , CGImageGetBytesPerRow(maskImage)
                                    ,  CGImageGetDataProvider(maskImage)
                                    , NULL
                                    , false);


//finally clip the context to the mask.

CGContextClipToMask( context , CGRectMake(0, 0, 243, 243) , maskRef );


//draw the image
[firstPieceView.image drawInRect:CGRectMake(0, 0, 320, 480)];
// [firstPieceView drawRect:CGRectMake(0, 0, 320, 480)];

//extract a new image
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

NSLog(@"self.firstPieceView is %@", NSStringFromCGRect(self.firstPieceView.frame));
UIGraphicsEndImageContext();


self.firstPieceView.image = outputImage;

I would appreciate any directions.


Solution

  • I suspect you need to rephrase your question better. There's plenty of example code for whatever you're trying to do out there.

    Here's how you could implement a custom UIView subclass to clip am image to an ellipse:

    - (void)drawInRect:(CGRect)rect {
      UIImage image;// set/get from somewhere
      CGImageRef imageRef = [image CGImageRef];
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGContextAddEllipseInRect(context, self.bounds);
      CGContextClip(context);
      CGContextDrawImage(context, self.bounds, imageRef);
    }
    

    caveat emptor


    Edit (a day later, free time produces):

    - (void)drawRect:(CGRect)rect {
      // we're ignoring rect and drawing the whole view
      CGImageRef imageRef = [_image CGImage]; // ivar: UIImage *_image;
      CGContextRef context = UIGraphicsGetCurrentContext();
    
      // set the background to black
      [[UIColor blackColor] setFill];
      CGContextFillRect(context, self.bounds);
    
    
      // modify the context coordinates,
      // UIKit and CoreGraphics are oriented differently
      CGContextSaveGState(context);
        CGContextTranslateCTM(context, 0, CGRectGetHeight(rect));
        CGContextScaleCTM(context, 1, -1);
    
        // add clipping path to the context, then execute the clip
        // this is in effect for all drawing until GState restored
        CGContextAddEllipseInRect(context, self.bounds);
        CGContextClip(context);
    
        // stretch the image to be the size of the view
        CGContextDrawImage(context, self.bounds, imageRef);
      CGContextRestoreGState(context);
    }