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

Контекст

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

Для справки, я загрузил несколько изображений на imgur, где вы можете найти исходные изображения, которые я тестирую, и сделанные мной скриншоты UIImageView с розовым фоном, отображающие полученные изображения с конфигурацией «Aspect Fit». Вот ссылка: 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 или более старые версии? Кто-нибудь может предложить другие варианты решения этой проблемы?

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


person Vinicius Uzeda    schedule 17.05.2015    source источник
comment
PHImageContentMode.AspectFill вместо этого можно попробовать PHImageContentMode.AspectFit?   -  person jarora    schedule 03.06.2015
comment
Вы когда-нибудь решали эту проблему?   -  person AnthonyMDev    schedule 11.01.2016


Ответы (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)
            }
        }
    }
}

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

person Vinicius Uzeda    schedule 06.04.2016