UIImagePNGПроблемы с представлением? / Изображение повернуто на 90 градусов

Я хочу загрузить изображения из UIImagePickerController, а затем сохранить выбранную фотографию в каталог документов моего приложения.

UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *data1 = UIImagePNGRepresentation(image);

NSString *fileName = "1.png";
NSString *path = //get Document path, then add fileName
BOOL succ = [data1 writeToFile:path atomically:YES];

но после того, как я сохранил изображение в свой документ, я обнаружил, что изображение было повернуто на 90 градусов, затем я меняю метод UIImagePNGRepresentation на UIImageJPEGRepresentation, на этот раз все в порядке, кто-нибудь знает, в чем проблема?


person disorderdev    schedule 24.08.2010    source источник
comment
возможный дубликат ориентации изображения результата iOS UIImagePickerController после загрузки   -  person Axel Guilmin    schedule 03.04.2015


Ответы (6)


У меня была та же проблема, и я просто выяснил причину: начиная с iOS 4.0, когда камера делает снимок, она не поворачивает его перед сохранением, а просто устанавливает флаг поворота в данных EXIF ​​файла JPEG.

Если вы сохраните UIImage как JPEG, он установит флаг поворота.

PNG не поддерживают флаг вращения, поэтому, если вы сохраните UIImage как PNG, он будет повернут неправильно и не будет установлен флаг для его исправления. Так что, если вам нужны PNG, вы должны сами их повернуть.

Я бы назвал это ошибкой в ​​функции сохранения PNG, но это всего лишь мнение (они должны хотя бы предупредить вас об этом).

person jasongregori    schedule 01.02.2011
comment
Я потратил, вероятно, час или около того, пытаясь заставить мой PNG CGImageSource (созданный из данных) правильно повернуться при создании большого пальца ... вставив данные exif в мои параметры создания CGImageSource и т. Д. И т. Д. И UIImageJPEGRepresentation исправил это сразу! Спасибо! - person taber; 28.09.2011
comment
@jasongregori: Даже сохранение в формате JPEG не решает моей проблемы. Изображение по-прежнему вращается. - person rohan-patel; 02.01.2012
comment
Это частично решило мою проблему !! Когда я беру изображение в ландшафтном режиме, оно сохраняется правильно, а когда я извлекаю его, оно находится в альбомном. Но если я сделаю изображение в портретном режиме, когда я получу его в альбомном режиме. То есть только для портрета он вращается. - person Bharathi; 03.07.2012
comment
У меня была такая же проблема, и предложенная здесь категория: stackoverflow.com/a/5427890/1327557 решила ее навсегда - person Axel Guilmin; 03.04.2015

Пожалуйста, попробуйте это.

func rotateImage(image: UIImage) -> UIImage? {
    if image.imageOrientation == UIImage.Orientation.up {
        return image /// already upright, no need for changes
    }
    UIGraphicsBeginImageContext(image.size)
    image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
    let copy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return copy
}

Удачного кодирования :)

person Stefan    schedule 23.10.2015
comment
Большое Вам спасибо. Сделав это перед сохранением изображения как .png, я решил эту проблему. - person Alexandros; 21.01.2018
comment
сделал то же самое и отлично сработал для меня, только ~ 3 небольших исправления, чтобы добраться до Swift 4! Большое Вам спасибо :) - person agrippa; 17.05.2018
comment
замечательный материал, спасибо! - person Israel Tabadi; 05.03.2021
comment
У меня это сработало, спасибо! - person Juan David Torres; 22.05.2021
comment
Идеально! Отлично работает в Swift 5, Xcode 12. - person aheze; 14.06.2021

Я решаю эту проблему с помощью следующего кода.

- (UIImage *)scaleAndRotateImage:(UIImage *)image
{
    int kMaxResolution = 640; 

    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;
}
person İbrahim Özbölük    schedule 16.12.2013
comment
Мне нравится этот код, и почему-то он единственный, который работает с точки зрения поворота моего изображения. В любом случае у меня проблемы с его работой в iOS 7.1 и цикле ARC. Есть идеи, в чем может заключаться проблема? - person Matthias Max; 29.08.2014
comment
Спасибо тебе за это! Работал как шарм! Я перевел его на swift 2.0 для своего текущего проекта. Вот суть: gist.github.com/fnk0/2e108700bdbe4a92766c - person Marcus Gabilheri; 13.10.2015
comment
@MarcusGabilheri, как мне использовать ваш код для поворота на 90 градусов? - person alex; 22.10.2015

Следующая быстрая функция решает проблему.

func rotateImage(image: UIImage) -> UIImage? {
        if (image.imageOrientation == UIImage.Orientation.up ) {
            return image
        }
        UIGraphicsBeginImageContext(image.size)
        image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
        let copy = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return copy
    }

Да, это так просто, потому что функция drawInRect учитывает ориентацию изображения.

person devfreak    schedule 07.09.2015
comment
как мне это использовать? на данный момент мой код imageHolder выглядит так: invoiceImageHolder.image = loadImageFromPath(fileInDocumentsDirectory(("\(imagePath!)"))), и я получаю ошибки Использование неразрешенного идентификатора imageOrientation - person alex; 22.10.2015

Я создал это расширение UIImage, чтобы решить эту проблему с помощью UIImagePNGRepresentation на основе этот ответ. Поэтому я предлагаю использовать этот класс func UIImage.PNGRepresentation(img: UIImage) вместо UIKit func UIImagePNGRepresentation.

Код Swift 3:

//  MyUIImage.swift
//  MyEasyMovie-Public-App
//
//  Created by Ahmed Zahraz on 19/12/2016.
//  Copyright © 2016 AhmedZahraz. All rights reserved.    

import Foundation
import UIKit

extension UIImage {


    public class func PNGRepresentation(_ img: UIImage) -> Data? {
        // No-op if the orientation is already correct
        if (img.imageOrientation == UIImageOrientation.up) {
            return UIImagePNGRepresentation(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 UIImagePNGRepresentation(imgEnd)
    }

}
person AhmedZah    schedule 20.12.2016
comment
кажется, что оно возвращает правильно ориентированное черное изображение .. Может я что-то делаю не так? - person suprandr; 20.03.2018

Ответ Стефана обновлен для Swift 4:

func rotateImage(image: UIImage) -> UIImage {
        if (image.imageOrientation == UIImage.Orientation.up) {
            return image
        }
        UIGraphicsBeginImageContext(image.size)
        image.draw(in: CGRect(origin: .zero, size: image.size))
        let copy = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return copy!
    }

А потом:

var originalImage = yourImage.image!
image = rotateImage(image: originalImage)
person squarehippo10    schedule 21.10.2018