UIBezierPath-lijn 1px lijn en vul 1px breedte rechthoek - verschillende resultaten.

Hier is een eenvoudige tekening

    

- (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];

}

Op niet-retina 3GS en simulator is de eerste lijn wazig en ziet hij breder dan 1 px, maar de tweede lijn is helder.

Helaas heb ik noch iPhone4 noch de nieuwe iPad om te testen, maar op de retina-simulator zien beide lijnen er hetzelfde uit.

Vraag: Is rechthoek in plaats van lijn de enige manier om hetzelfde resultaat te verkrijgen voor niet-retina- en retina-apparaten?

23

2 antwoord

Je vult de binnenkant van de rechthoek, maar je strijkt de lijn vanuit het midden. Omdat de coördinaten in beide gevallen (de hoeken van de rechthoek en de begin- en eindcoördinaten in de lijn) zijn gedefinieerd als gehele getalwaarden (geen breuken), liggen de coördinaten op exacte puntgrenzen.

Ik zei hierboven 'coördinaten' als ik het had over de punten van de lijn, om ze niet te verwarren met de punten op het scherm. Ik heb ook om dezelfde reden "puntgrenzen" in plaats van "pixelgrenzen" gezegd. iOS definieert de coördinaten en alle punten in zogenaamde "punten" in plaats van pixels. Een punt is een resolutieonafhankelijke meting. Zowel de retina- als de niet-retina-apparaten hebben hetzelfde aantal punten op het scherm, alleen komen ze overeen met een ander aantal werkelijke pixels.

Laten we eens kijken naar het strijken van een lijn die op de puntgrenzen ligt (zoals in uw vraag) in vergelijking met het vullen van een rechthoek waar de hoeken op de puntgrenzen liggen:

In de onderstaande illustraties streel ik een lijn met zwart en vul ik een rechthoek met oranje op zowel een niet-retinascherm als een retinascherm. Ik heb ook de lijn en de rechthoek met blauw geschetst. In beide gevallen kunt u de grootte van een punt voor die resolutie bekijken en deze vergelijken met het werkelijke pixelraster.

In het geval van het niet-netvlies, kunt u zien dat als u probeert de lijn vanaf het midden af ​​te lijnen met een 1-puntslijn met (in dit geval overeenkomend met een lijnlijn van 1 pixel) de helft van de pixels boven en de helft van de pixels zou worden opgevuld hieronder. Omdat de pixels slechts voor de helft gevuld zijn, is de dekking voor die pixels 50%. Dit resulteert in de lichtere kleur (op een witte achtergrond). Omdat zowel de pixels aan de bovenkant als daaronder partijgevuld zijn, strijken de vullingen beide pixels boven en onder. Hierdoor ziet de lijn eruit alsof deze 2 pixels breed is in plaats van één.

Je kunt dat snel vergelijken met de rechthoek die aan de binnenkant is gevuld.

non retina

Hetzelfde geval op een netvliesscherm ziet er anders uit. In dit geval is de grootte van een punt hetzelfde, maar deze bestaat uit 4 pixels in plaats van 1. Deze keer, wanneer u de lijn aait, wordt een half punt boven de lijn en een half punt onder de lijn volledig gevuld met de rij pixels boven en onder vanwege het scherm met hogere resolutie. Dit betekent dat de lijn er als één punt breed uitziet en dat de kleur er volledig ondoorzichtig uitziet.

We kunnen ook zien dat de gevulde rechthoek er hetzelfde uitziet.

retina


Om dit te verhelpen, plaatst u de punten voor uw lijn op halve pixels. Door de lijn vanaf het midden op een apparaat met lage resolutie te strijken, betekent dit dat de lijn zich een halve punt naar boven en een half punt naar beneden uitstrekt. Omdat het midden van de lijn nu in het midden van het punt ligt, betekent dit dat de gestreept lijn volledig in de pixels ligt en de lijn er scherp uitziet. Als u dit doet, heeft dit geen effect op de netvlieslijn, omdat een punt naar beneden (of hoger) nog steeds betekent dat u de pixels boven en onder volledig vult.

In de onderstaande illustratie (voor netvlies) heb ik zowel het puntenraster als het pixelraster getoond.

half pixel non-retina half pixel retina

52
toegevoegd

De reden dat u verschillende resultaten krijgt met lijn en vulling is dat hun interpretaties van argumenten anders zijn.

Streek voegt de helft van de breedte van de lijn aan elke zijde van de coördinaat toe. Dus, je punt is 20.0 en de breedte van de lijn is 1px. Het resultaat is theoretisch een zwarte lijn van 1 pixel tussen (19.5-20.5). Aangezien er geen niet-integrale pixel op het scherm van het apparaat staat, wordt deze geconverteerd naar een grijs/wazige lijn van 2 pixels tussen (19-21). om dit te omzeilen, moet je elk van je coördinaten optellen met 0.5 (zoals in CGPointMake (20.5, 10.5)), zodat de breedte niet langer wordt verdeeld tussen pixels.

De argumenten in de opvulling worden echter gebruikt om de grenzen van de te vullen regio in te stellen, CGRectMake (40.0, 10.0, 1.0, 390.0) impliceert een regio tussen (40 - 41). Als gevolg hiervan is er geen fractioneel deel dat op de pixels valt om er wazig uit te zien.

2
toegevoegd