UIImagePickerController возвращает неправильную ориентацию изображения

Я использую UIImagePickerController для захвата изображения и последующего его сохранения. Однако, когда я пытаюсь масштабировать его, значение ориентации, которое я получаю из этого изображения, неверно. Когда я делаю снимок, удерживая телефон вверх, он дает мне ориентацию влево. Кто-нибудь сталкивался с этой проблемой?

Словарь UIImagePickerController показывает следующую информацию:

{
    UIImagePickerControllerMediaMetadata =     {
        DPIHeight = 72;
        DPIWidth = 72;
        Orientation = 3;
        "{Exif}" =         {
            ApertureValue = "2.970853654340484";
            ColorSpace = 1;
            DateTimeDigitized = "2011:02:14 10:26:17";
            DateTimeOriginal = "2011:02:14 10:26:17";
            ExposureMode = 0;
            ExposureProgram = 2;
            ExposureTime = "0.06666666666666667";
            FNumber = "2.8";
            Flash = 32;
            FocalLength = "3.85";
            ISOSpeedRatings =             (
                125
            );
            MeteringMode = 1;
            PixelXDimension = 2048;
            PixelYDimension = 1536;
            SceneType = 1;
            SensingMethod = 2;
            Sharpness = 1;
            ShutterSpeedValue = "3.910431673351467";
            SubjectArea =             (
                1023,
                767,
                614,
                614
            );
            WhiteBalance = 0;
        };
        "{TIFF}" =         {
            DateTime = "2011:02:14 10:26:17";
            Make = Apple;
            Model = "iPhone 3GS";
            Software = "4.2.1";
            XResolution = 72;
            YResolution = 72;
        };
    };
    UIImagePickerControllerMediaType = "public.image";
    UIImagePickerControllerOriginalImage = "<UIImage: 0x40efb50>";
}

Однако изображение возвращает imageOrientation == 1;

UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage];             

person Mustafa    schedule 14.02.2011    source источник


Ответы (6)


Я только начал работать над этой проблемой в своем собственном приложении.

Я использовал созданную Тревором Хармоном категорию UIImage для изменения размера изображения и фиксации его ориентации, UIImage+Resize.

Затем вы можете сделать что-то подобное в -imagePickerController:didFinishPickingMediaWithInfo:

UIImage *pickedImage = [info objectForKey:UIImagePickerControllerEditedImage];
UIImage *resized = [pickedImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:pickedImage.size interpolationQuality:kCGInterpolationHigh];

Это устранило проблему для меня. Изображение с измененным размером визуально ориентировано правильно, и свойство imageOrientation сообщает UIImageOrientationUp.

Существует несколько версий этого кода масштабирования/изменения размера/обрезки; Я использовал Trevor, потому что он кажется довольно чистым и включает в себя некоторые другие манипуляторы UIImage, которые я хочу использовать позже.

person Bill Garrison    schedule 18.02.2011
comment
Похоже, это не работает с кодом, совместимым с ARC. Он завершается с ошибкой: «Нет видимого @interface для UIImage» объявляет селектор «resizedImageWithContentMode:bounds:interpolationQuality:» - person mpemburn; 10.10.2012
comment
Вы можете посмотреть более актуальную версию этого кода, поддерживаемую Марком Шарбонно на GitHub. ‹github.com/mbcharbonneau/UIImage-Categories - person Bill Garrison; 10.10.2012
comment
Даже используя вилку Марка, это все равно не фиксирует ориентацию. - person Will; 03.05.2013
comment
Он всегда будет возвращать UIImageOrientationUp. поэтому это работает только для ориентации UIImageOrientationUp и не будет работать для других ориентаций. - person Keshav; 20.06.2014

Это то, что я нашел для исправления проблемы с ориентацией; Работает на меня

UIImage *initialImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
NSData *data = UIImagePNGRepresentation(self.initialImage);

UIImage *tempImage = [UIImage imageWithData:data];
UIImage *fixedOrientationImage = [UIImage imageWithCGImage:tempImage.CGImage
                                     scale:initialImage.scale
                               orientation:self.initialImage.imageOrientation];
initialImage = fixedOrientationImage;
person Shekhar Gupta    schedule 09.03.2013
comment
это даст вам. Получено предупреждение памяти. - person Omarj; 13.03.2013
comment
Спасибо, это исправило это для меня! - person Flappy; 08.10.2014
comment
К сожалению, это не работает. Новое изображение точно такое же, но с неправильной ориентацией. - person Eugene Alexeev; 30.01.2020

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

let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!
person Jean Le Moignan    schedule 31.10.2014

Я использую следующий код, который я поместил в отдельный объектный файл утилиты изображения, в котором есть множество других методов редактирования для UIImages:

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSizeWithSameAspectRatio:(CGSize)targetSize
{
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor) {
            scaleFactor = widthFactor; // scale to fit height
        }
        else {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
        }
        else if (widthFactor < heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }

    // In the right or left cases, we need to switch scaledWidth and scaledHeight,
    // and also the thumbnail point
    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
        CGFloat oldScaledWidth = scaledWidth;
        scaledWidth = scaledHeight;
        scaledHeight = oldScaledWidth;

        CGContextRotateCTM (bitmap, M_PI_2); // + 90 degrees
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
        CGFloat oldScaledWidth = scaledWidth;
        scaledWidth = scaledHeight;
        scaledHeight = oldScaledWidth;

        CGContextRotateCTM (bitmap, -M_PI_2); // - 90 degrees
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, -M_PI); // - 180 degrees
    }

    CGContextDrawImage(bitmap, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

И тогда я звоню

UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
        UIImage *fixedOriginal = [ImageUtil imageWithImage:[mediaInfoDict objectForKey:UIImagePickerControllerOriginalImage] scaledToSizeWithSameAspectRatio:pickedImage.size];
person Will    schedule 03.05.2013

В iOS 7 мне нужен код, зависящий от UIImage.imageOrientation, для корректировки различных ориентаций. Теперь, в iOS 8.2, когда я выбираю свои старые тестовые изображения из альбома через UIImagePickerController, ориентация будет UIImageOrientationUp для ВСЕХ изображений. Когда я делаю снимок (UIImagePickerControllerSourceTypeCamera), эти изображения также всегда будут вверху, независимо от ориентации устройства. Таким образом, между этими версиями iOS, очевидно, было исправление, в котором UIImagePickerController уже поворачивает изображения, если это необходимо. Вы даже можете заметить, что при отображении изображений альбома: на долю секунды они будут отображаться в исходной ориентации, прежде чем они появятся в новой ориентации вверх.

person Jekapa    schedule 03.04.2015

Единственное, что сработало для меня, - это снова перерисовать изображение, что задает правильную ориентацию.

if (photo.imageOrientation != .up) {
   UIGraphicsBeginImageContextWithOptions(photo.size, false, 1.0);
   let rect = CGRect(x: 0, y: 0, width: photo.size.width, height: photo.size.height);
   photo.draw(in: rect)
   let newImage = UIGraphicsGetImageFromCurrentImageContext()
   UIGraphicsEndImageContext()
   photo = newImage;
}
person N S    schedule 10.07.2018