0

代码如下:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    CGContextRef context = ctx;
    CGContextRetain(context);
    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
    CGContextSetLineCap(context, kCGLineCapButt);
    CGContextSetLineWidth(context, 1);
    CGContextSetRGBStrokeColor(context, 0, 0, 0, 0.8);

    // draw image
    CGContextSaveGState(context);
    CGAffineTransform flipVertical = CGAffineTransformMake(
                                                           1, 0, 0, -1, 0, layer.bounds.size.height
                                                           );
    CGContextConcatCTM(context, flipVertical);

    CGContextDrawImage(context, layer.bounds, imageRef);
    CGContextRestoreGState(context);

    // draw borders
    CGContextAddRect(context, layer.bounds);
    CGContextDrawPath(context, kCGPathStroke);

    CGFloat apertureSize = scaleFactor * (2 * samplingLevel - 1) - 1;
    CGFloat x = self.bounds.size.width / 2 - apertureSize / 2;
    CGFloat y = self.bounds.size.height / 2 - apertureSize / 2;
    CGRect apertureRect = CGRectMake(x, y, apertureSize, apertureSize);

    // draw the aperture
    CGContextSaveGState(context);
    CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);      
    CGContextSetShouldAntialias(context, NO);
    CGContextStrokeRect(context, apertureRect);
    CGContextRestoreGState(context);

    CGContextRelease(context);
}

它崩溃了:

(lldb) thread backtrace
* thread #1: tid = 0x1c03, 0x37537a5c CoreGraphics`argb32_image_mark_rgb32 + 800, stop reason = EXC_BAD_ACCESS (code=1, address=0x7314b0)
frame #0: 0x37537a5c CoreGraphics`argb32_image_mark_rgb32 + 800
frame #1: 0x3750e400 CoreGraphics`argb32_image + 5948
frame #2: 0x313c5894 libRIP.A.dylib`ripl_Mark + 16
frame #3: 0x313ca68a libRIP.A.dylib`ripl_BltImage + 998
frame #4: 0x313c2468 libRIP.A.dylib`ripc_RenderImage + 180
frame #5: 0x313be300 libRIP.A.dylib`ripc_DrawImage + 584
frame #6: 0x3750a928 CoreGraphics`CGContextDelegateDrawImage + 48
frame #7: 0x3750a794 CoreGraphics`CGContextDrawImage + 292
frame #8: 0x00166e34 MyApp`-[MyView drawLayer:inContext:] + 380 at MyView.m:43
frame #9: 0x33f054e4 QuartzCore`-[CALayer drawInContext:] + 116
frame #10: 0x33f04b3e QuartzCore`CABackingStoreUpdate_ + 1782
frame #11: 0x33f04334 QuartzCore`CA::Layer::display_() + 956
frame #12: 0x33f03f60 QuartzCore`CA::Layer::display() + 128

有谁知道为什么?谢谢!我猜它是由 CGImage 或 CGContext 引起的,但它们在调试时都是非空的。我用来更新视图的图像是通过相机捕获生成的。

4

3 回答 3

4

我使用苹果提供的示例代码(AV Foundation Programming Guide)来创建imageRef

UIImage *imageFromSampleBuffer(CMSampleBufferRef sampleBuffer) {

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    // Lock the base address of the pixel buffer.
    CVPixelBufferLockBaseAddress(imageBuffer,0);

    // Get the number of bytes per row for the pixel buffer.
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    // Get the pixel buffer width and height.
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);

    // Create a device-dependent RGB color space.
    static CGColorSpaceRef colorSpace = NULL;
    if (colorSpace == NULL) {
        colorSpace = CGColorSpaceCreateDeviceRGB();
            if (colorSpace == NULL) {
            // Handle the error appropriately.
            return nil;
        }
    }

    // Get the base address of the pixel buffer.
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    // Get the data size for contiguous planes of the pixel buffer.
    size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer);

    // Create a Quartz direct-access data provider that uses data we supply.
    CGDataProviderRef dataProvider =
        CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, NULL);
    // Create a bitmap image from data supplied by the data provider.
    CGImageRef cgImage =
        CGImageCreate(width, height, 8, 32, bytesPerRow,
                        colorSpace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
                        dataProvider, NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);

    // Create and return an image object to represent the Quartz image.
    UIImage *image = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

    return image;
}

注意这一行:

CGDataProviderRef dataProvider =
        CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, NULL);

CMSampleBuffer直接用于创建一个CGImageRef,所以CGImageRef一旦释放缓冲区就会失效。

使用缓冲区数据的副本将解决此问题:

NSData *data = [NSData dataWithBytes:baseAddress length:bufferSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
于 2012-05-29T12:01:17.283 回答
3

我遇到了同样的问题,但问题与 ARC 和正确释放 CGImageRef 有关。确保调用以下内容:

CGImageRelease(imageRef);
于 2012-12-24T02:14:10.727 回答
0

改变

CGDataProviderRef dataProvider =
    CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, NULL);

NSData *data = [NSData dataWithBytes:baseAddress length:bufferSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

真的很有帮助。

于 2014-01-08T10:23:21.310 回答