Запрос изображений в PHImageManager приводит к неправильному изображению в iOS 8.3

контекст

Я использую среду Photoshop для отображения пользовательских изображений в приложении для iOS, над которым я работаю.

Для справки, я загрузил несколько изображений в imgur, где вы можете найти исходные изображения, с которыми я тестирую, и снимки экрана, которые я сделал для UIImageView с розовым фоном, отображая извлеченные изображения с конфигурацией "Подгонка по размеру". Вот ссылка: http://imgur.com/a/VPJ9J

Я использую два сценария тестирования: во-первых, пейзажное изображение, чьи imageOrientation является UIImageOrientation.Up (0); во-вторых, портретное изображение, с UIImageOrientation.Right (3). Вы можете проверить в документации (я бы поставил здесь ссылку, но мне не хватает репутации, извините).

проблема

IPhone 4S (iOS 8.1.2) отображает альбомное изображение в альбомной ориентации внутри розового UIImageView и портрет с макетом портрета, как и ожидалось. Но iPhone 5 и 6 Plus (оба iOS 8.3) отображают оба изображения в горизонтальной ориентации.

Код

Это код, который я использую для запроса изображений:

var targetSize = CGSizeMake(1000, (CGFloat(asset.pixelHeight) / CGFloat(asset.pixelWidth)) * 1000)

var options = PHImageRequestOptions()
options.version = PHImageRequestOptionsVersion.Current
options.deliveryMode =  PHImageRequestOptionsDeliveryMode.HighQualityFormat
options.resizeMode = PHImageRequestOptionsResizeMode.Exact
options.networkAccessAllowed = true

PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: PHImageContentMode.AspectFill, options: options) { (result: UIImage!, info) -> Void in
    if !info[PHImageResultIsDegradedKey]!.boolValue {
        println("asset.pixelWidth: \(asset.pixelWidth)")
        println("asset.pixelHeight: \(asset.pixelHeight)")
        println("targetSize: \(targetSize)")
        println("result.size: \(result.size)")
        println("result.imageOrientation: \(result.imageOrientation.rawValue)")

        completion(result)
    }
}

тесты

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

Случай 1: iPhone 4S (8.1.2)

Пейзаж:

asset.pixelWidth: 3264
asset.pixelHeight: 2448
targetSize: (1000.0, 750.0)
result.size: (1000.0, 750.0)
result.imageOrientation: 0

Портрет:

asset.pixelWidth: 2448
asset.pixelHeight: 3264
targetSize: (1000.0, 1333.33)
result.size: (1000.0, 1332.0)
result.imageOrientation: 3

Дело 2: iPhone 5 (8,3)

Пейзаж:

asset.pixelWidth: 3264
asset.pixelHeight: 2448
targetSize: (1000.0, 750.0)
result.size: (1000.0, 750.0)
result.imageOrientation: 0

Портрет:

asset.pixelWidth: 2448
asset.pixelHeight: 3264
targetSize: (1000.0, 1333.33)
result.size: (1334.0, 1000.0)
result.imageOrientation: 3

Дело 3: iPhone 6 Plus (8,3)

Пейзаж:

asset.pixelWidth: 3264
asset.pixelHeight: 2448
targetSize: (1000.0, 750.0)
result.size: (1000.0, 750.0)
result.imageOrientation: 0

Портрет:

asset.pixelWidth: 2448
asset.pixelHeight: 3264
targetSize: (1000.0, 1333.33333333333)
result.size: (1334.0, 1000.0)
result.imageOrientation: 3

Заключение

Из журналов видно, что версия iOS 8.1.2 соответствует targetSize указано для обоих изображений, но версии 8.3 выбирают изображения с инвертированными размерами (запрашивается (1000.0, 1333.33) но получил (1334.0, 1000.0)).

В данный момент мне кажется, что мой единственный вариант - проверить, какая версия iOS работает, а затем инвертировать параметры при запросе изображения с повернутой ориентацией (я тестировал только с UIImageOrientation.Right, но есть также .Left, .LeftMirrored а также .RightMirrored).

К сожалению, PHAsset не содержит ориентацию изображения. Я могу знать это только после запроса изображения к PHImageManagerпоэтому мне придется сделать два запроса на эти изображения, один для получения ориентации, а другой для получения правильного изображения.

Вопрос

Это проблема с моей логикой? Или это ошибка в iOS? Если это ошибка, то какое поведение правильное, iOS 8.3 или более старая версия? Кто-нибудь может предложить другие варианты решения этой проблемы?

Извините за длинный пост и за плохой английский. Заранее спасибо!

1 ответ

Решение

Я сделал странный обходной путь:

func getAssetImage(asset: PHAsset, completion: (UIImage?) -> Void) {
    getAssetImage(asset, firstTry: true, completion: completion)
}

private func getAssetImage(asset: PHAsset, firstTry: Bool, completion: (UIImage?) -> Void) {
    let targetSize = CGSizeMake(1000, (CGFloat(asset.pixelHeight) / CGFloat(asset.pixelWidth)) * 1000)

    let options = PHImageRequestOptions()
    options.version = PHImageRequestOptionsVersion.Current
    options.deliveryMode =  PHImageRequestOptionsDeliveryMode.HighQualityFormat
    options.resizeMode = PHImageRequestOptionsResizeMode.Exact
    options.networkAccessAllowed = true

    PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: PHImageContentMode.AspectFill, options: options) { (result: UIImage?, info) -> Void in
        let degraded = info?[PHImageResultIsDegradedKey] as? NSNumber

        if degraded != nil && !degraded!.boolValue {
            print("asset.pixelWidth: \(asset.pixelWidth)")
            print("asset.pixelHeight: \(asset.pixelHeight)")
            print("targetSize: \(targetSize)")
            print("result.size: \(result!.size)")
            print("result.imageOrientation: \(result!.imageOrientation.rawValue)")

            if (targetSize.width - targetSize.height) * (result!.size.width - result!.size.height) < 0 {
                if firstTry {
                    print("Resulting image's dimensions are not in accordance with target size. Reversing dimensions!")
                    self.getAssetImage(asset, firstTry: false, completion: completion)
                } else {
                    print("Resulting image's dimensions are still not in accordance with target size. Giving up!")
                    completion(nil)
                }

            } else {
                completion(result)
            }
        }
    }
}

Производительность этого решения весьма сомнительна, но это был один из самых надежных способов решения этой проблемы.

Другие вопросы по тегам