varias una tamaño resolucion reducir mac imagen fotos formato como cambiar aumentar ios objective-c image cocoa-touch resize

ios - una - ¿Cuál es la forma más fácil de redimensionar/optimizar un tamaño de imagen con el iPhone SDK?



como aumentar la resolucion de una imagen en mac (18)

Mi aplicación descarga un conjunto de archivos de imagen de la red y los guarda en el disco local de iPhone. Algunas de esas imágenes son bastante grandes (anchuras de más de 500 píxeles, por ejemplo). Como el iPhone ni siquiera tiene una pantalla lo suficientemente grande como para mostrar la imagen en su tamaño original, estoy planeando cambiar el tamaño de la imagen a algo un poco más pequeño para ahorrar espacio / rendimiento.

Además, algunas de esas imágenes son JPEG y no se guardan como la configuración de calidad del 60% habitual.

¿Cómo puedo cambiar el tamaño de una imagen con el iPhone SDK, y cómo puedo cambiar la configuración de calidad de una imagen JPEG?


func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {

let scale = newWidth / image.size.width let newHeight = CGFloat(200.0) UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight)) image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage }


Agregando a la gran cantidad de respuestas aquí, pero he ido por una solución que cambia el tamaño por tamaño de archivo, en lugar de dimensiones.

Esto reducirá las dimensiones y la calidad de la imagen hasta que alcance su tamaño.

func compressTo(toSizeInMB size: Double) -> UIImage? { let bytes = size * 1024 * 1024 let sizeInBytes = Int(bytes) var needCompress:Bool = true var imgData:Data? var compressingValue:CGFloat = 1.0 while (needCompress) { if let resizedImage = scaleImage(byMultiplicationFactorOf: compressingValue), let data: Data = UIImageJPEGRepresentation(resizedImage, compressingValue) { if data.count < sizeInBytes || compressingValue < 0.1 { needCompress = false imgData = data } else { compressingValue -= 0.1 } } } if let data = imgData { print("Finished with compression value of: /(compressingValue)") return UIImage(data: data) } return nil } private func scaleImage(byMultiplicationFactorOf factor: CGFloat) -> UIImage? { let size = CGSize(width: self.size.width*factor, height: self.size.height*factor) UIGraphicsBeginImageContext(size) draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) if let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() { UIGraphicsEndImageContext() return newImage; } return nil }

Crédito por escalar por tamaño de respuesta


Desarrollé una solución definitiva para escalar imágenes en Swift.

Puede usarlo para cambiar el tamaño de la imagen para rellenar, llenar aspecto o ajustar el tamaño del aspecto.

Puede alinear la imagen al centro o cualquiera de los cuatro bordes y cuatro esquinas.

Y también puede recortar el espacio adicional que se agrega si las proporciones de aspecto de la imagen original y el tamaño del objetivo no son iguales.

enum UIImageAlignment { case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight } enum UIImageScaleMode { case Fill, AspectFill, AspectFit(UIImageAlignment) } extension UIImage { func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage { let preWidthScale = width.map { $0 / size.width } let preHeightScale = height.map { $0 / size.height } var widthScale = preWidthScale ?? preHeightScale ?? 1 var heightScale = preHeightScale ?? widthScale switch scaleMode { case .AspectFit(_): let scale = min(widthScale, heightScale) widthScale = scale heightScale = scale case .AspectFill: let scale = max(widthScale, heightScale) widthScale = scale heightScale = scale default: break } let newWidth = size.width * widthScale let newHeight = size.height * heightScale let canvasWidth = trim ? newWidth : (width ?? newWidth) let canvasHeight = trim ? newHeight : (height ?? newHeight) UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0) var originX: CGFloat = 0 var originY: CGFloat = 0 switch scaleMode { case .AspectFit(let alignment): switch alignment { case .Center: originX = (canvasWidth - newWidth) / 2 originY = (canvasHeight - newHeight) / 2 case .Top: originX = (canvasWidth - newWidth) / 2 case .Left: originY = (canvasHeight - newHeight) / 2 case .Bottom: originX = (canvasWidth - newWidth) / 2 originY = canvasHeight - newHeight case .Right: originX = canvasWidth - newWidth originY = (canvasHeight - newHeight) / 2 case .TopLeft: break case .TopRight: originX = canvasWidth - newWidth case .BottomLeft: originY = canvasHeight - newHeight case .BottomRight: originX = canvasWidth - newWidth originY = canvasHeight - newHeight } default: break } self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight)) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } }

