Boe*_*ckm 88 iphone objective-c ios
在过去的几周里,我一直在使用objective-c中的图像并注意到许多奇怪的行为.首先,像许多其他人一样,我一直遇到这个问题,用相机拍摄的图像(或用别人的相机和MMS给我拍摄)旋转90度.我不确定为什么这个世界会发生这种情况(因此我的问题),但我能够提出一个廉价的工作.
这次我的问题是为什么会发生这种情况?为什么Apple会旋转图像?当我用相机正面拍摄照片时,除非我执行上面提到的代码,否则当我保存照片时,它会被保存为旋转状态.现在,我的解决方法在几天前还可以.
我的应用程序修改的图像的各个像素,特别是PNG(所以任何JPEG转换被抛出窗外对我的情况)的alpha通道.几天前,我注意到即使图像在我的应用程序中正确显示,这要归功于我的解决方法代码,当我的算法修改图像的各个像素时,它认为图像是旋转的.因此,而不是在图像的顶部修改像素,它修改的图像侧的像素(因为它认为它应该被旋转)!我无法弄清楚如何在内存中旋转图像 - 理想情况下,我宁愿只是擦掉那个imageOrientation标志.
这是另一个令我困惑的东西......当我拍摄照片时,imageOrientation设置为3.我的解决方法代码非常智能,可以实现这一点并将其翻转,以便用户永远不会注意到.此外,我将图像保存到库中的代码实现了这一点,将其翻转,然后将其保存,使其正确显示在相机胶卷中.
该代码如下所示:
NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
Run Code Online (Sandbox Code Playgroud)
当我这个新保存的图像加载到我的应用程序,则imageOrientation是0 -正是我想看到的,而我的旋转解决办法甚至不需要运行(注:加载从互联网上的图像时,而不是用相机拍摄的图像,imageOrientation总是0,导致完美的行为).出于某种原因,我的保存代码似乎擦除了这个imageOrientation标志.我希望只是窃取该代码,并在用户拍照并将其添加到应用程序时使用它来擦除我的imageOrientation,但它似乎不起作用.有UIImageWriteToSavedPhotosAlbum什么特别的imageOrientation吗?
对于这个问题,最好的解决办法就是imageOrientation在用户完成拍摄图像后立即将其吹走.我认为Apple出于某种原因完成了旋转行为,对吧?一些人认为这是Apple的缺陷.
(...如果你还没有丢失......注2:当我拍摄水平照片时,一切似乎都很完美,就像从互联网上拍摄的照片一样)
编辑:
以下是一些图像和场景的实际情况.根据目前为止的评论,看起来这种奇怪的行为不仅仅是一种iPhone行为,我认为这种行为很好.
这是我带着我的手机(注意正确的方向)的照片的图片,它显示的样子,因为它没有我的电话时,我拍下照片:

以下是我通过电子邮件将图片发送给自己后的图片(看起来像Gmail正确处理):

这是图像在Windows中作为缩略图的样子(看起来不像是正确处理):

以下是使用Windows Photo Viewer打开时的实际图像(仍未正确处理):

