如何将 UIImage 旋转 90 度?
我有一个 UIImage
,它是 UIImageOrientationUp
(纵向),我想将其逆时针旋转 90 度(横向)。我不想使用 CGAffineTransform
。我希望 UIImage 的像素实际移动位置。我正在使用一段代码(如下所示),最初旨在调整 UIImage
的大小来执行此操作。我将目标大小设置为 UIImage 的当前大小,但出现错误:
(错误):CGBitmapContextCreate:无效数据字节/行:对于 8 个整数位/组件、3 个组件、kCGImageAlphaPremultipliedLast,应至少为 1708。
(顺便说一句,每当我提供较小的尺寸作为目标尺寸时,我都不会收到错误)。如何仅使用核心图形函数将我的 UIImage
逆时针旋转 90 度,同时保留当前大小?
-(UIImage*)reverseImageByScalingToSize:(CGSize)targetSize:(UIImage*)anImage
{
UIImage* sourceImage = anImage;
CGFloat targetWidth = targetSize.height;
CGFloat targetHeight = targetSize.width;
CGImageRef imageRef = [sourceImage CGImage];
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
if (bitmapInfo == kCGImageAlphaNone) {
bitmapInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef bitmap;
if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
} else {
bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
}
if (sourceImage.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
} else if (sourceImage.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -targetWidth, 0);
} else if (sourceImage.imageOrientation == UIImageOrientationDown) {
// NOTHING
} else if (sourceImage.imageOrientation == UIImageOrientationUp) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
return newImage;
}
I have a UIImage
that is UIImageOrientationUp
(portrait) that I would like to rotate counter-clockwise by 90 degrees (to landscape). I don't want to use a CGAffineTransform
. I want the pixels of the UIImage
to actually shift position. I am using a block of code (shown below) originally intended to resize a UIImage
to do this. I set a target size as the current size of the UIImage
but I get an error:
(Error): CGBitmapContextCreate: invalid data bytes/row: should be at least 1708 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedLast.
(I don't get an error whenever I provide a SMALLER size as the target size BTW). How can I ROTATE my UIImage
90 degrees CCW using just core graphics functions while preserving the current size?
-(UIImage*)reverseImageByScalingToSize:(CGSize)targetSize:(UIImage*)anImage
{
UIImage* sourceImage = anImage;
CGFloat targetWidth = targetSize.height;
CGFloat targetHeight = targetSize.width;
CGImageRef imageRef = [sourceImage CGImage];
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
if (bitmapInfo == kCGImageAlphaNone) {
bitmapInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef bitmap;
if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
} else {
bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
}
if (sourceImage.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
} else if (sourceImage.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -targetWidth, 0);
} else if (sourceImage.imageOrientation == UIImageOrientationDown) {
// NOTHING
} else if (sourceImage.imageOrientation == UIImageOrientationUp) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
return newImage;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
“tint uiimage Grayscale”似乎是适合我的Google-Fu,
我立即得到:
https://discussions.apple.com/message/8104516?messageID=8104516�
https://discussions.apple.com/thread/2751445?start=0&tstart=0
如何在 iPhone 上以编程方式对图像进行着色?
"tint uiimage grayscale" appears to be the appropriate Google-Fu for this one
straight away I get:
https://discussions.apple.com/message/8104516?messageID=8104516�
https://discussions.apple.com/thread/2751445?start=0&tstart=0
How would I tint an image programmatically on the iPhone?
我喜欢
Peter Sarnowski
简单优雅的回答,但当您不能依赖EXIF
元数据等时,它可能会导致问题。在您需要旋转实际图像数据的情况下,我建议您这样做:上面的代码采用方向为
横向
的图像(不记得是横向左
还是横向右
)并将其旋转为纵向
。这是一个示例,可以根据您的需要进行修改。您必须使用的关键参数是 CGContextRotateCTM(context, M_PI_2),您可以在其中决定要旋转的程度,但随后您必须确保图片仍然使用 <代码>CGContextTranslateCTM(上下文,0,-640)。最后一部分对于确保您看到图像而不是空白屏幕非常重要。
如需了解更多信息,请查看来源。
I like the simple elegance of
Peter Sarnowski
's answer, but it can cause problems when you can't rely onEXIF
metadata and the like. In situations where you need to rotate the actual image data I would recommend something like this:The above code takes an image whose orientation is
Landscape
(can't remember if it'sLandscape Left
orLandscape Right
) and rotates it intoPortrait
. It is an example which can be modified for your needs.The key arguments you would have to play with are
CGContextRotateCTM(context, M_PI_2)
where you decide how much you want to rotate by, but then you have to make sure the picture still draws on the screen usingCGContextTranslateCTM(context, 0, -640)
. This last part is quite important to make sure you see the image and not a blank screen.For more info check out the source.
调整大小-a-uiimage-the -right-way 解释了许多执行此操作的代码示例所存在的一些问题,并且有一些代码片段来帮助处理 UIImages - UIImage+resize.m 中的私有帮助器方法接受允许旋转的转换,因此您只需将其公开为公共接口即可。
这是该文件的许可证:
resize-a-uiimage-the-right-way explains some of the issues many code samples for doing this have, and has some code snippets to help deal with UIImages - the private helper method in UIImage+resize.m accepts a transform to allow rotation, so you'd just need to expose that as a public interface.
This is the license from that file:
有一个非常高效的 UIImage 类别,名为 NYXImagesKit。它使用 vDSP、CoreImage 和 vImage 来尽可能快。它有一个 UIImage+Rotating 类别,拯救了我的日子:)
https://github.com/Nyx0uf/NYXImagesKit
There is a extremely efficient UIImage category named NYXImagesKit. It uses vDSP, CoreImage and vImage to be as fast as possible. It has a UIImage+Rotating category that saved my day :)
https://github.com/Nyx0uf/NYXImagesKit
对于 Swift:这是 UIImage 的一个简单扩展:(
来源< /a>)
使用它:
如果翻转设置为 true,前者将旋转图像并翻转它。
For Swift: Here is a simple extension to UIImage:
(Source)
Use it with:
The former will rotate an image and flip it if flip is set to true.
我相信最简单的方法(也是线程安全的)是:
注意:正如 Brainware 所说,这只会修改图像的方向数据 - 像素数据不变。对于某些应用程序来说,这可能还不够。
或者用斯威夫特:
I believe the easiest way (and thread safe too) is to do:
Note: As Brainware said this only modifies the orientation data of the image - the pixel data is untouched. For some applications, this may not be enough.
Or in Swift:
查看 Hardy Macia 简单而出色的代码:剪切缩放和旋转 uiimages
只需致电,
谢谢 Hardy Macia!
标题:
由于链接可能会失效,因此这是完整的代码
Check out the simple and awesome code of Hardy Macia at: cutting-scaling-and-rotating-uiimages
Just call
Thanks Hardy Macia!
Header:
Since the link may die, here's the complete code
怎么样:
What about something like:
尽管这看起来很奇怪,但以下代码为我解决了这个问题:
As strange as this seems, the following code solved the problem for me:
线程安全的旋转函数如下(它工作得更好):
A thread safe rotation function is the following (it works much better):
我对上述所有问题都遇到了麻烦,包括批准的答案。我将 Hardy 的类别转换回一种方法,因为我想要的只是旋转图像。这是代码和用法:
和用法:
谢谢 Hardy!
I had trouble with ll of the above, including the approved answer. I converted Hardy's category back into a method since all i wanted was to rotate an image. Here's the code and usage:
And the usage:
Thanks Hardy!
将图像旋转90度(顺时针/逆时针方向)
函数调用 -
实现:
Rotate Image by 90 degree (clockwise/anti-clockwise direction)
Function call -
Implementation:
简单的。只需更改图像方向标志即可。
Simple. Just change the image orientation flag.
这是 UIImage 的 Swift 扩展,可以将图像旋转任意角度。像这样使用它:
letrotatedImage = image.rotated(byDegrees: Degree)
。我在其他答案之一中使用了 Objective-C 代码,并删除了一些我们不正确的行(旋转框内容),并将其变成了 UIImage 的扩展。
Here is a Swift extension to UIImage that rotates the image by any arbitrary angle. Use it like this:
let rotatedImage = image.rotated(byDegrees: degree)
.I used the Objective-C code in one of the other answers and removed a few lines that we incorrect (rotated box stuff) and turned it into an extension for UIImage.
如果您想添加一个照片旋转按钮,以 90 度的增量持续旋转照片,就可以了。 (
finalImage
是一个已经在其他地方创建的 UIImage。)If you want to add a photo rotate button that'll keep rotating the photo in 90 degree increments, here you go. (
finalImage
is a UIImage that's already been created elsewhere.)Swift 3 UIImage 扩展:
Swift 3 UIImage extension:
Swift 4.2 版本的 RawMean 的答案:
Swift 4.2 version of RawMean's answer:
我尝试了这个代码,它有效,并取自 http://www.catamount.com/blog/1015/uiimage-extensions-for-cutting-scaling-and-rotating-uiimages/
I try this code, it works, and took from http://www.catamount.com/blog/1015/uiimage-extensions-for-cutting-scaling-and-rotating-uiimages/
对基于 Hardy Macia 代码的其他答案进行微小更改。不需要简单地创建整个
UIView
对象来计算旋转图像的边界矩形。只需使用 CGRectApplyAffineTransform 对图像矩形应用旋转变换即可。Minor change to the other answers that are based on Hardy Macia's code. There is no need to create a whole
UIView
object simply to calculate the bounding rectangle of the rotated image. Just apply a rotate transform to the image rectangle usingCGRectApplyAffineTransform
.