Я загружаю изображение в режим просмотра изображений с режимом "Aspect Fit". Мне нужно знать размер, на который масштабируется мой образ. Пожалуйста, помогите.
Как узнать размер изображения после применения аспектного соответствия для изображения в UIImageView
Ответ 1
Пожалуйста, обратитесь к @Paul-de-Lange вместо этого
Я не мог найти что-либо в легкодоступной переменной, которая имела это, так что вот путь грубой силы:
- (CGSize) aspectScaledImageSizeForImageView:(UIImageView *)iv image:(UIImage *)im {
float x,y;
float a,b;
x = iv.frame.size.width;
y = iv.frame.size.height;
a = im.size.width;
b = im.size.height;
if ( x == a && y == b ) {           // image fits exactly, no scaling required
    // return iv.frame.size;
}
else if ( x > a && y > b ) {         // image fits completely within the imageview frame
    if ( x-a > y-b ) {              // image height is limiting factor, scale by height
        a = y/b * a;
        b = y;
    } else {
        b = x/a * b;                // image width is limiting factor, scale by width
        a = x;
    }
} 
else if ( x < a && y < b ) {        // image is wider and taller than image view
    if ( a - x > b - y ) {          // height is limiting factor, scale by height
        a = y/b * a;
        b = y;
    } else {                        // width is limiting factor, scale by width
        b = x/a * b;
        a = x;
    }
}
else if ( x < a && y > b ) {        // image is wider than view, scale by width
    b = x/a * b;
    a = x;
}
else if ( x > a && y < b ) {        // image is taller than view, scale by height
    a = y/b * a;
    b = y;
}
else if ( x == a ) {
    a = y/b * a;
    b = y;
} else if ( y == b ) {
    b = x/a * b;
    a = x;
}
return CGSizeMake(a,b);
}
		Ответ 2
Почему бы не использовать функцию ОС AVMakeRectWithAspectRatioInsideRect?
Ответ 3
Я хотел использовать AVMakeRectWithAspectRatioInsideRect() без включения рамки AVFoundation.
Итак, я реализовал следующие две служебные функции:
CGSize CGSizeAspectFit(CGSize aspectRatio, CGSize boundingSize)
{
    float mW = boundingSize.width / aspectRatio.width;
    float mH = boundingSize.height / aspectRatio.height;
    if( mH < mW )
        boundingSize.width = boundingSize.height / aspectRatio.height * aspectRatio.width;
    else if( mW < mH )
        boundingSize.height = boundingSize.width / aspectRatio.width * aspectRatio.height;
    return boundingSize;
}
CGSize CGSizeAspectFill(CGSize aspectRatio, CGSize minimumSize)
{
    float mW = minimumSize.width / aspectRatio.width;
    float mH = minimumSize.height / aspectRatio.height;
    if( mH > mW )
        minimumSize.width = minimumSize.height / aspectRatio.height * aspectRatio.width;
    else if( mW > mH )
        minimumSize.height = minimumSize.width / aspectRatio.width * aspectRatio.height;
    return minimumSize;
}
Изменить: оптимизировано ниже путем удаления повторяющихся разделов.
CGSize CGSizeAspectFit(const CGSize aspectRatio, const CGSize boundingSize)
{
    CGSize aspectFitSize = CGSizeMake(boundingSize.width, boundingSize.height);
    float mW = boundingSize.width / aspectRatio.width;
    float mH = boundingSize.height / aspectRatio.height;
    if( mH < mW )
        aspectFitSize.width = mH * aspectRatio.width;
    else if( mW < mH )
        aspectFitSize.height = mW * aspectRatio.height;
    return aspectFitSize;
}
CGSize CGSizeAspectFill(const CGSize aspectRatio, const CGSize minimumSize)
{
    CGSize aspectFillSize = CGSizeMake(minimumSize.width, minimumSize.height);
    float mW = minimumSize.width / aspectRatio.width;
    float mH = minimumSize.height / aspectRatio.height;
    if( mH > mW )
        aspectFillSize.width = mH * aspectRatio.width;
    else if( mW > mH )
        aspectFillSize.height = mW * aspectRatio.height;
    return aspectFillSize;
}
Конец редактирования
Это принимает заданный размер (первый параметр) и поддерживает его соотношение сторон. Затем он заполняет заданные границы (второй параметр) как можно больше, не нарушая соотношение сторон.
Используя это, чтобы ответить на исходный вопрос:
// Using aspect fit, scale the image (size) to the image view size.
CGSize sizeBeingScaledTo = CGSizeAspectFit(theImage.size, theImageView.frame.size);
Обратите внимание, как изображение определяет соотношение сторон, в то время как представление изображения определяет размер, который нужно заполнить.
Обратная связь очень приветствуется.
Ответ 4
Эта простая функция рассчитает размер изображения после соответствия аспекту:
    -(CGSize)imageSizeAfterAspectFit:(UIImageView*)imgview{
    float newwidth;
    float newheight;
    UIImage *image=imgview.image;
    if (image.size.height>=image.size.width){
        newheight=imgview.frame.size.height;
        newwidth=(image.size.width/image.size.height)*newheight;
        if(newwidth>imgview.frame.size.width){
            float diff=imgview.frame.size.width-newwidth;
            newheight=newheight+diff/newheight*newheight;
            newwidth=imgview.frame.size.width;
        }
    }
    else{
        newwidth=imgview.frame.size.width;
        newheight=(image.size.height/image.size.width)*newwidth;
        if(newheight>imgview.frame.size.height){
            float diff=imgview.frame.size.height-newheight;
            newwidth=newwidth+diff/newwidth*newwidth;
            newheight=imgview.frame.size.height;
        }
    }
    NSLog(@"image after aspect fit: width=%f height=%f",newwidth,newheight);
    //adapt UIImageView size to image size
    //imgview.frame=CGRectMake(imgview.frame.origin.x+(imgview.frame.size.width-newwidth)/2,imgview.frame.origin.y+(imgview.frame.size.height-newheight)/2,newwidth,newheight);
    return CGSizeMake(newwidth, newheight);
}
		Ответ 5
