La forma más simple de cambiar el tamaño de un UIImage?

En mi aplicación de iPhone, tomo una foto con la camera, luego quiero cambiar el tamaño a 290 * 390 píxeles. Estaba usando este método para cambiar el tamaño de la image:

UIImage *newImage = [image _imageScaledToSize:CGSizeMake(290, 390) interpolationQuality:1]; 

Funciona perfectamente, pero es una function no documentada, así que ya no puedo usarlo con iPhone OS4.

Entonces … ¿cuál es la forma más simple de cambiar el tamaño de un UIImage?

La forma más simple es establecer el marco de tu UIImageView y establecer el contentMode en una de las opciones de cambio de tamaño.

O puede usar este método de utilidad, si realmente necesita cambiar el tamaño de una image:

 + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { //UIGraphicsBeginImageContext(newSize); // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution). // Pass 1.0 to force exact pixel size. UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Ejemplo de uso:

 #import "MYUtil.h" … UIImage *myIcon = [MYUtil imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)]; 

Aquí está la versión Swift de la respuesta de Paul Lynch

 func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{ UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0); image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height)) let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } 

Versión Swift 3.0:

 func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{ UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0); image.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: newSize.width, height: newSize.height))) let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return newImage } 

Trevor Howard tiene algunas categorías UIImage que manejan cambiar el tamaño bastante bien. Si nada más puedes usar el código como ejemplos.

Nota: A partir de iOS 5.1, esta respuesta puede ser inválida. Ver el comentario a continuación.

También he visto esto hecho también (que utilizo en UIButtons para el estado Normal y Seleccionado ya que los botones no cambian de tamaño para adaptarse). El crédito es para quien fuera el autor original.

Primero crea un file .h y .m vacío llamado UIImageResizing.h y UIImageResizing.m

 // Put this in UIImageResizing.h @interface UIImage (Resize) - (UIImage*)scaleToSize:(CGSize)size; @end // Put this in UIImageResizing.m @implementation UIImage (Resize) - (UIImage*)scaleToSize:(CGSize)size { UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, 0.0, size.height); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage); UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage; } @end 

Incluya ese file .h en cualquier file .m en el que vaya a utilizar la function y luego llámelo de la siguiente manera:

 UIImage* image = [UIImage imageNamed:@"largeImage.png"]; UIImage* smallImage = [image scaleToSize:CGSizeMake(100.0f,100.0f)]; 

Esta mejora del código de Paul le dará una image nítida de alta resolución en un iPhone con una pantalla retina. De lo contrario, al networkingucirlo es borroso.

 + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { if ([[UIScreen mainScreen] scale] == 2.0) { UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0); } else { UIGraphicsBeginImageContext(newSize); } } else { UIGraphicsBeginImageContext(newSize); } [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Aquí hay una modificación de la categoría escrita por iWasRobbed arriba. Mantiene la relación de aspecto de la image original en lugar de distorsionarla.

 - (UIImage*)scaleToSizeKeepAspect:(CGSize)size { UIGraphicsBeginImageContext(size); CGFloat ws = size.width/self.size.width; CGFloat hs = size.height/self.size.height; if (ws > hs) { ws = hs/ws; hs = 1.0; } else { hs = ws/hs; ws = 1.0; } CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, 0.0, size.height); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, CGRectMake(size.width/2-(size.width*ws)/2, size.height/2-(size.height*hs)/2, size.width*ws, size.height*hs), self.CGImage); UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage; } 

Aquí hay una manera simple:

  UIImage * image = [UIImage imageNamed:@"image"]; CGSize sacleSize = CGSizeMake(10, 10); UIGraphicsBeginImageContextWithOptions(sacleSize, NO, 0.0); [image drawInRect:CGRectMake(0, 0, sacleSize.width, sacleSize.height)]; UIImage * resizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

resizedImage es una nueva image.

Si solo desea una image más pequeña y no le importa el tamaño exacto:

 + (UIImage *)imageWithImage:(UIImage *)image scaledToScale:(CGFloat)scale { UIGraphicsBeginImageContextWithOptions(self.size, YES, scale); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetInterpolationQuality(context, kCGInterpolationHigh); [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Ajustar la escala a 0.25f le dará una image de 816 por 612 de una camera de 8MP.

Aquí hay una categoría UIImage + Scale para aquellos que la necesitan.

Encontré una categoría para UIImage en los propios ejemplos de Apple, que hace el mismo truco. Aquí está el enlace: https://developer.apple.com/library/ios/samplecode/sc2273/Listings/AirDropSample_UIImage_Resize_m.html .

Simplemente tendrás que cambiar la llamada:

 UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0); 

en imageWithImage:scaledToSize:inRect: con:

 UIGraphicsBeginImageContextWithOptions(newSize, NO, 2.0); 

Para considerar el canal alfa en la image.

  func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage { let scale = newWidth / image.size.width let newHeight = image.size.height * scale UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)) image.drawInRect(CGRectMake(0, 0, newWidth, newHeight)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } 

