SharpDX之Direct2D教程II——加载位图文件和保存位图文件

本系列文章目录:

SharpDX之Direct2D教程I——简单示例和Color(颜色)

 

绘制位图是绘制操作的不可缺少的一部分。在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)));
        }
    }
}

时间: 2024-09-16 17:43:41

SharpDX之Direct2D教程II——加载位图文件和保存位图文件的相关文章

[Android]异步加载图片,内存缓存,文件缓存,imageview显示图片时增加淡入淡出动画

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3574131.html  这个可以实现ImageView异步加载图片,内存缓存,文件缓存,imageview显示图片时增加淡入淡出动画. github地址:https://github.com/wangjiegulu/ImageLoaderSample 解决了: 1. listview加载oom问题 2. listview加载时卡顿的现象 3. listview

加载带有手势识别器的XIB文件需注意哪些问题_IOS

如果在你的应用程序中需要检测手势,比如点击(tap).二指拨动 (pinch).拖移(pan)和旋转(rotation),那么通过创建UIGestureRecognizer类来实现将十分简单. 接下来小编给大家分享加载带有手势识别器的XIB文件需主要的问题. 首先新建一个继承自UIView的类,并创建相应的XIB文件 #import <UIKit/UIKit.h> @interface ZHDemoView : UIView + (instancetype)demoView; @end 提供一

c#-如何加载一个已经加密的XML文件

问题描述 如何加载一个已经加密的XML文件 如何加载一个已经加密的XML文件,为什么使用了xmldoc.Load(filepath),却报"根级别上的数据无效,第1行,位置1" 解决方案 先解密然后读 假如你有一个类,在它的上面加上[Serializable]属性就可以了,表示这个类是可以序列化的 [Serializable] public class People { public string Name { get; set; } public int Age { get; set

antlr g文件-java中如何加载后缀为g的语法文件?

问题描述 java中如何加载后缀为g的语法文件? 我是在netbeans7.4下开发的,java版本为jdk1.7.0_51.在类文件中引用了两个类,分别是 JSHOP2Lexer和JSHOP2Parser,而这两个类是在一个JSHOP.g的文件中定义的,这个文件已经导入,但是属性显示不能识别,在我的类文件中也显示这两个类"找不到符号". 请问在netbeans中如何导入.g文件中定义的类呢? JSHOP.g文件是用基于antlr.jar写的语法文件,是JSHOP2项目的(http:/

javascript-使用require.js加载我自己写的js文件,当我修改了js后,怎么强制让浏览器更新 ?

问题描述 使用require.js加载我自己写的js文件,当我修改了js后,怎么强制让浏览器更新 ? 比如使用同步加载时可以在js后面加上?,比如 <script type="text/javascript" src="../../resources/js/libs/iscroll-probe.js?v=1.2"> 但使用require.js后,所有js都是通过main.js配置的: 如下: require.config({ shim: { 'backb

如何调试异步加载页面里包含的js文件_javascript技巧

最近在一个新的web项目中开发功能.这个项目的管理界面有一个特点,框架是固定的,不会刷新,每次点新的页面仅仅刷新一个div.div里面不是套的iframe,于是导致了一个问题,用浏览器无法调试异步加载页面里包含的js文件.简单的说就是在调试工具里面看不到异步加载页面里包含的js文件. 网上找到了一个解决办法,就是在需要调试的js文件顶部加一行代码: //@ sourceURL=msgprompt.js 注意,@符号和sourceURL间必须有空格.Chrome下效果: FireFox下也是OK的

SharpDX之Direct2D教程I——简单示例和Color(颜色)

研究Direct2D已经有一段时间了,也写了一个系列的文章 Direct2D ,是基于Windows API Code Pack 1.1.在前文 Direct2D教程VIII--几何(Geometry)对象的运算,本系列的终结篇 中介绍,由于Windows API Code Pack 1.1有错误问题,加上长时间没有更新(可以看出是2010年推出的),于是终止了该系列的教程.   在网上寻寻觅觅Windows API Code Pack 1.1的替代品.找到了SharpDX.SharpDX官网:

Excel动画教程:加载“宏”

先将加载宏文档保存到相应的文件夹中,然后在Excel加载使用. 执行"工具加载宏"命令,打开"加载宏"对话框,点击"浏览"按钮,打开"浏览"对话框,选中需要加载的宏,依次确定返回. 注意:①如果是系统自身的加载,直接在"加载宏"窗口中选择相应的宏,确定即可. ②如果你找不到加载宏文件夹,不能复制文件到其中,可以这样操作:将加载宏文件复制一下,然后在打开上述"浏览"窗口时,右击鼠标,在随后

Javascript教程动态加载事件的方法

 本篇文章主要是对js 动态加载事件的几种方法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 有些时候需要动态加载javascript事件的一些方法 往往我们需要在 JS 中动态添加事件,这就涉及到浏览器兼容性问题了,以下谈及的几种方法,我们也常常混合使用.   方法一.setAttribute var obj = document.getElementById("obj"); obj.setAttribute("onclick", "