Преобразование 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;
}