我正在iOS 3.1.3 iPhone上测试我的iPhone应用程序。我正在使用UIImagePickerController选择/捕获图像:

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setDelegate:self];
[self.navigationController presentModalViewController:imagePicker animated:YES];
[imagePicker release];



- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    self.image = [info objectForKey:UIImagePickerControllerOriginalImage];
    imageView.image = self.image;
    [self.navigationController dismissModalViewControllerAnimated:YES];
    submitButton.enabled = YES;
}

然后在某个时候,我使用ASI类将它发送到我的web服务器:

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://example.com/myscript.php"]];
[request setDelegate:self];
[request setStringEncoding:NSUTF8StringEncoding];
[request setShouldContinueWhenAppEntersBackground:YES];
//other post keys/values
[request setFile:UIImageJPEGRepresentation(self.image, 100.0f) withFileName:[NSString stringWithFormat:@"%d.jpg", [[NSDate date] timeIntervalSinceNow]] andContentType:@"image/jpg" forKey:@"imageFile"];
[request startAsynchronous];

存在的问题: 当我拿着iPhone拍照时,照片会被上传到服务器,就像你期望的那样。手持竖屏拍照时,上传的照片是旋转90度后观看的。

我的应用程序被设置为只在纵向模式(倒置和常规)下工作。

我怎样才能使图像始终显示正确的方向后上传?

在UIImageView中显示的图像是正确的(直接在拍照后),但在服务器上查看则不然。


当前回答

我在设计我的应用程序拍照时使用了这个页面,我发现以下方法将纠正方向,并且比以前的答案使用更少的内存和处理器:

CGImageRef cgRef = image.CGImage;
image = [[UIImage alloc] initWithCGImage:cgRef scale:1.0 orientation:UIImageOrientationUp];

这基本上只是用一个新的方向重新包装实际的图像数据。我使用@an0的代码,但它使一个新的图像在内存中,这可能是一个326x2448的图像,你可能会从相机。

其他回答

基于Sourabh Sharma的回答更新了Swift 3.1,并清理了代码。

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

        var transform:CGAffineTransform = .identity
        switch imageOrientation {
        case .down, .downMirrored:
            transform = transform.translatedBy(x: size.width, y: size.height).rotated(by: .pi)
        case .left, .leftMirrored:
            transform = transform.translatedBy(x: size.width, y: 0).rotated(by: .pi/2)
        case .right, .rightMirrored:
            transform = transform.translatedBy(x: 0, y: size.height).rotated(by: -.pi/2)
        default: break
        }

        switch imageOrientation {
        case .upMirrored, .downMirrored:
            transform = transform.translatedBy(x: size.width, y: 0).scaledBy(x: -1, y: 1)
        case .leftMirrored, .rightMirrored:
            transform = transform.translatedBy(x: size.height, y: 0).scaledBy(x: -1, y: 1)
        default: break
        }

        let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height),
                                       bitsPerComponent: cgImage!.bitsPerComponent, bytesPerRow: 0,
                                       space: cgImage!.colorSpace!, bitmapInfo: cgImage!.bitmapInfo.rawValue)!
        ctx.concatenate(transform)

        switch imageOrientation {
        case .left, .leftMirrored, .right, .rightMirrored:
            ctx.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.height,height: size.width))
        default:
            ctx.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.width,height: size.height))
        }
        return UIImage(cgImage: ctx.makeImage()!)
    }
}

选取器委托方法示例:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    guard let originalImage = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
    let fixedImage = originalImage.fixedOrientation()
    // do your work
}

我想出了一个更简单的方法:

- (UIImage *)normalizedImage {
    if (self.imageOrientation == UIImageOrientationUp) return self; 

    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [self drawInRect:(CGRect){0, 0, self.size}];
    UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return normalizedImage;
}

顺便说一句:@Anomie的代码没有考虑到比例,所以不适合2倍的图像。

如果我没理解错的话,你想做的是忽略UIImage的方向?如果是这样,那么你可以这样做:-

