Another iPhone - CGBitmapContextCreateImage Leak

后端 未结 5 1418
心在旅途
心在旅途 2020-12-10 08:40

Like in this post:

  • iPhone - UIImage Leak, ObjectAlloc Building

I\'m having a similar problem. The pointer from the malloc in create_bitmap

5条回答
  •  青春惊慌失措
    2020-12-10 09:20

    I had this problem and it drove me nuts for a few days. After much digging and noticing a leak in CG Raster Data using Instruments.

    The problem seems to lie inside CoreGraphics. My problem was when i was using CGBitmapContextCreateImage in a tight loop it would over a period of time retain some images (800kb each) and this slowly leaked out.

    After a few days of tracing with Instruments I found a workaround was to use CGDataProviderCreateWithData method instead. The interesting thing was the output was the same CGImageRef but this time there would be no CG Raster Data used in VM by Core graphics and no leak. Im assuming this is an internal problem or were misusing it.

    Here is the code that saved me:

    @autoreleasepool {
        CGImageRef cgImage;
        CreateCGImageFromCVPixelBuffer(pixelBuffer,&cgImage);
    
        UIImage *image= [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationUp];
    
        // DO SOMETHING HERE WITH IMAGE
    
        CGImageRelease(cgImage);
    }
    

    The key was using CGDataProviderCreateWithData in the method below.

    static OSStatus CreateCGImageFromCVPixelBuffer(CVPixelBufferRef pixelBuffer, CGImageRef *imageOut)
        {
            OSStatus err = noErr;
            OSType sourcePixelFormat;
            size_t width, height, sourceRowBytes;
            void *sourceBaseAddr = NULL;
            CGBitmapInfo bitmapInfo;
            CGColorSpaceRef colorspace = NULL;
            CGDataProviderRef provider = NULL;
            CGImageRef image = NULL;
    
            sourcePixelFormat = CVPixelBufferGetPixelFormatType( pixelBuffer );
            if ( kCVPixelFormatType_32ARGB == sourcePixelFormat )
                bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst;
            else if ( kCVPixelFormatType_32BGRA == sourcePixelFormat )
                bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst;
            else
                return -95014; // only uncompressed pixel formats
    
            sourceRowBytes = CVPixelBufferGetBytesPerRow( pixelBuffer );
            width = CVPixelBufferGetWidth( pixelBuffer );
            height = CVPixelBufferGetHeight( pixelBuffer );
    
            CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
            sourceBaseAddr = CVPixelBufferGetBaseAddress( pixelBuffer );
    
            colorspace = CGColorSpaceCreateDeviceRGB();
    
            CVPixelBufferRetain( pixelBuffer );
            provider = CGDataProviderCreateWithData( (void *)pixelBuffer, sourceBaseAddr, sourceRowBytes * height, ReleaseCVPixelBuffer);
            image = CGImageCreate(width, height, 8, 32, sourceRowBytes, colorspace, bitmapInfo, provider, NULL, true, kCGRenderingIntentDefault);
    
            if ( err && image ) {
                CGImageRelease( image );
                image = NULL;
            }
            if ( provider ) CGDataProviderRelease( provider );
            if ( colorspace ) CGColorSpaceRelease( colorspace );
            *imageOut = image;
            return err;
        }
    
        static void ReleaseCVPixelBuffer(void *pixel, const void *data, size_t size)
        {
            CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)pixel;
            CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
            CVPixelBufferRelease( pixelBuffer );
        }
    

提交回复
热议问题