create ios image uiimage

ios - create - Centro de cultivo cuadrado de UIImage.



uiimageview set image swift (16)

¡Creo que aquí sería la solución perfecta!
NO es una buena idea recortar la imagen en función del toSize del toSize . Se verá raro cuando la resolución de la imagen (tamaño) sea muy grande.
El siguiente código recortará la imagen según la relación de toSize del toSize .
Mejorado de la respuesta de @BlackRider .

- (UIImage *)imageByCroppingImage:(UIImage *)image toSize:(CGSize)size { double newCropWidth, newCropHeight; //=== To crop more efficently =====// if(image.size.width < image.size.height){ if (image.size.width < size.width) { newCropWidth = size.width; } else { newCropWidth = image.size.width; } newCropHeight = (newCropWidth * size.height)/size.width; } else { if (image.size.height < size.height) { newCropHeight = size.height; } else { newCropHeight = image.size.height; } newCropWidth = (newCropHeight * size.width)/size.height; } //==============================// double x = image.size.width/2.0 - newCropWidth/2.0; double y = image.size.height/2.0 - newCropHeight/2.0; CGRect cropRect = CGRectMake(x, y, newCropWidth, newCropHeight); CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect); UIImage *cropped = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return cropped; }

Así que aquí es donde lo he hecho hasta ahora. Estoy usando un UIImage capturado de la cámara y puedo recortar la plaza central cuando está en el paisaje. Por alguna razón, esto no se traduce en modo retrato como se esperaba. Publicaré mi código y registros solo para referencia.

Código:

CGRect squareRect = CGRectMake(offsetX, offsetY, newWidth, newHeight); CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], squareRect); image = [UIImage imageWithCGImage:imageRef scale:1 orientation:image.imageOrientation];

Resultados de retrato (no cuadrados):

original image size: {1536, 2048}, with orientation: 3 squareRect: {{0, 256}, {1536, 1536}} new image size: {1280, 1536}, with orientation: 3 <--- not expected

Resultados del paisaje (cuadrado):

original image size: {2048, 1536}, with orientation: 1 squareRect: {{256, 0}, {1536, 1536}} new image size: {1536, 1536}, with orientation: 1

¿Es este un error dentro de CGImageCreateWithImageInRect () o me estoy perdiendo algo aquí?


¿Qué hay de obtener ayuda de UIImageView?

+ (UIImage *)laodSquareImage:(UIImage *)image withDiameter:(CGFloat)diameter { CGRect frame = CGRectMake(0.0f, 0.0f, diameter, diameter); UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame]; imageView.contentMode = UIViewContentModeScaleAspectFill; imageView.clipsToBounds = YES; imageView.image = image; CALayer *layer = imageView.layer; layer.masksToBounds = YES; UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,NO, [UIScreen mainScreen].scale); CGContextRef context = UIGraphicsGetCurrentContext(); [layer renderInContext:context]; UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return roundedImage; }

Y también puedes hacer el círculo de la imagen agregando solo una línea.

layer.cornerRadius =MAX( imageView.frame.size.height,imageView.frame.size.width)/2;


Basada en la respuesta verificada por Elmundo y su versión rápida de Imbrue, aquí está la misma solución que calcula automáticamente el tamaño del centro de la imagen (teniendo en cuenta la orientación), y teniendo en cuenta los errores:

func cropImageToSquare(image: UIImage) -> UIImage? { var imageHeight = image.size.height var imageWidth = image.size.width if imageHeight > imageWidth { imageHeight = imageWidth } else { imageWidth = imageHeight } let size = CGSize(width: imageWidth, height: imageHeight) let refWidth : CGFloat = CGFloat(CGImageGetWidth(image.CGImage)) let refHeight : CGFloat = CGFloat(CGImageGetHeight(image.CGImage)) let x = (refWidth - size.width) / 2 let y = (refHeight - size.height) / 2 let cropRect = CGRectMake(x, y, size.height, size.width) if let imageRef = CGImageCreateWithImageInRect(image.CGImage, cropRect) { return UIImage(CGImage: imageRef, scale: 0, orientation: image.imageOrientation) } return nil }

