web-dev-qa-db-ja.com

UIBezierPathは1pxの線を描き、1pxの幅の長方形を塗りつぶします-異なる結果。

これは簡単な絵です

    

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

}

Retina以外の3GSとシミュレータでは、最初のラインはぼやけて1ピクセルよりも広く見えますが、2番目のラインはくっきりしています。

残念ながら、テストするiPhone4も新しいiPadもありませんが、Retinaシミュレータでは両方のラインが同じに見えます。

質問:網膜ではなく網膜のデバイスで同じ結果を得るには、ストロークではなく長方形が唯一の方法ですか?

23
Michael

長方形の内側を塗りつぶしていますが、中心から線をなでています。どちらの場合も座標(長方形の角と線の始点と終点の座標)は整数値(分数なし)として定義されるため、座標は正確なポイント境界にあります。

画面上の点と混同しないように、線の点について話すときは、上の「座標」と言いました。同じ理由で「ピクセル境界」ではなく「ポイント境界」とも言いました。 iOSは、ピクセルの代わりに「座標」と呼ばれるもので座標とすべての座標を定義します。ポイントは、解像度に依存しない測定です。網膜デバイスと非網膜デバイスの両方が画面上に同じ数のポイントを持っています。それは、実際のピクセルの異なる数に対応しているということです。

角がポイント境界にある長方形を塗りつぶすことと比較して、(質問のように)ポイント境界にあるラインをなでるのを見てみましょう:

以下の図では、非網膜画面と網膜画面の両方で、黒で線を描き、長方形をオレンジで塗りつぶしています。また、線と長方形の輪郭を青色で示しました。どちらの場合も、その解像度のポイントのサイズを確認して、実際のピクセルグリッドと比較できます。

網膜以外の場合、1ポイントの線(この場合は1ピクセルの線幅に対応)を使用して中心から線をストロークしようとすると、上部のピクセルの半分とピクセルの半分が塗りつぶされます。未満。ピクセルは半分だけ塗りつぶされているため、それらのピクセルの不透明度は50%です。これにより、(白い背景の)明るい色になります。上と下の両方のピクセルがパーティーで塗りつぶされるので、ストロークを打つと上と下の両方のピクセルが塗りつぶされます。これにより、線が1ピクセルではなく2ピクセル幅のように見えます。

あなたはすぐにそれを内側で塗りつぶされた長方形と比較することができます。

non retina

網膜画面の同じケースは異なって見えます。この場合、ポイントのサイズは同じですが、1の代わりに4ピクセルで構成されます。今回、ラインをストロークすると、ラインの上半分のポイントとラインの下半分のポイントがピクセルの行を完全に塗りつぶしますより高い解像度の画面のために上下に。これは、線が1ポイント幅のように見え、色が完全に不透明に見えることを意味します。

塗りつぶされた長方形が同じに見えることもわかります。

retina


これを修正するには、ラインのポイントを半ピクセルに配置します。低解像度のデバイスで中心から線をなでることは、線が半分上向きに伸び、半分下向きに伸びることを意味します。ラインの中心がポイントの中心にあるため、ストロークされたラインは完全にピクセル内にあり、ラインはシャープに見えます。これを行っても、網膜のラインには何の影響もありません。半ポイント下(または上)に移動しても、上下のピクセルが完全に塗りつぶされることを意味します。

下の図(網膜の場合)では、ポイントグリッドとピクセルグリッドの両方を示しています。

half pixel non-retinahalf pixel retina

53

ストロークと塗りつぶしで異なる結果が得られるのは、引数の解釈が異なるためです。

ストロークは、座標の両側に線の幅の半分を追加します。したがって、ポイントは20.0で、線の幅は1pxです。結果は、理論的には(19.5-20.5)の間に1ピクセルの黒い線になります。デバイス画面には整数でないピクセルがないため、(19-21)の間の2ピクセルの灰色/ぼやけた線に変換されます。これを回避するには、各座標を0.5で合計する必要があります(CGPointMake(20.5、10.5)のように)。これにより、幅がピクセル間で分割されなくなります。

ただし、塗りつぶしの引数は、塗りつぶす領域の境界を設定するために使用されます。CGRectMake(40.0、10.0、1.0、390.0)は、(40-41)の間の領域を意味します。その結果、ぼやけて見えるようにピクセルに落ちる部分はありません。

2
Özgür