Вопрос по objective-c, iphone, ios – Ориентация изображения iOS имеет странное поведение

83

Последние несколько недель я работал с изображениями в объективе-c и замечал много странного поведения. Во-первых, как и у многих других людей, у меня возникла такая проблема, когда изображения, сделанные с помощью камеры (или сделанные с помощью чужой камеры и MMS для меня), поворачиваются на 90 градусов. Я не был уверен, почему в мире это происходит (следовательно,мой вопрос) но я смог придумать дешевую работу вокруг.

Мой вопрос на этот разwhy is this happening? Почему Apple вращает изображения? Когда я делаю фотографию правой стороной вверх, если я не выполняю код, упомянутый выше, при сохранении фотографии она сохраняется повернутой. Теперь мой обходной путь был в порядке вплоть до нескольких дней назад.

Мое приложение изменяет отдельные пиксели изображения, в частности альфа-канал PNG (поэтому любое преобразование JPEG выбрасывается из окна для моего сценария). Несколько дней назад я заметил, что несмотря на то, что изображение правильно отображается в моем приложении благодаря моему временному коду, когда мой алгоритм изменяет отдельные пиксели изображения, он думает, что изображение поворачивается. Таким образом, вместо изменения пикселей в верхней части изображения, он изменяет пиксели сбоку изображения (потому что считает, что его нужно повернуть)! Я не могу понять, как вращать изображение в памяти - в идеале я бы предпочел просто стереть этоimageOrientation пометить все вместе.

Вот еще кое-что, что меня также сбивало с толку ... Когда я фотографирую,imageOrientation установлен на 3. Мой обходной код достаточно умен, чтобы понять это и перевернуть, чтобы пользователь никогда не заметил. Кроме того, мой код для сохранения изображения в библиотеке понимает это, переворачивает его,then сохраняет его так, чтобы он правильно отображался в рулоне камеры.

Этот код выглядит так:

NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap 
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];   
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);

Когда я загружаю это недавно сохраненное изображение в мое приложение,imageOrientation равно 0 - именно то, что я хочу видеть, и мой обходной путь вращения даже не нужно запускать (примечание: при загрузке изображений из Интернета в отличие от изображений, снятых камерой,imageOrientation всегда 0, что приводит к идеальному поведению). По какой-то причине мой код сохранения, кажется, стирает этоimageOrientation флаг. Я надеялся просто украсть этот код и использовать его, чтобы стереть мою imageOrientation, как только пользователь сделает фотографию и добавит ее в приложение, но она, похоже, не работает. Есть лиUIImageWriteToSavedPhotosAlbum сделать что-то особенное сimageOrientation?

Будет ли лучшим решением этой проблемы просто сдутьimageOrientation как только пользователь закончит фотографировать. Я предполагаю, что у Apple есть поведение поворота, сделанное по причине, правильно? Несколько человек предположили, что это дефект Apple.

(... если вы еще не потерялись ... Примечание 2: Когда я делаю горизонтальную фотографию, кажется, что все работает идеально, как фотографии из Интернета)

РЕДАКТИРОВАТЬ:

Вот как на самом деле выглядят некоторые изображения и сценарии. Судя по комментариям, похоже, что это странное поведение - это больше, чем просто поведение iPhone, что я считаю хорошим.

Это фотография фотографии, которую я сделал своим телефоном (обратите внимание на правильную ориентацию), она выглядит точно так же, как и на моем телефоне, когда я делал снимок:

Actual Photo taken on iPhone

Вот как выглядит изображение в Gmail после того, как я отправил его себе по электронной почте (похоже, Gmail обрабатывает его правильно):

Photo as it appears in Gmail

Вот как изображение выглядит как миниатюра в окнах (не похоже, что оно обрабатывается должным образом):

Windows Thumbnail

А вот как выглядит настоящее изображение при открытии с помощью Windows Photo Viewer (все еще не обрабатывается должным образом):

Windows Photo Viewer Version

