8

I'm trying to clip a region of an UIView, into a UIImage for later reuse.

I've worked out this code from some snippets:

 CGRect _frameIWant = CGRectMake(100, 100, 100, 100);

 UIGraphicsBeginImageContext(view.frame.size);
 [view.layer renderInContext:UIGraphicsGetCurrentContext()];

 //STEP A: GET AN IMAGE FOR THE FULL FRAME
 UIImage *_fullFrame = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();

 //STEP B: CLIP THE IMAGE
 CGImageRef _regionImage = CGImageCreateWithImageInRect([_fullFrame CGImage], _frameIWant);
 UIImage *_finalImage = [UIImage imageWithCGImage:_regionImage];
 CGImageRelease(_regionImage);

'view' is the UIView which I'm clipping and _finalImage is the UIImage I want.

The code works without problem, however is kind of slow. I believe that some performance could be gained by taking just the portion of the screen directly in Step A.

I'm looking for something like renderInContext: withRect: or UIGraphicsGetImageFromCurrentImageContextWithRect() hehe.

Still haven't found anything yet :(, please help me if you know of some alternative.

1
  • could you reformat? hard to read
    – Rudiger
    Commented Oct 12, 2010 at 20:49

3 Answers 3

7

This method clips a region of the view using less memory and CPU time:

-(UIImage*)clippedImageForRect:(CGRect)clipRect inView:(UIView*)view
{
    UIGraphicsBeginImageContextWithOptions(clipRect.size, YES, 1.f);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -clipRect.origin.x, -clipRect.origin.y);
    [view.layer renderInContext:ctx];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}
0

You could try rasterizing the UIView first:

view.layer.shouldRasterize = YES;

I have limited success using this but is saying that I'm doing the same thing as you (plus the above line) and it works fine. In what context are you doing this in? It may be your performance issue.

EDIT: Also you could try using the bounds of the view instead of the frame of the view. They are not always the same.

1
  • The 'main' context I think. I create a new context on the main thread. :S Commented Nov 16, 2010 at 22:15
0

Swift version of @phix23 solution . adding scale

func clippedImageForRect(clipRect: CGRect, inView view: UIView) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(clipRect.size, true, UIScreen.mainScreen().scale);
    let ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -clipRect.origin.x, -clipRect.origin.y);
    view.layer.renderInContext(ctx!)
    let img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.