UIImage Aspect Fit when using drawInRect?

后端 未结 6 1185
囚心锁ツ
囚心锁ツ 2020-12-13 18:51

UIView provides for the \"aspect fit\" content mode. However, I\'ve subclasses UIView and would like to draw a UIImage using drawInRect with an aspect fit. Is there any way

相关标签:
6条回答
  • 2020-12-13 19:22

    here's the solution

    CGSize imageSize = yourImage.size;
    CGSize viewSize = CGSizeMake(450, 340); // size in which you want to draw
    
    float hfactor = imageSize.width / viewSize.width;
    float vfactor = imageSize.height / viewSize.height;
    
    float factor = fmax(hfactor, vfactor);
    
    // Divide the size by the greater of the vertical or horizontal shrinkage factor
    float newWidth = imageSize.width / factor;
    float newHeight = imageSize.height / factor;
    
    CGRect newRect = CGRectMake(xOffset,yOffset, newWidth, newHeight);
    [image drawInRect:newRect];
    

    -- courtesy https://stackoverflow.com/a/1703210

    another alternative for aspect fit

    -(CGSize ) getImageSize :(CGSize )imgViewSize andActualImageSize:(CGSize )actualImageSize {
    
         // imgViewSize = size of view in which image is to be drawn
         // actualImageSize = size of image which is to be drawn
    
         CGSize drawImageSize;
    
         if (actualImageSize.height > actualImageSize.width) {
    
            drawImageSize.height = imgViewSize.height;
            drawImageSize.width = actualImageSize.width/actualImageSize.height * imgViewSize.height;
    
         }else {
    
            drawImageSize.width = imgViewSize.width;
            drawImageSize.height = imgViewSize.width * actualImageSize.height /  actualImageSize.width;
         }
         return drawImageSize;
    }
    

    Code for swift 3.0:

    func getAspectFitFrame(sizeImgView:CGSize, sizeImage:CGSize) -> CGRect{
    
        let imageSize:CGSize  = sizeImage
        let viewSize:CGSize = sizeImgView
    
        let hfactor : CGFloat = imageSize.width/viewSize.width
        let vfactor : CGFloat = imageSize.height/viewSize.height
    
        let factor : CGFloat = max(hfactor, vfactor)
    
        // Divide the size by the greater of the vertical or horizontal shrinkage factor
        let newWidth : CGFloat = imageSize.width / factor
        let newHeight : CGFloat = imageSize.height / factor
    
        var x:CGFloat = 0.0
        var y:CGFloat = 0.0
        if newWidth > newHeight{
            y = (sizeImgView.height - newHeight)/2
        }
        if newHeight > newWidth{
            x = (sizeImgView.width - newWidth)/2
        }
        let newRect:CGRect = CGRect(x: x, y: y, width: newWidth, height: newHeight)
    
        return newRect
    
    }
    
    0 讨论(0)
  • 2020-12-13 19:25

    The following will let you determine the size to draw in. You specify the aspect ratio and the bounding size to fit into.

    CGSizeAspectFit & CGSizeAspectFill

    0 讨论(0)
  • 2020-12-13 19:27

    The math for that is a little bit hairy, but fortunately, here's a solution I prepared earlier:

    - (UIImage *)imageScaledToSize:(CGSize)size
    {
        //create drawing context
        UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
    
        //draw
        [self drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];
    
        //capture resultant image
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    
    - (UIImage *)imageScaledToFitSize:(CGSize)size
    {
        //calculate rect
        CGFloat aspect = self.size.width / self.size.height;
        if (size.width / aspect <= size.height)
        {
            return [self imageScaledToSize:CGSizeMake(size.width, size.width / aspect)];
        }
        else
        {
            return [self imageScaledToSize:CGSizeMake(size.height * aspect, size.height)];
        }
    }
    

    The first function is equivalent to "scale to fill", the second (which calls the first) is equivalent to "aspect fit". These methods were written as a category on UIImage so to use them from within another class you'll need to tweak them by passing the image in as a second parameter (or just make a category on UIImage like I did).

    0 讨论(0)
  • 2020-12-13 19:27

    this might help you, give it a try

    UIImage *logoImage = [UIImage imageNamed:@"logo.png"];
    
    float newHeight = ((logoImage.size.height / logoImage.size.width) * 100.0);
    CGRect newLogoImageRect = CGRectMake(0, 0, 80.0, newHeight);
    [logoImage drawInRect:newLogoImageRect];
    

    specify your maximum height instead of 100.0 and maximum width instead of 80.0

    0 讨论(0)
  • 2020-12-13 19:29

    Here's a helper CGSize extension that you might find useful:

    extension CGSize
    {
        func sizeThatFitsSize(_ aSize: CGSize) -> CGSize
        {
            let width = min(self.width * aSize.height / self.height, aSize.width)
            return CGSize(width: width, height: self.height * width / self.width)
        }
    }
    

    Then in -drawInRect: implementation one would do the following:

    let imageSizeThatFitsViewBounds = self.image.size.sizeThatFitsSize(self.bounds.size)
    let imageRectX = (self.bounds.size.width - imageSizeThatFitsViewBounds.width) / 2
    let imageRectY = (self.bounds.size.height - imageSizeThatFitsViewBounds.height) / 2
    let imageRect = CGRect(origin: CGPoint(x: imageRectX, y: imageRectY), size: imageSizeThatFitsViewBounds)
    
    0 讨论(0)
  • 2020-12-13 19:49

    You have to draw in the rect provided by

    Swift:

    func AVMakeRect(aspectRatio: CGSize, insideRect boundingRect: CGRect) -> CGRect

    Objective-C:

    CGRect AVMakeRectWithAspectRatioInsideRect(CGSize aspectRatio, CGRect boundingRect);
    

    See doc

    The aspect ratio is preserved and the drawing centred.

    It works in absolutely all cases.

    0 讨论(0)
提交回复
热议问题