【问题标题】:Convert UIView Layer to UIImage将 UIView 图层转换为 UIImage
【发布时间】:2012-12-25 21:34:49
【问题描述】:

我在视图中使用 AVPlayerLayer 播放视频。我需要将视图转换为图像,我试过了

[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;
}

【问题讨论】:

标签: iphone ios objective-c ipad


【解决方案1】:

您可以将 UIView 保存为文档目录中的图像,例如:

-(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];



}

【讨论】:

  • 我也试过这个。因为那个 View 上的 AVPlayerLayer 只给了我空白图像:(
  • 你的 View 是 self.view 还是 other ?你的视图名称是什么..IBOutlat..?
  • 播放器视图是 IBOutlet。这有什么问题吗?
【解决方案2】:

请尝试以下代码。它非常适合我。

并参考UIKit Function Reference。

+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

也可以试试this。

【讨论】:

  • 我也试过了,但是 img 是黑色和空白的。在您的情况下,您是否在视图上使用了 avplayerlayer?
【解决方案3】:

当用户想要捕获当前视图 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;

}

另请参阅我的这个答案....My Answer

更新:

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];
        }
    }   
}

【讨论】:

  • 我在这个视图中使用了 AVPlayerLayer。如果我尝试将该视图转换为图像,则会给我黑色图像。您是否尝试过带有该视图的 AVPlayerLayer?
  • 是的,有没有我用我的答案测试过的问题,而您在 AVSimpleEditoriOS 演示图像中仅捕获 Avplayer blackScreen,,(
  • @Ganesh 看到这个答案伙计stackoverflow.com/questions/13046936/… 在让我知道你明白了吗??
  • @ParasJoshi 好的,我会试试这个,然后告诉你。
  • @ParasJoshi copyNextSampleBuffer 不起作用。它总是给出 nil 值
【解决方案4】:
-(UIImage *)imagefromview {
    UIGraphicsBeginImageContext(view.frame.size);
    [[self imageFromView:view] drawInRect:view.frame];
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return resultingImage;
}

【讨论】:

    【解决方案5】:

    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;
    }
    

    只需使用视频的路径调用它,然后在您想要获取图像的时间。

    【讨论】:

      【解决方案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;
        }
        

        【讨论】:

        • 我不想捕获所有窗口。我只需要捕获特定的视图,其中包含 AVPlayerLayer 作为子层。当我在 contextref 中渲染 view.layer 时,视频屏幕是黑色的。
        猜你喜欢
        • 2018-01-09
        • 2011-07-25
        • 2016-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-13
        • 1970-01-01
        相关资源
        最近更新 更多