【问题标题】:How to render UIView/UIImageView to UIImage with exact size of the image without using the scale of screen?如何在不使用屏幕比例的情况下将 UIView/UIImageView 渲染为具有精确图像大小的 UIImage?
【发布时间】:2018-06-27 12:01:51
【问题描述】:

我进行了很多搜索,并尝试了在 StackOverflow 中可以找到的每一种方法,但都没有奏效。假设我有一个 UIView,它的 UIImageView 包含一个尺寸为 1800x2300 的 UIImage,这显然大于 iPhone 7/8 屏幕的尺寸,因此即使使用屏幕比例也无助于渲染包含此图像的此视图。是的,我也尝试过https://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina-display,我想要一个比我的 Retina 屏幕尺寸更大的渲染,但它不适合我。这些是我尝试这样做的方法,它们不会渲染任何大于我的 imageRect * Scale of my screen 的大小

    // Approach 1
    @autoreleasepool{
        //imageRect is a CGRect which is the rect I defined for my 
        //UIImageView to be aspect fitted in it.
        //_viewWithLoadedImages is the UIView containing two transparent 
        //UIImageViews on top of each other, each containing images 
        //bigger than screen size of iPhones.

        UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0);
        CGContextRef c = UIGraphicsGetCurrentContext();
        CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-imageRect.origin.x, -imageRect.origin.y));
        [_viewWithLoadedImages.layer renderInContext:c];
        UIImage*renderedImage = 
        UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return renderedImage;
    }

    //Approach 2
    @autoreleasepool{
        UIGraphicsImageRenderer * Renderer = [[UIGraphicsImageRenderer alloc] initWithBounds:imageRect];
        self.tempImage=[Renderer imageWithActions:^(UIGraphicsImageRendererContext*_Nonnull context){[_viewWithLoadedImages.layer renderInContext:context.CGContext];}];
            return self.tempImage;
    }

    //Approach 3 
    UIGraphicsBeginImageContextWithOptions(imagerect, NO, 0.0f);
    [_viewWithLoadedImages drawViewHierarchyInRect:imagerect afterScreenUpdates:YES];
    UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;

它们的输出大小都等于 ImageRect * ScreenScale 的大小,但我想从我的 UIView (_viewWithLoadedImages) 获得更大的输出图像,我该怎么办?我几乎尝试了一切。 非常感谢任何帮助。

【问题讨论】:

    标签: objective-c uiview uiimageview uiimage uigraphicscontext


    【解决方案1】:

    假设您有两个 UIImageView,并且可以使用其中一个来调整最终图像的大小,您可以这样做。

    // Desired dimension in pixels
    CGRect frame = CGRectMake(0.0, 0.0,
                              _imageView1.image.size.width * _imageView1.image.scale,
                             _imageView1.image.size.height * _imageView1.image.scale);
    
    // Use scale 1.0 for pixel size
    UIGraphicsBeginImageContextWithOptions(frame.size, NO, 1.0);
    
    // Draw the images on top of each other
    [_imageView1.image drawInRect:frame];
    [_imageView2.image drawInRect:frame];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
    

    【讨论】:

    • 究竟是什么不起作用?我自己试过了,它会以全分辨率渲染图像。
    • 它确实有效。 UIGraphicsBeginImageContextWithOptions 创建一个新的当前上下文,drawInRect 将在该上下文中绘制。我从按钮推送事件中测试了它,而不是在 drawRect 中。
    • 不确定我是否看到了真正的问题。如果我理解正确,您有各种视图,其中可能包含按比例缩小的合成图像。然后,您想获得这种视图的全分辨率图像表示,以便在其他地方使用?如果是这样,那么这是一种方法。如果你想要一个更通用的方法来做,那么你可以把它放在一个以父视图作为参数的方法中,让该方法循环遍历其中的所有图像视图以创建结果图像。
    • 您可以随时使用[_bgImageView.layer.mask drawInContext:context];。使用CGContextRef context = UIGraphicsGetCurrentContext(); 获取上下文。如果这不起作用,您可以在渲染它们之前将遮罩应用于每个子视图。
    • 您需要将掩码应用于您的上下文。我认为这种混合模式应该可以做到。如果您在那之后进行任何绘图,请不要忘记将其更改回来。 CGContextSetBlendMode(context, kCGBlendModeDestinationIn); [_bgImageView.layer.mask drawInContext:context];
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多