2010-05-18 13 views
15

Tengo un UIImageView con una imagen. He rotado la imagen antes de visualizar estableciendo la propiedad de transformación de UIImageView en CGAffineTransformMakeRotation (ángulo) donde angle es el ángulo en radianes.Crear un UIImage desde un UIImageView girado

Quiero ser capaz de crear otro UIImage que corresponda a la versión girada que puedo ver en mi opinión.

Estoy casi allí, girando el contexto imagen me sale una imagen rotada:

- (UIImage *) rotatedImageFromImageView: (UIImageView *) imageView 
{ 
    UIImage *rotatedImage; 

    // Get image width, height of the bounding rectangle 
    CGRect boundingRect = [self getBoundingRectAfterRotation: imageView.bounds byAngle:angle]; 

    // Create a graphics context the size of the bounding rectangle 
    UIGraphicsBeginImageContext(boundingRect.size); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Rotate and translate the context 
    CGAffineTransform ourTransform = CGAffineTransformIdentity; 
    ourTransform = CGAffineTransformConcat(ourTransform, CGAffineTransformMakeRotation(angle)); 

    CGContextConcatCTM(context, ourTransform); 

    // Draw the image into the context 
    CGContextDrawImage(context, CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage); 

    // Get an image from the context 
    rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)]; 

    // Clean up 
    UIGraphicsEndImageContext(); 
    return rotatedImage; 
} 

Sin embargo, la imagen no se gira alrededor de su centro. He intentado todo tipo de transformaciones concatenadas con mi rotación para que gire alrededor del centro, pero fue en vano. ¿Me estoy perdiendo un truco? ¿Es esto posible ya que estoy rotando el contexto y no la imagen?

Desesperado por hacer que esto funcione ahora, por lo que cualquier ayuda sería apreciada.

de Dave

EDITAR: Me han preguntado varias veces por mi código boundingRect, así que aquí está:

- (CGRect) getBoundingRectAfterRotation: (CGRect) rectangle byAngle: (CGFloat) angleOfRotation { 
    // Calculate the width and height of the bounding rectangle using basic trig 
    CGFloat newWidth = rectangle.size.width * fabs(cosf(angleOfRotation)) + rectangle.size.height * fabs(sinf(angleOfRotation)); 
    CGFloat newHeight = rectangle.size.height * fabs(cosf(angleOfRotation)) + rectangle.size.width * fabs(sinf(angleOfRotation)); 

    // Calculate the position of the origin 
    CGFloat newX = rectangle.origin.x + ((rectangle.size.width - newWidth)/2); 
    CGFloat newY = rectangle.origin.y + ((rectangle.size.height - newHeight)/2); 

    // Return the rectangle 
    return CGRectMake(newX, newY, newWidth, newHeight); 
} 
+0

¿Qué es esta función 'getBoundingRectAfterRotation'? – bmdhacks

+0

Hola @bmdhacks getBoundingRectAfterRotation es un método que he creado, por lo que no lo encontrarás en ninguna de las clases de Cocoa-Touch. Toma un rect y un ángulo como argumentos y devuelve un nuevo CGRect que abarcaría el rect original si fuera rotado por el ángulo dado. –

+0

Hola @bmdhacks debido a la demanda popular han agregado el método en una edición a mi pregunta original. –

Respuesta

22

OK - por fin parece haber hecho. Cualquier comentario sobre la corrección sería útil ... se necesita una traducción, una rotación, una escala y un desplazamiento desde la posición de trazado para hacer que funcione. El código está aquí:

CGAffineTransform transform = CGAffineTransformIdentity; 
transform = CGAffineTransformTranslate(transform, boundingRect.size.width/2, boundingRect.size.height/2); 
transform = CGAffineTransformRotate(transform, angle); 
transform = CGAffineTransformScale(transform, 1.0, -1.0); 

CGContextConcatCTM(context, transform); 

// Draw the image into the context 
CGContextDrawImage(context, CGRectMake(-imageView.image.size.width/2, -imageView.image.size.height/2, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage); 

// Get an image from the context 
rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)]; 
+1

¿Por qué necesita 'transform = CGAffineTransformScale (transform, 1.0, -1.0);' ? – Hlung

+3

CoreGraphics utiliza un sistema de coordenadas donde el origen es la parte inferior izquierda. Los objetos UIKit usan un origen en la parte superior izquierda con el eje y aumentando a medida que se mueve hacia abajo en la pantalla. Esta transformación gira el eje y para garantizar que la imagen se dibuja hacia arriba. –

+1

Gracias! Estaba luchando para dibujar una imagen en el contexto con la traducción, la rotación y la escala. Probé el 'drawInRect:' de UIImage y traduje el contexto, pero siempre gira alrededor de la parte superior izquierda (0,0). ¡Tu solución es la única que funciona! :) – Hlung

Cuestiones relacionadas