Versión Swift 3

func cropImageToSquare(image: UIImage) -> UIImage? { var imageHeight = image.size.height var imageWidth = image.size.width if imageHeight > imageWidth { imageHeight = imageWidth } else { imageWidth = imageHeight } let size = CGSize(width: imageWidth, height: imageHeight) let refWidth : CGFloat = CGFloat(image.cgImage!.width) let refHeight : CGFloat = CGFloat(image.cgImage!.height) let x = (refWidth - size.width) / 2 let y = (refHeight - size.height) / 2 let cropRect = CGRect(x: x, y: y, width: size.height, height: size.width) if let imageRef = image.cgImage!.cropping(to: cropRect) { return UIImage(cgImage: imageRef, scale: 0, orientation: image.imageOrientation) } return nil }


Esta es una pregunta antigua, pero ninguna de las respuestas es realmente correcta (incluso la respuesta aceptada). Lo importante a entender es que UIImageOrientation ( image.imageOrientation ) es realmente correcta, pero su definición de UP y nuestra definición de UP son diferentes. Para nosotros, UP es la parte superior del dispositivo (donde está el botón de encendido). Para UIImageOrientation , UP es el lado opuesto de los botones de control de volumen. Entonces, si el dispositivo toma una imagen con los controles de volumen hacia abajo, esto es UIImageOrientationUp . Si toma una imagen en modo vertical (con el botón de inicio presionado), se trata de UIImageOrientationLeft .

Para poder calcular el centro en vertical, puede aplicar la siguiente transformación a la imagen para que el recorte se encuentre en el lugar correcto.

- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect { CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) { return deg / 180.0f * (CGFloat) M_PI; }; // determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position CGAffineTransform rectTransform; switch (image.imageOrientation) { case UIImageOrientationLeft: rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height); break; case UIImageOrientationRight: rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0); break; case UIImageOrientationDown: rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height); break; default: rectTransform = CGAffineTransformIdentity; }; // adjust the transformation scale based on the image scale rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale); // apply the transformation to the rect to create a new, shifted rect CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform); // use the rect to crop the image CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare); // create a new UIImage and set the scale and orientation appropriately UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation]; // memory cleanup CGImageRelease(imageRef); return result; }

Este código desplaza la casilla de recorte para que se encuentre en la posición relativa correcta.


Esto funciona con diferentes orientaciones. Tanto la orientación vertical como la horizontal funcionan correctamente.

