次の方法で共有


WPF アプリケーションのピクセル スナップ

[このドキュメントはプレビュー版であり、後のリリースで変更されることがあります。 空白のトピックは、プレースホルダーとして挿入されています。]

WPF のグラフィックス システムでは、解像度やデバイスへの依存を避けるために、デバイスに依存しない独立した単位が使用されます。 各デバイス非依存ピクセルは、システムのドット/インチ (dpi) 設定に従って自動的にスケーリングされます。 これにより、さまざまな WPF 設定で dpi アプリケーションが適切にスケーリングされ、アプリケーションが自動的に dpi に対応するようになります。

However, this dpi independence can create irregular edge rendering due to anti-aliasing. These artifacts, commonly seen as blurry, or semi-transparent, edges can occur when the location of an edge falls in the middle of a device pixel rather than between device pixels. この問題に対処するために、WPF では、ピクセル スナップを使用してビジュアル ツリーのオブジェクトの端をデバイス ピクセルにスナップ (つまり固定) し、アンチエイリアシングで生じる半透明のエッジを解消する方法を使用できます。

ピクセル スナップは、ビジュアルのジオメトリに小さいオフセットを適用してジオメトリをデバイス ピクセルに揃えることでこのようなビジュアル アイテムを抑えるための手段です。

このトピックには次のセクションが含まれています。

  • アンチエイリアス化されたレンダリングに対するピクセル スナップ
  • ガイドライン
  • ビットマップ イメージ
  • 関連トピック

アンチエイリアス化されたレンダリングに対するピクセル スナップ

鮮明な線

ピクセル スナップを行わないと、エッジがデバイス ピクセルの間にない場合、アンチエイリアス化されてレンダリングされた線が半透明になる可能性があります。 次の図は、幅が 1 ピクセルのアンチエイリアス化された線の出力が、デバイス ピクセル内にある場合と (左)、デバイス ピクセルとデバイス ピクセルの間にある場合 (右) を示したものです。

アンチエイリアス化された線のレンダリング

単一のピクセル線と比較したアンチエイリアス線。

ピクセル スナップを行うと、アンチエイリアス化された線はデバイス ピクセルにスナップし (固定され)、半透明な線のレンダリングが回避されます。 The following example demonstrates the effect that the SnapsToDevicePixels property has on a single pixel line. ウィンドウのサイズをゆっくり変更すると、位置が変化する際に、スナップされていない線 (左) ではビジュアル アイテムが発生し、スナップされている線 (右) ではサイズが固定されています。

<Page x:Class="PixelSnapping.Lines"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Lines" Name="linesPage"
    >
  <StackPanel Width="150"  Margin="7" Orientation="Horizontal">
    <!-- Single pixel line with pixel snapping turned OFF.-->
    <Rectangle SnapsToDevicePixels="False"
       Width="45.5" Margin="10" Height="1" Fill="Red"/>
    <!-- Single pixel line with pixel snapping turned ON.-->
    <Rectangle SnapsToDevicePixels="True"
      Width="45.5" Margin="10" Height="1" Fill="Red"/>
  </StackPanel>
  <!-- Background Grid -->
  <Page.Background>
    <DrawingBrush  Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,1,1" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>
          <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
          <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Page.Background>
</Page>

注意

SnapsToDevicePixels は、レイアウト パスを通過する要素に対してのみ影響を与えます。Drawing オブジェクトの DrawingGroup プロパティを使用すると、GuidelineSet にガイドラインを設定できます。Visual のガイドラインを手動で設定するには、VisualYSnappingGuidelines プロパティと VisualXSnappingGuidelines プロパティを使用して、新しいガイドラインを作成します。

ピクセル スナップにより鮮明になるのは横線と縦線だけであり、斜線には効果がありません。

隣接するオブジェクト

オブジェクト間のエッジが接していて、隣接するエッジがデバイス ピクセルの行または列の間に正確に揃っていない場合も、アンチエイリアス化によってビジュアル アイテムが発生する可能性があります。 アンチエイリアス化されたシーンでは、基になっている背景色を使用してエッジが滑らかにされ、各オブジェクトの間のエッジの色が透明になる浸透効果が生成される可能性があります。 次の図は、この浸透効果を示したものです。

隣接するオブジェクトでの浸透効果

隣接したオブジェクト間に浸透する背景。

ピクセル スナップを有効にすると、隣接するエッジがデバイス ピクセルにスナップされ、浸透効果が発生しなくなります。 The following example demonstrates the effect of the SnapsToDevicePixels property on abutting objects. ウィンドウのサイズをゆっくり変更すると、スナップされていない四角形 (左) では浸透効果が発生しますが、スナップされている四角形 (右) では表示の異常は発生しません。

<Page x:Class="PixelSnapping.Seeping"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Seeping"
    >
  <StackPanel Orientation="Horizontal" Height="100">
    <Border  
      SnapsToDevicePixels="False"
      Margin="10" BorderThickness="1" BorderBrush="Black" Height="80" Background="White">
      <StackPanel Height="100.0">
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
      </StackPanel>
    </Border>
    <Border
      SnapsToDevicePixels="True"
        Margin="10" BorderThickness="1" BorderBrush="Black" Height="80" Background="White">
      <StackPanel Height="100.0">
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
        <Rectangle Width="20" Height="20" Fill="Red"/>
      </StackPanel>
    </Border>
  </StackPanel>
  <!-- Background Grid -->
  <Page.Background>
    <DrawingBrush  Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,1,1" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>
          <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
          <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Page.Background>