После всех комментариев по этому вопросу, вот о чем я думаю ... iPhone берет изображение и говорит, что для правильного отображения его нужно повернуть на 90 градусов. Эта информация будет в данных EXIF. (Почему его нужно повернуть на 90 градусов, а не по умолчанию на прямую вертикаль, я не знаю). Отсюда, Gmail достаточно умен, чтобы читать и анализировать эти данные EXIF и правильно отображать их. Однако Windows недостаточно умна для чтения данных EXIF и поэтому отображает изображениеimproperly, Верны ли мои предположения?

Вы устанавливаете режим фотосъемки на «Портрет», и вы не поворачиваете камеру под прямым углом, или установлен режим «Пейзаж», и камера захватывает изображение под прямым углом, датчик автоматически установит правильную ориентацию. Проверьте это HarshIT
Решение, скорее всего, вашему приложению необходимо прочитать метаданные и повернуть изображение и / или изменить метаданные в соответствии с требованиями. HarshIT
Смотрите, как ваша камера записывает метаданные, чтобы повернуть ее на 90 градусов, некоторые ОС читают эти метаданные, а остальные не делают. HarshIT
Интересно ... если это правда, почему полученные изображения устанавливаются под прямым углом? Я знаю, что это не дефект iPhone, потому что я заметил похожее поведение, когда друг (с BlackBerry) берет изображение, а MMS отправляет его мне. Boeckm
Довольно хорошо прочитал (см. Ответ @ Хэдли ниже - раньше был в комментарии). Поэтому мое приложение должно быть достаточно умным, чтобы обрабатывать изображения, содержащие данные EXIF, а также изображения, которые их не содержат ... Я до сих пор не понимаю, почему, когда я делаю фотографию правой стороной вверх, флаг ориентации говорит, что нужно повернуть на 90 градусов? Boeckm

Ваш Ответ

12   ответов
10

images?

Ответ на это очень прост. Apple НЕ поворачивает изображение. Вот в чем путаница.

ПЗС-камера не вращается, поэтому она всегда делает снимок в ландшафтном режиме.

Apple сделала очень умную вещь - вместо того, чтобы тратить все время на вращение изображения - перетасовывая мегабайты данных вокруг - просто пометьте это КАК был сделан снимок.

OpenGL делает переводы очень легко - поэтому ДАННЫЕ никогда не перетасовываются - просто КАК ЕГО РИСУНОК.

Отсюда и метаданные ориентации.

Это становится проблемой, если вы хотите обрезать, изменять размер и т. Д., Но как только вы узнаете, что происходит, вы просто определяете свою матрицу, и все работает.

Спасибо за это объяснение. Здравый смысл, когда вы думаете об этом, но никакой другой результат Google не объяснил это.
0

в чем твоя проблема. Вы используете UIImagePicker, что странно во всех смыслах. Я бы посоветовал вам использовать AVFoundation для камеры, которая дает гибкость в ориентации, а также качество. Используйте AVCaptureSession. Вы можете получить код здесьКак сохранить фотографии, сделанные с помощью AVFoundation, в фотоальбом?

53

когда я получаю изображение с камеры, я поставил следующий код, чтобы исправить это .. Добавил метод 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;
}
Как выглядит ваш код scaleAndRotateImage? После гугла, это так же, как здесь?discussions.apple.com/thread/1537011?start=0&tstart=0 Boeckm
Это отличная ссылка Boeckm .. Она дает больше информации об ориентации изображения ..
Я думаю, что в вашем методе отсутствует часть, но этого и ссылки все еще было достаточно для того, чтобы я поработал с остальными и, наконец, получил правильное представление обрезки изображения, так что спасибо :)
ВАУ ... Ха-ха! Это сработало очень хорошо! Я использовал код в моем комментарии выше. Я получил два удивительных ответа на мой вопрос! Я думаю, это означает, что я задал слишком большой вопрос ... Спасибо за тонну. У меня есть кое-что для глубокого тестирования, но пока проблема ориентации прекрасно работает с вертикально и горизонтально сделанными фотографиями. Boeckm
13

Ответ Дилипа.

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
}
У меня иногда возникала проблема: после масштабирования внизу изображения появлялась белая линия. Это потому, что CGFloat кажется недостаточно точным. Я исправил это сbounds.size.height.round() а такжеbounds.size.width.round()
Вы также можете сделать(bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height) без создания переменной в качестве хранилища.
3

