tamaño plus para pantalla medidas imagenes fondo apps iphone ipad uiimageview uiimage aspect-ratio

para - tamaño fondo de pantalla iphone 6s plus



Cómo saber el tamaño de la imagen después de aplicar el aspecto adecuado para la imagen en un UIImageView (18)

¿Por qué no utilizar la función del sistema operativo AVMakeRectWithAspectRatioInsideRect ?

Estoy cargando una imagen a una vista de imagen con modo como ''Ajuste de aspecto''. Necesito saber el tamaño al que se está escalando mi imagen. Por favor ayuda.


Aquí está mi solución AVFoundation-less.

Primero aquí hay una extensión CGSize para calcular un tamaño que se ajustaría a otro tamaño:

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) } }

Entonces, la solución al problema de OP se reduce a:

let resultSize = image.size.sizeThatFitsSize(imageView.bounds.size)

También aquí hay otra extensión para ajustar un rect dentro de otro rect (utiliza la extensión CGSize anterior):

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 } }


Aquí está mi solución para el mismo problema: https://github.com/alexgarbarev/UIImageView-ImageFrame

Ventajas:

  • Modos UIViewContentMode compatibles
  • Puede consultar escalas y rect por separado
  • Puede preguntar sobre el marco de la imagen directamente desde UIImageView

Esta sencilla función calculará el tamaño de la imagen después del ajuste de aspecto:

-(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); }


Esta sola línea puede hacer este trabajo

CGSize sizeInView = AVMakeRectWithAspectRatioInsideRect (imgViewFake.image.size, imgViewFake.bounds) .size;


Estoy usando lo siguiente en 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 }

Lo estoy usando así:

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)


La respuesta aceptada es increíblemente complicada y falla en algunos casos extremos. Creo que esta solución es mucho más elegante:

- (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); }


Los métodos mencionados anteriormente nunca dan los valores requeridos. Como el ajuste de aspecto mantiene la misma relación de aspecto, solo necesitamos cálculos simples para calcular los valores.

Detecta la relación de aspecto

CGFloat imageViewAspectRatio = backgroundImageView.bounds.size.width / backgroundImageView.bounds.size.height; CGFloat imageAspectRatio = backgroundImageView.image.size.width / backgroundImageView.image.size.height; CGFloat mulFactor = imageViewAspectRatio/imageAspectRatio;

Obtenga los nuevos valores

CGFloat newImageWidth = mulFactor * backgroundImageView.bounds.size.width; CGFloat newImageHeight = mulFactor * backgroundImageView.bounds.size.height;


Quería utilizar AVMakeRectWithAspectRatioInsideRect() sin incluir el marco AVFoundation .

Así que he implementado las siguientes dos funciones de utilidad:

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

Editar: optimizado a continuación eliminando divisiones duplicadas.

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

Fin de editar

Esto toma un tamaño dado (primer parámetro) y mantiene su relación de aspecto. Luego llena los límites dados (segundo parámetro) tanto como sea posible sin violar la relación de aspecto.

Usando esto para responder la pregunta original:

// Using aspect fit, scale the image (size) to the image view''s size. CGSize sizeBeingScaledTo = CGSizeAspectFit(theImage.size, theImageView.frame.size);

Observe cómo la imagen determina la relación de aspecto, mientras que la vista de la imagen determina el tamaño que se debe llenar.

Los comentarios son bienvenidos.


Si solo conoce el ancho de la vista de la imagen y cuando la altura de la imagen es dinámica, entonces necesita escalar la altura de la imagen de acuerdo con el ancho dado para eliminar los espacios en blanco arriba y debajo de su imagen. Utilice el siguiente método desde here para escalar la altura de la imagen de acuerdo con el ancho estándar de su pantalla.

-(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; }

Y llámalo desde tu método cellForRowAtIndexPath: de esta manera:

UIImage *img = [dictImages objectForKey:yourImageKey]; // loaded the image cell.imgView.image = [self imageWithImage:img scaledToWidth:self.view.frame.size.width];


Swift 3 UIImageView extensión:

import AVFoundation extension UIImageView { var imageSize: CGSize { if let image = image { return AVMakeRect(aspectRatio: image.size, insideRect: bounds).size } return CGSize.zero } }


Tal vez no se ajuste a su caso, pero este sencillo enfoque soluciona mi problema en un caso similar:

UIImageView *imageView = [[UIImageView alloc] initWithImage:bigSizeImage]; [imageView sizeToFit];

Después de que la vista de imagen ejecute sizeToFit si consulta el archivo imageView.frame.size , obtendrá el nuevo tamaño de vista de imagen que se ajusta al nuevo tamaño de imagen.


También quería calcular la altura después de aplicar la relación de aspecto para poder calcular la altura de la celda de la vista de tabla. Entonces, logré a través de pequeñas matemáticas

ratio = width / height

y la altura se convertiría

height = width / ratio

Así que el fragmento de código sería

UIImage *img = [UIImage imageNamed:@"anImage"]; float aspectRatio = img.size.width/img.size.height; float requiredHeight = self.view.bounds.size.width / aspectRatio;


Por favor, vea la respuesta de @ Paul-de-Lange en lugar de esta

No pude encontrar nada en una variable de fácil acceso que tuviera esto, así que aquí está la manera de la fuerza bruta:

- (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); }


Para usar Swift debajo del código

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) }

Y función de llamada

imgFeed.sd_setImageWithURL(NSURL(string:"Your image URL"))) self.imageSizeAfterAspectFit(imgFeed)


Swift 3 versión humana legible

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 } }


Swift 4: Frame para la imagen .aspectFit es -

import AVFoundation

let x: CGRect = AVMakeRect(aspectRatio: myImage.size, insideRect: sampleImageView.frame)


+(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; }