【问题标题】:UIImage from SKTexture来自 SKTexture 的 UIImage
【发布时间】:2014-01-11 10:38:23
【问题描述】:

如何从SKTexture获取UIImage

我尝试从SKTextureAtlas 获取UIImage,但似乎也不起作用:

// p40_prop1 is a part of SKTextureAtlas
UIImage *image = [UIImage imageNamed:@"p40_prop1"];

image 为零。

【问题讨论】:

  • 您应该将 MutantJedi 的答案标记为已接受。

标签: objective-c uiimage sprite-kit sktexture


【解决方案1】:

从 iOS 9 开始,这是小菜一碟。 SKTexture 现在有 CGImage 属性,它是 CGImageRef 类型。所以从纹理中获取图像现在只需一行:

let image : UIImage = UIImage(CGImage:texture.CGImage)

【讨论】:

  • 上述泄漏内存顺便说一句,您需要添加对 CGImageRelease(texture.CGImage) 的调用,尽管这似乎是一个错误。
【解决方案2】:

这似乎对我有用:

- (UIImage*) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);

    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return img;
}


- (UIImage*) imageFromNode:(SKNode*)node
{
    SKTexture*      tex     = [self.scene.view textureFromNode:node];
    SKView*         view    = [[SKView alloc]initWithFrame:CGRectMake(0, 0, tex.size.width, tex.size.height)];
    SKScene*        scene   = [SKScene sceneWithSize:tex.size];
    SKSpriteNode*   sprite  = [SKSpriteNode spriteNodeWithTexture:tex];
    sprite.position = CGPointMake( CGRectGetMidX(view.frame), CGRectGetMidY(view.frame) );
    [scene addChild:sprite];
    [view presentScene:scene];

    return [self imageWithView:view];
}
  1. 使用当前 SKView 为您的节点获取 SKTexture
  2. 制作另一个刚好适合您的纹理的 SKView
  3. 将带有纹理的 SKSpriteNode 添加到新场景中,并将其放在中间
  4. 将视图渲染到图形上下文中

或者对于那些更喜欢 Swift 的人:

func imageWithView(view : UIView) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
    view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
    let img = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return img
}

func imageFromNode(node : SKNode) -> UIImage? {
    if let tex = self.scene?.view?.textureFromNode(node) {
        let view = SKView(frame:CGRectMake(0, 0, tex.size().width, tex.size().height))
        let scene = SKScene(size: tex.size())
        let sprite  = SKSpriteNode(texture: tex)
        sprite.position = CGPoint(x: CGRectGetMidX(view.frame), y: CGRectGetMidY(view.frame))
        scene.addChild(sprite)
        view.presentScene(scene)
        return self.imageWithView(view)
    }
    return nil
}

【讨论】:

    【解决方案3】:

    实际上有一种方法可以从 iOS 7.0 中的 SKView 中获取 UIImage!

    它使用常规的 UIView API 将视图渲染到 ImageContext 中,然后从中提取 UIImage。但是,此解决方案的范围非常有限。它将 SKView 绘制到 UIImage 中,然后裁剪生成的图像以适合给定节点的框架。所以不能有任何东西覆盖你要快照的那个节点。此外,视图和场景都必须在屏幕上可见(这比通常的-[SKView textureFromNode:] 方法更严格)。甚至可能还有一些我没有发现的限制。

    鉴于这一切,这个过程仍然足以满足我的需要,所以我认为值得分享。

    +(UIImage *)imageFromNode:(SKNode *)node {
        SKView *view = node.scene.view;
        CGFloat scale = [UIScreen mainScreen].scale;
        CGRect nodeFrame = [node calculateAccumulatedFrame];
    
        // render SKView into UIImage
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0);
        [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
        UIImage *sceneSnapshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        // crop to the requested node (making sure to flip the y-coordinate)
        CGFloat originY = sceneSnapshot.size.height*scale - nodeFrame.origin.y*scale - nodeFrame.size.height*scale;   
        CGRect cropRect = CGRectMake(nodeFrame.origin.x * scale, originY, nodeFrame.size.width*scale, nodeFrame.size.height*scale);
        CGImageRef croppedSnapshot = CGImageCreateWithImageInRect(sceneSnapshot.CGImage, cropRect);
        UIImage *nodeSnapshot = [UIImage imageWithCGImage:croppedSnapshot];
        CGImageRelease(croppedSnapshot);
    
        return nodeSnapshot;
    }
    

    我已经在 3.5 英寸和 4 英寸视网膜 iPhone、视网膜和非视网膜 iPad 上的模拟器上对此进行了测试。至于实际设备,它适用于运行 7.0.4 的 iPhone 4S、iPhone 5S 和 iPad 2。

    【讨论】:

    • 我需要从SKTexture 获取UIImage,而不是SKNode
    • 您可以使用SKSpriteNodeSKTexture 绘制到屏幕上,然后使用上面的代码对其进行快照。我描述的警告仍然适用。
    【解决方案4】:

    从 iOS 7.0 开始,无法从 SKTexture、SKTextureAtlas 或 SKView 获取 UIImage。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多