iosobjective-cuiimagecgcontextdrawimage

Scaling UIImage for use with with CGContextDrawImage


I have an image which measures 480px x 480px and I'd like to display it in a view which measures 375px x 375px using CGContextDrawImage as below. At the moment the image doesn't scale to fit the view - it is drawn at full size. How can I adjust the code below to scale the image to fit the view please?

self.image = [UIImage imageNamed:@"image2.png"];
CGContextRef layerContext = CGLayerGetContext(drawingLayer);
CGContextSaveGState(layerContext);
UIGraphicsBeginImageContext (self.viewRect.size);
CGContextTranslateCTM(layerContext, 0, self.image.size.width);
CGContextScaleCTM(layerContext, 1.0, -1.0);
CGContextDrawImage(layerContext, self.viewRect, self.image.CGImage);
UIGraphicsEndImageContext();
CGContextRestoreGState(layerContext);

Solution

  • Nowadays you might use UIGraphicsImageRenderer, which gets you out of the weeds of all those CoreGraphics calls:

    CGRect rect = CGRectMake(0, 0, 375, 375);
    UIImage *smallImage = [[[UIGraphicsImageRenderer alloc] initWithBounds:rect] imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
        [self.image drawInRect:rect];
    }];
    

    But my original answer is below.


    The CGContextDrawImage function will scale the image drawing to fit the view. As the documentation for this function says:

    Draws an image into a graphics context.

    Quartz scales the image—disproportionately, if necessary—to fit the bounds specified by the rect parameter.

    The only thing that looks highly suspect is the line that says:

    CGContextTranslateCTM(layerContext, 0, self.image.size.width);
    

    First, you want to translate vertically by the height, not the width. Second, you want to translate by the height of the viewRect, not of the image. Thus:

    CGContextTranslateCTM(layerContext, 0, self.viewRect.size.height);
    

    If the image still isn't getting scaled correctly, I'd suggest you double check the viewRect. But CGContextDrawImage definitely draws the image scaled within the specified CGRect.