UIBezierPath обводит линию шириной 1 пиксель и заполняет прямоугольник шириной 1 пиксель - разные результаты.

Вот простой рисунок

    

- (void)drawRect:(CGRect)rect
{
    //vertical line with 1 px stroking
    UIBezierPath *vertLine = [[UIBezierPath alloc] init];
    [vertLine moveToPoint:CGPointMake(20.0, 10.0)];
    [vertLine addLineToPoint:CGPointMake(20.0, 400.0)];
    vertLine.lineWidth = 1.0;
    [[UIColor blackColor] setStroke];
    [vertLine stroke];

    //vertical rectangle 1px width 
    UIBezierPath *vertRect= [UIBezierPath bezierPathWithRect:CGRectMake(40.0, 10.0, 1.0, 390.0)];
    [[UIColor blackColor] setFill];
    [vertRect fill];

}

На 3GS без сетчатки и симуляторе первая линия размыта и выглядит шире 1 пикселя, но вторая линия четкая.

К сожалению, у меня нет ни iPhone 4, ни нового iPad для тестирования, но на симуляторе retina обе линии выглядят одинаково.

Вопрос: Является ли прямоугольник вместо обводки единственным способом получить одинаковый результат для устройств с сетчаткой и без сетчатки?


person Michael    schedule 24.06.2012    source источник


Ответы (2)


Вы заполняете внутреннюю часть прямоугольника, но проводите линию от центра. Поскольку координаты в обоих случаях (углы прямоугольника и начальная и конечная координаты в строке) определяются как целые числа (без дробей), координаты лежат на точных границах точек.

Я сказал "координаты" выше, говоря о точках линии, чтобы не путать их с точками на экране. Я также сказал «точечные границы» вместо «границы пикселей» по той же причине. iOS определяет свои координаты и все точки в так называемых «точках», а не в пикселях. Точка – это измерение, не зависящее от разрешения. И устройства с сетчаткой, и без сетчатки имеют одинаковое количество точек на экране, просто они соответствуют разному количеству реальных пикселей.

Давайте посмотрим на штриховку линии, лежащей на границах точек (как в вашем вопросе), по сравнению с заполнением прямоугольника, где углы лежат на границах точек:

На приведенных ниже иллюстрациях я обвожу линию черным цветом и закрашиваю прямоугольник оранжевым цветом как на экране без сетчатки, так и на экране сетчатки. Я также обвел линию и прямоугольник синим цветом. В обоих случаях вы можете увидеть размер точки для этого разрешения и сравнить его с фактической пиксельной сеткой.

В случае без сетчатки вы можете видеть, что попытка обвести линию от центра линией в 1 точку с (в данном случае соответствующей ширине линии в 1 пиксель) заполнит половину пикселей сверху и половину пикселей. ниже. Поскольку пиксели заполнены только наполовину, непрозрачность этих пикселей составляет 50%. Это приводит к более светлому цвету (на белом фоне). Так как пиксели сверху и снизу заполнены партиями, обводка заполняет как пиксели сверху, так и снизу. Это заставляет линию выглядеть так, как будто она имеет ширину 2 пикселя вместо одного.

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

без сетчатки

Тот же корпус на ретина-экране выглядит иначе. В этом случае размер точки тот же, но он состоит из 4 пикселей вместо 1. На этот раз при обводке линии пол точки над линией и пол точки ниже линии полностью заполнит ряд пикселей. выше и ниже из-за более высокого разрешения экрана. Это означает, что линия выглядит так, как будто ее ширина составляет 1 пункт, а цвет выглядит полностью непрозрачным.

Мы также можем видеть, что заполненный прямоугольник выглядит так же.

сетчатка


Чтобы исправить это, вы должны поместить точки вашей линии на половину пикселей. Проведение линии от центра на устройстве с низким разрешением означает, что линия проходит на полпункта вверх и на полпункта вниз. Поскольку центр линии теперь лежит в центре точки, это означает, что обведенная линия полностью лежит в пределах пикселей, и линия выглядит четкой. Это не повлияет на линию сетчатки, поскольку перемещение вниз (или вверх) на полпункта по-прежнему означает, что вы полностью заполните пиксели сверху и снизу.

На иллюстрации ниже (для сетчатки) я показал и сетку точек, и сетку пикселей.

половина пикселя без сетчаткиполупиксельная сетчатка

person David Rönnqvist    schedule 24.06.2012

Причина, по которой вы получаете разные результаты с помощью штриха и заливки, заключается в том, что их интерпретации аргументов различны.

Обводка добавляет половину ширины линии с каждой стороны координаты. Итак, ваша точка равна 20,0, а ширина линии составляет 1 пиксель. Теоретически результатом будет черная линия шириной 1 пиксель между (19,5-20,5). Поскольку на экране устройства нет нецелого пикселя, он будет преобразован в 2 пикселя серой/размытой линии между (19-21). чтобы обойти это, вам нужно суммировать каждую из ваших координат с 0,5 (как в CGPointMake(20.5, 10.5) ), чтобы ширина больше не делилась между пикселями.

Однако аргументы в fill используются для установки границ области для заполнения, CGRectMake(40.0, 10.0, 1.0, 390.0) подразумевает область между (40 - 41). В результате на пиксели не падает дробная часть, которая выглядит размытой.

person Özgür    schedule 24.04.2014