26

在我正在编写的 iOS 应用程序中,我处理 PNG,因为我处理的是 alpha 通道。出于某种原因,我可以将 PNG 加载到我的imageView文件中,但是当需要将图像从我的应用程序中复制出来(到粘贴板上)或将图像保存到我的相机胶卷时,图像会旋转 90 度。

我到处搜索,我学到的一件事是,如果我使用 JPEG,由于 EXIF 信息,我不会有这个问题(听起来)。

我的应用程序具有完整的复制/粘贴功能,这是最重要的(我将分步编写,以便更容易理解):

  1. 转到我的相机胶卷并复制图像
  2. 进入我的应用程序并按“粘贴”,图像粘贴得很好,我可以整天这样做
  3. 单击我实现的复制功能,然后单击“粘贴”,图像粘贴但旋转。

我 100% 确定我的复制和粘贴代码在这里没有问题,因为如果我回到上面的第 2 步,然后单击“保存”,照片会保存到我的库中,但它会旋转 90 度!

更奇怪的是,它似乎可以很好地处理从互联网上下载的图像,但对于我用手机手动拍摄的图像来说却很受欢迎。有的有用,有的没用……

有人对此有任何想法吗?我可以使用任何可能的解决方法?我对代码非常有信心,因为它适用于我大约 75% 的图像。我可以根据要求发布代码。

4

6 回答 6

26

对于那些想要 Swift 解决方案的人,创建 UIImage 的扩展并添加以下方法:

func correctlyOrientedImage() -> UIImage {
    if self.imageOrientation == .up {
        return self
    }

    UIGraphicsBeginImageContextWithOptions(size, false, scale)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    let normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return normalizedImage ?? self;
}
于 2014-10-27T00:45:22.883 回答
14

如果您由于现有的图像imageOrientation属性而遇到问题,您可以构造一个具有不同方向的其他相同图像,如下所示:

CGImageRef imageRef = [sourceImage CGImage];

UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];

您可能需要尝试在替换图像上设置什么方向,可能会根据您开始使用的方向进行切换。

还要注意您的内存使用情况。摄影应用程序经常用完,这将使每张照片的存储空间增加一倍,直到您发布源图像。

于 2012-04-25T02:46:32.593 回答
13

花了几天时间,但由于@Dondragmer 发布的答案,我终于弄明白了。但我想我会发布我的完整解决方案。

所以基本上我必须编写一种方法来智能地自动旋转我的图像。缺点是我必须在我的代码中到处调用这个方法,它是处理器密集型的,尤其是在移动设备上工作时,但优点是我可以拍摄图像、复制图像、粘贴图像和保存图像和它们都正确旋转。这是我最终使用的代码(该方法还没有 100% 完成,仍然需要编辑内存泄漏等等)。

我最终了解到,第一次将图像插入到我的应用程序中(无论是由于用户按下“拍摄图像”、“粘贴图像”还是“选择图像”,由于某种原因,它在没有自动的情况下插入就好了旋转。此时,我将旋转值存储在一个名为 的全局变量中imageOrientationWhenAddedToScreen。这让我的生活更轻松,因为当需要操作图像并将图像保存到程序之外时,我只需检查这个缓存的全局变量并确定我是否需要正确旋转图像。

    - (UIImage*) rotateImageAppropriately:(UIImage*) imageToRotate {
    //This method will properly rotate our image, we need to make sure that
    //We call this method everywhere pretty much...

    CGImageRef imageRef = [imageToRotate CGImage];
    UIImage* properlyRotatedImage;

    if (imageOrientationWhenAddedToScreen == 0) {
       //Don't rotate the image
        properlyRotatedImage = imageToRotate;

    } else if (imageOrientationWhenAddedToScreen == 3) {

        //We need to rotate the image back to a 3
        properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:3];

    } else if (imageOrientationWhenAddedToScreen == 1) {

        //We need to rotate the image back to a 1
        properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:1];        

    }

    return properlyRotatedImage;

}

我仍然不能 100% 确定为什么 Apple 会有这种奇怪的图像旋转行为(试试这个……拿起你的手机,把它倒过来拍照,你会注意到最终的照片是正面朝上的——也许这个为什么苹果有这种功能?)。