//image is your original image
image = [UIImage imageWithCGImage:[image CGImage]
                             scale:[image scale]
                       orientation: UIImageOrientationUp];

或者用Swift:-

image = UIImage(CGImage: image.CGImage!, scale: image.scale, orientation:.Up)

它解决了我的裁剪问题。霍普,这就是你要找的…

这是一个不改变原始图像颜色空间的解决方案。如果你想规范化一个灰度图像的方向,你不会幸运地使用所有基于UIGraphicsBeginImageContextWithOptions的解决方案,因为它在RGB颜色空间中创建了一个上下文。相反,你必须创建一个具有与原始图像相同属性的上下文并绘制:

extension UIImage {
    static let rotatedOrentations: [UIImage.Orientation] = [.left, .leftMirrored, .right, .rightMirrored]

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

        let image = self.cgImage!
        let swapOrientation = UIImage.rotatedOrentations.contains(imageOrientation)
        let width = swapOrientation ? image.height : image.width
        let height = swapOrientation ? image.width : image.height
        let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: image.bitsPerComponent, bytesPerRow: image.bytesPerRow, space: image.colorSpace!, bitmapInfo: image.bitmapInfo.rawValue)!
        let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height));
        context.concatenate(flipVertical)
        UIGraphicsPushContext(context)
        self.draw(at: .zero)
        UIGraphicsPopContext()

        return UIImage(cgImage: context.makeImage()!)
    }
}

迅捷;)

更新swift 3.0: d

func sFunc_imageFixOrientation(img:UIImage) -> UIImage {


    // No-op if the orientation is already correct
    if (img.imageOrientation == UIImageOrientation.up) {
        return img;
    }
    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    var transform:CGAffineTransform = CGAffineTransform.identity

    if (img.imageOrientation == UIImageOrientation.down
        || img.imageOrientation == UIImageOrientation.downMirrored) {

        transform = transform.translatedBy(x: img.size.width, y: img.size.height)
        transform = transform.rotated(by: CGFloat(M_PI))
    }

    if (img.imageOrientation == UIImageOrientation.left
        || img.imageOrientation == UIImageOrientation.leftMirrored) {

        transform = transform.translatedBy(x: img.size.width, y: 0)
        transform = transform.rotated(by: CGFloat(M_PI_2))
    }

    if (img.imageOrientation == UIImageOrientation.right
        || img.imageOrientation == UIImageOrientation.rightMirrored) {

        transform = transform.translatedBy(x: 0, y: img.size.height);
        transform = transform.rotated(by: CGFloat(-M_PI_2));
    }

    if (img.imageOrientation == UIImageOrientation.upMirrored
        || img.imageOrientation == UIImageOrientation.downMirrored) {

        transform = transform.translatedBy(x: img.size.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)
    }

    if (img.imageOrientation == UIImageOrientation.leftMirrored
        || img.imageOrientation == UIImageOrientation.rightMirrored) {

        transform = transform.translatedBy(x: img.size.height, y: 0);
        transform = transform.scaledBy(x: -1, y: 1);
    }


    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    let ctx:CGContext = CGContext(data: nil, width: Int(img.size.width), height: Int(img.size.height),
                                  bitsPerComponent: img.cgImage!.bitsPerComponent, bytesPerRow: 0,
                                  space: img.cgImage!.colorSpace!,
                                  bitmapInfo: img.cgImage!.bitmapInfo.rawValue)!

    ctx.concatenate(transform)


    if (img.imageOrientation == UIImageOrientation.left
        || img.imageOrientation == UIImageOrientation.leftMirrored
        || img.imageOrientation == UIImageOrientation.right
        || img.imageOrientation == UIImageOrientation.rightMirrored
        ) {


        ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.height,height:img.size.width))

    } else {
        ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.width,height:img.size.height))
    }


    // And now we just create a new UIImage from the drawing context
    let cgimg:CGImage = ctx.makeImage()!
    let imgEnd:UIImage = UIImage(cgImage: cgimg)

    return imgEnd
}