Я также хотел рассчитать высоту после применения соотношения сторон, чтобы вычислить высоту ячейки таблицы. Итак, я достиг через небольшую математику
ratio = width / height
и высота станет
height = width / ratio
Итак, фрагмент кода будет
UIImage *img = [UIImage imageNamed:@"anImage"];
float aspectRatio = img.size.width/img.size.height;
float requiredHeight = self.view.bounds.size.width / aspectRatio;
		Ответ 6
Для Swift используйте код ниже
func imageSizeAspectFit(imgview: UIImageView) -> CGSize {
        var newwidth: CGFloat
        var newheight: CGFloat
        let image: UIImage = imgFeed.image!
        if image.size.height >= image.size.width {
            newheight = imgview.frame.size.height;
            newwidth = (image.size.width / image.size.height) * newheight
            if newwidth > imgview.frame.size.width {
                let diff: CGFloat = imgview.frame.size.width - newwidth
                newheight = newheight + diff / newheight * newheight
                newwidth = imgview.frame.size.width
            }
        }
        else {
            newwidth = imgview.frame.size.width
            newheight = (image.size.height / image.size.width) * newwidth
            if newheight > imgview.frame.size.height {
                let diff: CGFloat = imgview.frame.size.height - newheight
                newwidth = newwidth + diff / newwidth * newwidth
                newheight = imgview.frame.size.height
            }
        }
       print(newwidth, newheight)
        //adapt UIImageView size to image size
        return CGSizeMake(newwidth, newheight)
    }
И функция вызова
imgFeed.sd_setImageWithURL(NSURL(string:"Your image URL")))
self.imageSizeAfterAspectFit(imgFeed)
		Ответ 7
Swift 3 Человеческая читаемая версия
extension UIImageView {
    /// Find the size of the image, once the parent imageView has been given a contentMode of .scaleAspectFit
    /// Querying the image.size returns the non-scaled size. This helper property is needed for accurate results.
    var aspectFitSize: CGSize {
        guard let image = image else { return CGSize.zero }
        var aspectFitSize = CGSize(width: frame.size.width, height: frame.size.height)
        let newWidth: CGFloat = frame.size.width / image.size.width
        let newHeight: CGFloat = frame.size.height / image.size.height
        if newHeight < newWidth {
            aspectFitSize.width = newHeight * image.size.width
        } else if newWidth < newHeight {
            aspectFitSize.height = newWidth * image.size.height
        }
        return aspectFitSize
    }
    /// Find the size of the image, once the parent imageView has been given a contentMode of .scaleAspectFill
    /// Querying the image.size returns the non-scaled, vastly too large size. This helper property is needed for accurate results.
    var aspectFillSize: CGSize {
        guard let image = image else { return CGSize.zero }
        var aspectFillSize = CGSize(width: frame.size.width, height: frame.size.height)
        let newWidth: CGFloat = frame.size.width / image.size.width
        let newHeight: CGFloat = frame.size.height / image.size.height
        if newHeight > newWidth {
            aspectFillSize.width = newHeight * image.size.width
        } else if newWidth > newHeight {
            aspectFillSize.height = newWidth * image.size.height
        }
        return aspectFillSize
    }
}
		Ответ 8
