WPF之圖片處理系列

来源:https://www.cnblogs.com/Big-Head/archive/2019/12/19/12068230.html
-Advertisement-
Play Games

WPF中一些圖片處理方案整理,可以大致實現類似PS的一些基本功能:移動,裁剪,摳圖,背景橡皮擦等等 ...


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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 為了向別人、向世界證明自己而努力拼搏,而一旦你真的取得了成績,才會明白:人無須向別人證明什麼,只要你能超越自己。 ...
  • 前情提要 "Scala函數式編程指南(一) 函數式思想介紹" "scala函數式編程(二) scala基礎語法介紹" "Scala函數式編程(三) scala集合和函數" "Scala函數式編程(四)函數式的數據結構 上" 1.List代碼解析 今天介紹的內容,主要是對上一篇介紹的scala函數式數 ...
  • 在逛 Stack Overflow 的時候,發現了一些訪問量像熊耳山一樣高的問題,比如說這個:為什麼不應該使用Java的原始類型?訪問量足足有 205K+,這不得了啊!說明有很多很多的程式員被這個問題困擾過。實話實說吧,本文之前的我就是其中之一。 <!--more--> 來回顧一下提問者的問題吧: ...
  • 首要作者本人要聲明一下,寫下此文章技術不是教你去黑傳奇SF,只是想以本文引起4F擁有者的留意方案,哈哈。 如何入侵傳奇SF刷元寶,首先要溫故下自己的專業技術水平。 我也非常喜歡玩游戲,但卻玩得特別菜,也沒有時間去玩只想玩著過癮,所以當我開始玩傳奇時,雖覺得是好玩,但玩盛大的簡直是在受罪,晉級慢,沒好 ...
  • 時間如流水,只能流去不流回! 點贊再看,養成習慣,這是您給我創作的動力! 本文 Dotnet9 https://dotnet9.com 已收錄,站長樂於分享dotnet相關技術,比如Winform、WPF、ASP.NET Core等,亦有C++桌面相關的Qt Quick和Qt Widgets等,只分 ...
  • 首先在ConfigureServices添加 public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddPolicy("any", builder => ...
  • .NET Core 3.1 作為LTS長期支持版本,會提供3年的支持(明年就出.net5),值得升級(嗎)。 目前主流的第三方包大多都已經提供了支持,2.x => 3.1還是變化不是特別多,EF Core坑就大咯,謹慎。 ASP.NET Core 3.1 的新增功能 https://docs.mic ...
  • 我們搜索一下yum庫關於nginx的rpm包:yum list | grep nginx 找到rpm安裝包,我們就可以使用yum直接安裝了:yum install nginx 修改nginx配置文件:vi /etc/nginx/nginx.conf 註釋掉下麵的配置: 創建一個netcore.con ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...