- (UIImage *)imageByCroppingImage:(UIImage *)image toSize:(CGSize)size { // not equivalent to image.size (which depends on the imageOrientation)! double refWidth = CGImageGetWidth(image.CGImage); double refHeight = CGImageGetHeight(image.CGImage); double x = (refWidth - size.width) / 2.0; double y = (refHeight - size.height) / 2.0; CGRect cropRect = CGRectMake(x, y, size.height, size.width); CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect); UIImage *cropped = [UIImage imageWithCGImage:imageRef scale:0.0 orientation:self.imageOrientation]; CGImageRelease(imageRef); return cropped; }


Esto se basa en la respuesta Swift 3 de @ Alonzo, con el código simplificado y simplificado para que sea más comprensible y conciso. También se rescata si la imagen ya es cuadrada.

extension UIImage { func square() -> UIImage? { if size.width == size.height { return self } let cropWidth = min(size.width, size.height) let cropRect = CGRect( x: (size.width - cropWidth) * scale / 2.0, y: (size.height - cropWidth) * scale / 2.0, width: cropWidth * scale, height: cropWidth * scale ) guard let imageRef = cgImage?.cropping(to: cropRect) else { return nil } return UIImage(cgImage: imageRef, scale: scale, orientation: imageOrientation) } }


Estoy tratando con lo siguiente

extension UIImage { var cgImageWidth: Int { return cgImage?.width ?? 0 } var cgImageheight: Int { return cgImage?.height ?? 0 } var blance: CGFloat { return min(size.width, size.height)} var blanceSize: CGSize { return CGSize(width: blance, height: blance) } var blanceRect: CGRect { return CGRect(origin: .zero, size: blanceSize) } var roundedImage: UIImage? { UIGraphicsBeginImageContextWithOptions(blanceSize, false, scale) defer { UIGraphicsEndImageContext() } guard let cgImage = cgImage?.cropping(to: CGRect(origin: CGPoint(x: max(0, CGFloat(cgImageWidth) - blance)/2.0, y: max(0, CGFloat(cgImageheight) - blance)/2.0), size: blanceSize)) else { return nil } UIBezierPath(ovalIn: blanceRect).addClip() UIImage(cgImage: cgImage, scale: 1.0, orientation: self.imageOrientation).draw(in: blanceRect) return UIGraphicsGetImageFromCurrentImageContext() } }


Existe la versión swift para la solución comprobada:

private func imageByCroppingImage(image : UIImage, size : CGSize) -> UIImage{ var refWidth : CGFloat = CGFloat(CGImageGetWidth(image.CGImage)) var refHeight : CGFloat = CGFloat(CGImageGetHeight(image.CGImage)) var x = (refWidth - size.width) / 2 var y = (refHeight - size.height) / 2 let cropRect = CGRectMake(x, y, size.height, size.width) let imageRef = CGImageCreateWithImageInRect(image.CGImage, cropRect) let cropped : UIImage = UIImage(CGImage: imageRef, scale: 0, orientation: image.imageOrientation)! return cropped }


Intenta algo como esto:

- (UIImage *)imageByCroppingImage:(UIImage *)image toSize:(CGSize)size { double x = (image.size.width - size.width) / 2.0; double y = (image.size.height - size.height) / 2.0; CGRect cropRect = CGRectMake(x, y, size.height, size.width); CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect); UIImage *cropped = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return cropped; }

Como ves, no especifico la orientación en la llamada a UIImage imageWithCGImage: Me pregunto si ese es el problema en su código.


Pude lograrlo con algo como esto:

UIImage *thisImage = [[UIImage alloc] initWithContentsOfFile:imagePath]; double x = (thisImage.size.width )/2.0; double y = (thisImage.size.height)/2.0; mediaImage = [self imageByCropping:thisImage toRect:CGRectMake(x, y, 60, 60)]; [thisImage release];


Solución basada en la extensión Swift 2. Improvisado de @Geoffrey y @Nirav Dangi. Tenga en cuenta que establecemos newCropWidth y newCropHeight en el ancho o alto de la imagen cuando son menores que el ancho o alto dado.

extension UIImage { func imageByCroppingImage(size: CGSize) -> UIImage { let newCropWidth, newCropHeight : CGFloat; if(self.size.width < self.size.height) { if (self.size.width < size.width) { newCropWidth = self.size.width; } else { newCropWidth = size.width; } newCropHeight = (newCropWidth * size.height)/size.width; } else { if (self.size.height < size.height) { newCropHeight = self.size.height; } else { newCropHeight = size.height; } newCropWidth = (newCropHeight * size.width)/size.height; } let x = self.size.width / 2 - newCropWidth / 2; let y = self.size.height / 2 - newCropHeight / 2; let cropRect = CGRectMake(x, y, newCropWidth, newCropHeight); let imageRef = CGImageCreateWithImageInRect(self.CGImage, cropRect); let croppedImage : UIImage = UIImage(CGImage: imageRef!, scale: 0, orientation: self.imageOrientation); return croppedImage; } }


Swift 2 utilizando la extensión UIImage

extension UIImage { func imageByCroppingImage(size : CGSize) -> UIImage { let refWidth : CGFloat = CGFloat(CGImageGetWidth(self.CGImage)) let refHeight : CGFloat = CGFloat(CGImageGetHeight(self.CGImage)) let x = (refWidth - size.width) / 2 let y = (refHeight - size.height) / 2 let cropRect = CGRectMake(x, y, size.width, size.height) let imageRef = CGImageCreateWithImageInRect(self.CGImage, cropRect) let cropped : UIImage = UIImage(CGImage: imageRef!, scale: 0, orientation: self.imageOrientation) return cropped } }


