Image控件展現算法
Xaml代碼:canvas
<Image source="/Resources/Images/1.png"/>
縮放位圖渲染算法c#
Xaml代碼:api
<Image Source="/Resources/Images/1.jpg" RenderOptions.BitmapScalingMode="Fant"/>
枚舉值 | 描述 |
---|---|
Fant | 使用超高質量 Fant 位圖縮放,雖然速度比全部其餘位圖縮放模式都慢,但輸出質量更高。 |
HighQuality | 使用高質量位圖縮放,雖然速度比 LowQuality 模式慢,但輸出質量更高。 HighQuality 模式與 Fant 模式相同。 |
Linear | 使用線性位圖縮放,雖然速度比 HighQuality 模式快,但輸出質量較低。 |
LowQuality | 使用雙線性位圖縮放,雖然速度比 HighQuality 快,但輸出質量較低。 LowQuality 模式與 Linear 模式相同。 |
NearesNeighbor | 使用最近鄰域位圖縮放,當使用軟件光柵器時,該縮放提供優於 LowQuality 模式的性能。 該模式經常使用於放大位圖。 |
Unspecified | 使用默認位圖縮放模式,即 Linear。 |
OpacityMask數組
來自微軟官方的說明:
獲取或設置一個做爲 Brush 實現的不透明蒙板,該蒙板可應用到此元素所呈現內容的任何 Alpha 通道蒙板。 這是依賴項屬性。ide
來自我的的經驗解釋:
OpacityMask也是一張圖片,它用來改變被它遮住的內容的顯示區域,
OpacityMasK自己:有內容的區域被鏤空,沒有內容的區域被填充
被它遮住的控件或者畫布:鏤空的區域就展現,填充的區域變透明函數
來自微軟官方的說明:
Transform 定義如何將點從一個座標空間映射或轉換到另外一個座標空間。 此映射由轉換 Matrix描述,該轉換是包含三列 Double 值的三行的集合。性能
枚舉值 | 描述 |
---|---|
RotateTransform | 按指定角度旋轉元素。 |
ScaleTranform | 按指定的 ScaleX 和 ScaleY 量來縮放元素。 |
SkewTransform | 按指定的 AngleX 和 AngleY 量傾斜元素。 |
TranslateTransform | 按指定的 X 和 Y 量移動(平移)元素。 |
Xaml代碼:測試
<Image Width="450" Source="/Images/3.jpg"> <Image.RenderTransform> <TransformGroup> <TranslateTransform X="10" Y="10" /> <RotateTransform Angle="20" CenterX="200" CenterY="121"/> <ScaleTransform ScaleX="1.5" ScaleY="1.5" CenterX="200" CenterY="121"/> <SkewTransform AngleX="10" AngleY="10" CenterX="200" CenterY="121"/> </TransformGroup> </Image.RenderTransform> </Image>
與Bitmap.Save()不一樣,須要對BitmapImage的數據轉爲Stream,經過文件流保存this
C#代碼
BitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frame.Add(BitmapFrame.Create(bitmapImage)); using(var straem=new FileStream(path,FileMode.Create)){ encoder.Save(stream); }
Width和Height:獲取位圖的寬/高度(以與設備無關的單位(每一個單位 1/96 英寸)爲單位)。(會根據電腦DPI的更改獲取到不一樣的值)
PixelWidth和PixelHeight:獲取位圖的寬/高度(以像素爲單位)
一樣是轉爲流數據,向Bitmap的構造函數傳參
//BitmapImage to Bitmap public static Bitmap GetBitmapByBitmapImage(this BitmapImage bitmapImage,bool isPng=false) { Bitmap bitmap; MemoryStream outStream = new MemoryStream(); BitmapEncoder enc = new BmpBitmapEncoder(); if (isPng) { enc = new PngBitmapEncoder(); } enc.Frames.Add(BitmapFrame.Create(bitmapImage)); enc.Save(outStream); bitmap = new Bitmap(outStream); return bitmap; } // Bitmap to BitmapImage public static BitmapImage GetBitmapImageBybitmap(this Bitmap bitmap) { BitmapImage bitmapImage = new BitmapImage(); try { using (MemoryStream ms = new MemoryStream()) { bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); bitmapImage.BeginInit(); bitmapImage.StreamSource = ms; bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); bitmapImage.Freeze(); } } catch (Exception ex) { log.ErrorFormat("bitmap to BitmapImage Failed:" + ex.Message); } return bitmapImage; }
Visual:爲 WPF 中的呈現提供支持,其中包括命中測試、座標轉換和邊界框計算。
層級關係:
System.Windows.Media.Visual
System.Windows.Media.ContainerVisual
System.Windows.UIElement
DrawingContext:使用繪圖、推送和彈出命令描述可視內容。
繪製方法:
DrawDrawing: 畫Drawing對象
DrawEllipse: 畫圓
DrawGeometry: 畫幾何圖形
DrawGlyphRun:畫文字
DrawImage: 畫圖
DrawLine:畫線
DrawRectangle/DrawRoundedRectangle:畫矩形
DrawText:畫帶格式的文本
DrawVideo:畫視頻
PushClip:推送剪切區域
RenderTargetBitmap:將System.Windows.Media.Visual 對象轉換爲位圖。
和控件方式相似,在後臺代碼中使用Visual來展現
C#代碼
RenderTargetBitmap bmp = new RenderTargetBitmap((int)img.Source.Width, (int)img.Source.Height, 96, 96, PixelFormats.Default); DrawingVisual visual = new DrawingVisual() { OpacityMask = imgBrush };//遮罩Visual using (DrawingContext dc = visual.RenderOpen()) { dc.DrawImage(img.Source, new Rect(0, 0, img.Source.Width, img.Source.Height)); } bmp.Render(visual);
一樣是修改Visual的Transform
這裏注意:文件渲染的Transform和前臺的Transform不全相同!!!!
由於界面顯示的圖片大小和實際大小不同
C#代碼
RenderTargetBitmap bmp = new RenderTargetBitmap((int)img.Source.Width, (int)img.Source.Height, 96, 96, PixelFormats.Default); DrawingVisual visual = new DrawingVisual() { Transform=img.RenderTransform };//修改Transform using (DrawingContext dc = visual.RenderOpen()) { dc.DrawImage(img.Source, new Rect(0, 0, img.Source.Width, img.Source.Height)); } bmp.Render(visual);
來自微軟官方的解釋:表示一個可能由弧、曲線、橢圓、直線和矩形組成的複雜形狀
LineGeometry 直線
ps:這個LineGeometry能夠實現線頭和線尾的圓滑筆觸效果
new LineGeometry(start, end).GetWidenedPathGeometry(new Pen(Brushes.Black, 10) { StartLineCap = PenLineCap.Round, EndLineCap = PenLineCap.Round });
EllipseGeometry 圓
RectangleGeometry 矩形
經過DrawingContext的PushClip能夠將指定的剪輯區域推送到繪圖上下文上。
須要利用到上面的Geometry幾何圖形
配合一些鼠標事件能夠手動實現inkcanvas和相似PS的背景橡皮擦
C#代碼
RenderTargetBitmap bmp = new RenderTargetBitmap((int)img.Source.Width, (int)img.Source.Height, 96, 96, PixelFormats.Default); DrawingVisual visual = new DrawingVisual() { OpacityMask = imgBrush };//遮罩Visual using (DrawingContext dc = visual.RenderOpen()) { RectangleGeometry full = new RectangleGeometry(new Rect(0,0,777,523));//全圖區域 var clip= Geometry.Combine(full, new RectangleGeometry(new Rect(200,200,300,300)), GeometryCombineMode.Exclude, null);//減去一個矩形的區域 dc.PushClip(clip);//推送clip區域結果 dc.DrawImage(img.Source, new Rect(0, 0, img.Source.Width, img.Source.Height)); } bmp.Render(visual);
正方形摳圖
線條摳圖
stride:位圖的跨距(一行的字節數)。
pixels:表示位圖圖像內容的字節數組。
public static BitmapSource CutImage(BitmapSource bitmapSource, Int32Rect cut) { //計算Stride var stride = bitmapSource.Format.BitsPerPixel * cut.Width / 8; //聲明字節數組 byte[] data = new byte[cut.Height * stride]; //調用CopyPixels bitmapSource.CopyPixels(cut, data, stride, 0); return BitmapSource.Create(cut.Width, cut.Height, 0, 0, PixelFormats.Bgra32, null, data, stride); }