2014-01-11 4 views
2

У меня есть время кошмара, пытаясь исправить фотографию, сделанную с AVFoundationcaptureStillImageAsynchronouslyFromConnection, чтобы размер и ориентация точно отображались на экране.AVFoundation размер и поворот фото

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

previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; 
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
previewLayer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); 
if ([[previewLayer connection] isVideoOrientationSupported]) 
{ 
    [[previewLayer connection] setVideoOrientation:(AVCaptureVideoOrientation)[UIApplication sharedApplication].statusBarOrientation]; 
} 
[self.view.layer insertSublayer:previewLayer atIndex:0]; 

Теперь, когда у меня есть возвращенное изображение он нуждается в обрезке это гораздо больше, чем то, что отображалось. Я знаю, что есть примеры UIImage обрезки, но первое препятствие, которое у меня похоже, это найти правильный CGRect. Когда я просто обрезаю до self.view.frame, изображение обрезается в неправильном месте.

Предварительный просмотр использует AVLayerVideoGravityResizeAspectFill и у меня есть мой UIImageView также установлен AspectFill

Так как я могу получить правильный кадр, который AVFoundation отображает на экране из предварительного просмотра слоя?

EDIT ----

Вот пример проблемы я столкнулся. Используя переднюю камеру iPad Mini, камера использует разрешение 720x1280, но дисплей имеет размер 768x0124. В представлении отображается это (см облицовочных рельс в верхней части изображения:

enter image description here

Тогда, когда я беру изображение и отобразить его, это выглядит следующим образом:

enter image description here

Очевидно изображение камеры было сосредоточено в представлении, но обрезанное изображение взято из верхней (ни одной видимой) части фотографии.

ответ

3

Я сейчас работаю над подобным проектом и думаю, что смогу чтобы помочь, если вы еще этого не поняли.

первое препятствие, которое у меня похоже, - это найти правильный CGRect для использования. Когда я просто обрезаю изображение self.view.frame, изображение обрезается в неправильном месте.

Допустим, что ваш образ 720x1280, и вы хотите, чтобы ваше изображение будет обрезано до прямоугольника дисплея, который является CGRect размером 768x1024. Вы не можете просто передать прямоугольник размером 768x1024. Во-первых, ваше изображение не имеет ширины 768 пикселей. Во-вторых, вам нужно указать размещение этого прямоугольника по отношению к изображению (т. Е. Указав начальную точку прямоугольника). В вашем примере self.view.frame является CGRect, который имеет начало координат (0, 0). Вот почему вы всегда обрезаете с сверху вашего изображения, а не из центра.

Расчет прямоугольника обрезки немного сложнее, потому что у вас есть несколько разных систем координат.

  • Вы получили вид на ваш взгляд контроллера, который имеет ...
  • ... видео-превью слой в качестве подслоя, который отображается аспектно заполненным изображение, но ...
  • ...AVCaptureOutput возвращает UIImage, который не только имеет разную ширину/высоту, чем предварительный просмотр видео, но также имеет другое соотношение сторон.

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

  • имеет такое же отношение отображения как self.view.bounds
  • Имеет тот же меньший размер размера как меньший размер UIImage (т.е. аспект приступа)
  • центрируются в UIImage

Так что-то вроде этого:

// Determine the width:height ratio of the crop rect, based on self.bounds 
CGFloat widthToHeightRatio = self.bounds.size.width/self.bounds.size.height; 
CGRect cropRect; 
// Set the crop rect's smaller dimension to match the image's smaller dimension, and 
// scale its other dimension according to the width:height ratio. 
if (image.size.width < image.size.height) { 
    cropRect.size.width = image.size.width; 
    cropRect.size.height = cropRect.size.width/widthToHeightRatio; 
} else { 
    cropRect.size.width = image.size.height * widthToHeightRatio; 
    cropRect.size.height = image.size.height; 
} 
// Center the rect in the longer dimension 
if (cropRect.size.width < cropRect.size.height) { 
    cropRect.origin.x = 0; 
    cropRect.origin.y = (image.size.height - cropRect.size.height)/2.0; 
} else { 
    cropRect.origin.x = (image.size.width - cropRect.size.width)/2.0; 
    cropRect.origin.y = 0; 
} 

Итак, наконец, вернуться к исходному примеру, когда изображение 720x1280, и вы хотите, чтобы ваше изображение будет обрезано до прямоугольника дисплея, который 768x1024, вы получите CGRect размером 720x960 с началом x = 0, y = 1280-960/2 = 160.

+0

Ричард, я просто потратил 2 дня, пытаясь решить эту же проблему, снимая фото с слой предварительного просмотра, который занимает верхние 50% экрана, а затем обрезает точную часть изображения, которая была видна в предварительном просмотре. Пройдя каждую нить обрезки на SO, ваша единственная, которая работает отлично. СПАСИБО. – user3117509

+0

Одна вещь, хотя по какой-то причине мои «cropRect.origin.y» и «cropRect.origin.x» продолжают получать 0 значений, но что странно, если я их NSLog они печатают со значением 714, поэтому мне пришлось вручную введите этот номер в окончательный CGRectMake. Помимо этого, ваш код работает отлично. – user3117509

+0

Прохладный! Рад был помочь. Этот фрагмент кода был тем, что я написал «на лету», чтобы продемонстрировать технику, поэтому я не удивлен, если у вас есть какие-то сумасшедшие результаты. Рад, что тебе удалось обойти его! –

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