iOS:保存为PNG表示数据后,图像旋转90度

时间:2012-06-01 12:23:12

标签: iphone uiimage image-rotation ios5.1 landscape-portrait

我已经研究了足够的工作,但无法修复它。只要我将图像存储为UIImage,从相机拍照后,它就可以了,但只要我将此图像存储为PNG表示,它就会旋转90度。

以下是我的代码以及我尝试过的所有内容:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
    NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];

    if([mediaType isEqualToString:(NSString*)kUTTypeImage]) 
    {
        AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        delegate.originalPhoto  = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        NSLog(@"Saving photo");
        [self saveImage];
        NSLog(@"Fixing orientation");
        delegate.fixOrientationPhoto  = [self fixOrientation:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]];      
        NSLog(@"Scaling photo");
        delegate.scaledAndRotatedPhoto  =  [self scaleAndRotateImage:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]];
    }
    [picker dismissModalViewControllerAnimated:YES];
    [picker release];
}


- (void)saveImage
{
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSData *imageData = UIImagePNGRepresentation(delegate.originalPhoto);
    [imageData writeToFile:[delegate filePath:imageName] atomically:YES];
}

这里的fixOrientation和scaleAndRotateImage函数分别来自herehere。当我在UIImage上应用它们时,它们可以正常工作并旋转图像,但如果我将图像保存为PNG表示并应用它们则无效。

执行上述功能后请参考以下图片:

The first photo is original, second is saved, and third and fourth after applying fixorientation and scaleandrotate functions on saved image

8 个答案:

答案 0 :(得分:67)

从相机拍照后的iOS 4.0开始,在保存之前它不会旋转它,

只需在JPEG的EXIF数据中设置旋转标志。如果将UIImage保存为JPEG,则

将设置旋转标志.PNG不支持旋转标志,因此如果将UIImage保存为

PNG,它将被错误旋转,并且没有设置标志来修复它。所以如果你想要PNG

图片必须自行旋转,为此检查link

答案 1 :(得分:23)

Rao发布的UIImage扩展的Swift 3.1版本:

extension UIImage {
    func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.up {
            return self
        }
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        if let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return normalizedImage
        } else {
            return self
        }
    }
}

用法:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()

答案 2 :(得分:18)

对于Swift 2.1

将以下内容添加为UIImage扩展名

extension UIImage {
   func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.Up {
            return self
        }

        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.drawInRect(CGRectMake(0, 0, self.size.width, self.size.height))
        let normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return normalizedImage;
    }
}

使用示例:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()

答案 3 :(得分:6)

我发现以下提示非常有用:

1。自然输出是风景

2。 .width / .height受.imageOrientation

影响

3使用短尺寸而不是.width


(1)相机的“自然”输出,用于剧照 IS LANDSCAPE。

这是违反直觉的。肖像是UIImagePickerController等提供的唯一方式。但是当使用“普通”肖像相机时,你将获得UIImageOrientationRight作为“正常”方向

(我记得这一点 - 视频的自然输出是(当然)风景;所以剧照是一样的 - 即使iPhone完全是关于肖像。)


(2).width和.height 确实受.imageOrientation影响!!!!!!!!!

一定要这样做,并在iPhone上尝试两种方式,

NSLog(@"fromImage.imageOrientation is %d", fromImage.imageOrientation);
NSLog(@"fromImage.size.width  %f   fromImage.size.height  %f",
            fromImage.size.width, fromImage.size.height);

你会看到.height和.width交换,“即使”真正的像素是风景。


(3)简单地使用“短维度”而不是.width,通常可以解决很多问题

我发现这非常有帮助。假设您想要图像的顶部正方形:

CGRect topRectOfOriginal = CGRectMake(0,0, im.size.width,im.size.width);

实际上无法正常工作,当相机被(“真的”)保持风景时,你会得到一张压扁的图像。

然而,如果你只是这样做

float shortDimension = fminf(im.size.width, im.size.height);
CGRect topRectOfOriginal = CGRectMake(0,0, shortDimension,shortDimension);

然后“一切都已修复”,你实际上“不需要担心”方向标志。再说一点(3)并不是万灵药,但它经常解决所有问题。

希望能帮助别人节省一些时间。

答案 4 :(得分:3)

试试这个, 你可以使用

NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0);

而不是

NSData *somenewImageData = UIImagePNGRepresentation(newimg);

答案 5 :(得分:2)

我找到了这段代码here,它实际上是为我修复的。对于我的应用程序,我拍了一张照片并保存了,每次加载它时,它都会附加恼人的旋转(我抬起头来,这显然与EXIF以及iPhone拍摄和存储图像的方式有关)。这段代码为我修好了。我不得不说,它最初是作为类/扩展/类别的补充(你可以从链接中找到原文。我使用它像下面的一个简单的方法,因为我真的不想做一个整体这个类或类别。我只使用肖像,但我认为代码适用于任何方向。我不确定

Rant over,这是代码:

Collection<Person> selectedPeople = filterWhenMultipleOccurance(people, p -> p.getAge(), 3);
System.out.println("---------------");
selectedPeople.forEach(p -> System.out.println(p.getName()));

我不确定这对你有多大帮助,但我希望它有所帮助:)

答案 6 :(得分:1)

请尝试以下代码

UIImage *sourceImage = ... // Our image
CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0);
CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage,
selectionRect);
UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef];

并且

CGRect TransformCGRectForUIImageOrientation(CGRect source, UIImageOrientation orientation, CGSize imageSize) {
switch (orientation) {
case UIImageOrientationLeft: { // EXIF #8
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI_2);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationDown: { // EXIF #3
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationRight: { // EXIF #6
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(0.0, imageSize.width);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI + M_PI_2);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationUp: // EXIF #1 - do nothing
  default: // EXIF 2,4,5,7 - ignore
  return source;
}
}
  ...
UIImage *sourceImage = ... // Our image
 CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0);
CGRect transformedRect = TransformCGRectForUIImageOrientation(selectionRect,  sourceImage.imageOrientation, sourceImage.size);
CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, transformedRect);
UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef];

我从以下链接中引用了更多detail

最诚挚的问候: - )

答案 7 :(得分:0)

试试这段代码:

NSData *imageData = UIImageJPEGRepresentation(delegate.originalPhoto,100);