¿Por qué tan complicado? Creo que usar la API del sistema puede lograr el mismo resultado:

 UIImage *largeImage; CGFloat ratio = 0.4; // you want to get a new image that is 40% the size of large image. UIImage *newImage = [UIImage imageWithCGImage:largeImage.CGImage scale:1/ratio orientation:largeImage.imageOrientation]; // notice the second argument, it is 1/ratio, not ratio. 

El único problema es que debe pasar la razón inversa del objective como el segundo argumento, ya que de acuerdo con el documento, el segundo parámetro especifica la relación de la image original en comparación con la nueva escalada.

Si desea hacer una miniatura de UIImage (con cambio de tamaño proporcional o tal vez algún recorte), consulte la categoría UIImage + Cambiar tamaño que le permite usar una syntax concisa, parecida a ImageMagick:

 UIImage* squareImage = [image resizedImageByMagick: @"320x320#"]; 

Proper Swift 3.0 para la solución de iOS 10+ : utilizando ImageRenderer y syntax de cierre

  func imageWith(newSize: CGSize) -> UIImage { let renderer = UIGraphicsImageRenderer(size:newSize) let image = renderer.image{_ in self.draw(in: CGRect.init(origin: CGPoint.zero, size: newSize)) } return image } 

Rogerio Chaves responde como una extensión rápida

 func scaledTo(size: CGSize) -> UIImage{ UIGraphicsBeginImageContextWithOptions(size, false, 0.0); self.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return newImage } 

Y también bonificación

 func scaledTo(height: CGFloat) -> UIImage{ let width = height*self.size.width/self.size.height return scaledTo(size: CGSize(width: width, height: height)) } 

Swift 3.0 con opción de security (devuelve la image original en caso de error):

 func resize(image: UIImage, toSize size: CGSize) -> UIImage{ UIGraphicsBeginImageContextWithOptions(size,false,1.0) image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) if let resizedImage = UIGraphicsGetImageFromCurrentImageContext() { UIGraphicsEndImageContext() return resizedImage } UIGraphicsEndImageContext() return image } 

La respuesta de @Paul Lynch es genial, pero cambiaría la proporción de imágenes. si no desea cambiar la relación de image y desea que la nueva image sea adecuada para un nuevo tamaño, pruebe esto.

 + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { // calculate a new size which ratio is same to original image CGFloat ratioW = image.size.width / newSize.width; CGFloat ratioH = image.size.height / newSize.height; CGFloat ratio = image.size.width / image.size.height; CGSize showSize = CGSizeZero; if (ratioW > 1 && ratioH > 1) { if (ratioW > ratioH) { showSize.width = newSize.width; showSize.height = showSize.width / ratio; } else { showSize.height = newSize.height; showSize.width = showSize.height * ratio; } } else if (ratioW > 1) { showSize.width = showSize.width; showSize.height = showSize.width / ratio; } else if (ratioH > 1) { showSize.height = showSize.height; showSize.width = showSize.height * ratio; } //UIGraphicsBeginImageContext(newSize); // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution). // Pass 1.0 to force exact pixel size. UIGraphicsBeginImageContextWithOptions(showSize, NO, 0.0); [image drawInRect:CGRectMake(0, 0, showSize.width, showSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage;} 

usa esta extensión

 extension UIImage { public func resize(size:CGSize, completionHandler:(resizedImage:UIImage, data:NSData?)->()) { dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { () -> Void in let newSize:CGSize = size let rect = CGRectMake(0, 0, newSize.width, newSize.height) UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0) self.drawInRect(rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() let imageData = UIImageJPEGRepresentation(newImage, 0.5) dispatch_async(dispatch_get_main_queue(), { () -> Void in completionHandler(resizedImage: newImage, data:imageData) }) }) } } 

[cf Chris] Para cambiar el tamaño a un tamaño deseado:

 UIImage *after = [UIImage imageWithCGImage:before.CGImage scale:CGImageGetHeight(before.CGImage)/DESIREDHEIGHT orientation:UIImageOrientationUp]; 

o, equivalentemente, sustituya CGImageGetWidth(...)/DESIREDWIDTH

