WPF之圖片處理系列


WPF 中的一些圖片處理方法

一,視覺處理(控件展示)

1,顯示圖片

  • Image控件展示

Xaml代碼:

<Image source="/Resources/Images/1.png"/>
  • 縮放位圖渲染算法

Xaml代碼:

<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。

2,Image遮罩

  • OpacityMask

來自微軟官方的說明:
獲取或設置一個作為 Brush 實現的不透明蒙板,該蒙板可應用到此元素所呈現內容的任何 Alpha 通道蒙板。 這是依賴項屬性。

來自個人的經驗解釋:
OpacityMask也是一張圖片,它用來改變被它遮住的內容的顯示區域,
OpacityMasK本身:有內容的區域被鏤空,沒有內容的區域被填充
被它遮住的控件或者畫布:鏤空的區域就展示,填充的區域變透明


3,圖片DPI

  • 圖片DPI是每英寸顯示的點的個數(點/英寸)
  • 圖片的寬像素=寬dpi*尺寸
  • 圖片的高像素=高dpi*尺寸
  • WPF 中,所有圖片在Xaml中都會被強制拉成96dpi。

4,控件的Transform

來自微軟官方的說明:
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>


二,輸出文件

1,顯示圖片

①,BitmapImage的保存

與Bitmap.Save()不同,需要對BitmapImage的數據轉為Stream,通過文件流保存

C#代碼

BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frame.Add(BitmapFrame.Create(bitmapImage));
using(var straem=new FileStream(path,FileMode.Create)){
    encoder.Save(stream);
}

②,BitmapImage的Width,Height和PixelWidth,PixelHeight

Width和Height:獲取位圖的寬/高度(以與設備無關的單位(每個單位 1/96 英寸)為單位)。(會根據電腦DPI的更改獲取到不同的值)
PixelWidth和PixelHeight:獲取位圖的寬/高度(以像素為單位)

③,BitmapImage與Bitmap的互相轉換

同樣是轉為流數據,向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;
}

2,Visual和DrawingContext

①,Visual

Visual:為 WPF 中的呈現提供支持,其中包括命中測試、坐標轉換和邊界框計算。

層級關系:
System.Windows.Media.Visual
     System.Windows.Media.ContainerVisual
            System.Windows.UIElement

②,DrawingContext

DrawingContext:使用繪圖、推送和彈出命令描述可視內容。

繪制方法:

DrawDrawing: 畫Drawing對象

DrawEllipse: 畫圓

DrawGeometry: 畫幾何圖形

DrawGlyphRun:畫文字

DrawImage: 畫圖

DrawLine:畫線

DrawRectangle/DrawRoundedRectangle:畫矩形

DrawText:畫帶格式的文本

DrawVideo:畫視頻

PushClip:推送剪切區域

③,RenderTargetBitmap

RenderTargetBitmap:將System.Windows.Media.Visual 對象轉換為位圖。

④,Image遮罩

和控件方式類似,在后台代碼中使用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);

⑥,PathGeometry

來自微軟官方的解釋:表示一個可能由弧、曲線、橢圓、直線和矩形組成的復雜形狀

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);

正方形摳圖

線條摳圖

⑧,裁剪

  • BitmapSource中有一個方法叫做CopyPixels,復制像素點集到一個新的BitmapSource里面。可以實現裁剪

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);
}           


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM