博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SharpDX之Direct2D教程II——加载位图文件和保存位图文件
阅读量:6970 次
发布时间:2019-06-27

本文共 7150 字,大约阅读时间需要 23 分钟。

本系列文章目录:

 

绘制位图是绘制操作的不可缺少的一部分。在Direct2D中绘制位图,必须先利用WIC组件将位图加载到内存中,再绘制到RenderTarget中去

 

在SharpDX中绘制位图,分成两个部分:

利用WIC在SharpDX中加载位图,生成Bitmap对象

利用RenderTarget对象的DrawBitmap方法把Bitmap对象绘制到RenderTarget中去

 

利用WIC在SharpDX中加载位图文件

 

利用WIC在SharpDX中绘制位图文件的核心内容就是把位图文件转换为Bitmap对象。它的操作过程如下:

1、创建WIC的ImagingFactory类。

2、根据位图文件创建BitmapDecoder对象(实际上调用系统解码器解析位图文件)。

      BitmapDecoder对象有1个属性和1个函数

      FrameCount属性:只读属性,说明该位图对象包含的帧数。一般gif文件能包含多个帧,其余格式的一般只有1个帧

      GetFrame函数:返回指定帧对象。参数index是整形,说明是第几帧(从0开始)。返回的是BitmapFrameDecode对象

3、利用BitmapDecoder对象的GetFrame函数,返回指定帧的BitmapFrameDecode对象。(参数index一般是0,返回第1帧)

 

一般情况下,到此就可以了。但是,位图格式有很多,你可能不是很确定你的位图格式是否兼容SharpDX的Bitmap对象。因此,比较好的做法是继续下面的步骤,将位图格式转换为兼容SharpDX的Bitmap对象

 

4、创建FormatConverter对象。该对象负责进行格式转换。

5、调用FormatConverter对象的Initialize方法,进行格式转换。

 

6、最后,利用Bitmap对象的FromWicBitmap函数将之前的FormatConverter对象转换为SharpDX的Bitmap对象

 

和Windows API Code Pack 1.1中的Direct2D略有不同的是,BitmapFrameDecode对象和FormatConverter对象都继承BitmapSource对象,省去了一个转换的过程

 

下面是代码

  
    
