Преобразование точек с изображения в точки UIImageView, contentMode-aware

122
6

Скажем, у меня есть изображение (например, 1024 x 768 px), которое отображается в UIImageView (например, 300 x 300 пикселей).
Теперь я хотел бы преобразовать точку из изображения, например. положение носа человека (x: 500, y: 600), в соответствующую точку на UIImageView с учетом его contentMode.


Если contentMode зафиксирован в UIViewContentModeScaleToFill, преобразование будет простым. Но если это UIViewContentModeScaleAspectFit, все становится более сложным.


Есть ли элегантный способ достичь этого? Я действительно не хочу вычислять это для каждого единственного contentMode (более 10, я думаю).


Спасибо!

спросил(а) 2011-08-27T22:00:00+04:00 8 лет, 3 месяца назад
4
Решение
165

Сегодня у меня было свободное время, чтобы собрать решение этой проблемы и опубликовать ее на GitHub: UIImageView-GeometryConversion


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

Надеюсь, вам понравится!

ответил(а) 2012-04-18T18:05:00+04:00 7 лет, 7 месяцев назад
Еще 3 ответа
109

Это мое быстрое решение:


- (CGPoint)convertPoint:(CGPoint)sourcePoint fromContentSize:(CGSize)sourceSize {
CGPoint targetPoint = sourcePoint;
CGSize targetSize = self.bounds.size;

CGFloat ratioX = targetSize.width / sourceSize.width;
CGFloat ratioY = targetSize.height / sourceSize.height;

if (self.contentMode == UIViewContentModeScaleToFill) {
targetPoint.x *= ratioX;
targetPoint.y *= ratioY;
}
else if(self.contentMode == UIViewContentModeScaleAspectFit) {
CGFloat scale = MIN(ratioX, ratioY);

targetPoint.x *= scale;
targetPoint.y *= scale;

targetPoint.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetPoint.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
}
else if(self.contentMode == UIViewContentModeScaleAspectFill) {
CGFloat scale = MAX(ratioX, ratioY);

targetPoint.x *= scale;
targetPoint.y *= scale;

targetPoint.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetPoint.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
}

return targetPoint;
}

- (CGRect)convertRect:(CGRect)sourceRect fromContentSize:(CGSize)sourceSize {
CGRect targetRect = sourceRect;
CGSize targetSize = self.bounds.size;

CGFloat ratioX = targetSize.width / sourceSize.width;
CGFloat ratioY = targetSize.height / sourceSize.height;

if (self.contentMode == UIViewContentModeScaleToFill) {
targetRect.origin.x *= ratioX;
targetRect.origin.y *= ratioY;

targetRect.size.width *= ratioX;
targetRect.size.height *= ratioY;
}
else if(self.contentMode == UIViewContentModeScaleAspectFit) {
CGFloat scale = MIN(ratioX, ratioY);

targetRect.origin.x *= scale;
targetRect.origin.y *= scale;

targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;

targetRect.size.width *= scale;
targetRect.size.height *= scale;
}
else if(self.contentMode == UIViewContentModeScaleAspectFill) {
CGFloat scale = MAX(ratioX, ratioY);

targetRect.origin.x *= scale;
targetRect.origin.y *= scale;

targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;

targetRect.size.width *= scale;
targetRect.size.height *= scale;
}

return targetRect;
}

Когда он будет реорганизован и оптимизирован, я опубликую его на github и отправлю ссылку здесь.
Возможно, даже этот фрагмент может быть полезен для кого-то.

ответил(а) 2011-08-29T00:19:00+04:00 8 лет, 3 месяца назад
54

Нет, нет встроенного, открытого или элегантного способа сделать это.


Вам нужно перепроектировать функции для режимов контента, в которых вы нуждаетесь.

ответил(а) 2011-08-27T22:13:00+04:00 8 лет, 3 месяца назад
-3

Почему вы не можете просто перемасштабировать координаты:


X (UIImageView) = (X (изображение)/1024) * 300


и


Y (UIImageView) = (Y (изображение)/768) * 300

ответил(а) 2011-08-27T22:18:00+04:00 8 лет, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема