深入WPF中的影象畫刷(ImageBrush)之2——ImageBrush的鋪設方式

weixin_33912246發表於2018-10-25
原文:深入WPF中的影象畫刷(ImageBrush)之2——ImageBrush的鋪設方式

--------------------------------------------------------------------------------
引用或轉載時請保留以下資訊:
大可山 [MSN:a3news(AT)hotmail.com]
http://www.zpxp.com http://www.brawdraw.com
蘿蔔鼠線上圖形影象處理
--------------------------------------------------------------------------------

承接上篇:深入WPF中的影象畫刷(ImageBrush)之1——ImageBrush使用舉例,本篇著重介紹ImageBrush的鋪設方式。

先來看看ImageBrush在不使用鋪設方式時的效果:
ImageBrush不使用鋪設方式時的效果
圖1為原圖,圖2,3,4為使用ImageBrush填充到橢圓中的效果。
圖1的XAML程式碼:
  <Border Width="142" BorderBrush="#FF000000" BorderThickness="1,1,1,1" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" Margin="8,11.159,0,0" VerticalAlignment="Top" Height="150">
   <Image Source="xian.png" Stretch="Fill" Width="142" Height="150"/>
  </Border>
(Border作為定位及畫邊框用途)

圖2的XAML程式碼:
<Ellipse x:Name="ellipseWithImageBrush" Stroke="#FF000000" Height="150" Margin="169.557,8,0,0" HorizontalAlignment="Left" Width="150" d:LayoutOverrides="Height" VerticalAlignment="Top">
   <Ellipse.Fill>
    
<ImageBrush ImageSource="xian.png"/>
   </Ellipse.Fill>

  </Ellipse>
這裡使用了Ellipse的Fill屬性,這樣ImageBrush就作為Ellipse的填充畫刷了。

圖3的XAML程式碼:
<Ellipse x:Name="ellipsFillWithImageBrush" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Margin="0,11.159,167.443,0" VerticalAlignment="Top" Height="150" HorizontalAlignment="Right" Width="150">
  <Ellipse.Fill>
 <ImageBrush ImageSource="xian.png" Viewport="-0.05,-0.1,1,1.1" />
  </Ellipse.Fill>
</Ellipse>

圖4的XAML程式碼:
<Ellipse x:Name="ellipsFillWithImageBrushFill" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Margin="0,8,2,0" VerticalAlignment="Top" Height="150" HorizontalAlignment="Right" Width="150">
  <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png" Viewport="-0.16,-0.16,1.18,1.28"/>
  </Ellipse.Fill>
</Ellipse>
你可以自行比較Viewport引數對最終效果產生的影響。(關於Viewport的更多說明見後)

再來看看ImageBrush的各種鋪設方式效果:
ImageBrush的鋪設方式

下面分別予以介紹各種不同的輔設方式及其程式碼。

上圖5至圖9中,我們在ImageBrush中都使用了Viewport="0,0,0.3,0.3"。其中,前兩個引數(0,0)表示起始位置,後面兩個引數(0.3,0.3)表示縮放比例。例如圖5(XAML程式碼):
<Ellipse x:Name="ellipsFillWithImageBrushTile" Stroke="#FF000000" HorizontalAlignment="Left" Margin="8,177.015,0,240.985" Width="208" Height="208">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"
     Viewport="0,0,0.3,0.3"
     TileMode="None"
     AlignmentX="Left"
     AlignmentY="Top"
    />
   </Ellipse.Fill>
  </Ellipse>
(由於使用了TileMode.None,所以,圓形中小圖沒有平鋪,只在左上角放了一張小圖片)

圖6的XAML程式碼:
<Ellipse x:Name="ellipsFillWithImageBrushTile_Copy3" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Height="208" d:LayoutOverrides="Height" Margin="225,177.015,219,240.985">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"
     TileMode="FlipX"
     AlignmentX="Left"
     AlignmentY="Top"
     Viewport="0,0,0.3,0.3"

    />
   </Ellipse.Fill>
  </Ellipse>
說明:由於這裡使用了TileMode.FlipX,我們發現圖片在水平(X)方向上做了映象對稱反轉。

圖7的XAML程式碼:
  <Ellipse x:Name="ellipsFillWithImageBrushTile_Copy1" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Margin="0,177.015,4,240.985" d:LayoutOverrides="Width" HorizontalAlignment="Right" Width="208" Height="208">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"
     Viewport="0,0,0.3,0.3"
     TileMode="FlipY"
     AlignmentX="Left"
     AlignmentY="Top
