2

タイル張りの画像を描画し、通常のパンとズームのジェスチャを使用してそれらを変換したいと考えています。ここでの問題は、小数点以下の桁数が多いスケーリング変換を行うと、タイルの中央にピクセルの細い線 (1 または 2) が表示されることです。私はこのように問題を切り分けることができました:

CGContextSaveGState(UIGraphicsGetCurrentContext());

CGContextSetFillColor(UIGraphicsGetCurrentContext(), CGColorGetComponents([UIColor redColor].CGColor));
CGContextFillRect(UIGraphicsGetCurrentContext(), rect);//rect from drawRect:

float scale = 0.7;
CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(50, 50, 100, 100), testImage);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(150, 50, 100, 100), testImage);
CGContextRestoreGState(UIGraphicsGetCurrentContext());

スケールが 0.7 の場合、2 つの画像は正しく並べて表示されます。 0.7 スケール

スケールが 0.777777 の場合 (6 行目を "float scale = 0.777777;" に変更)、視覚的なアーティファクトが表示されます。

0.777777 スケール

この問題を回避する方法はありますか? これは、CGImage、CGLayer、および長方形などのプリミティブ フォームで発生します。MacOSx でも発生します。

助けてくれてありがとう!

編集: これは CGContextFillRect のようなプリミティブ フォームでも発生することを追加しました

edit2: MacOSx でも発生します!

4

2 に答える 2

2

Quartzには浮動小数点座標系があるため、スケーリングにより、ピクセル境界上にない値が生成され、エッジでアンチエイリアシングが表示される場合があります。それを望まない場合は、2つのオプションがあります。

  1. すべてのスケーリングされた座標が積分されるように、スケール係数を調整します。これは、特にたくさんのものを描いている場合は、常に可能であるとは限りません。

  2. を使用して、グラフィックスコンテキストのアンチエイリアスを無効にしますCGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), false);。これにより、鮮明なピクセル境界が得られますが、直線以外のものはあまり見栄えが良くない可能性があります。

于 2012-08-28T19:22:31.747 に答える
0

結局のところ、iOS は整数境界上の個別のピクセルを処理しています。フレームが 0.7 縮小されると、50 はピクセル境界で 35 に縮小されます。0.777777 ではそうではないため、iOS は適応し、移動/縮小/ブレンドします。

あなたには本当に2つの選択肢があります。コンテキストのスケーリングを使用する場合は、整数のスケーリングされたフレーム値になるように、目的の値を切り上げまたは切り捨てます (コードでは、標準の乗算値として 50 が表示されます)。

それ以外の場合、コンテキストをスケーリングすることはできませんが、コンテンツを 1 つずつスケーリングし、必要に応じて CGIntegralRect を使用してすべてのディメンションを切り上げまたは切り捨てます。

編集: 私の疑いが正しければ、さらに別の選択肢があります。.77777 の倍率と 50,50,100,100 のフレームが必要だとしましょう。50 を取得し、それをスケールで乗算してから、戻り値を切り上げまたは切り捨てます。次に、その値を 0.7777 で割った値を使用して新しいフレームを再計算し、0.7777 でスケーリングすると整数を返す小数値を取得します。Quartz は、整数値を意味することを理解するのに非常に優れているため、小さな丸め誤差は無視されます。これでうまくいくと思います。

于 2012-08-28T17:56:13.660 に答える