Запрос изображений в 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)
}
}
}
}
Производительность этого решения весьма сомнительна, но это был один из самых надежных способов решения этой проблемы.