Я пишу приложение для микроскопии для MacOS (самое последнее, Obj-C).
Я использую AVCaptureSession
для предварительного просмотра живого видео с камеры микроскопа на экране, но я также хочу позволить пользователю делать неподвижные изображения, когда они узнают что-то интересное. Я хочу сохранить изображение максимально возможного качества в файл на диске.
Для этого я пытаюсь использовать AVCaptureStillImageOutput
, что по заголовкам - то, что мне нужно. Я настроил его и добавил в сеанс захвата следующим образом:
self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *compressionSettings = @{AVVideoQualityKey : @(1.0)};
NSDictionary *outputSettings = @{ AVVideoCodecKey : AVVideoCodecJPEG,
AVVideoCompressionPropertiesKey : compressionSettings,
AVVideoWidthKey : @(1024),
AVVideoHeightKey : @(768)
};
[self.stillImageOutput setOutputSettings:outputSettings];
[self.session addOutput: stillImageOutput];
Позже, когда пользователь выбирает снимок - я вызываю этот метод, чтобы попытаться захватить неподвижное изображение:
// Capture a single video frame during a video capture
-(BOOL)captureStillImage: (CGRect)cropRect {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
if (videoConnection == nil) { return NO };
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:
^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
CVImageBufferRef imageBufferRef = CMSampleBufferGetImageBuffer(imageSampleBuffer);
if(imageBufferRef==nil) // <<< HERE I ALWAYS GET NULL
return;
NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:imageBufferRef]];
NSImage *compositeImage = [[NSImage alloc] initWithSize:[imageRep size]];
NSImage *videoFrameImage = [[NSImage alloc] initWithSize:[imageRep size]];
[videoFrameImage addRepresentation:imageRep];
NSRect r = NSMakeRect(0.0f, 0.0f, [imageRep size].width, [imageRep size].height);
[compositeImage lockFocus];
[videoFrameImage drawAtPoint:NSMakePoint(0.0f, 0.0f) fromRect:r operation:NSCompositeSourceOver fraction:1.0f];
[compositeImage unlockFocus];
NSData *tiffImageData = [videoFrameImage TIFFRepresentation];
NSBitmapImageRep *tiffRep = [NSBitmapImageRep imageRepWithData:tiffImageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
tiffImageData = [tiffRep representationUsingType:NSJPEGFileType properties:imageProps];
// Save data to file
static NSUInteger imageNumber = 0;
NSString *imageFilePath = [@"/Users/me/Desktop/" stringByAppendingPathComponent: [NSString stringWithFormat:@"image_%lu", imageNumber++]];
imageFilePath = [imageFilePath stringByAppendingPathExtension:@"JPG"];
[tiffImageData writeToFile: imageFilePath atomically: NO];
}];
return YES;
}
Я нашел похожие вопросы других пользователей - но ответы всегда включали: «вы не применили« OutputSettings », как я, - поэтому я действительно озадачен здесь.
В качестве примечания: если я использую «сокращенный» API:
NSData *pixelData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
в моем обратном вызове - это успешно, но pixelData содержит плохое, низкое разрешение и маленькое изображение - конечно, не то качество, которое я вижу в моем предварительном просмотре. Более того - он сжат в формате JPEG, поэтому если я хочу его обрезать, мне нужно будет его декодировать, затем обрезать, а затем снова сжать, что приведет к еще большему снижению и без того низкого качества. Вот почему я пытаюсь использовать объект AVCaptureStillImageOutput
.
Может кто-нибудь пролить свет или направить меня к правильным документам по этому поводу? Я уже уделяю этому слишком много времени, и множество задействованных фреймворков (CoreMedia, CoreVideo, CoreImage, AVFoundation) действительно плохо документированы или имеют какую-либо разумную архитектуру, которую можно понять. Ну и дела, я скучаю по компонентам QuickTime и старой APIS.
Помогите пожалуйста? кто-нибудь?