Вращение контекста изображения (CGContextRotateCTM), заставляющее его становиться пустым. Зачем?
#define radians(degrees) (degrees * M_PI/180)
UIImage *rotate(UIImage *image) {
CGSize size = image.size;;
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// If this is commented out, image is returned as it is.
CGContextRotateCTM (context, radians(90));
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Может ли что-то другое ошибиться? Из идей.
Ответы
Ответ 1
Проблема заключается в том, что ваш контекст поворачивается вокруг (0,0), который является верхним левым углом. Если вы поворачиваете на 90 градусов в верхнем левом углу, весь ваш рисунок будет выходить за пределы контекста. Вам понадобится двухэтапное преобразование, чтобы переместить начало контекста на него в середине, и THEN поверните. Также вам нужно нарисовать свое изображение с центром вокруг перемещенного/повернутого начала, например:
CGContextTranslateCTM( context, 0.5f * size.width, 0.5f * size.height ) ;
CGContextRotateCTM( context, radians( 90 ) ) ;
[ image drawInRect:(CGRect){ { -size.width * 0.5f, -size.height * 0.5f }, size } ] ;
НТН
Ответ 2
Я пытаюсь использовать следующий код, он работает, от http://www.catamount.com/blog/1015/uiimage-extensions-for-cutting-scaling-and-rotating-uiimages/
+ (UIImage *)rotateImage:(UIImage*)src byRadian:(CGFloat)radian
{
// calculate the size of the rotated view containing box for our drawing space
//UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0, src.size.width, src.size.height)];
//CGAffineTransform t = CGAffineTransformMakeRotation(radian);
//rotatedViewBox.transform = t;
//CGSize rotatedSize = rotatedViewBox.frame.size;
CGRect rect = CGRectApplyAffineTransform(CGRectMake(0,0, src.size.width, src.size.height), CGAffineTransformMakeRotation(radian));
CGSize rotatedSize = rect.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, radian);
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-src.size.width / 2, -src.size.height / 2, src.size.width, src.size.height), [src CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Ответ 3
Если вы не хотите изменять все происхождение и размеры, переместите центр, поверните и снова измените центр на угол так:
CGContextTranslateCTM( context, 0.5f * size.width, 0.5f * size.height ) ;
CGContextRotateCTM( context, radians( 90 ) ) ;
CGContextTranslateCTM( context, -0.5f * size.width, -0.5f * size.height ) ;
Затем нарисуйте обычно так:
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
Ответ 4
Развернувшись на ответе Nielsbot, я создал следующий фрагмент. Обратите внимание, что для предотвращения "копирования/вставки" рекомендуется использовать функцию, а не фрагмент кода. Я еще не дошел до этого, поэтому не стесняйтесь адаптировать его.
Фрагмент кода:
// <Draw in frame with orientation>
UIImage* imageToDrawRotated = <#image#>;
float rotationAngle = <#angle#>;
CGRect drawFrame = CGRectMake(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat width#>, <#CGFloat height#>);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), floor(drawFrame.origin.x + drawFrame.size.width/2), floor(drawFrame.origin.y + drawFrame.size.height/2));
CGContextRotateCTM(UIGraphicsGetCurrentContext(), rotationAngle);
[imageToDrawRotated drawInRect:CGRectMake(-floor(drawFrame.size.width/2), -floor(drawFrame.size.height/2), drawFrame.size.width, drawFrame.size.height)];
CGContextRotateCTM(UIGraphicsGetCurrentContext(), -rotationAngle);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -floor(drawFrame.origin.x + drawFrame.size.width/2), -floor(drawFrame.origin.y + drawFrame.size.height/2));
// </Draw in frame with orientation>
Кроме того, я приветствую лучший способ reset CGContext в его предыдущее состояние.
Ответ 5
Мне понравилось решение от @lbsweek, но я немного беспокоился о распределении UIView только для преобразования, вместо этого я попробовал ниже
- (UIImage *)rotateImage:(UIImage *)sourceImage byDegrees:(float)degrees
{
CGFloat radian = degrees * (M_PI/ 180);
CGRect contextRect = CGRectMake(0, 0, sourceImage.size.width, sourceImage.size.height);
float newSide = MAX([sourceImage size].width, [sourceImage size].height);
CGSize newSize = CGSizeMake(newSide, newSide);
UIGraphicsBeginImageContext(newSize);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGPoint contextCenter = CGPointMake(CGRectGetMidX(contextRect), CGRectGetMidY(contextRect));
CGContextTranslateCTM(ctx, contextCenter.x, contextCenter.y);
CGContextRotateCTM(ctx, radian);
CGContextTranslateCTM(ctx, -contextCenter.x, -contextCenter.y);
[sourceImage drawInRect:contextRect];
UIImage* rotatedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return rotatedImage;
}