Hay ejemplos de aplicar esta solución a continuación.

Rectángulo gris: la imagen del sitio de destino se redimensionará a. Los círculos azules en rectángulo azul claro son la imagen (utilicé círculos porque es fácil de ver cuando se escala sin conservar el aspecto). El color naranja claro marca las áreas que se recortarán si pasa el trim: true .

Ajuste de aspecto antes y después de escalar:

Otro ejemplo de ajuste de aspecto :

Aspecto ajustado con la alineación superior:

Relleno de aspecto :

Rellenar

Usé la ampliación en mis ejemplos porque es más fácil de demostrar pero la solución también funciona para la reducción de escala como en cuestión.

Para la compresión JPEG, debe usar esto:

let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality if let data = UIImageJPEGRepresentation(image, compressionQuality) { // ... }

Puedes ver mi gist con Xcode playground.


La forma más fácil y directa de redimensionar sus imágenes sería esta

float actualHeight = image.size.height; float actualWidth = image.size.width; float imgRatio = actualWidth/actualHeight; float maxRatio = 320.0/480.0; if(imgRatio!=maxRatio){ if(imgRatio < maxRatio){ imgRatio = 480.0 / actualHeight; actualWidth = imgRatio * actualWidth; actualHeight = 480.0; } else{ imgRatio = 320.0 / actualWidth; actualHeight = imgRatio * actualHeight; actualWidth = 320.0; } } CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight); UIGraphicsBeginImageContext(rect.size); [image drawInRect:rect]; UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();


La mejor forma de escalar imágenes sin perder la relación de aspecto (es decir, sin estirar la emoción) es utilizar este método:

//to scale images without changing aspect ratio + (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize { float width = newSize.width; float height = newSize.height; UIGraphicsBeginImageContext(newSize); CGRect rect = CGRectMake(0, 0, width, height); float widthRatio = image.size.width / width; float heightRatio = image.size.height / height; float divisor = widthRatio > heightRatio ? widthRatio : heightRatio; width = image.size.width / divisor; height = image.size.height / divisor; rect.size.width = width; rect.size.height = height; //indent in case of width or height difference float offset = (width - height) / 2; if (offset > 0) { rect.origin.y = offset; } else { rect.origin.x = -offset; } [image drawInRect: rect]; UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return smallImage; }

Agregue este método a su clase de Utilidad para que pueda usarlo en todo su proyecto, y acceda a él de la siguiente manera:

xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];

Este método se encarga de escalar manteniendo la relación de aspecto. También agrega sangrías a la imagen en caso de que la imagen reducida tenga más ancho que alto (o viceversa).


Los métodos anteriores funcionan bien para imágenes pequeñas, pero cuando intenta cambiar el tamaño de una imagen muy grande, se quedará rápidamente sin memoria y bloqueará la aplicación. Una forma mucho mejor es usar CGImageSourceCreateThumbnailAtIndex para cambiar el tamaño de la imagen sin descodificarla por completo primero.

Si tiene la ruta a la imagen que desea cambiar de tamaño, puede usar esto:

