Добавление обтравочного контура в UIImage, сохранение обрезанной версии в папке «Документы», а затем ее отображение - PullRequest
0 голосов
/ 18 ноября 2011

В моем приложении пользователь начинает с UIImage. На основе пользовательского ввода приложение создает обтравочный контур вокруг определенной части изображения. Затем я хочу сохранить эту обрезанную версию в каталоге «Документы» приложения, чтобы ее можно было просмотреть позже.

Насколько я могу судить, все это происходит гладко , за исключением , показывающего отсеченное изображение позднее. Как только я пытаюсь показать изображение (добавляя пользовательский вид), я получаю множество ошибок invalid context, а также message sent to deallocated instance. Хотя я не уверен, что является причиной последнего, меня больше всего волнует invalid context, потому что концепция графического контекста мне совсем не нравится.

Вот точные ошибки:

<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

В этот момент я собираюсь опубликовать код, который создает обтравочный контур, затем код, который пытается сохранить контекст с обрезанным изображением как новое изображение, и, наконец, код, который пытается показать изображение снова. Как я уже говорил выше, я не получаю сообщение об ошибке, пока не попытаюсь снова показать изображение.

Создать обтравочный контур:

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

Практически все, что я делаю с контекстами и contextRefs выше, является для меня полной магией. Это то, что я собрал из других постов здесь, в SO, и понятия не имею, что он делает. Шокирующее, что я закончил со всеми этими ошибками контекста, а? ;)

Сохранение изображения с последующей немедленной попыткой его отображения (в последней строке появляются ошибки):

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

}

Класс ShowImage является простым UIView подклассом. Все, что он делает, это инициализируется с указанным UIImage, и это drawRect: метод следующий:

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

Стоит отметить, что ошибки возникают даже до того, как одна строка в drawRect: методе выше даже вызывается (я пытался установить точку останова на этой строке, но сначала приложение вылетает).

Я знаю, что кода много, но это потому, что я даже не знаю, с чего начать отладку этого. Наряду с решением моей конкретной проблемы, я хотел бы получить ответ, который более широко рассматривает мое использование / неправильное использование контекстов.

1 Ответ

0 голосов
/ 18 ноября 2011

Попробуйте создать новый контекст для вашего рисунка, а затем закончите его, когда закончите рисовать. Это может исправить ваши контекстные ошибки.

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

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

UIGraphicsEndImageContext();
...