Учитывая UIImage любого размера, я хочу сгенерировать квадратную версию "иконы" размером px
пикселей в сторону, без каких-либо искажений (растяжений). Тем не менее, я сталкиваюсь с небольшой загадкой. Не совсем уверен, где проблема. Вот что я делаю до сих пор.
Во-первых, учитывая UImage size
, я определяю три вещи: ratio
для использования при уменьшении изображения; delta
(разница между желаемым размером значка и самой длинной стороной) и offset
(который используется для определения нашей исходной координаты при отсечении изображения):
if (size.width > size.height) {
ratio = px / size.width;
delta = (ratio*size.width - ratio*size.height);
offset = CGPointMake(delta/2, 0);
} else {
ratio = px / size.height;
delta = (ratio*size.height - ratio*size.width);
offset = CGPointMake(0, delta/2);
}
Теперь предположим, что у вас есть изображение шириной 640px и высотой 480px, и мы хотим получить из этого значок размером 50px x 50px. Ширина больше, чем высота, поэтому наши расчеты:
ratio = 50px / 640px = 0.078125
delta = (ratio * 640px) - (ratio * 480px) = 50px - 37.5px = 12.5px
offset = {x=6.25, y=0}
Затем я создаю CGRect rect
, который достаточно большой, чтобы обрезать его до нужного размера иконки без искажений, плюс clipRect
для отсечения:
CGRect rect = CGRectMake(0.0, 0.0, (ratio * size.width) + delta,
(ratio * size.height) + delta);
CGRect clipRect = CGRectMake(offset.x, offset.y, px, px);
Подставляя наши значения сверху, получаем:
rect = origin {x=0.0, y=0.0}, size {width=62.5, height=50.0}
clipRect = origin {x=6.25, y=0}, size {width=50.0, height=50.0}
Итак, теперь у нас есть прямоугольник шириной 62,5 х 50 х и для работы с ним, а также прямоугольник отсечения, который захватывает «среднюю» часть 50х50.
На домашнем участке! Затем мы устанавливаем наш контекст изображения, рисуем UIImage (называемый здесь myImage
) в прямоугольник, устанавливаем прямоугольник отсечения, получаем (предположительно теперь обрезанное) изображение, используем его и, наконец, очищаем наш контекст изображения:
UIGraphicsBeginImageContext(rect.size);
[myImage drawInRect:rect];
UIRectClip(clipRect);
UIImage *icon = UIGraphicsGetImageFromCurrentImageContext();
// Do something with the icon here ...
UIGraphicsEndImageContext();
Только одна проблема: отсечение никогда не происходит! Я получаю изображение шириной 63px и высотой 50px. :(
Возможно, я неправильно использую / неправильно понимаю UIRectClip ? Я пытался перемешать разные вещи: поменять местами rect
и clipRect
, переместить UIRectClip до drawInRect: . Без кубиков.
Я попытался найти пример этого метода в Интернете, но безрезультатно. Для записи UIRectClip определяется как:
Изменяет текущий путь отсечения
пересекая его с указанным
прямоугольник.
Перемешивание вещей делает нас немного ближе:
UIGraphicsBeginImageContext(clipRect.size);
UIRectClip(rect);
[myImage drawInRect:rect];
Теперь у нас нет искажений, но вырезанное изображение не отцентрировано на оригинале, как я ожидал. Тем не менее, по крайней мере, изображение имеет размер 50x50, хотя имена переменных теперь загрязняются в результате этой перестановки. (Я почтительно оставлю переименование в качестве упражнения для читателя.)