Search code examples
objective-cuiviewuiimageviewuiimageuigraphicscontext

How to render UIView/UIImageView to UIImage with exact size of the image without using the scale of screen?


I have searched a lot and have tried every single method that I could find in StackOverflow and none of them has worked. let's say I have a UIView which has a UIImageView containing a UIImage with a size of 1800x2300, this is obviously bigger than a size of iPhone 7/8's screen so even using Screen scale won't help to render this View which contains this Image.And yes I have tried https://stackoverflow.com/questions/4334233/how-to-capture-uiview-to-uiimage-without-loss-of-quality-on-retina-display too, I want a render bigger than my retina screen size and it doesn't do it for me. These are the ways I tried to do it, they won't render anything bigger than the size of my 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;

They all have output sizes that equal to the size of the ImageRect * ScreenScale but I want a bigger output image from my UIView (_viewWithLoadedImages) What should I do? I have tried almost everything. Any help is much appreciated.


Solution

  • Assuming you have two UIImageView's and can use one of them to size the final image, you can do like this.

    // 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;