Преобразование UIView Layer в UIImage
Я воспроизвожу видео, используя AVPlayerLayer в представлении. Мне нужно преобразовать View to Image, я попробовал
[myview.layer renderInContext:context];
но это дает только черное изображение. Я хочу преобразовать это представление в изображение с видео в это время. Это преобразование будет происходить одновременно 0,05 с.
Я попробовал с AVAssetImageGenerator. Это дает мне правильное изображение с помощью Asset. Но это занимает немного больше времени, что делает некоторые проблемы с производительностью в моем приложении. Может ли кто-нибудь помочь мне, как уменьшить процесс преобразования видео в изображение для конкретного CMTime.
Ниже мое кодирование.
- (UIImage *)currentItemScreenShot
{
AVPlayer *abovePlayer = [objVC player];
if(imageGenerator == nil)
{
AVAsset *asset = [[[objVC player] currentItem] asset];
imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
}
CMTime time = [[abovePlayer currentItem] currentTime];
if ([imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceBefore:)] && [imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceAfter:)]) {
[imageGenerator setRequestedTimeToleranceBefore:kCMTimeZero];
[imageGenerator setRequestedTimeToleranceAfter:kCMTimeZero];
}
CGImageRef imgRef = [imageGenerator copyCGImageAtTime:time
actualTime:NULL
error:NULL];
if (imgRef == nil) {
if ([imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceBefore:)] && [imageGenerator respondsToSelector:@selector(setRequestedTimeToleranceAfter:)]) {
[imageGenerator setRequestedTimeToleranceBefore:kCMTimePositiveInfinity];
[imageGenerator setRequestedTimeToleranceAfter:kCMTimePositiveInfinity];
}
imgRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
}
UIImage *image = [UIImage imageWithCGImage:imgRef];
CGImageRelease(imgRef);
image = [self reverseImageByScalingToSize:image.size :image];
return image;
}
Ответы
Ответ 1
MPMoviePlayerController позволяет легко получить изображение из фильма в определенный момент в фильме.
- (UIImage*)imageFromVideoAtPath:(NSString *)path atTime:(NSTimeInterval)time {
NSURL *videoURL = [NSURL fileURLWithPath:path];
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[moviePlayer prepareToPlay];
UIImage *thumbnail = [moviePlayer thumbnailImageAtTime:time timeOption:MPMovieTimeOptionNearestKeyFrame];
[moviePlayer stop];
return thumbnail;
}
Просто назовите это дорожкой видео и в то время, когда вы хотите получить изображение.
Ответ 2
Пожалуйста, попробуйте ввести код ниже. Он отлично работает для меня.
И ссылайтесь на Справочник по функциям UIKit.
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Также попробуйте этот.
Ответ 3
вы можете сохранить свой UIView как изображение в Document Diretory, например:
-(IBAction)ViewTOimage:(id)sender
{
UIGraphicsBeginImageContext(self.view.bounds.size); //instad of self.view you can set your view IBOutlet name
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *saveImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(saveImage);
NSFileManager *fileMan = [NSFileManager defaultManager];
NSString *fileName = [NSString stringWithFormat:@"%d.png",1];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];
[fileMan createFileAtPath:pdfFileName contents:imageData attributes:nil];
}
Ответ 4
Этот код полезен, когда пользователь хочет захватить текущий вид ScreenShot и поделиться или сохранить это изображение....
- (UIImage *)captureView {
//hide controls if needed
CGRect rect = [self.view bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
См. мой этот ответ Также.... Мой ответ
UPDATE:
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:yourURL];
AVPlayer *player = [AVPlayer playerWithPlayerItem:pItem];
//observe 'status'
[playerItem addObserver:self forKeyPath:@"status" options:0 context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"status"]) {
AVPlayerItem *item = (AVPlayerItem *)object;
if (item.status == AVPlayerItemStatusReadyToPlay) {
AVURLAsset *asset = (AVURLAsset *)item.asset;
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
CGImageRef thumb = [imageGenerator copyCGImageAtTime:CMTimeMakeWithSeconds(10.0, 1.0)
actualTime:NULL
error:NULL];
}
}
}
Ответ 5
-(UIImage *)imagefromview {
UIGraphicsBeginImageContext(view.frame.size);
[[self imageFromView:view] drawInRect:view.frame];
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
Ответ 6
Я один из проектов, я использовал приведенный ниже код для получения изображения от воспроизведения видео, это тоже поможет... взгляните и попробуйте настроить код с помощью своих.
#import <AVFoundation/AVFoundation.h>
@property (nonatomic,retain) AVCaptureStillImageOutput * resultImageOutput;
- (UIImage*)stillImageFromVideo
{
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in [[self resultImageOutput] connections]) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo]) {
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
[[self resultImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer,
kCGImagePropertyExifDictionary, NULL);
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
return image;
}
Ответ 7
Попробуйте сделать снимок экрана и отсечение. В противном случае вам может потребоваться рекурсивно отобразить представление и все его подпрограммы.
-(UIImage *)videoScreenCap:(CGRect)cropRect{
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:@"foo.png" atomically:YES];
CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
UIImage * img = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return img;
}