Возможно, это не подходит вашему делу, но этот простой подход разрешает мою проблему в аналогичном случае:
    UIImageView *imageView = [[UIImageView alloc] initWithImage:bigSizeImage];
    [imageView sizeToFit];
После просмотра размера изображения sizeToFit, если вы запрашиваете imageView.frame.size, вы получите новый размер изображения, соответствующий размеру нового изображения.
Ответ 9
+(UIImage *)CreateAResizeImage:(UIImage *)Img ThumbSize:(CGSize)ThumbSize 
{
    float actualHeight = Img.size.height;
    float actualWidth = Img.size.width;
    if(actualWidth==actualHeight) 
    {
        actualWidth = ThumbSize.width; 
        actualHeight = ThumbSize.height;
    }
    float imgRatio = actualWidth/actualHeight;
    float maxRatio = ThumbSize.width/ThumbSize.height; //320.0/480.0;
    if(imgRatio!=maxRatio)
    {
        if(imgRatio < maxRatio)
        {
            imgRatio = ThumbSize.height / actualHeight; //480.0 / actualHeight;
            actualWidth = imgRatio * actualWidth;
            actualHeight = ThumbSize.height; //480.0;
        }
        else
        {
            imgRatio = ThumbSize.width / actualWidth; //320.0 / actualWidth;
            actualHeight = imgRatio * actualHeight;
            actualWidth = ThumbSize.width; //320.0;
        }
    } 
    else 
    {
        actualWidth = ThumbSize.width;
        actualHeight = ThumbSize.height; 
    }
    CGRect rect = CGRectMake(0, 0, (int)actualWidth, (int)actualHeight);
    UIGraphicsBeginImageContext(rect.size);
    [Img drawInRect:rect];
    UIImage *NewImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return NewImg;
}
		Ответ 10
  Swift 4:
Рамка для изображения .aspectFit -
import AVFoundation
 let x: CGRect = AVMakeRect(aspectRatio: myImage.size, insideRect: sampleImageView.frame)
Ответ 11
Принятый ответ невероятно сложный и не подходит для некоторых краевых случаев. Я думаю, что это решение намного более элегантно:
- (CGSize) sizeOfImage:(UIImage*)image inAspectFitImageView:(UIImageView*)imageView
{
    UKAssert(imageView.contentMode == UIViewContentModeScaleAspectFit, @"Image View must use contentMode = UIViewContentModeScaleAspectFit");
    CGFloat imageViewWidth = imageView.bounds.size.width;
    CGFloat imageViewHeight = imageView.bounds.size.height;
    CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = image.size.height;
    CGFloat scaleFactor = MIN(imageViewWidth / imageWidth, imageViewHeight / imageHeight);
    return CGSizeMake(image.size.width*scaleFactor, image.size.height*scaleFactor);
}
		Ответ 12
Вот мое решение для той же проблемы: https://github.com/alexgarbarev/UIImageView-ImageFrame
Преимущества:
- Поддерживаются режимы UIViewContentMode
 - Можно запросить масштаб и для прямого выбора
 - Можно спросить о кадре изображения прямо из UIImageView
 
Ответ 13
Эта единственная строка может сделать эту работу
CGSize sizeInView = AVMakeRectWithAspectRatioInsideRect(imgViewFake.image.size, imgViewFake.bounds).size;
		Ответ 14
Swift 3 Расширение UIImageView:
import AVFoundation
extension UIImageView {
  var imageSize: CGSize {
    if let image = image {
      return AVMakeRect(aspectRatio: image.size, insideRect: bounds).size
    }
    return CGSize.zero
  }  
}
		Ответ 15
Здесь мое решение без AVFoundation.
Сначала добавьте расширение CGSize для вычисления размера, который будет соответствовать другому размеру:
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)
    }
}
Таким образом, решение проблемы OP сводится к:
let resultSize = image.size.sizeThatFitsSize(imageView.bounds.size)
Также здесь добавлено еще одно расширение для установки прямоугольника в другом прямоугольнике (оно использует указанное расширение CGSize):
extension CGRect
{
    func rectThatFitsRect(_ aRect:CGRect) -> CGRect
    {
        let sizeThatFits = self.size.sizeThatFitsSize(aRect.size)
        let xPos = (aRect.size.width - sizeThatFits.width) / 2
        let yPos = (aRect.size.height - sizeThatFits.height) / 2
        let ret = CGRect(x: xPos, y: yPos, width: sizeThatFits.width, height: sizeThatFits.height)
        return ret
    }
}
		Ответ 16
