【问题标题】:Non-null invalid context error when creating a UIImage from a UIView从 UIView 创建 UIImage 时出现非 null 无效上下文错误
【发布时间】:2012-04-25 04:30:08
【问题描述】:

我正在使用以下内容从 UIView 生成 UIImage

UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, [[UIScreen mainScreen] scale]);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

这通常有效,但大约有一半的时间,当调用 renderInContext 时出现此错误:

<Error>: CGContextDrawImage: invalid context 0x84d0b20

有谁知道为什么会发生这种情况或如何检测它何时发生?我想如果上下文的地址是 0x0 我会感觉更好,因为它至少是我可以测试和处理的东西,但到目前为止这让我很难过。

编辑:哎呀。意味着使用 view.frame.size 而不是 view.bounds.size。

【问题讨论】:

  • 你明白了吗?我也收到非空无效上下文错误...我从UIGraphicsGetImageFromCurrentImageContext() 得到的 UIImage 看起来不错...
  • 很遗憾,没有。我想我将不得不求助于重新绘制我试图用绘图命令捕获的东西。
  • @minovsky 我遇到了同样的上下文问题,但我的情况有点不同。无论如何,就我而言,这是 UIGraphicsPushContext/UIGraphicsPopContext 平衡的问题。我弹出的不仅仅是推送,当我尝试对该上下文执行任何操作时(即使它在使用之前被推送) - 出现了 Invalid Context 错误。

标签: iphone uiview uiimage cgcontext


【解决方案1】:

如果您创建一个宽度或高度为零的上下文,则该上下文将无效。如果视图大小在任一轴上为零,则可能发生这种情况,如果视图为nil

另外,由于您正在渲染一个图层,您可能希望获得 layer 边界和比例,而不是 视图边界屏幕比例。大多数情况下,这些值是相同的,但最好考虑到它们不同的时候。

// Debugging output to see how if an invalid context is being created due to zero size.
NSLog(@"View = %@", view);
NSLog(@"View size = %@", NSStringFromCGSize(view.bounds.size));

UIGraphicsBeginImageContextWithOptions(view.layer.bounds.size, YES, view.layer.contentsScale);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

【讨论】:

  • 我会试试的。我发布的代码实际上有一个错误;我实际上使用的是 view.frame.size 而不是边界。不过,我会尝试图层边界。我知道视图和尺寸是有效的,因为我有代码可以打印出它们的值。另一件事也是,这不会一直发生。
  • 如果您向UIGraphicsBeginImageContextWithOptions 发送有效参数,则问题可能在此代码之外。有可能以仅在损坏完成后才可见的方式损坏图形状态。你有没有看到invalid context error when drawing a UIImage,有人建议调用CGContextSaveGState 可能会导致它,而问题原来是CALayer 无论如何都不需要?
  • 另外,你是在主线程上调用它吗? UIKit Function Reference 指定它不能在其他任何地方调用。
  • 这是在主线程上调用的。我认为这不是常规之外的事情,因为它是一个非常简单的应用程序(如果您从事统计分析,则应用程序商店中的 TC-Stats)。我并没有对 UIViews 和其他东西做任何奇怪的事情。实际上,代码的用途是将现有视图(例如 UITableView)导出为 PNG 文件。
  • 之后你是否碰巧在任何地方绘制了该 PNG 文件?当我故意构造一个无效的上下文并将一个层告诉renderInContext 时,我会收到几十个invalid context 错误,其中一个来自CGContextSaveGState。您是否只收到来自CGContextDrawImage 的一个错误?作为一个实验,此时尝试创建一个无效的上下文(使用CGSizeZero 而不是正确的大小)。您应该得到invalid context 错误,但它们是否来自同一来源?
【解决方案2】:

我有一个类似的问题,但能够通过在我的图层渲染其内容之前推送和弹出图像上下文来解决它。

试试这样的:

UIImage *snapshotImage = nil;
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, view.layer.contentsScale);
{
    CGContextRef imageContext = UIGraphicsGetCurrentContext();

    if (imageContext != NULL) {
        UIGraphicsPushContext(imageContext);
        {
            [view.layer renderInContext:imageContext];
        }
        UIGraphicsPopContext();
    }

    snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();

值得一提的是,还有其他(并且更有效)的方法来获取快照,但它仍处于 NDA 之下。

【讨论】:

  • 谢谢!我将接受这个答案,因为您实际上已经看到了这个问题并有一个解决方法。我假设替代方案在 iOS 7 下?我在 iOS 5 下遇到了这个错误,但最终通过使用 CoreGraphics 手动绘制所有内容来解决它。
  • 是的。如果您有权访问 iOS7 文档,请查看添加到 UIView 的一些新方法 :)
  • 酷!它也适用于我。但是有人可以解释为什么它会起作用吗?
【解决方案3】:
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

希望对你有所帮助....

【讨论】:

  • 当你释放当前图形上下文引用时会发生这种情况。如果你像CGContextRef Context = UIGraphicsGetCurrentContext()一样制作上下文,那么你不应该释放Context,如果你想释放它而不是使用CGBitmapContextCreate来创建上下文,否则它将总是给你&lt;Error&gt;: CGContextDrawImage: invalid context 0x84d0b20
  • 我没有任何代码可以释放除 UIGraphicsEndImageContext 之外的上下文。你是说我应该改用 CGBitmapContextCreate 并在完成后显式释放它?
  • 是的,但是这段代码对我来说也可以正常工作...我在运行时获取屏幕截图..
  • 是的,我也这样做,但有时,我会收到无效的上下文错误,这就是我最终要追查的原因。
  • @Vince ;我建议您显示更多代码..可能是由于其他原因而出现错误..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多