IOS PNG Изображение повернуто на 90 градусов

В моем приложении iOS я пишу, я имею дело с PNG, потому что я имею дело с альфа-каналом. По какой-то причине я могу загружать PNG в мой imageView просто отлично, но когда приходит время либо скопировать изображение из моего приложения (на PasteBoard), либо сохранить изображение в рулоне камеры, изображение поворачивается на 90 градусов,

Я искал всюду на этом, и одна из вещей, которые я узнал, - это то, что если бы я использовал JPEG, у меня не было бы этой проблемы (это звучит) из-за информации EXIF.

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

  • Перейдите к рулону камеры и скопируйте изображение.
  • Зайдите в мое приложение и нажмите "Вставить", изображение вставляется в порядке, и я могу сделать это весь день.
  • Выберите функцию копирования, которую я выполнил, а затем нажмите "Вставить", и изображение вставляется, но повернуто.

Я на 100% уверен, что мой код для копирования и вставки не является тем, что здесь неправильно, потому что, если я вернусь к шагу 2 выше и нажмите "сохранить", фотография будет сохранена в моей библиотеке, но она будет повернута на 90 градусов!

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

Есть ли у кого-нибудь мысли об этом? Любая возможная работа, которую я могу использовать? Я довольно уверен в коде, потому что он работает примерно на 75% моих изображений. Я могу отправить код по запросу, хотя.

Ответ 1

Взял несколько дней, но я, наконец, понял это благодаря ответу @Dondragmer. Но я решил, что отправлю свое полное решение.

Так что в основном мне приходилось писать метод, чтобы интеллектуально автоматически поворачивать мои изображения. Недостатком является то, что я должен называть этот метод всюду по всему моему коду, и он очень интенсивный, особенно при работе на мобильных устройствах, но плюс сторона заключается в том, что я могу снимать изображения, копировать изображения, вставлять изображения и сохранять изображения и все они вращаются должным образом. Здесь код, который я использовал (метод не на 100% завершен, все равно нужно отредактировать утечки памяти, а что нет).

В итоге я узнал, что в первый раз изображение было вставлено в мое приложение (будь то из-за нажатия пользователем "взять изображение", "вставить изображение" или "выбрать изображение", по какой-то причине он вставляет только отлично, без автоматического поворота. В этот момент я сохранил все значения вращения в глобальной переменной под названием imageOrientationWhenAddedToScreen. Это облегчило мою жизнь, потому что, когда пришло время манипулировать изображением и сохранить изображение из программы, я просто проверил эту глобальную переменную cached и определил, нужно ли мне правильно поворачивать изображение.

    - (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 есть это странное поведение в обращении с картинками (попробуйте это... Возьмите свой телефон и переверните его вверх дном и сделайте снимок, вы заметите, что окончательное изображение получается справа вверх - возможно, именно поэтому у Apple есть такая функциональность?).

Я знаю, что потратил много времени на это, поэтому надеюсь, что это поможет другим людям!

Ответ 2

Для тех, кто хочет решение Swift, создайте расширение UIImage и добавьте следующий метод:

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

    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    self.drawInRect(CGRectMake(0, 0, self.size.width, self.size.height))
    var normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return normalizedImage;
}

Ответ 3

Если у вас возникли проблемы из-за существующего образа imageOrientation, вы можете построить другое идентичное изображение с другой ориентацией, например:

CGImageRef imageRef = [sourceImage CGImage];

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

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

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

Ответ 4

Такое поведение "странного вращения" действительно не так уж и странно. Это разумно, и по умному я имею в виду эффективность памяти. При повороте устройства 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);

Ответ 5

Вот еще один способ добиться этого:

@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)
}

Ответ 6

Вы можете использовать Image I/O для сохранения изображения PNG в файл (или NSMutableData) относительно ориентации изображения. В приведенном ниже примере я сохраняю 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;
}

Вы также можете сохранить изображение NSData с помощью CGImageDestinationCreateWithData и передать NSMutableData вместо NSURL в CGImageDestinationCreateWithURL.