Как обрезать UIImageView для нового UIImage в режиме «подгонка аспекта»?

enter image description here

Я хотел бы создать новый UIImage, обрезая изображение внутри UIImageView. Например, на картинке выше я хочу новый UIImage области, обведенной зеленым. Я нашел код для этого, обычно он выглядит примерно так (как категория UIImage):

- (UIImage *)croppedImage:(CGRect)bounds {
    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return croppedImage;
}

Имеет смысл. ОДНАКО, мой UIImageView находится в contentMode «подходящий аспект». Похоже, это усложняет вычисления CGRect для CGImageCreateWithImageInRect, и я не смог найти правильное решение.

Я полагаю, мне нужно применить те же преобразования к зеленому прямоугольнику, как и к изображению?

ТАКЖЕ: я нашел этот другой вопрос здесь (Как узнать размер изображения после применения подгонки изображения в UIImageView), который, кажется, показывает грубый способ получения размера, но я все еще не уверен, как это вписывается в ситуацию обрезки.

Есть идеи?

EDITВ моем случае у меня буквально есть квадрат, как показано выше, нарисованный в режиме наложения поверх UIImageView. Поэтому, хотя я понимаю, что обрезаю UIImage (внутри UIImageView), мне нужно каким-то образом изменить зеленый CGRect таким образом, чтобы он «соответствовал». преобразование, выполненное, когда «аспект подходит» применены. Например, если я оставлю свой UIImageView в «верхнем левом углу»; режим, то все работает нормально, потому что между базовым UIImage и UIImageView есть отображение 1: 1. Проблема в «верхнем левом углу»; Режим состоит в том, что все изображение не всегда отображается, потому что оно может быть больше, чем мой UIImageView.

Ответы на вопрос(4)

вы не понимаете, что делаете. Вы можете "т" обрезать " UIImageView - только UIImages. Таким образом, ваш метод croppedImage должен быть в категории UIImage, а не в категории UIImageView. Прямоугольник границ, передаваемый методу кадрирования, должен соответствовать размеру изображения, а не границам изображения. Неважно, что такое contentMode представления изображения - обрезка изображения всегда будет работать одинаково. Сначала получите изображение из представления изображения. Затем создайте из него новое обрезанное изображение и, наконец, установите обрезанное изображение для просмотра изображения. Это можно сделать одной строкой кода:

imageView.image = [imageView.image croppedImage:rect];

Так как ваш contentMode является "подходящим для аспекта" новое изображение автоматически растянется, чтобы поместиться в рамку просмотра. Вы также можете попытаться изменить рамку просмотра на основе image.size, чтобы избежать эффектов пикселизации.

 02 июн. 2012 г., 22:00
хорошо, теперь я понял, я думаю. Я напишу новый ответ ...
 pj453302 июн. 2012 г., 16:09
Я хочу создать новое изображение части внутри зеленого прямоугольника.
 pj453302 июн. 2012 г., 15:08
Я пытался перефразировать вопрос. Я понимаю разницу между UIImageView и UIImage. Смотрите мои вышеупомянутые правки, имеет смысл сейчас?
 02 июн. 2012 г., 15:25
Я не уверен, правильно ли я вас понимаю. Вы хотите замаскировать изображение так, чтобы оно показывало только часть в зеленом прямоугольнике? Тогда нет необходимости в обрезке. Или вы просто хотите нарисовать зеленый прямоугольник в правильном положении?

-(UIImage *)getNeedImageFrom:(UIImage*)image cropRect:(CGRect)rect
{
   CGSize cropSize = rect.size;
   CGFloat widthScale =  
   image.size.width/self.imageViewOriginal.bounds.size.width;
   CGFloat heightScale = 
   image.size.height/self.imageViewOriginal.bounds.size.height;
   cropSize = CGSizeMake(rect.size.width*widthScale,  
   rect.size.height*heightScale);
   CGPoint  pointCrop = CGPointMake(rect.origin.x*widthScale, 
   rect.origin.y*heightScale);
   rect = CGRectMake(pointCrop.x, pointCrop.y, cropSize.width, 
   cropSize.height);
   CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
   UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
   CGImageRelease(subImage);
   return croppedImage;

   }
 29 янв. 2016 г., 14:14
Добавить объяснение того, как этот метод работает для требований OP.

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

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

-(UIImage*)crop:(CGRect)frame
{
    // Find the scalefactors  UIImageView's widht and height / UIImage width and height
    CGFloat widthScale = self.bounds.size.width / self.image.size.width;
    CGFloat heightScale = self.bounds.size.height / self.image.size.height;

    // Calculate the right crop rectangle 
    frame.origin.x = frame.origin.x * (1 / widthScale);
    frame.origin.y = frame.origin.y * (1 / heightScale);
    frame.size.width = frame.size.width * (1 / widthScale);
    frame.size.height = frame.size.height * (1 / heightScale);

    // Create a new UIImage
    CGImageRef imageRef = CGImageCreateWithImageInRect(self.image.CGImage, frame);
    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return croppedImage;
}
Решение Вопроса

другой ответ на аналогичный вопрос я написал этот метод для категории UIImageView:

-(CGRect) cropRectForFrame:(CGRect)frame
{
    NSAssert(self.contentMode == UIViewContentModeScaleAspectFit, @"content mode must be aspect fit");

    CGFloat widthScale = self.bounds.size.width / self.image.size.width;
    CGFloat heightScale = self.bounds.size.height / self.image.size.height;

    float x, y, w, h, offset;
    if (widthScale<heightScale) {
        offset = (self.bounds.size.height - (self.image.size.height*widthScale))/2;
        x = frame.origin.x / widthScale;
        y = (frame.origin.y-offset) / widthScale;
        w = frame.size.width / widthScale;
        h = frame.size.height / widthScale;
    } else {
        offset = (self.bounds.size.width - (self.image.size.width*heightScale))/2;
        x = (frame.origin.x-offset) / heightScale;
        y = frame.origin.y / heightScale;
        w = frame.size.width / heightScale;
        h = frame.size.height / heightScale;
    }
    return CGRectMake(x, y, w, h);
}

Вы можете передать кадр вашего зеленого прямоугольника (при условии, что это подпредставление представления изображения) и вернуть прямоугольник обрезки для обрезки UIImage. Обратите внимание, что это работает только для «подгонки аспекта» Режим! Я не проверял это все же. Итак, скажите мне, если это работает!

 03 июл. 2017 г., 03:37
Как бы вы изменили этот алгоритм для учета изображений, которые 2х и 3х? Для изображений 1x это работает отлично, но не обрезается точно для изображений с масштабом 2x и 3x.
 07 дек. 2016 г., 14:31
Спасибо! Это было прекрасно
 19 мар. 2018 г., 02:40
@ Феликс хороший ответ!
 28 нояб. 2012 г., 11:16
Можете ли вы помочь мне с приведенным выше кодом для масштаба, чтобы заполнить режим?
 pj453304 июн. 2012 г., 13:20
У меня еще не было возможности реализовать это, но я как можно скорее. Спасибо за это, похоже, это имеет смысл.

Ваш ответ на вопрос