- (void)resizeImageAtPath:(NSString *)imagePath { // Create the image source (from path) CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL); // To create image source from UIImage, use this // NSData* pngData = UIImagePNGRepresentation(image); // CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL); // Create thumbnail options CFDictionaryRef options = (__bridge CFDictionaryRef) @{ (id) kCGImageSourceCreateThumbnailWithTransform : @YES, (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES, (id) kCGImageSourceThumbnailMaxPixelSize : @(640) }; // Generate the thumbnail CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); CFRelease(src); // Write the thumbnail at path CGImageWriteToFile(thumbnail, imagePath); }

Más detalles here .


Para Swift 3, el siguiente código escala la imagen manteniendo la relación de aspecto. Puede leer más sobre ImageContext en la documentación de Apple :

extension UIImage { class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage { let scale = newHeight / image.size.height let newWidth = image.size.width * scale UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight)) image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! } }

Para usarlo, llame resizeImage() método resizeImage() :

UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)


Para cambiar el tamaño de una imagen, tengo mejores resultados (gráficos) al usar esta función en lugar de DrawInRect:

- (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth { float lScale = pWidth / pImage.size.width; CGImageRef cgImage = pImage.CGImage; UIImage *lResult = [UIImage imageWithCGImage:cgImage scale:lScale orientation:UIImageOrientationRight]; return lResult; }

La relación de aspecto se ocupa de forma automática


Prueba esto, funciona para mí,

CGRect rect =CGRectMake (0, 0,1200,900); UIGraphicsBeginImageContext( rect.size ); [image drawInRect:rect]; UIImage *picture1 = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); NSData *imageData = UIImagePNGRepresentation(picture1); UIImage *img=[UIImage imageWithData:imageData]; [imageArray addObject:img];


Si alguien todavía está buscando una mejor opción

