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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...