【问题标题】:Capture a Screen Shot of UIView - Slow Performance捕获 UIView 的屏幕截图 - 性能缓慢
【发布时间】:2013-01-24 22:57:24
【问题描述】:

我有一个绘图应用程序,我想创建 Canvas UIView(屏幕上和屏幕外)的快照,然后将其缩小。我在 iPad 3 上执行此操作的代码永远是血腥的。模拟器没有延迟。画布为 2048x2048。

还有其他方法我应该这样做吗?还是我在代码中遗漏了什么?

谢谢!

-(UIImage *) createScreenShotThumbnailWithWidth:(CGFloat)width{
        // Size of our View
    CGSize size = editorContentView.bounds.size;


        //First Grab our Screen Shot at Full Resolution
    UIGraphicsBeginImageContext(size);
    [editorContentView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

        //Calculate the scal ratio of the image with the width supplied.
    CGFloat ratio = 0;
    if (size.width > size.height) {
        ratio = width / size.width;
    } else {
         ratio = width / size.height;
    }

        //Setup our rect to draw the Screen shot into 
    CGSize newSize = CGSizeMake(ratio * size.width, ratio * size.height);

        //Send back our screen shot
    return [self imageWithImage:screenShot scaledToSize:newSize];

}

【问题讨论】:

  • 重要的是要记住,模拟器只是一个模拟器,而不是 iPad、iPhone 或 iPod 性能的真实代表。那里的任何代码都可以访问您计算机的全部资源,这将比 iPad 3 强大得多。正如下面 AliSoftware 提到的,在尝试绘制图像之前缩放图像可能是一个更好的主意,这样你就可以剪掉你目前正在做的工作的大约 50%。

标签: ios xcode uiimage thumbnails


【解决方案1】:

您是否使用“时间分析器”工具(“产品”菜单 ->“配置文件”)来检查您在代码中花费最多时间的位置? (当然,将它与您的设备一起使用,而不是模拟器,以获得真实的配置文件)。我猜它不在您在问题中引用的图像捕获部分,而是在您的重新缩放方法imageWithImage:scaledToSize: 方法中。

不要在上下文中以整个大小渲染图像,然后将图像重新缩放到最终大小,您应该通过对上下文应用一些仿射变换直接以预期大小在上下文中渲染图层。

因此,只需在UIGraphicsBeginImageContext(size); 行之后的UIGraphicsGetCurrentContext() 上使用CGContextConcatCTM(someScalingAffineTransform);,即可应用缩放仿射变换,使图层以不同的比例/大小呈现。 p>

这样,它将直接渲染为预期的大小,速度会更快,而不是以 100% 渲染,然后让您以耗时的方式重新调整它 p>

【讨论】:

  • 感谢您的建议。这是我目前的解决方案的一个很好的线索。使用CGContextConcatCTM 我可以减少一秒钟的时间。虽然我最终使用了UIGraphicsBeginImageContextWithOptions,它缩短了 2 秒。
  • UIGraphicsBeginImageContextWithOptions 似乎在做我想做的事,尽管图像的物理尺寸从未改变。我确实最终使用了CGContextConcatCTM 谢谢
  • UIGraphicsBeginImageContextWithOptions中的scale参数影响像素点比(即非视网膜为1,视网膜为2),而不是渲染大小的变换矩阵,所以当然,图像的物理尺寸不受此影响。这就是为什么我建议CGContextConcatCTM(ctx,CGAffineTransformMakeScale(ratio,ratio)) 而不是这个。
【解决方案2】:

谢谢AliSoftware,这是我最终使用的代码:

    -(UIImage *) createScreenShotThumbnailWithWidth:(CGFloat)width{
        if (IoUIDebug & IoUIDebugSelectorNames) {
            NSLog(@"%@ - %@", INTERFACENAME, NSStringFromSelector(_cmd) );
        }
            // Size of our View
        CGSize size = editorContentView.bounds.size;

            //Calculate the scal ratio of the image with the width supplied.
        CGFloat ratio = 0;
        if (size.width > size.height) {
            ratio = width / size.width;
        } else {
            ratio = width / size.height;
        }
        CGSize newSize = CGSizeMake(ratio * size.width, ratio * size.height);

            //Create GraphicsContext with our new size
        UIGraphicsBeginImageContext(newSize);

            //Create Transform to scale down the Context
        CGAffineTransform transform = CGAffineTransformIdentity;
        transform = CGAffineTransformScale(transform, ratio, ratio);

            //Apply the Transform to the Context
        CGContextConcatCTM(UIGraphicsGetCurrentContext(),transform);

            //Render our Image into the the Scaled Graphic Context
        [editorContentView.layer renderInContext:UIGraphicsGetCurrentContext()];

            //Save a copy of the Image of the Graphic Context
        UIImage* screenShot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return screenShot;

    }

【讨论】:

  • renderInContext: 现在是吃时间的人了。 Instruments 说 renderSubLayers 大约 800ms,foregroundLayer 大约 800ms。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 2012-01-20
  • 2014-03-07
  • 2018-05-06
  • 2011-01-13
相关资源
最近更新 更多