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. 【Stream—7】NetworkStream相关知识分享

    一.NetworkStream的作用 和先前的流有所不同,NetworkStream的特殊性可以在它的命名空间中得以了解(System.Net.Sockets),聪明的你马上就会反应过来:既然是在网络 ...

  2. 新闻实时分析系统Hive与HBase集成进行数据分析

    (一)Hive 概述 (二)Hive在Hadoop生态圈中的位置 (三)Hive 架构设计 (四)Hive 的优点及应用场景 (五)Hive 的下载和安装部署 1.Hive 下载 Apache版本的H ...

  3. day 36 html的补充

    参考博客:https://www.cnblogs.com/majj/p/9062540.html 内容回顾: 0.浏览器 1.标签 - 行内标签 a span i em strong b.label ...

  4. 迈进java初中级程序员分水岭是否合格?十个题告诉你!

    前言 不论你是职场新人还是步入职场N年的职场新人大哥大~当然这个N<3~,我能担保你答不对这十个题~不要问我为什么这么自信~,这些个题还是"有水平"的javase的基础题,传 ...

  5. FileReader.result

    FileReader.result 该属性返回文件的内容.此属性仅在读取操作完成后才有效,并且数据的格式取决于用于启动读取操作的方法.FileReader]**result** 句法 var file ...

  6. hadoop环境的安装 和 spark环境的安装

    hadoop环境的安装1.前提:安装了java spark环境的安装1.前提:安装了java,python2.直接pip install pyspark就可以安装完成.(pip是python的软件安装 ...

  7. 一文看尽Java-并发编程知识点

    一.前言     从7月份开始一直加班比较多,一直到双11结束,博客没跟上写,接下来写一点总结性的东西,比如Java并发编程总结.Mybatis源码总结.Spring源码和基础知识总结,首先来看下并发 ...

  8. 一句话总结flux,以及我们为何需要flux

    如果让你用一句话总结一下什么是flux,该怎么说? 官网上有这样的介绍:flux是一种思想,一种框架,是facebook给react... 这样的解释对程序员来说,显得过于抽象又不具体了. 阮老师的文 ...

  9. sync.Map(在并发环境中使用的map)

    sync.Map 有以下特性: 需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是 ...

  10. 即将到来的“分布式云”(DPaaS):分布式计算+ DB +存储即服务

    我在区块链会议上就即将到来的公共"分布式云"系统进行了讨论,该系统将主流的公共云平台(如AWS,Azure,Google Cloud,Heroku等)与区块链和P2P网络相结合,比 ...