iOS:在屏幕上捕获 CAEmitterLayer 粒子

Posted

技术标签:

【中文标题】iOS:在屏幕上捕获 CAEmitterLayer 粒子【英文标题】:iOS: capturing CAEmitterLayer particles on screen 【发布时间】:2012-08-01 15:12:43 【问题描述】:

有没有办法在捕获 ios 设备屏幕时捕获 CAEmitterCells(使用 CAEmitterLayer 生成)?UIGetScreenImage() 有效,但由于它是私有方法,因此我不允许使用它.UIGraphicsBeginImageContext 似乎不起作用,只是从生成的图像中省略了粒子。

编辑: 这是我目前用来捕获视图的代码。实际上,我正在使用 aroth 在here 提供的代码录制一段 30 秒长的屏幕视频。它每秒记录 25 个自身的图像(它的一个 UIView 子类)及其子视图(在我们的例子中包括其层是 CAEmitterLayer 的 UIView),并使用 AVAssetWriter 来组成记录。 有点拗口,所以我就把相关的行放在这里: 我使用 XCode 中的 ARC 工具对代码进行了 ARC 编辑,因此代码在内存管理方面可能有点不同。

- (CGContextRef) createBitmapContextOfSize:(CGSize) size 
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    bitmapBytesPerRow   = (size.width * 4);
    bitmapByteCount     = (bitmapBytesPerRow * size.height);
    colorSpace = CGColorSpaceCreateDeviceRGB();
    if (bitmapData != NULL) 
        free(bitmapData);
    
    bitmapData = malloc( bitmapByteCount );
    if (bitmapData == NULL) 
        fprintf (stderr, "Memory not allocated!");
        return NULL;
    

    context = CGBitmapContextCreate (bitmapData,
                                     size.width,
                                     size.height,
                                     8,      // bits per component
                                     bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaNoneSkipFirst);

    CGContextSetAllowsAntialiasing(context,NO);
    if (context== NULL) 
        free (bitmapData);
        fprintf (stderr, "Context not created!");
        return NULL;
    
    CGColorSpaceRelease( colorSpace );

    return context;


//static int frameCount = 0;            //debugging
- (void) drawRect:(CGRect)rect 
    NSDate* start = [NSDate date];
    CGContextRef context = [self createBitmapContextOfSize:self.frame.size];

    //not sure why this is necessary...image renders upside-down and mirrored
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, self.frame.size.height);
    CGContextConcatCTM(context, flipVertical);

    [self.layer renderInContext:context];

    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    UIImage* background = [UIImage imageWithCGImage: cgImage];
    CGImageRelease(cgImage);

    self.currentScreen = background;

    //debugging
    //if (frameCount < 40) 
    //      NSString* filename = [NSString stringWithFormat:@"Documents/frame_%d.png", frameCount];
    //      NSString* pngPath = [NSHomeDirectory() stringByAppendingPathComponent:filename];
    //      [UIImagePNGRepresentation(self.currentScreen) writeToFile: pngPath atomically: YES];
    //      frameCount++;
    //

    //NOTE:  to record a scrollview while it is scrolling you need to implement your UIScrollViewDelegate such that it calls
    //       'setNeedsDisplay' on the ScreenCaptureView.
    if (_recording) 
        float millisElapsed = [[NSDate date] timeIntervalSinceDate:startedAt] * 1000.0;
        [self writeVideoFrameAtTime:CMTimeMake((int)millisElapsed, 1000)];
    

    float processingSeconds = [[NSDate date] timeIntervalSinceDate:start];
    float delayRemaining = (1.0 / self.frameRate) - processingSeconds;

    CGContextRelease(context);

    //redraw at the specified framerate
    [self performSelector:@selector(setNeedsDisplay) withObject:nil afterDelay:delayRemaining > 0.0 ? delayRemaining : 0.01];

真的希望这会有所帮助。感谢您的支持!

【问题讨论】:

顺便说一句——你可以为CGBitmapContextCreate()data参数传递NULL,在这种情况下数据将由CG自动分配/释放跨度> 另外,我在这个 sn-p 中没有看到你的渲染代码? 你能解决这个问题吗? 【参考方案1】:

您是否尝试过使用-[CALayer renderInContext:]

【讨论】:

我认为他想要整个屏幕图像。啊,所以也许你的意思是渲染他想要的视图(可能包含 CAEmitterLayer)。这听起来很有希望。 进一步考虑,UIWindow 也是一个UIView,因此有一个支持层——你也许可以渲染它。 我的想法是,如果他可以在一个图像中获得所有其他内容,他也许可以让 CAEmitterLayer 渲染为透明图像,它们将其覆盖在第一张图像上以获得合成。你必须跳过箍来渲染一个 CATiledLayer(问我是怎么知道的 :-) @nielsbot 确实我做到了,我更新了我的问题,以便更清楚我的目标是什么。我确实尝试了 UIWindow 渲染,没有帮助。 @David H 您能否详细说明将 CAEmitterLayer 渲染为透明图像?具体怎么做呢? :) 顺便感谢您的想法!

以上是关于iOS:在屏幕上捕获 CAEmitterLayer 粒子的主要内容,如果未能解决你的问题,请参考以下文章

iOS 使用 CAEmitterLayer 创建落叶动画

只运行一次 CAEmitterLayer

iOS之CAEmitterLayer粒子引擎

用于从屏幕捕获视频的 iOS 应用

iOS 烟花撒花效果,图层渐变,图层倒影特效。CAEmitterLayer粒子发射器

CAEmitterLayer