"
    />
   </Ellipse.Fill>
  </Ellipse>
說明:由於這裡使用了TileMode.FlipY,我們發現圖片在垂直(Y)方向上做了映象對稱反轉(正立/倒立)。

圖8的XAML程式碼:
  <Ellipse x:Name="ellipsFillWithImageBrushTile_Copy4" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Width="208" Height="208" d:LayoutOverrides="Width, Height" HorizontalAlignment="Left" Margin="8,0,0,8" VerticalAlignment="Bottom">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"
     Viewport="0,0,0.3,0.3"
     TileMode="Tile"
     AlignmentX="Left"
     AlignmentY="Top"
    />
   </Ellipse.Fill>
  </Ellipse>
說明:由於這裡使用了TileMode.Tile,我們發現圖片象鋪地磚式地一張張平鋪到一起,填充到圓中,但沒有做任何映象對稱反轉。

圖9的XAML程式碼:
  <Ellipse x:Name="ellipsFillWithImageBrushTile_Copy2" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Margin="225,0,219,8" d:LayoutOverrides="Height" VerticalAlignment="Bottom" Height="208">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"
     Viewport="0,0,0.3,0.3"
     TileMode="FlipXY"
     AlignmentX="Left"
     AlignmentY="Top"
    />
   </Ellipse.Fill>
  </Ellipse>
說明:由於這裡使用了TileMode.FlipXY,我們發現圖片不但在水平方向上做了映象對稱反轉,而且在垂直(Y)方向上做了映象對稱反轉(正立/倒立)。

圖10的XAML程式碼:
  <Ellipse x:Name="ellipsFillWithImageBrushTile_Copy" Stroke="#FF000000" RenderTransformOrigin="0.5,0.5" Height="208" d:LayoutOverrides="Height" HorizontalAlignment="Right" Margin="0,0,4,8" VerticalAlignment="Bottom" Width="208">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"
     Viewport="0,0,0.18,0.18"
     TileMode="FlipXY"
     AlignmentX="Left"
     AlignmentY="Top"

    />
   </Ellipse.Fill>
  </Ellipse>
比較圖9和圖10,看看它們的程式碼,Viewport屬性值由"0,0,0.3,0.3"變成了"0,0,0.18,0.18",這樣,我們看到的裡面填充的小圖片比例縮得更小了(當然也就可以放更多的小圖片了)。

需要指出的是,Viewport是在WPF中,使用一個Rect物件來表示。如果需要指定絕對數值而不是縮放比例,那麼,就需要設定BrushMappingMode為BrushMappingMode.Absolute。同時指定Viewport的絕對值,比如將圖6所對應的XAML程式碼改為:
<ImageBrush
      Viewport="0,0,25,25"
      ViewportUnits="Absolute"
      TileMode="Tile"
      ImageSource="xian.png" />

之後,得到如下效果:
使用Viewport絕對值的效果
這裡的填充小圖每個圖的寬度和高度分別為25,25畫素了。

為了加深大家的印象,不妨與GDI+的圖片畫刷作一個比較。
在GDI+中,與WPF中ImageBrush對應的是TextureBrush,與ImageBrush.TileMode對應的是TextureBrush.WrapMode, 而WrapMode的列舉值(注意是“列舉值”)是:Clamp,Tile,

TileFlipX,TileFlipY和TileFlipXY,分別與TileMode屬性值(注意是“屬性值”)的None,Tile,FlipX,FlipY和FlipXY對應。
與WPF中指定Viewport屬性來控制起點及影象縮放不同的是:在GDI+中,graphic.RenderingOrigin將對TextureBrush的圖片繪製的起始位置產生影響,如果需要對TextureBrush 物件的區域性做幾何變換縮放,可以使用ScaleTransform()方法,例如:
public void ScaleTransform_Example(PaintEventArgs e)
{
  TextureBrush tBrush = new TextureBrush(new Bitmap("texture.jpg"));
  tBrush.ScaleTransform(2, 1, MatrixOrder.Prepend);
  e.Graphics.FillRectangle(tBrush, 0, 0, 100, 100);
}

相關文章:
深入WPF中的影象畫刷(ImageBrush)之1——ImageBrush使用舉例
深入WPF中的影象畫刷(ImageBrush)之2——ImageBrush的鋪設方式〔本篇〕
簡述WPF中的畫刷(Brush)

相關文章