-(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize { UIImage *sourceImage = image; UIImage *newImage = nil; CGSize imageSize = sourceImage.size; CGFloat width = imageSize.width; CGFloat height = imageSize.height; CGFloat targetWidth = targetSize.width; CGFloat targetHeight = targetSize.height; CGFloat scaleFactor = 0.0; CGFloat scaledWidth = targetWidth; CGFloat scaledHeight = targetHeight; CGPoint thumbnailPoint = CGPointMake(0.0,0.0); if (CGSizeEqualToSize(imageSize, targetSize) == NO) { CGFloat widthFactor = targetWidth / width; CGFloat heightFactor = targetHeight / height; if (widthFactor < heightFactor) scaleFactor = widthFactor; else scaleFactor = heightFactor; scaledWidth = width * scaleFactor; scaledHeight = height * scaleFactor; // center the image if (widthFactor < heightFactor) { thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; } else if (widthFactor > heightFactor) { thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; } } // this is actually the interesting part: UIGraphicsBeginImageContext(targetSize); CGRect thumbnailRect = CGRectZero; thumbnailRect.origin = thumbnailPoint; thumbnailRect.size.width = scaledWidth; thumbnailRect.size.height = scaledHeight; [sourceImage drawInRect:thumbnailRect]; newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); if(newImage == nil) NSLog(@"could not scale image"); return newImage ; }


Si su imagen está en el directorio de documentos, agregue esta extensión de URL :

extension URL { func compressedImageURL(quality: CGFloat = 0.3) throws -> URL? { let imageData = try Data(contentsOf: self) debugPrint("Image file size before compression: /(imageData.count) bytes") let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".jpg") guard let actualImage = UIImage(data: imageData) else { return nil } guard let compressedImageData = UIImageJPEGRepresentation(actualImage, quality) else { return nil } debugPrint("Image file size after compression: /(compressedImageData.count) bytes") do { try compressedImageData.write(to: compressedURL) return compressedURL } catch { return nil } } }

Uso:

guard let localImageURL = URL(string: "< LocalImagePath.jpg >") else { return } //Here you will get URL of compressed image guard let compressedImageURL = try localImageURL.compressedImageURL() else { return } debugPrint("compressedImageURL: /(compressedImageURL.absoluteString)")

Nota: - Cambie <LocalImagePath.jpg> con su ruta de imagen jpg local.


Si tiene control sobre el servidor, recomiendo encarecidamente cambiar el tamaño del lado del servidor de imágenes con ImageMagik . Descargar imágenes grandes y cambiar su tamaño en el teléfono es un desperdicio de muchos recursos valiosos: ancho de banda, batería y memoria. Todo lo cual es escaso en los teléfonos.


Solo quería responder esa pregunta para los programadores de Cocoa Swift. Esta función devuelve NSImage con un nuevo tamaño. Puedes usar esa función de esta manera.

let sizeChangedImage = changeImageSize(image, ratio: 2) // changes image size func changeImageSize (image: NSImage, ratio: CGFloat) -> NSImage { // getting the current image size let w = image.size.width let h = image.size.height // calculating new size let w_new = w / ratio let h_new = h / ratio // creating size constant let newSize = CGSizeMake(w_new ,h_new) //creating rect let rect = NSMakeRect(0, 0, w_new, h_new) // creating a image context with new size let newImage = NSImage.init(size:newSize) newImage.lockFocus() // drawing image with new size in context image.drawInRect(rect) newImage.unlockFocus() return newImage }


Terminé usando la técnica Brads para crear un método scaleToFitWidth en UIImage+Extensions si eso es útil para cualquiera ...

-(UIImage *)scaleToFitWidth:(CGFloat)width { CGFloat ratio = width / self.size.width; CGFloat height = self.size.height * ratio; NSLog(@"W:%f H:%f",width,height); UIGraphicsBeginImageContext(CGSizeMake(width, height)); [self drawInRect:CGRectMake(0.0f,0.0f,width,height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }

entonces donde quieras

#import "UIImage+Extensions.h"

UIImage *newImage = [image scaleToFitWidth:100.0f];

También vale la pena señalar que puede avanzar más hacia abajo en una clase UIView+Extensions si desea renderizar imágenes desde una UIView


Un par de sugerencias se proporcionan como respuestas a esta pregunta . Le sugerí la técnica descrita en esta publicación , con el código correspondiente:

+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize; { UIGraphicsBeginImageContext( newSize ); [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }

En cuanto al almacenamiento de la imagen, el formato de imagen más rápido para usar con el iPhone es PNG, porque tiene optimizaciones para ese formato. Sin embargo, si desea almacenar estas imágenes como archivos JPEG, puede tomar su UIImage y hacer lo siguiente:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

Esto crea una instancia de NSData que contiene los bytes sin formato para una imagen JPEG con una configuración de calidad del 60%. El contenido de esa instancia de NSData se puede escribir en el disco o guardar en caché en la memoria.


Un problema que puede ocurrir en las pantallas Retina es que la escala de la imagen está configurada por ImageCapture más o menos. Las funciones de cambio de tamaño anteriores no cambiarán eso. En estos casos, el cambio de tamaño no funcionará correctamente.

En el siguiente código, la escala se establece en 1 (no en escala) y la imagen devuelta tiene el tamaño que usted esperaría. Esto se hace en la llamada UIGraphicsBeginImageContextWithOptions .

-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize { UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0); [theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }


puede usar este código para escalar la imagen en el tamaño requerido.

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize { CGSize actSize = image.size; float scale = actSize.width/actSize.height; if (scale < 1) { newSize.height = newSize.width/scale; } else { newSize.width = newSize.height*scale; } UIGraphicsBeginImageContext(newSize); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }


- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize { CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height)); CGImageRef imageRef = image.CGImage; UIGraphicsBeginImageContextWithOptions(newSize, NO, 0); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetInterpolationQuality(context, kCGInterpolationHigh); CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height); CGContextConcatCTM(context, flipVertical); CGContextDrawImage(context, newRect, imageRef); CGImageRef newImageRef = CGBitmapContextCreateImage(context); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; CGImageRelease(newImageRef); UIGraphicsEndImageContext(); return newImage; }