</Page>

スナップされている四角形では SnapsToDevicePixels プロパティの値を明示的に設定していないことに注意してください。 このプロパティは、ルート要素で true に設定するだけで、すべての子要素で動作が有効になります。

テキスト

Windows Presentation Foundation (WPF) は常にアンチエイリアスされたテキストを生成します。生成されたテキストが静的な場合は、ピクセル スナップされます。 これにより、グリフがピクセル グリッド上に直接配置されて、アンチエイリアスされたテキストの外観が鮮明になり、テキストがよりクリアになります。 ただし、Windows Presentation Foundation (WPF) が、スクロール、スケーリング、アニメーション化された変換など、アニメーション的な動きを検出すると、そのような動きが完了するまでピクセル スナップはオフになります。 アニメーションやスクロールの動きが完了すると、ピクセル スナップがゆっくりと復活します。

ガイドライン

基本的に、ピクセル スナップはガイドラインによって制御されます。 ガイドラインは、ジオメトリの位置をデバイス ピクセル グリッドに合わせるのに役立ちます。 通常は、SnapsToDevicePixels プロパティを使用してピクセル スナップを行うと、意図した結果が得られます。 しかし、このプロパティを使用できない場合もあり (特に、Drawing オブジェクトを使用している場合や DrawingContext を直接処理する場合)、ピクセル スナップによって提供される目的の鮮明さを実現するために、ガイドラインの設定が必要になります。

Drawing および DrawingContext オブジェクトにガイドラインを設定するには、GuidelineSet クラスを使用します。 このクラスを使用すると、DrawingGroup に適用できる、または以降の描画コマンドのために DrawingContext にプッシュできる、水平および垂直のガイドラインを作成できます。 ガイドラインは、どの線をデバイス ピクセルにスナップする必要があるかを描画に指示します。 GuidelineSet の使用の詳細な例については、「方法 : Apply a GuidelineSet to a Drawing」を参照してください。

水平および垂直のガイドライン コレクションを変更することで、ガイドラインを Visual レベルで設定することもできます。 これらには、VisualYSnappingGuidelines プロパティおよび VisualXSnappingGuidelines プロパティを使用してアクセスできます。

ビットマップ イメージ

dpi は WPF に依存しないため、ビットマップ ベースの UI は意図したとおりの表示結果にならない場合があります。 Anti-aliased scenes can blur an image due to fractional-pixel alignment issues. This is particularly true for images that contain high frequency changes such as single pixel lines with contrasting elements adjacent to them (such as alternating black and white lines). 次の図は、揃えられたイメージ (左) と、デバイス ピクセルにオフセットが揃えられていないイメージ (右) での、イメージ品質の違いを示しています。

デバイス ピクセルに合わせたイメージの位置調整

デバイス ピクセルが配置されていないためにぼかされたイメージ。

UI のイメージでよくあるシナリオは、アイコンを表すイメージを別のオブジェクトの中央に揃える場合です。 通常、アイコンは変化の頻度が高い小さなイメージであるため、アンチエイリアス化によりビジュアル アイテムが生成されるのを防ぐため、アプリケーションのレイアウトに合わせた調整が必要になる場合があります。

イメージを正確に中央に揃えるには、イメージのピクセルの幅または高さが偶数の場合は、コンテナーの幅または高さも偶数である必要があります。 イメージの幅または高さが奇数ピクセルの場合は、含まれる要素の幅または高さも奇数ピクセルである必要があります。

Border を格納した 2 つの Image オブジェクトを作成する例を次に示します。 上の境界の幅と高さは偶数で、イメージと一致しています。 下の境界の幅と高さは奇数です。

The following illustration shows the output from the example and the effect the container size has on image.

境界線内の中央に配置されたイメージ。

<Page x:Class="PixelSnapping.Images"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="Images"
    >
  <StackPanel>
    <!-- Image has a pixel dimension of 144x96. -->
    <!-- Because the image has a even width and height, 
         an even border width and height allows the image to proper center. 
    -->
    <Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="100">
      <Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="sharpness.png" Stretch="None"/>
    </Border>
    <!-- Image has a pixel dimension of 144x96. -->
    <!-- Because the image has a even width and height, 
         an odd border width and height causes the image to soften. 
    -->
    <Border HorizontalAlignment="Left" VerticalAlignment="Top" Width="201" Height="101">
      <Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="sharpness.png" Stretch="None"/>
    </Border>
  </StackPanel>
  <!-- Grid Background -->
  <Page.Background>
    <DrawingBrush  Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,1,1" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>
          <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" />
          <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" />
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Page.Background>
</Page>

残念ながら、コンテナー オブジェクトのサイズを調節するだけでは、デバイス ピクセルの調整は保証されません。 The entire layout of an application can have an effect on the alignment of the image. ディスプレイのドット/インチ (dpi) も、イメージの位置調整に影響します。 In the example above, the image alignment will only work if the display is set to 96 ドット/インチ (dpi). At any other setting, the layout needs to be adjusted to accommodate the display settings. Windows Presentation Foundation (WPF) アプリケーションでは、頻繁に変化するイメージは可能な限り避ける必要があります。

参照

参照

Image

VisualXSnappingGuidelines

VisualYSnappingGuidelines

概念

レイアウト システム