在对这个问题的所有评论之后,这就是我在想的...... iPhone拍摄了一张图片,并说"要正确显示它,它需要旋转90度".此信息将在EXIF数据中.(为什么它需要旋转90度,而不是默认直线垂直,我不知道).从这里开始,Gmail非常智能,可以读取和分析EXIF数据,并正确显示它.但是,Windows不够智能,无法读取EXIF数据,因此显示图像不正确.我的假设是否正确?
Dil*_*mar 55
当我从Camera获取图像时遇到了同样的问题,我将以下代码修复它.从这里添加方法scaleAndRotateImage
- (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo {
// Images from the camera are always in landscape, so rotate
UIImage *image = [self scaleAndRotateImage: [imageInfo objectForKey:UIImagePickerControllerOriginalImage]];
//then save the image to photo gallery or wherever
}
- (UIImage *)scaleAndRotateImage:(UIImage *) image {
int kMaxResolution = 320;
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = bounds.size.width / ratio;
}
else {
bounds.size.height = kMaxResolution;
bounds.size.width = bounds.size.height * ratio;
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
}
else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
Run Code Online (Sandbox Code Playgroud)
Har*_*hIT 48
我对它进行了研发并发现,每个图像文件都有元数据属性.如果元数据指定图像的方向,除了Mac之外,其他操作系统通常会忽略该方向.拍摄的大多数图像都将其元数据属性设置为直角.所以Mac显示它旋转90度的方式.您可以在Windows操作系统中以适当的方式查看相同的图像.
有关详细信息,请阅读此答案http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm
尝试阅读你的图像exif http://www.exifviewer.org/ ,或http://regex.info/exif.cgi,或http://www.addictivetips.com/internet-tips/view-complete-exif -元数据信息-的-任何-JPEG图像,在线/
tha*_*son 18
快速复制/粘贴快速翻译Dilip的优秀答案.
import Darwin
class func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
let imgRef = imageSource.CGImage;
let width = CGFloat(CGImageGetWidth(imgRef));
let height = CGFloat(CGImageGetHeight(imgRef));
var bounds = CGRectMake(0, 0, width, height)
var scaleRatio : CGFloat = 1
if (width > maxResolution || height > maxResolution) {
scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
bounds.size.height = bounds.size.height * scaleRatio
bounds.size.width = bounds.size.width * scaleRatio
}
var transform = CGAffineTransformIdentity
let orient = imageSource.imageOrientation
let imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef)))
switch(imageSource.imageOrientation) {
case .Up :
transform = CGAffineTransformIdentity
case .UpMirrored :
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
case .Down :
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, CGFloat(M_PI));
case .DownMirrored :
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
case .Left :
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);
case .LeftMirrored :
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);
case .Right :
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);
case .RightMirrored :
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);
default : ()
}
UIGraphicsBeginImageContext(bounds.size)
let context = UIGraphicsGetCurrentContext()
if orient == .Right || orient == .Left {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
} else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
Run Code Online (Sandbox Code Playgroud)
Dáv*_*már 16
Swift 4版本,对Dilip的答案进行安全检查.
public static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? {
guard let imgRef = imageSource.cgImage else {
return nil
}
let width = CGFloat(imgRef.width)
let height = CGFloat(imgRef.height)
var bounds = CGRect(x: 0, y: 0, width: width, height: height)
var scaleRatio : CGFloat = 1
if (width > maxResolution || height > maxResolution) {
scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
bounds.size.height = bounds.size.height * scaleRatio
bounds.size.width = bounds.size.width * scaleRatio
}
var transform = CGAffineTransform.identity
let orient = imageSource.imageOrientation
let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))
switch(imageSource.imageOrientation) {
case .up:
transform = .identity
case .upMirrored:
transform = CGAffineTransform
.init(translationX: imageSize.width, y: 0)
.scaledBy(x: -1.0, y: 1.0)
case .down:
transform = CGAffineTransform
.init(translationX: imageSize.width, y: imageSize.height)
.rotated(by: CGFloat.pi)
case .downMirrored:
transform = CGAffineTransform
.init(translationX: 0, y: imageSize.height)
.scaledBy(x: 1.0, y: -1.0)
case .left:
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(translationX: 0, y: imageSize.width)
.rotated(by: 3.0 * CGFloat.pi / 2.0)
case .leftMirrored:
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(translationX: imageSize.height, y: imageSize.width)
.scaledBy(x: -1.0, y: 1.0)
.rotated(by: 3.0 * CGFloat.pi / 2.0)
case .right :
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(translationX: imageSize.height, y: 0)
.rotated(by: CGFloat.pi / 2.0)
case .rightMirrored:
let storedHeight = bounds.size.height
bounds.size.height = bounds.size.width;
bounds.size.width = storedHeight;
transform = CGAffineTransform
.init(scaleX: -1.0, y: 1.0)
.rotated(by: CGFloat.pi / 2.0)
}
UIGraphicsBeginImageContext(bounds.size)
if let context = UIGraphicsGetCurrentContext() {
if orient == .right || orient == .left {
context.scaleBy(x: -scaleRatio, y: scaleRatio)
context.translateBy(x: -height, y: 0)
} else {
context.scaleBy(x: scaleRatio, y: -scaleRatio)
context.translateBy(x: 0, y: -height)
}
context.concatenate(transform)
context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))
}
let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageCopy
}
Run Code Online (Sandbox Code Playgroud)
小智 15
这次我的问题是为什么会发生这种情况?为什么Apple会旋转图像?
答案很简单.Apple不会旋转图像.这就是混乱所在.
CCD相机不会旋转,因此它始终以横向模式拍摄照片.
Apple做了一件非常聪明的事情 - 而不是花费所有时间来旋转图像 - 改变数兆字节的数据 - 只需用照片拍摄它来标记它.
OpenGL非常容易进行翻译 - 所以DATA永远不会被洗牌 - 只是它如何绘制.
因此,方向元数据.
如果你想裁剪,调整大小等,这就成了一个问题 - 但是一旦你知道发生了什么,你只需定义你的矩阵,一切都会成功.
ATO*_*TOA 12
iPhone/iPad生成的任何图像都将保存为Landscape Left,并带有EXIF Orientation标记(Exif.Image.Orientation),指定实际方向.
它具有以下值:1:横向左6:纵向正常3:横向右4:纵向颠倒
在IOS中,正确读取EXIF信息,并以与拍摄时相同的方式显示图像.但在Windows中,不使用EXIF信息.
如果您在GIMP中打开其中一个图像,则会说该图像具有旋转信息.
小智 8
对于任何使用Xamarin的人来说,这里是Dilip 很好的答案的C#翻译,并感谢thetyson的Swift翻译.
public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution) {
var imgRef = imageSource.CGImage;
var width = (nfloat)imgRef.Width;
var height = (nfloat)imgRef.Height;
var bounds = new CGRect(0, 0, width, height);
nfloat scaleRatio = 1;
if (width > maxResolution || height > maxResolution)
{
scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height);
bounds.Height = bounds.Height * scaleRatio;
bounds.Width = bounds.Width * scaleRatio;
}
var transform = CGAffineTransform.MakeIdentity();
var orient = imageSource.Orientation;
var imageSize = new CGSize(imgRef.Width, imgRef.Height);
nfloat storedHeight;
switch(imageSource.Orientation) {
case UIImageOrientation.Up:
transform = CGAffineTransform.MakeIdentity();
break;
case UIImageOrientation.UpMirrored :
transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f);
transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
break;
case UIImageOrientation.Down :
transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height);
transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI);
break;
case UIImageOrientation.DownMirrored :
transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height);
transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f);
break;
case UIImageOrientation.Left:
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width);
transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
break;
case UIImageOrientation.LeftMirrored :
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width);
transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
break;
case UIImageOrientation.Right :
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f);
transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
break;
case UIImageOrientation.RightMirrored :
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeScale(-1.0f, 1.0f);
transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
break;
default :
break;
}
UIGraphics.BeginImageContext(bounds.Size);
var context = UIGraphics.GetCurrentContext();
if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) {
context.ScaleCTM(-scaleRatio, scaleRatio);
context.TranslateCTM(-height, 0);
} else {
context.ScaleCTM(scaleRatio, -scaleRatio);
context.TranslateCTM(0, -height);
}
context.ConcatCTM(transform);
context.DrawImage(new CGRect(0, 0, width, height), imgRef);
var imageCopy = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return imageCopy;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
89372 次 |
| 最近记录: |