0

ディスクから画像をロードし、それらをCVPixelBufferRefに変換し、いくつかのことを行ってから、 UIImageに変換してディスクに保存します。必要なものをすべて確実に解放するように努めましたが、アプリのメモリ使用量はクラッシュするまで常に増加します。

for (//iterate through images) {
    CVPixelBufferRef pixelBuffer = [self pixelBufferFromCGImage:image.CGImage];
    // do some stuff
    UIImage *newImage = [self imageFromPixelBuffer:pixelBuffer];
    CVPixelBufferRelease(pixelBuffer);
}

私が使用する2つの方法は次のとおりです。

- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image {

    CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
    CVPixelBufferRef pxbuffer = NULL;

    CVReturn status = CVPixelBufferCreate(
                        kCFAllocatorDefault, frameSize.width, frameSize.height,
                        kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef)options,
                        &pxbuffer);
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);

    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(
                                                 pxdata, frameSize.width, frameSize.height,
                                                 8, CVPixelBufferGetBytesPerRow(pxbuffer),
                                                 rgbColorSpace,
                                                 (CGBitmapInfo)kCGBitmapByteOrder32Little |
                                                 kCGImageAlphaPremultipliedFirst);

    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

    CGImageRelease(image);

    return pxbuffer;
}

- (UIImage *)imageFromPixelBuffer:(CVPixelBufferRef)pixelBuffer {
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef myImage = [context createCGImage:ciImage fromRect:CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer))];
    UIImage *image = [UIImage imageWithCGImage:myImage];

    CGImageRelease(myImage);

    return image;
}

もちろん、実際のアプリケーションでは、まったく同じ画像を保存するだけでなく、最初の画像から新しいピクセル バッファーを作成し、それらの画像をすべて保存します。ただし、この些細な例でもメモリ増加の問題は存在します。

私は何か初歩的なことを見逃しているに違いありません。これは私を夢中にさせています。

4

2 に答える 2

0

Instruments でアプリをビルドして開き、Leaks インストゥルメントを選択して、アプリを実行します。

追跡できるメモリリークが表示されます。

実際にリークがない場合は、より微妙な問題があります。Allocations インストゥルメントを実行し、アプリを実行すると、(説明していることから) 段階的なランプが表示されます。ランプの領域を選択し、すべての新しい割り当てを調べます。パターンが見え始めます。同様に表示される割り当てのグループです。これらは、解放されていない割り当てがコードのどこで発生しているかについての手がかりを与えてくれます。

于 2017-01-12T23:58:26.563 に答える
-1

行を削除しCGImageRelease(image)ます。image.CGImageの引数として using を参照しているだけですpixelBufferFromCGImage:。つまり、あなたはそれを作成したり保持したりしているのではないので、それを解放する責任はありません。

于 2017-01-12T19:21:31.493 に答える