iOS上的CGImage旋转方法内存泄漏

时间:2012-02-22 12:07:18

标签: ios memory rotation memory-leaks cgimage

我有这个代码来旋转CGImage:

- (CGImageRef)rotateCGImageRef:(CGImageRef)imageRef toOrientation:(UIImageOrientation)orientation
{
    CGRect             bnds = CGRectZero;
    CGImageRef         copy = nil;
    CGContextRef       ctxt = nil;
    CGRect             rect = CGRectZero;
    CGAffineTransform  tran = CGAffineTransformIdentity;

    @autoreleasepool {
        bnds.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size;
        rect.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size;

        switch (orientation)
        {
            case UIImageOrientationUp:
                return imageRef;

            case UIImageOrientationUpMirrored:
                tran = CGAffineTransformMakeTranslation(rect.size.width, 0.0);
                tran = CGAffineTransformScale(tran, -1.0, 1.0);
                break;

            case UIImageOrientationDown:
                tran = CGAffineTransformMakeTranslation(rect.size.width, rect.size.height);
                tran = CGAffineTransformRotate(tran, degreesToRadians(180.0));
                break;

            case UIImageOrientationDownMirrored:
                tran = CGAffineTransformMakeTranslation(0.0, rect.size.height);
                tran = CGAffineTransformScale(tran, 1.0, -1.0);
                break;

            case UIImageOrientationLeft:
                bnds.size = swapWidthAndHeight(bnds.size);
                tran = CGAffineTransformMakeTranslation(0.0, rect.size.width);
                tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0));
                break;

            case UIImageOrientationLeftMirrored:
                bnds.size = swapWidthAndHeight(bnds.size);
                tran = CGAffineTransformMakeTranslation(rect.size.height, rect.size.width);
                tran = CGAffineTransformScale(tran, -1.0, 1.0);
                tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0));
                break;

            case UIImageOrientationRight:
                bnds.size = swapWidthAndHeight(bnds.size);
                tran = CGAffineTransformMakeTranslation(rect.size.height, 0.0);
                tran = CGAffineTransformRotate(tran, degreesToRadians(90.0));
                break;

            case UIImageOrientationRightMirrored:
                bnds.size = swapWidthAndHeight(bnds.size);
                tran = CGAffineTransformMakeScale(-1.0, 1.0);
                tran = CGAffineTransformRotate(tran, degreesToRadians(90.0));
                break;

            default:
                // orientation value supplied is invalid
                assert(false);
                return nil;
        }

        UIGraphicsBeginImageContext(bnds.size);
        ctxt = UIGraphicsGetCurrentContext();

        switch (orientation)
        {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                CGContextScaleCTM(ctxt, -1.0, 1.0);
                CGContextTranslateCTM(ctxt, -rect.size.height, 0.0);
                break;

            default:
                CGContextScaleCTM(ctxt, 1.0, -1.0);
                CGContextTranslateCTM(ctxt, 0.0, -rect.size.height);
                break;
        }

        CGContextConcatCTM(ctxt, tran);
        CGContextDrawImage(ctxt, rect, imageRef);

        //copy = UIGraphicsGetImageFromCurrentImageContext();
        copy = CGBitmapContextCreateImage(ctxt);
        UIGraphicsEndImageContext();
    }
    return copy;
}

但分析师说它有泄漏: memory leak

我无法释放复制对象cos我方法正在返回它。

究竟是什么泄漏?

修改 这是转换为C函数的最终代码:

CGImageRef CreateRotatedImage(CGImageRef imageRef, UIImageOrientation orientation)
{
    CGRect             bnds = CGRectZero;
    CGImageRef         copy = nil;
    CGContextRef       ctxt = nil;
    CGRect             rect = CGRectZero;
    CGAffineTransform  tran = CGAffineTransformIdentity;

    bnds.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size;
    rect.size = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); //self.size;

    switch (orientation)
    {
        case UIImageOrientationUp:
            return imageRef;

        case UIImageOrientationUpMirrored:
            tran = CGAffineTransformMakeTranslation(rect.size.width, 0.0);
            tran = CGAffineTransformScale(tran, -1.0, 1.0);
            break;

        case UIImageOrientationDown:
            tran = CGAffineTransformMakeTranslation(rect.size.width, rect.size.height);
            tran = CGAffineTransformRotate(tran, degreesToRadians(180.0));
            break;

        case UIImageOrientationDownMirrored:
            tran = CGAffineTransformMakeTranslation(0.0, rect.size.height);
            tran = CGAffineTransformScale(tran, 1.0, -1.0);
            break;

        case UIImageOrientationLeft:
            bnds.size = swapWidthAndHeight(bnds.size);
            tran = CGAffineTransformMakeTranslation(0.0, rect.size.width);
            tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0));
            break;

        case UIImageOrientationLeftMirrored:
            bnds.size = swapWidthAndHeight(bnds.size);
            tran = CGAffineTransformMakeTranslation(rect.size.height, rect.size.width);
            tran = CGAffineTransformScale(tran, -1.0, 1.0);
            tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0));
            break;

        case UIImageOrientationRight:
            bnds.size = swapWidthAndHeight(bnds.size);
            tran = CGAffineTransformMakeTranslation(rect.size.height, 0.0);
            tran = CGAffineTransformRotate(tran, degreesToRadians(90.0));
            break;

        case UIImageOrientationRightMirrored:
            bnds.size = swapWidthAndHeight(bnds.size);
            tran = CGAffineTransformMakeScale(-1.0, 1.0);
            tran = CGAffineTransformRotate(tran, degreesToRadians(90.0));
            break;

        default:
            // orientation value supplied is invalid
            assert(false);
            return nil;
    }

    UIGraphicsBeginImageContext(bnds.size);
    ctxt = UIGraphicsGetCurrentContext();

    switch (orientation)
    {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            CGContextScaleCTM(ctxt, -1.0, 1.0);
            CGContextTranslateCTM(ctxt, -rect.size.height, 0.0);
            break;

        default:
            CGContextScaleCTM(ctxt, 1.0, -1.0);
            CGContextTranslateCTM(ctxt, 0.0, -rect.size.height);
            break;
    }

    CGContextConcatCTM(ctxt, tran);
    CGContextDrawImage(ctxt, rect, imageRef);

    //copy = UIGraphicsGetImageFromCurrentImageContext();
    copy = CGBitmapContextCreateImage(ctxt);
    UIGraphicsEndImageContext();
    return copy;
}

调用此C函数:

imageRef = CreateRotatedImage(imageRef, UIImageOrientationRight);

3 个答案:

答案 0 :(得分:2)

我认为您的问题是您从Obj-C方法返回CGImageRefCGImageRef是C-struct指针的typedef,而不是NSObject,因此无法自动释放。

我会考虑两个选项 - 将方法转换为C函数或将返回的值放入NSObject(例如UIImage)。

编辑:

CGImageRef CreateRotatedImage(CGImageRef imageRef, UIImageOrientation toOrientation) {
    [... your code ...]
}

呼叫:

CGImageRef rotatedImage = CreateRotatedImage(image, orientation);

答案 1 :(得分:0)

您必须释放CGImageRef copyCFType应该知道如何处理releaseautorelease。试试这个:

return (CGImageRef)[(id)copy autorelease];

首先,您必须将其强制转换为Objective-C指针。接下来,您将其转换回CGImageRef。请参阅此答案:https://stackoverflow.com/a/7061168/656036

答案 2 :(得分:0)

您应该阅读分析仪所说的内容:它是潜在的泄漏。分析器不会告诉您这是否真的是泄漏,以获取从仪器运行泄漏工具所需的信息。

Analyzer正确地警告您,您将返回一个您必须自行释放的值。

在接收功能中,只需拨打

即可
CGImageRelease(img);

完成CGImageRef后。