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

WPF之图片处理系列的更多相关文章

  1. WPF之图片处理系列(19/590)

    https://www.cnblogs.com/Big-Head/p/12068230.html

  2. WPF Step By Step 系列 - 开篇 ·

    WPF Step By Step 系列 - 开篇 公司最近要去我去整理出一个完整的WPF培训的教程,我刚好将自己学习WPF的过程和经验总结整理成笔记的方式来讲述,这里就不按照书上面的东西来说了,书本上 ...

  3. C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试(续)

    介绍 本文是接着上文<C# WPF 显示图片和视频显示 EmuguCv.AForge.Net测试>写的,建议先看下上文,因为有些代码还需要了解. 增添 接着上文的代码,我们可以在事件处理方 ...

  4. WPF Step By Step 系列-Prism框架在项目中使用

    WPF Step By Step 系列-Prism框架在项目中使用 回顾 上一篇,我们介绍了关于控件模板的用法,本节我们将继续说明WPF更加实用的内容,在大型的项目中如何使用Prism框架,并给予Pr ...

  5. WPF从我炫系列4---装饰控件的用法

    这一节的讲解中,我将为大家介绍WPF装饰控件的用法,主要为大家讲解一下几个控件的用法. ScrollViewer滚动条控件 Border边框控件 ViewBox自由缩放控件 1. ScrollView ...

  6. WPF显示图片

    1.WPF显示图片内部一部分 <Rectangle Height="> <Rectangle.Fill > <ImageBrush ImageSource=&q ...

  7. Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决

    关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能 ...

  8. WPF 修改图片颜色

    原文:WPF 修改图片颜色 本文告诉大家如何修改图片的颜色,如去掉图片的蓝色 在 WPF 可以使用很多图片处理的方法,本文告诉大家的是一个图片处理,可以把处理的图片保存在文件. 在阅读本文,我假设大家 ...

  9. 使用WPF将图片转变为灰度并加上水印并保存为文件

    原文:使用WPF将图片转变为灰度并加上水印并保存为文件 运行效果: (上图中左下角为原图的缩小显示,By:Johnson为TextBlock)保存的结果图片:上图的"Test Words.& ...

随机推荐

  1. CCF-画字符-详细的注释

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  2. 业务领域建模Domain Modeling

    我的工程实践选题为ESP32低功耗的实现,本项目基于ESP32嵌入式开发平台.下文将以需求为基础,对该项目进行领域建模. 一.概念介绍 1.业务建模 1.1 概念介绍 业务建模(Business Mo ...

  3. Centos7下oracle12c的安装与配置(详细)

    一.硬件配置 CentOS7@VMware® Workstation 15 Pro,分配资源:CPU:2颗,内存:4GB,硬盘空间:30GB 二.软件准备  linux.x64_11gR2_datab ...

  4. 🙈羞,Spring Bean 初始化/销毁竟然有这么多姿势

    文章来源:http://1t.click/bfHN 一.前言 日常开发过程有时需要在应用启动之后加载某些资源,或者在应用关闭之前释放资源.Spring 框架提供相关功能,围绕 Spring Bean ...

  5. JavaWeb02-Servlet

    Servlet概述 生命周期方法: l  void init(ServletConfig):出生之后(1次): l  void service(ServletRequest request, Serv ...

  6. C语言之路

    C 简介 C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的.C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现. 在 1978 ...

  7. vue computed计算属性 watch监听

    计算属性 computed:{ 变量:function(){ return 计算好的值 } } 这时候计算好的值 就付给了你的变量 在实例中可以this.使用 注意 声明的变量的data中不可以重复声 ...

  8. 开始你的api:NetApiStarter

    在此之前,写过一篇 给新手的WebAPI实践 ,获得了很多新人的认可,那时还是基于.net mvc,文档生成还是自己闹洞大开写出来的,经过这两年的时间,netcore的发展已经势不可挡,自己也在不断的 ...

  9. Socket 实现简单的多线程服务器程序

    **********服务器端************* public class ServerSocket{ public static void main(String[] args) throws ...

  10. Linux权限基础

    Linux权限基础 四种权限大类 基本权限 特殊权限 隐藏权限 file ACL权限 三种基本权限 r(read) 读是基本权限,没有读权限其他的一切操作都会被限制 读 4 w(write) 写 2 ...