代码之家  ›  专栏  ›  技术社区  ›  nacho4d

将CVImageBufferRef转换为PNG

  •  4
  • nacho4d  · 技术社区  · 14 年前

    我想使用将所有帧写入磁盘QTKit.框架用于摄像头输入。但是我得到的所有图像都是半透明的,没有一些颜色,可能是颜色空间的问题?;( 它们在预览视图中看起来不错,但是当我写它们的时候“有些事情”发生了。

    -(void)savePNGImage:(CGImageRef)imageRef path:(NSString *)path {
        NSURL *outURL = [[NSURL alloc] initFileURLWithPath:path]; 
        CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((CFURLRef)outURL, (CFStringRef)@"public.png" , 1, NULL);
        CGImageDestinationAddImage(dr, imageRef, NULL);
        CGImageDestinationFinalize(dr);
        [outURL release];
    }
    -(void)saveJPEGImage:(CGImageRef)imageRef path:(NSString *)path {
        CFMutableDictionaryRef mSaveMetaAndOpts = CFDictionaryCreateMutable(nil, 0,
                                                                        &kCFTypeDictionaryKeyCallBacks,  &kCFTypeDictionaryValueCallBacks);
        CFDictionarySetValue(mSaveMetaAndOpts, kCGImageDestinationLossyCompressionQuality, 
                             [NSNumber numberWithFloat:1.0]);   // set the compression quality here
        NSURL *outURL = [[NSURL alloc] initFileURLWithPath:path];
        CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((CFURLRef)outURL, (CFStringRef)@"public.jpeg" , 1, NULL);
        CGImageDestinationAddImage(dr, imageRef, mSaveMetaAndOpts);
        CGImageDestinationFinalize(dr);
        [outURL release];
    }
    
    
    - (void)captureOutput:(QTCaptureOutput *)captureOutput 
      didOutputVideoFrame:(CVImageBufferRef)videoFrame 
         withSampleBuffer:(QTSampleBuffer *)sampleBuffer 
           fromConnection:(QTCaptureConnection *)connection{
    
        CVPixelBufferLockBaseAddress(videoFrame,0); 
        uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(videoFrame); 
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoFrame); 
        size_t width = CVPixelBufferGetWidth(videoFrame); 
        size_t height = CVPixelBufferGetHeight(videoFrame); 
        CVPixelBufferUnlockBaseAddress(videoFrame,0);
    
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
        CGContextRef newContext = CGBitmapContextCreate(baseAddress, 
                                                            width, height, 8, 
                                                            bytesPerRow, 
                                                            colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
            CGImageRef frame = CGBitmapContextCreateImage(newContext); 
    
        CGContextRelease(newContext); 
        CGColorSpaceRelease(colorSpace);
    
        [self savePNGImage:frame path:[NSString stringWithFormat:@"/Users/nacho4d/Desktop/framesCam/frame%003d.png", frameNum++]];
    [self saveJPEGImage:frame path:[NSString stringWithFormat:@"/Users/nacho4d/Desktop/framesCam/frame%003d.jpeg", frameNum++]];
    
        CGImageRelease(frame);
    }
    

    捕获器属性只是帧大小和像素格式,如下所示: [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB], (id)kCVPixelBufferPixelFormatTypeKey

    我也尝试过JPEG,我得到了同样的图像,像是图像中缺少一些通道,所有写入的帧都有白色背景。(因为JPEG不允许透明??)

    alt text alt text (我不显示PNG,因为它是透明的,很难在浏览器中看到)

    提前谢谢。

    3 回复  |  直到 13 年前
        1
  •  3
  •   jakeva    13 年前

    我不知道你的问题是什么,但下面是我如何保存图像到磁盘。只需传入从委托方法获得的CVImageBufferRef,当然还有您自己的URL,它应该可以正常工作。至少对我来说是这样。祝你好运!

    -(void)saveImage:(CVImageBufferRef)image toURL:(NSURL*)url{
    
        NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:image]];
    
        NSImage *_image = [[NSImage alloc] initWithSize:[imageRep size]];
        [_image addRepresentation:imageRep];
    
        NSData *bitmapData = [_image TIFFRep    resentation];
        NSBitmapImageRep *bitmapRep = [NSBitmapImageRep imageRepWithData:bitmapData];
        NSData *imageData = [bitmapRep representationUsingType:NSJPEGFileType properties:nil];
    
        [_image release];
        _image = [[NSImage alloc] initWithData:imageData];
    
        NSBitmapImageRep *imgRep = [[_image representations] objectAtIndex: 0];
        NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
        [data writeToFile: [self getSaveString] atomically: NO];
    
        [_image release];
    }
    
        2
  •  1
  •   jjwchoy    13 年前

    CVPixelBufferUnlockBaseAddress(videoFrame,0);
    

    到最后

        3
  •  1
  •   Dave Branton    10 年前

    我做了一些类似的事情,看到了同样的问题。我稍微修改了你的代码 kCGImageAlphaPremultipliedFirst kCGImageAlphaNoneSkipFirst . 大概是因为帧不包含alpha,即使它是每像素32位,这就解决了我的问题。