Aquí mi código Swift algo detallado

 func scaleImage(image:UIImage, toSize:CGSize) -> UIImage { UIGraphicsBeginImageContextWithOptions(toSize, false, 0.0); let aspectRatioAwareSize = self.aspectRatioAwareSize(image.size, boxSize: toSize, useLetterBox: false) let leftMargin = (toSize.width - aspectRatioAwareSize.width) * 0.5 let topMargin = (toSize.height - aspectRatioAwareSize.height) * 0.5 image.drawInRect(CGRectMake(leftMargin, topMargin, aspectRatioAwareSize.width , aspectRatioAwareSize.height)) let retVal = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return retVal } func aspectRatioAwareSize(imageSize: CGSize, boxSize: CGSize, useLetterBox: Bool) -> CGSize { // aspect ratio aware size // http://stackoverflow.com/a/6565988/8047 let imageWidth = imageSize.width let imageHeight = imageSize.height let containerWidth = boxSize.width let containerHeight = boxSize.height let imageAspectRatio = imageWidth/imageHeight let containerAspectRatio = containerWidth/containerHeight let retVal : CGSize // use the else at your own risk: it seems to work, but I don't know // the math if (useLetterBox) { retVal = containerAspectRatio > imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth) } else { retVal = containerAspectRatio < imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth) } return retVal } 

Una versión más compacta para Swift 4 y iOS 10+:

 extension UIImage { func resized(to size: CGSize) -> UIImage { return UIGraphicsImageRenderer(size: size).image { _ in draw(in: CGRect(origin: .zero, size: size)) } } } 

Uso:

 let resizedImage = image.resized(to: CGSize(width: 50, height: 50)) 

Swift 2.0:

 let image = UIImage(named: "imageName") let newSize = CGSize(width: 10, height: 10) UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0) image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height)) let imageResized = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

Esta es una extensión de UIImage compatible con Swift 3 y Swift 4 que escala la image a un tamaño determinado con una relación de aspecto

 extension UIImage { func scaledImage(withSize size: CGSize) -> UIImage { UIGraphicsBeginImageContextWithOptions(size, false, 0.0) defer { UIGraphicsEndImageContext() } draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)) return UIGraphicsGetImageFromCurrentImageContext()! } func scaleImageToFitSize(size: CGSize) -> UIImage { let aspect = self.size.width / self.size.height if size.width / aspect <= size.height { return scaledImage(withSize: CGSize(width: size.width, height: size.width / aspect)) } else { return scaledImage(withSize: CGSize(width: size.height * aspect, height: size.height)) } } } 

Ejemplo de uso

 let image = UIImage(named: "apple") let scaledImage = image.scaleImageToFitSize(size: CGSize(width: 45.0, height: 45.0)) 

Descubrí que es difícil encontrar una respuesta que pueda usar fuera de la caja en su proyecto Swift 3 . El problema principal de otras respuestas es que no respetan el canal alfa de la image. Aquí está la técnica que estoy usando en mis proyectos.

 extension UIImage { func scaledToFit(toSize newSize: CGSize) -> UIImage { if (size.width < newSize.width && size.height < newSize.height) { return copy() as! UIImage } let widthScale = newSize.width / size.width let heightScale = newSize.height / size.height let scaleFactor = widthScale < heightScale ? widthScale : heightScale let scaledSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor) return self.scaled(toSize: scaledSize, in: CGRect(x: 0.0, y: 0.0, width: scaledSize.width, height: scaledSize.height)) } func scaled(toSize newSize: CGSize, in rect: CGRect) -> UIImage { if UIScreen.main.scale == 2.0 { UIGraphicsBeginImageContextWithOptions(newSize, !hasAlphaChannel, 2.0) } else { UIGraphicsBeginImageContext(newSize) } draw(in: rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage ?? UIImage() } var hasAlphaChannel: Bool { guard let alpha = cgImage?.alphaInfo else { return false } return alpha == CGImageAlphaInfo.first || alpha == CGImageAlphaInfo.last || alpha == CGImageAlphaInfo.premultipliedFirst || alpha == CGImageAlphaInfo.premultipliedLast } } 

Ejemplo de uso:

 override func viewDidLoad() { super.viewDidLoad() let size = CGSize(width: 14.0, height: 14.0) if let image = UIImage(named: "barbell")?.scaledToFit(toSize: size) { let imageView = UIImageView(image: image) imageView.center = CGPoint(x: 100, y: 100) view.addSubview(imageView) } } 

Este código es una reescritura de la extensión de Apple con soporte adicional para imágenes con y sin canal alfa.

Como lectura adicional, recomiendo consultar este artículo para diferentes técnicas de cambio de tamaño de imágenes. El enfoque actual ofrece un performance decente, opera API de alto nivel y es fácil de entender. Recomiendo seguirlo a less que encuentre que el cambio de tamaño de la image es un cuello de botella en su performance.

Swift 4 respuesta:

 func scaleDown(image: UIImage, withSize: CGSize) -> UIImage { let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(withSize, false, scale) image.draw(in: CGRect(x: 0, y: 0, width: withSize.width, height: withSize.height)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! } 

(Swift 4 compatible) iOS 10+ e iOS <10 solución (utilizando UIGraphicsImageRenderer si es posible, UIGraphicsGetImageFromCurrentImageContext contrario)

 /// Resizes an image /// /// - Parameter newSize: New size /// - Returns: Resized image func scaled(to newSize: CGSize) -> UIImage { let rect = CGRect(origin: .zero, size: newSize) if #available(iOS 10, *) { let renderer = UIGraphicsImageRenderer(size: newSize) return renderer.image { _ in self.draw(in: rect) } } else { UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0) self.draw(in: rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! } }