Swift 3

let refWidth : CGFloat = CGFloat(image.cgImage!.width) let refHeight : CGFloat = CGFloat(image.cgImage!.height) let x = (refWidth - size.width) / 2 let y = (refHeight - size.height) / 2 let cropRect = CGRect(x: x, y: y, width: size.width, height: size.height) let imageRef = image.cgImage!.cropping(to: cropRect) let cropped : UIImage = UIImage(cgImage: imageRef!, scale: 0, orientation: image.imageOrientation) return cropped


Xamarin:

UIImage ImageByCroppingImage(UIImage image, CGSize size) { double newCropWidth, newCropHeight; if (image.Size.Width < image.Size.Height) { newCropWidth = image.Size.Width < size.Width ? size.Width : image.Size.Width; newCropHeight = (newCropWidth * size.Height) / size.Width; } else { newCropHeight = image.Size.Height < size.Height ? size.Height : image.Size.Height; newCropWidth = (newCropHeight * size.Width) / size.Height; } double x = image.Size.Width / 2.0 - newCropWidth / 2.0; double y = image.Size.Height / 2.0 - newCropHeight / 2.0; CGRect cropRect = new CGRect(x, y, newCropWidth, newCropHeight); var imageRef = image.CGImage.WithImageInRect(cropRect); var cropped = new UIImage(imageRef); return cropped; }


Ya hay muchas soluciones, pero quiero publicar la mía:

extension UIImage { var cgImageWidth: Int { return cgImage?.width ?? 0 } var cgImageheight: Int { return cgImage?.height ?? 0 } var blance: CGFloat { return min(size.width, size.height)} var blanceSize: CGSize { return CGSize(width: blance, height: blance) } var blanceRect: CGRect { return CGRect(origin: .zero, size: blanceSize) } var roundedImage: UIImage? { UIGraphicsBeginImageContextWithOptions(blanceSize, false, scale) defer { UIGraphicsEndImageContext() } guard let cgImage = cgImage?.cropping(to: CGRect(origin: CGPoint(x: max(0, CGFloat(cgImageWidth) - blance)/2.0, y: max(0, CGFloat(cgImageheight) - blance)/2.0), size: blanceSize)) else { return nil } UIBezierPath(ovalIn: blanceRect).addClip() UIImage(cgImage: cgImage, scale: 1.0, orientation: self.imageOrientation).draw(in: blanceRect) return UIGraphicsGetImageFromCurrentImageContext() } }


mejorado de la respuesta de @Elmundo

+(UIImage *)getCenterMaxSquareImageByCroppingImage:(UIImage *)image withOrientation:(UIImageOrientation)imageOrientation { CGSize centerSquareSize; double oriImgWid = CGImageGetWidth(image.CGImage); double oriImgHgt = CGImageGetHeight(image.CGImage); NSLog(@"oriImgWid==[%.1f], oriImgHgt==[%.1f]", oriImgWid, oriImgHgt); if(oriImgHgt <= oriImgWid) { centerSquareSize.width = oriImgHgt; centerSquareSize.height = oriImgHgt; }else { centerSquareSize.width = oriImgWid; centerSquareSize.height = oriImgWid; } NSLog(@"squareWid==[%.1f], squareHgt==[%.1f]", centerSquareSize.width, centerSquareSize.height); double x = (oriImgWid - centerSquareSize.width) / 2.0; double y = (oriImgHgt - centerSquareSize.height) / 2.0; NSLog(@"x==[%.1f], x==[%.1f]", x, y); CGRect cropRect = CGRectMake(x, y, centerSquareSize.height, centerSquareSize.width); CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect); UIImage *cropped = [UIImage imageWithCGImage:imageRef scale:0.0 orientation:imageOrientation]; CGImageRelease(imageRef); return cropped; }