发布
社区首页 >问答首页 >UIImage是从CMSampleBufferRef创建的,没有在UIImageView中显示?

UIImage是从CMSampleBufferRef创建的,没有在UIImageView中显示?
EN

Stack Overflow用户
提问于 2010-07-22 04:54:11
回答 5查看 26.5K关注 0票数 23

我正在尝试实时显示来自相机的UIImage,而我的UIImageView似乎没有正确地显示图像。这是AVCaptureVideoDataOutputSampleBufferDelegate必须实现的方法。

代码语言:javascript
代码运行次数:0
复制
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
       fromConnection:(AVCaptureConnection *)connection
{ 
    // Create a UIImage from the sample buffer data
    UIImage *theImage = [self imageFromSampleBuffer:sampleBuffer];
//    NSLog(@"Got an image! %f %f", theImage.size.width, theImage.size.height);
//    NSLog(@"The image view is %@", imageView);
//    UIImage *theImage = [[UIImage alloc] initWithData:[NSData 
//        dataWithContentsOfURL:[NSURL 
//        URLWithString:@"http://farm4.static.flickr.com/3092/2915896504_a88b69c9de.jpg"]]];
    [self.session stopRunning];
    [imageView setImage: theImage];
}

为了解决这些简单的问题:

  • 使用UIImagePickerController不是一种选择(最终我们将实际使用图像)
  • 我知道正在调用处理程序(发出了NSLog调用,我看到了输出)
  • 我知道我已经正确地设置了IBOutlet声明。如果我使用上面的注释代码从web加载任意图像,而不是简单地将setImage:theImage发送到imageView,则图像将正确加载(第二次对NSLog的调用报告一个非零对象)。
  • 至少在基本程度上,我从imageFromSampleBuffer:获得的图像是很好的,因为NSLog报告的大小是360x480,这是我预期的大小。

我使用的代码是最近发布的苹果可用AVFoundation这里片段。

特别是,这是我使用的代码,用于设置AVCaptureSession对象和朋友(我对这些代码了解甚少),并从核心视频缓冲区(即imageFromSampleBuffer方法)创建UIImage对象。

最后,如果我尝试将drawInRect:发送到一个普通的UIView子类中,并使用由imageFromSamplerBuffer返回的UIImage,那么应用程序就会崩溃,而如果我使用来自URL的UIImage,则不会崩溃。下面是崩溃内部调试器的堆栈跟踪(我得到了一个EXC_BAD_ACCESS信号):

代码语言:javascript
代码运行次数:0
复制
#0  0x34a977ee in decode_swap ()
#1  0x34a8f80e in decode_data ()
#2  0x34a8f674 in img_decode_read ()
#3  0x34a8a76e in img_interpolate_read ()
#4  0x34a63b46 in img_data_lock ()
#5  0x34a62302 in CGSImageDataLock ()
#6  0x351ab812 in ripc_AcquireImage ()
#7  0x351a8f28 in ripc_DrawImage ()
#8  0x34a620f6 in CGContextDelegateDrawImage ()
#9  0x34a61fb4 in CGContextDrawImage ()
#10 0x321fd0d0 in -[UIImage drawInRect:blendMode:alpha:] ()
#11 0x321fcc38 in -[UIImage drawInRect:] ()

编辑:下面是关于该代码返回的UIImage的更多信息。

使用描述的这里方法,我可以找到像素并打印它们,乍一看它们看起来还不错(例如,alpha通道中的每个值都是255 )。但是,缓冲区的大小略有不同。我从那个URL中得到的Flickr图像是375x500,它的[pixelData length]给了我750000 = 375*500*4,这是期望值。然而,从imageFromSampleBuffer:返回的图像像素数据具有691208 = 360*480*4 + 8大小,因此像素数据中有8个额外的字节。CVPixelBufferGetDataSize本身返回的值为8.我曾经想过,这可能是由于在内存中对齐位置分配缓冲区,但是691200是256个的倍数,所以这也解释不了这一点。这种大小的差异是我唯一能看出的两个UIImages之间的差异,而且它可能会引起麻烦。但是,没有理由为缓冲区分配额外的内存会导致EXC_BAD_ACCESS冲突。

非常感谢您的帮助,如果您需要更多的信息,请告诉我。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-07-26 13:47:32

我也有同样的问题..。但是我找到了这个旧帖子,它创建CGImageRef的方法很管用!

http://forum.unity3d.com/viewtopic.php?p=300819

下面是一个工作样本:

代码语言:javascript
代码运行次数:0
复制
app has a member UIImage theImage;

// Delegate routine that is called when a sample buffer was written
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer  fromConnection:(AVCaptureConnection *)connection
{
        //... just an example of how to get an image out of this ...

    CGImageRef cgImage = [self imageFromSampleBuffer:sampleBuffer];
    theImage.image =     [UIImage imageWithCGImage: cgImage ];
    CGImageRelease( cgImage );
}

- (CGImageRef) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer // Create a CGImageRef from sample buffer data
{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer,0);        // Lock the image buffer 

    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);   // Get information of the image 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 
    CGContextRelease(newContext); 

    CGColorSpaceRelease(colorSpace); 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 
    /* CVBufferRelease(imageBuffer); */  // do not call this!

    return newImage;
}
票数 41
EN

Stack Overflow用户

发布于 2012-02-02 04:17:04

现在,苹果的技术问答QA1702很好地解释了视频帧的实时捕捉:

index.html

票数 10
EN

Stack Overflow用户

发布于 2012-10-19 11:30:53

设置正确的输出格式也很重要。当使用默认格式设置时,我在图像捕获方面遇到了问题。它应该是:

代码语言:javascript
代码运行次数:0
复制
[videoDataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey]];
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3305862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档