我知道我花了很多时间来解决这个问题,所以我希望它可以帮助其他人!

于 2012-04-29T03:13:33.173 回答
13

这种“奇怪的旋转”行为真的一点也不奇怪。它很聪明,我所说的聪明是指内存高效。当您旋转 iOS 设备时,相机硬件会随之旋转。当您拍照时,无论相机的方向如何,该照片都会被捕获。UIImage 能够使用此原始图片数据而无需复制,只需跟踪它应该处于的方向。当您使用时,UIImagePNGRepresentation()您会丢失此方向数据并获得底层图像的 PNG,因为它是由相机拍摄的。要解决此问题而不是旋转,您可以告诉原始图像将自己绘制到新的上下文并UIImage从该上下文中获得正确的方向。

UIImage *image = ...;

//Have the image draw itself in the correct orientation if necessary
if(!(image.imageOrientation == UIImageOrientationUp ||
    image.imageOrientation == UIImageOrientationUpMirrored))
{
    CGSize imgsize = image.size;
    UIGraphicsBeginImageContext(imgsize);
    [image drawInRect:CGRectMake(0.0, 0.0, imgsize.width, imgsize.height)];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

NSData *png = UIImagePNGRepresentation(image);
于 2014-02-05T19:35:13.817 回答
0

这是实现这一目标的另一种方法:

@IBAction func rightRotateAction(sender: AnyObject) {

    let imgToRotate = CIImage(CGImage: sourceImageView.image?.CGImage)
    let transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
    let rotatedImage = imgToRotate.imageByApplyingTransform(transform)
    let extent = rotatedImage.extent()
    let contex = CIContext(options: [kCIContextUseSoftwareRenderer: false])
    let cgImage = contex.createCGImage(rotatedImage, fromRect: extent)
    adjustedImage = UIImage(CGImage: cgImage)!
    UIView.transitionWithView(sourceImageView, duration: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
            self.sourceImageView.image = self.adjustedImage
        }, completion: nil)
}
于 2015-08-13T10:38:32.870 回答
0

您可以使用 Image I/O 根据图像NSMutableData的方向将 PNG 图像保存到文件(或)。在下面的示例中,我将 PNG 图像保存到path.

- (BOOL)savePngFile:(UIImage *)image toPath:(NSString *)path {
    NSData *data = UIImagePNGRepresentation(image);
    int exifOrientation = [UIImage cc_iOSOrientationToExifOrientation:image.imageOrientation];
    NSDictionary *metadata = @{(__bridge id)kCGImagePropertyOrientation:@(exifOrientation)};
    NSURL *url = [NSURL fileURLWithPath:path];
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    if (!source) {
        return NO;
    }
    CFStringRef UTI = CGImageSourceGetType(source);
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, UTI, 1, NULL);
    if (!destination) {
        CFRelease(source);
        return NO;
    }
    CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metadata);
    BOOL success = CGImageDestinationFinalize(destination);
    CFRelease(destination);
    CFRelease(source);
    return success;
}

cc_iOSOrientationToExifOrientation:是一种UIImage分类方法。

+ (int)cc_iOSOrientationToExifOrientation:(UIImageOrientation)iOSOrientation {
    int exifOrientation = -1;
    switch (iOSOrientation) {
        case UIImageOrientationUp:
            exifOrientation = 1;
            break;

        case UIImageOrientationDown:
            exifOrientation = 3;
            break;

        case UIImageOrientationLeft:
            exifOrientation = 8;
            break;

        case UIImageOrientationRight:
            exifOrientation = 6;
            break;

        case UIImageOrientationUpMirrored:
            exifOrientation = 2;
            break;

        case UIImageOrientationDownMirrored:
            exifOrientation = 4;
            break;

        case UIImageOrientationLeftMirrored:
            exifOrientation = 5;
            break;

        case UIImageOrientationRightMirrored:
            exifOrientation = 7;
            break;

        default:
            exifOrientation = -1;
    }
    return exifOrientation;
}

您也可以将图像保存到NSDatausingCGImageDestinationCreateWithData和 passNSMutableData而不是NSURLin CGImageDestinationCreateWithURL

于 2016-05-17T10:30:12.007 回答