Protected 
Function LoadBitmap(Render 
As D2D.
RenderTarget, File 
As 
String, FrameIndex 
As 
Integer
As D2D.
Bitmap 
        
Dim Decoder 
As 
New WIC.
BitmapDecoder(_ImagingFactory, File, DX.IO.
NativeFileAccess.Read, WIC.
DecodeOptions.CacheOnLoad) 
        
If FrameIndex > Decoder.FrameCount - 1 
OrElse FrameIndex < 0 
Then FrameIndex = 0 
        
Dim Source 
As WIC.
BitmapFrameDecode = Decoder.GetFrame(FrameIndex) 
        
Dim Converter 
As 
New WIC.
FormatConverter(_ImagingFactory) 
        Converter.Initialize(Source, WIC.
PixelFormat.Format32bppPBGRA) 
        
Return D2D.
Bitmap.FromWicBitmap(Render, Converter) 
    
End 
Function 

利用RenderTarget对象的DrawBitmap方法把Bitmap对象绘制到RenderTarget中去

下面是DrawBitmap方法的原型定义:

  
Public 
Sub DrawBitmap(bitmap 
As D2D.
Bitmap, destinationRectangle 
As DX.
RectangleF, opacity 
As 
Single, interpolationMode 
As D2D.
BitmapInterpolationMode, sourceRectangle 
As DX.
RectangleF
Public 
Sub DrawBitmap(bitmap 
As D2D.
Bitmap, opacity 
As 
Single, interpolationMode 
As D2D.
BitmapInterpolationMode
Public 
Sub DrawBitmap(bitmap 
As D2D.
Bitmap, destinationRectangle 
As DX.
RectangleF, opacity 
As 
Single, interpolationMode 
As D2D.
BitmapInterpolationMode
Public 
Sub DrawBitmap(bitmap 
As D2D.
Bitmap, opacity 
As 
Single, interpolationMode 
As D2D.
BitmapInterpolationMode, sourceRectangle 
As DX.
RectangleF)

参数的意义如下:

bitmap:要绘制的Bitmap对象

destinationRectangle:绘制在RenderTarget对象上的目标范围。缺省是在RenderTarget对象的左上角,宽高是Bitmap对象的宽高

opacity:不透明度

interpolationMode:图像缩放时的插值算法,是个枚举

sourceRectangle:要绘制的源目标范围。缺省是Bitmap对象的整个范围

 

下面是示例代码

  
Public 
Class 
clsSharpDXLoadBitmap 
    
Inherits 
clsSharpDXSampleBase 
    
Protected _ImagingFactory 
As WIC.
ImagingFactory 
    
Public 
Shadows 
Sub CreateDeviceResource(Target 
As 
Control
        
MyBase.CreateDeviceResource(Target) 
        _ImagingFactory = 
New WIC.
ImagingFactory 
    
End 
Sub 
    
Public 
Function LoadBitmap(File 
As 
String
Optional FrameIndex 
As 
Integer = 0) 
As D2D.
Bitmap 
        
Return LoadBitmap(_RenderTarget, File, FrameIndex) 
    
End 
Function 
    
Protected 
Function LoadBitmap(Render 
As D2D.
RenderTarget, File 
As 
String, FrameIndex 
As 
Integer
As D2D.
Bitmap 
        
Dim Decoder 
As 
New WIC.
BitmapDecoder(_ImagingFactory, File, DX.IO.
NativeFileAccess.Read, WIC.
DecodeOptions.CacheOnLoad) 
        
If FrameIndex > Decoder.FrameCount - 1 
OrElse FrameIndex < 0 
Then FrameIndex = 0 
        
Dim Source 
As WIC.
BitmapFrameDecode = Decoder.GetFrame(FrameIndex) 
        
Dim Converter 
As 
New WIC.
FormatConverter(_ImagingFactory) 
        Converter.Initialize(Source, WIC.
PixelFormat.Format32bppPBGRA) 
        
Return D2D.
Bitmap.FromWicBitmap(Render, Converter) 
    
End 
Function 
    
Public 
Shadows 
Sub Render() 
        
With _RenderTarget 
            .BeginDraw() 
            .Clear(DX.Color.Honeydew.ToColor4) 
            
Dim B 
As D2D.
Bitmap = LoadBitmap(
"216.png"
            .DrawBitmap(B, 1, SharpDX.Direct2D1.
BitmapInterpolationMode.NearestNeighbor, 
New DX.
RectangleF(0, 0, 260, 260)) 
            .EndDraw() 
        
End 
With 
    
End 
Sub 
End 
Class 

利用WIC保存图片

WIC既能负责图片的解码,也能负责图片的编码。我们也可以利用WIC编码图片。

 

在调试的时候出了问题,先看看下面两段代码

  
Public 
Class 
Class1 
    
Public 
Shared 
Sub Test() 
        
Dim wicFactory 
As WIC.
ImagingFactory = 
New WIC.
ImagingFactory 
        
Dim F 
As 
String = 
"333.png" 
        
If (
File.Exists(F)) 
Then 
File.Delete(F) 
        
Dim spStream 
As WIC.
WICStream = 
New WIC.
WICStream(wicFactory, F, 
NativeFileAccess.Write) 
        
Dim spBitmapEncoder 
As WIC.
PngBitmapEncoder = 
New WIC.
PngBitmapEncoder(wicFactory) 
        spBitmapEncoder.Initialize(spStream) 
    
End 
Sub 
End 
Class

上面的代码是用VB2010写的,仅仅写到PngBitmapEncoder对象的Initialize方法。

再看看下面这段代码,用的是C# 2010写的

  
    
class 
Class1 
    { 
       
public 
static  
void test() 
        { 
            
ImagingFactory  wicFactory = 
new 
ImagingFactory(); 
            
string F = 
"333.png"
            
            
if (
File.Exists(F))  
File.Delete(F); 
            
WICStream  stream = 
new 
WICStream(wicFactory, F, 
NativeFileAccess.Write); 
            
PngBitmapEncoder  encoder = 
new 
PngBitmapEncoder(wicFactory); 
            encoder.Initialize(stream); 
        } 
    }

可以看出,两段代码没什么不同(仅仅是语法上的不同而已),但是VB2010的代码在执行到Initialize时总是报错(内部错误),而C#2010在执行到Initialize方法很顺利的完成了。两段代码引用的是同一个动态库SharpDX的2.5.0的库。

我解释不出是什么原因,只能归结于SharpDX自身的原因了。

 

不过,我发现一个问题,写在这儿,给大家一个参考,也许谁能给出解决方案。(或者是我的设置有问题?)

在VB2010中,PngBitmapEncoder类的初始方法只能看到两个,New(Object)和New(IntPtr)

在C#2010中,PngBitmapEncoder类的初始方法能看到六个,除了上面的两个,还多了很多

打开SharpDX.Direct2D1.xml中也看到PngBitmapEncoder对象的初始方法有六个

 

难道SharpDX真的不能很好的运用于VB2010中么?

 

 

最后贴一段SharpDX中自带示例中的WIC保存图片的代码

  
using System; 
using System.IO; 
using SharpDX; 
using SharpDX.Direct2D1; 
using SharpDX.DXGI; 
using SharpDX.IO; 
using SharpDX.WIC; 
using 
AlphaMode = SharpDX.Direct2D1.
AlphaMode
using 
Bitmap = SharpDX.WIC.
Bitmap
using 
PixelFormat = SharpDX.Direct2D1.
PixelFormat
namespace RenderToWicApp 
    
internal 
static 
class 
Program 
    { 
        
private 
static 
void Main() 
        { 
            
var wicFactory = 
new 
ImagingFactory(); 
            
var d2dFactory = 
new SharpDX.Direct2D1.
Factory(); 
            
string filename = 
"output.png"
            
const 
int width = 512; 
            
const 
int height = 512; 
            
var rectangleGeometry = 
new 
RoundedRectangleGeometry(d2dFactory, 
new 
RoundedRectangle() { RadiusX = 32, RadiusY = 32, Rect = 
new 
RectangleF(128, 128, width - 128 * 2, height-128 * 2) }); 
            
var wicBitmap = 
new 
Bitmap(wicFactory, width, height, SharpDX.WIC.
PixelFormat.Format32bppBGR, 
BitmapCreateCacheOption.CacheOnLoad); 
            
var renderTargetProperties = 
new 
RenderTargetProperties(
RenderTargetType.Default, 
new 
PixelFormat(
Format.Unknown, 
AlphaMode.Unknown), 0, 0, 
RenderTargetUsage.None, 
FeatureLevel.Level_DEFAULT); 
            
var d2dRenderTarget = 
new 
WicRenderTarget(d2dFactory, wicBitmap, renderTargetProperties); 
            
var solidColorBrush = 
new 
SolidColorBrush(d2dRenderTarget, 
Color.White); 
            d2dRenderTarget.BeginDraw(); 
            d2dRenderTarget.Clear(
Color.Black); 
            d2dRenderTarget.FillGeometry(rectangleGeometry, solidColorBrush, 
null); 
            d2dRenderTarget.EndDraw(); 
            
if (
File.Exists(filename)) 
                
File.Delete(filename); 
            
var stream = 
new 
WICStream(wicFactory, filename, 
NativeFileAccess.Write); 
            
var encoder = 
new 
PngBitmapEncoder(wicFactory); 
            encoder.Initialize(stream); 
           
var bitmapFrameEncode = 
new 
BitmapFrameEncode(encoder); 
            bitmapFrameEncode.Initialize(); 
            bitmapFrameEncode.SetSize(width, height); 
            
var pixelFormatGuid = SharpDX.WIC.
PixelFormat.FormatDontCare; 
            bitmapFrameEncode.SetPixelFormat(
ref pixelFormatGuid); 
            bitmapFrameEncode.WriteSource(wicBitmap); 
            bitmapFrameEncode.Commit(); 
            encoder.Commit(); 
            bitmapFrameEncode.Dispose(); 
            encoder.Dispose(); 
            stream.Dispose(); 
            System.Diagnostics.
Process.Start(
Path.GetFullPath(
Path.Combine(
Environment.CurrentDirectory,filename))); 
        } 
    } 
}
    本文转自万仓一黍博客园博客,原文链接:http://www.cnblogs.com/grenet/p/3330440.html,如需转载请自行联系原作者
你可能感兴趣的文章
浅谈企业信息泄密:信任不存,效益焉在?
查看>>
Mysql密码管理及授权
查看>>
JAVA线程安全之synchronized关键字的正确用法
查看>>
springmvc+mybatis+dubbo分布式平台-maven构建根项目
查看>>
一个小常识
查看>>
Nginx防盗链 Nginx访问控制 Nginx解析php相关配置 Nginx代理
查看>>
解决虚拟机中使用ntpdate报错:ntpdate[46700]: no server suitab
查看>>
Docker 快速删除所有容器
查看>>
【OCP认证12c题库】CUUG 071题库考试原题及答案(27)
查看>>
OSS支持IPV6/IPV4双栈访问域名
查看>>
阿里云应用实时监控 ARMS 再升级,支持 Prometheus 开源生态
查看>>
最全面的IGMP协议总结!
查看>>
你还在 Select * 吗?
查看>>
机器学习能革了数据库索引的命吗?
查看>>
把PDF转成PPT的免费工具
查看>>
多线程 NSCondition线程同步(消费者等待工厂制作完成,工厂发消息)
查看>>
python 冒泡排序加入判断
查看>>
WEB+NFS+DNS的搭建
查看>>
SQL Server2008导出数据生成文件
查看>>
Symfony2出现加载WEB调试工具栏错误
查看>>