2017-01-15 15 views
6

Я работаю над добавлением поддержки широкоформатных фотографий в iOS 10. Когда пользователь снимает фотографию с камеры, мне нужно использовать новый API, который поддерживает новое цветовое пространство для сохранения фотоданных - UIGraphicsImageRendererjpegData вместо UIImageJPEGRepresentation.Замена UIImageJPEGпредложение с помощью jpegData UIGraphicsImageRenderer

У меня проблемы с ориентацией изображения. Снимая фотографию на моем iPad в портрете, изображение рисуется неправильно. Смотрите комментарии ниже:

Старый API:

let image = info[UIImagePickerControllerOriginalImage] as! UIImage 
let imageData = UIImageJPEGRepresentation(image, 1) 

Новый API:

let image = info[UIImagePickerControllerOriginalImage] as! UIImage 
let cgImage = image.cgImage! 
let ciImage = CIImage(cgImage: cgImage) 

let format = UIGraphicsImageRendererFormat() 
format.scale = 1 
format.prefersExtendedRange = true 

let renderer = UIGraphicsImageRenderer(bounds: ciImage.extent, format: format) 
let imageData = renderer.jpegData(withCompressionQuality: 1, actions: { context in 
    context.cgContext.draw(cgImage, in: ciImage.extent) //draws flipped horizontally 
    //image.draw(at: .zero) //draws rotated 90 degrees leaving black at bottom 
    //image.draw(in: ciImage.extent) //draws rotated 90 degrees stretching and compressing the image to fill the rect 
}) 

Что такое правильный способ заменить UIImageJPEGRepresentation с UIGraphicsImageRenderer «s jpegData?

+0

Является ли это на самом деле весь код, используемый? Метод image.draw должен «рисовать все изображение в текущем графическом контексте, учитывая настройку ориентации изображения». По моему опыту, неоригинальные входные изображения всегда перерисовываются в данные с ориентированным ориентированным представлением при использовании рендерера без дополнительного преобразования координат. – HuaTham

ответ

2

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

let renderer = UIGraphicsImageRenderer(size: image.size, format: format) 
let imageData = renderer.jpegData(withCompressionQuality: 1, actions: { context in 
    var workSize = image.size; 
    workSize.width = floor(workSize.width/image.scale) 
    workSize.height = floor(workSize.height/image.scale) 
    // No-op if the orientation is already correct 
    // if image.imageOrientation == .up { draw image } 

    // We need to calculate the proper transformation to make the image upright. 
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 

    var transform = CGAffineTransform.identity 

    switch image.imageOrientation 
    { 
     case .down, .downMirrored: 
      transform = transform.translatedBy(x: workSize.width, y: workSize.height) 
      transform = transform.rotated(by: CGFloat(Double.pi)) 
      break 

     case .left, .leftMirrored: 
      transform = transform.translatedBy(x: workSize.width, y: 0.0) 
      transform = transform.rotated(by: CGFloat(Double.pi/2.0)) 
      break 

     case .right, .rightMirrored: 
      transform = transform.translatedBy(x: 0.0, y: workSize.height) 
      transform = transform.rotated(by: CGFloat(-Double.pi/2.0)) 
      break 

     case .up, .upMirrored: 
      break 
    } 

    switch image.imageOrientation 
    { 
     case .upMirrored, .downMirrored: 
      transform = transform.translatedBy(x: workSize.width, y: 0.0) 
      transform = transform.scaledBy(x: -1.0, y: 1.0) 
      break 

     case .leftMirrored, .rightMirrored: 
      transform = transform.translatedBy(x: workSize.height, y: 0.0); 
      transform = transform.scaledBy(x: -1.0, y: 1.0); 
      break 

     case .up, .down, .left, .right: 
      break 
    } 

    // Now we draw the underlying CGImage into a new context, applying the transform 
    // calculated above. 

    let ctx = context.cgContext 

    ctx.concatenate(transform) 

    switch image.imageOrientation { 
     case .left, .leftMirrored, .right, .rightMirrored: 
      ctx.draw(image.cgImage!, in: CGRect(x: 0.0, y:0.0, width: workSize.height, height: workSize.width)) 
      break; 

     default: 
      ctx.draw(image.cgImage!, in: CGRect(origin: .zero, size: workSize)) 
      break; 
    } 
}) 

ответ, основанный на UIImage+fixOrientation

0

image.draw() метод должен correct the orientation automatically для вас:

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

Я не уверен, почему вам нужно использовать ci.extent. Кажется, что extent (я не претендую на то, чтобы быть экспертом в Core Image API) размером с «сырыми» данными изображения, которые сохраняются без коррекции ориентации изображения. Если вам необработанные данные нуждаются в ротации (не-Up ориентации, такие как Left, Right), объем по-прежнему будет оригинальным, что данные хранятся.

Я использую следующий код для изображения с imageOrientation.rawValue = 3, и мои данные получаются отлично в правильном размере с «исправленным» imageOrientation.rawValue = 0 при перезагрузке.

let imageSize = image.Size 
let renderer = UIGraphicsImageRenderer(size: renderedSize, format: UIGraphicsImageRendererFormat()) 
return renderer.jpegData(withCompressionQuality: 0.95) { (rendererContext) in 
    let rect = CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height) 
    image.draw(in: rect) 
} 

Мое входное изображение «корректно отображает» его данные с моим кодом, с учетом ориентации изображения. Справа я использую draw(in: extent). Однако изображение не вращается. Просто растянулся.

enter image description here

 Смежные вопросы

  • Нет связанных вопросов^_^