Обрезать изображение до квадрата в соответствии с размером UIView / CGRect

У меня есть реализация AVCaptureSession, и моя цель состоит в том, чтобы пользователь сделал снимок и сохранил только часть изображения внутри красной квадратной границы, как показано ниже:

UIViewController с реализацией AVCaptureSession

previewLayer (камера) AVCaptureSession простирается от (0,0) (вверху слева) до нижней части панели управления камерой (панель чуть выше представления, содержащего затвор). Моя панель навигации и панель управления полупрозрачны, поэтому камера может просвечивать.

Я использую [captureSession setSessionPreset:AVCaptureSessionPresetPhoto];, чтобы убедиться, что исходное изображение, сохраняемое в фотопленке, похоже на камеру Apple.

Пользователь сможет делать снимки в портретной, альбомной ориентации слева и справа, поэтому метод кадрирования должен учитывать это.

До сих пор я пытался обрезать исходное изображение с помощью этого кода:

DDLogVerbose(@"%@: Image crop rect: (%f, %f, %f, %f)", THIS_FILE, self.imageCropRect.origin.x, self.imageCropRect.origin.y, self.imageCropRect.size.width, self.imageCropRect.size.height);

// Create new image context (retina safe)
UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.imageCropRect.size.width, self.imageCropRect.size.width), NO, 0.0);

// Create rect for image
CGRect rect = self.imageCropRect;

// Draw the image into the rect
[self.captureManager.stillImage drawInRect:rect];

// Saving the image, ending image context
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();

Однако, когда я смотрю на обрезанное изображение в фотопленке, мне кажется, что оно только что сжало исходное изображение, а не отбросило верхнюю и нижнюю части изображения, как мне бы хотелось. Это также приводит к 53 пикселям белого пространства в верхней части «обрезанного» изображения, вероятно, из-за позиции y моего CGRect.

Это мой вывод журнала для CGRect:

 Image crop rect: (0.000000, 53.000000, 320.000000, 322.000000)

Это также описывает рамку вида с красной рамкой в ​​супервизоре.

Есть что-то важное, что я не замечаю?

P.S. Исходный размер изображения (снятого камерой в портретном режиме) составляет:

Original image size: (2448.000000, 3264.000000)

person swiftcode    schedule 09.01.2014    source источник


Ответы (3)


Вы можете обрезать изображения с помощью CGImageCreateWithImageInRect:

CGImageRef imageRef = CGImageCreateWithImageInRect([uncroppedImage CGImage], bounds);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
person Rob    schedule 09.01.2014
comment
Я отредактировал ваш ответ. Поскольку исходный размер изображения может отличаться от изображения, отображаемого на экране. :) - person Mani; 09.01.2014
comment
@Mani Спасибо. На самом деле я не хотел предлагать одно изображение в сравнении с другим в своем ответе, а скорее хотел показать общую процедуру кадрирования. (На самом деле он адаптирован из категории UIImage, которая явно ссылалась только на self, а не на какое-либо конкретное изображение). Я изменил имя переменной, чтобы будущие читатели не делали поспешных выводов. Делает ли снимок снимок и обрезает его или возвращается к исходному изображению (соответствующим образом изменяя обрезку CGRect) перед кадрированием, зависит от требований приложения. - person Rob; 09.01.2014
comment
очень важное замечание! Не могу это объяснить, но могу просто предположить, что Core Graphics обрабатывает инвертированную ось, x обозначает y, а y обозначает x. По крайней мере, для меня в портретном режиме при преобразовании изображения в изображение основной графики его ширина и высота меняются местами. Так что будьте осторожны, когда вы что-то обрезаете, особенно если вы хотите обрезать от определенного x или y, а не от (0,0). - person Fawkes; 09.10.2015

Не забудьте добавить параметр масштаба, иначе вы получите изображение с низким разрешением.

CGImageRef imageRef = CGImageCreateWithImageInRect([uncroppedImage CGImage], CGRectMake(0, 0, 30, 120));
[imageView setImage:[UIImage imageWithCGImage:imageRef scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationUp]];
CGImageRelease(imageRef);
person mfr    schedule 11.01.2014

Swift 3:

let imageRef:CGImage = uncroppedImage.cgImage!.cropping(to: bounds)!
let croppedImage:UIImage = UIImage(cgImage: imageRef)
person chengsam    schedule 12.10.2016
comment
Когда я это сделал, изображение поворачивается на 90 градусов против часовой стрелки. Вы знаете, как исправить поворот? - person Matthew Cawley; 04.12.2017
comment
Чтобы предотвратить вращение, используйте: let croppedImage = UIImage (cgImage: imageRef, scale: UIScreen.main.scale, ориентация: .right) - person Gurjit Singh; 14.02.2018