0

In my app, the user starts out with a UIImage. Based on user input, the app creates a clipping path around a certain part of the image. I then want to be able to save that clipped version to the app's Documents directory so that it can be shown at a later time.

As far as I can tell, all of that is going smoothly except showing the clipped image at a later time. As soon as I try showing the image (by adding a custom view), I get a variety of invalid context errors, as well as a message sent to deallocated instance. While I'm not sure what's causing the last one, it's the invalid context ones that I'm most concerned about because the concept of a graphics context is not something I'm at all comfortable with.

Here are the exact errors:

<Error>: CGBitmapContextSetData: invalid context 0x4b997b0
<Error>: CGContextGetBaseCTM: invalid context 0x4b997b0
<Error>: CGContextConcatCTM: invalid context 0x4b997b0
<Error>: CGContextSetBaseCTM: invalid context 0x4b997b0
<Error>: CGContextSetFillColorSpace: invalid context 0x4b997b0
<Error>: CGContextSetStrokeColorSpace: invalid context 0x4b997b0
*** -[Not A Type retain]: message sent to deallocated instance 0x4b997b0

At this point, I'm going to post the code that creates the clipping path, then the code that attempts to save the context with the clipped image as a new image, and finally the code that is trying to show the image again. As I said above, I don't get an error until I try to show the image again.

Create clipping path:

- (void)drawRect:(CGRect)rect
{   
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);

    //Create clippingPath
    UIBezierPath *edgePath = [[UIBezierPath alloc] init];
    NSValue *firstPt = [edgePts objectAtIndex:0];

    [edgePath moveToPoint:CGPointMake([firstPt CGPointValue].x / scaleRatio, [firstPt CGPointValue].y / scaleRatio + 20)];
    [edgePts removeObject:firstPt];

    for (NSValue *pt in edgePts) {
        [edgePath addLineToPoint:CGPointMake([pt CGPointValue].x / scaleRatio, [pt CGPointValue].y / scaleRatio + 20)];
    }

    clippingPath = edgePath;

    [clippingPath addClip];

    [img drawAtPoint:CGPointMake(0, 20)];

    clippedContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(clippedContext);

    CGContextRestoreGState(ctx);
}

Pretty much everything I'm doing with contexts and contextRefs above is total magic to me. It's something I pieced together from other posts here at SO and have basically no idea what any of it is doing. Shocking that I ended up with all those context errors, huh? ;)

Saving the image and then trying to display it immediately (erros occur on final line):

- (void)saveCutout
{
    CGImageRef clippedImageRef = CGBitmapContextCreateImage(imageView.clippedContext);
    CGContextRelease(imageView.clippedContext);
    UIImage *clippedImage = [UIImage imageWithCGImage:clippedImageRef];
    CGImageRelease(clippedImageRef);

    NSData *imgData = UIImagePNGRepresentation(clippedImage);
    NSString *imgPath = [NSString stringWithFormat:@"%@/1.png", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
    [imgData writeToFile:imgPath atomically:NO];

    //just testing to make sure it worked. first I hide the other two visible views
    imageView.hidden = YES;
    includedFrameView.hidden = YES;

    UIImage *newImg = [[UIImage imageWithContentsOfFile:imgPath] retain];
    ShowImage *imgView = [[ShowImage alloc] initWithFrame:CGRectMake(0, 0, 320, 480) andImage:newImg];

    [self.view addSubview:imgView]; //ERRORS occur once this line runs

}

The ShowImage class is a simple UIView subclass. All it does is get initialized with the specified UIImage, and it's drawRect: method is the following:

- (void)drawRect:(CGRect)rect
{
    [img drawAtPoint:CGPointMake(0, 20)];
}

It's worth noting that the errors occur even before the single line in the drawRect: method above even gets called (I've tried putting a break point on that line but the app crashes first).

I know it's a lot of code, but that's because I don't even know where to start debugging this one. Along with solving my particular issue, I'd love an answer that more broadly addresses my use/misuse of contexts.

maxedison
  • 17,243
  • 14
  • 67
  • 114

1 Answers1

0

Try creating a new context for your drawing, then ending it when you are done doing your drawing. This might fix your context errors.

CGSize mySize = CGSizeMake(rect.size.width,rect.size.height);
UIGraphicsBeginImageContext(mySize);
CGContextRef ctx = UIGraphicsGetCurrentContext();

// The rest of your code goes here...

UIGraphicsEndImageContext();
ozz
  • 1,137
  • 7
  • 9
  • Can you be more specific? Should that code go in the drawRect method in the block of code I posted under "Create clipping path" ? I tried that but now nothing shows up. – maxedison Nov 21 '11 at 23:37