Я использую следующее в Swift:
private func CGSizeAspectFit(aspectRatio:CGSize,boundingSize:CGSize) -> CGSize
{
    var aspectFitSize = boundingSize
    let mW = boundingSize.width / aspectRatio.width
    let mH = boundingSize.height / aspectRatio.height
    if( mH < mW )
    {
        aspectFitSize.width = mH * aspectRatio.width
    }
    else if( mW < mH )
    {
        aspectFitSize.height = mW * aspectRatio.height
    }
    return aspectFitSize
}
private func CGSizeAspectFill(aspectRatio:CGSize,minimumSize:CGSize) -> CGSize
{
    var aspectFillSize = minimumSize
    let mW = minimumSize.width / aspectRatio.width
    let mH = minimumSize.height / aspectRatio.height
    if( mH > mW )
    {
        aspectFillSize.width = mH * aspectRatio.width
    }
    else if( mW > mH )
    {
        aspectFillSize.height = mW * aspectRatio.height
    }
    return aspectFillSize
}
Я использую его вот так:
let aspectSize  = contentMode == .ScaleAspectFill ? CGSizeAspectFill(oldSize,minimumSize: newSize) : CGSizeAspectFit(oldSize, boundingSize: newSize)
let newRect = CGRect( x: (newSize.width - aspectSize.width)/2, y: (newSize.height - aspectSize.height)/2, width: aspectSize.width, height: aspectSize.height)
CGContextSetFillColorWithColor(context,IOSXColor.whiteColor().CGColor)
CGContextFillRect(context, CGRect(origin: CGPointZero,size: newSize))
CGContextDrawImage(context, newRect, cgImage)
		Ответ 17
Если вы знаете только ширину изображения и когда высота изображения динамическая, вам необходимо масштабировать высоту изображения в соответствии с заданной шириной, чтобы удалить белые пробелы выше и ниже вашего изображения. Используйте следующий метод здесь, чтобы увеличить высоту изображения в соответствии со стандартной шириной экрана.
-(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
    float oldWidth = sourceImage.size.width;
    float scaleFactor = i_width / oldWidth;
    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}
И вызовите его из вашего cellForRowAtIndexPath: метод вроде этого:
UIImage *img = [dictImages objectForKey:yourImageKey]; // loaded the image
cell.imgView.image = [self imageWithImage:img scaledToWidth:self.view.frame.size.width];
		Ответ 18
Версия Swift 4
extension CGSize {
   enum AspectMode {
       case fit
       case fill
   }
   enum Orientation {
       case portrait
       case landscape
   }
   func aspectCorrectSizeToFit(targetSize: CGSize, aspectMode: AspectMode = .fill) -> CGSize {
        switch aspectMode {
        case .fill: return aspectFill(targetSize: targetSize)
        case .fit: return aspectFit(targetSize: targetSize)
        }
    }
    var orientation: Orientation {
        if height >= width { return .portrait }
        else { return .landscape }
    }
    func aspectFit(targetSize: CGSize) -> CGSize {
        let wRatio = targetSize.width / width
        let hRatio = targetSize.height / height
        let scale = min(wRatio, hRatio)
        return applying(CGAffineTransform(scaleX: scale, y: scale))
    }
    func aspectFill(targetSize: CGSize) -> CGSize {
        let wRatio = targetSize.width / width
        let hRatio = targetSize.height / height
        let scale = max(wRatio, hRatio)
        return applying(CGAffineTransform(scaleX: scale, y: scale))
    }
}
		Ответ 19
Вышеупомянутые методы никогда не дают требуемых значений. Поскольку соответствие аспектам поддерживает одинаковое соотношение сторон, нам просто нужны простые математические вычисления для вычисления значений
Обнаружить соотношение сторон
CGFloat imageViewAspectRatio = backgroundImageView.bounds.size.width / backgroundImageView.bounds.size.height;
CGFloat imageAspectRatio =  backgroundImageView.image.size.width / backgroundImageView.image.size.height;
CGFloat mulFactor = imageViewAspectRatio/imageAspectRatio;
Получить новые значения
CGFloat newImageWidth = mulFactor * backgroundImageView.bounds.size.width;
CGFloat newImageHeight = mulFactor * backgroundImageView.bounds.size.height;