потому что у меня была похожая проблема, но я использовал Swift. Просто хотел дать ссылку на ответ, который работал для меня для любых других разработчиков Swift:https://stackoverflow.com/a/26676578/3904581

Вот фрагмент кода Swift, который эффективно устраняет проблему:

let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!

Супер просто. Одна строка кода. Задача решена.

Меня устраивает!! Спасибо!
не мог заставить это работать.
Это не сработало для меня, я использовал это решение:stackoverflow.com/a/27775741/945247
не получилось
Это сработало для меня!
0

ть, что все работает нормально?):

static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage

    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: imgRef!.width, height: imgRef!.height)

    switch imageSource.imageOrientation {
    case .up :
        transform = CGAffineTransform.identity

    case .upMirrored :
        transform = CGAffineTransform(translationX: imageSize.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)

    case .down :
        transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height)
        transform = transform.rotated(by: CGFloat.pi)

    case .downMirrored :
        transform = CGAffineTransform(translationX: 0, y: imageSize.height)
        transform = transform.scaledBy(x: 1, y: -1)

    case .left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: 0, y: imageSize.width)
        transform = transform.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(translationX: imageSize.height, y: imageSize.width)
        transform = transform.scaledBy(x: -1, y: 1)
        transform = transform.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(translationX: imageSize.height, y: 0)
        transform = transform.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(scaleX: -1, y: 1)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    }

    UIGraphicsBeginImageContext(bounds.size)
    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!
}
18

отличный ответ.

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;
}
Спасибо, но что такое "let ratio = ширина / высота"? используя для? Я не могу видеть ни одного места, использующего соотношение в этом {}
Большой! Это работает отлично.
большое спасибо
8

отличный ответи спасибо Тэттисону заСвифт перевод.

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;
}
Это помогло решить мою проблему, потратив на это много часов! Невероятно, что Xamarin не имеет встроенной поддержки для этого, поскольку теперь это продукт Microsoft.
12

сгенерированное iPhone / iPad, сохраняется как альбомная ориентация слева с тегом EXIF Orientation (Exif.Image.Orientation), указывающим фактическую ориентацию.

У него есть следующие значения: 1: Левый пейзаж 6: Портрет Нормальный 3: Пейзаж Право 4: портрет вверх ногами

В IOS информация EXIF читается правильно, и изображения отображаются так же, как и при съемке. Но в Windows информация EXIF НЕ используется.

Если вы откроете одно из этих изображений в GIMP, оно скажет, что изображение имеет информацию о повороте.

0

func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage!;

    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: width, height: height)


    switch(imageSource.imageOrientation) {
        case .up :
            transform = CGAffineTransform.identity

        case .upMirrored :
            transform = CGAffineTransform(translationX: imageSize.width, y: 0.0);
            transform = transform.scaledBy(x: -1, y: 1);

        case .down :
            transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height);
            transform = transform.rotated(by: CGFloat(Double.pi));

        case .downMirrored :
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.height);
            transform = transform.scaledBy(x: 1, y: -1);

        case .left :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.width);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .leftMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width);
            transform = transform.scaledBy(x: -1, y: 1);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .right :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: 0.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);

        case .rightMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(scaleX: -1.0, y: 1.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);
    }

    UIGraphicsBeginImageContext(bounds.size)
    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!;
}
44

D и обнаружил, что каждый файл изображения имеет свойство метаданных. Если в метаданных указана ориентация изображения, которая обычно игнорируется другими ОС, кроме 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-metadata-information-of-any-jpeg-image-online/

Первая ссылка exif теперь не работает, а вторая обновлена доexif.regex.info/exif.cgi Я пытался отредактировать ответ, но @ cj-dennis почему-то отклонил его.
ВОТ ЭТО ДА! Я понятия не имел, что ТАК МНОГО информации в данных EXIF!regex.info/exif.cgi это невероятный сайт! Я непременно поиграю с изображениями сегодня вечером на этом сайте. Мне придется протестировать каждый сценарий, снимки получаются прямо, снимки из Интернета, снимки поворачиваются и т. Д. Спасибо огромное! Boeckm
-3

я

Похожие вопросы