【题外话】

最近在做一个调用某实验仪器的程序,这个仪器提供了Windows上COM的接口。调用仪器的时候需要传输图片,提供的接口里使用了IPicture这个接口,由于以前没接触过,所以查找了一些资料,整理了一下与.NET中System.Drawing.Image的互转的方式。

【文章索引】

  1. IPicture和IPictureDisp是什么
  2. 使用AxHost实现与System.Drawing.Image的互转
  3. 使用VB6 compatibility library实现互转
  4. Alpha通道的问题

【一、IPicture和IPictureDisp是什么】

根据MSDN上对IPicture和IPictureDisp的说明来看,IPicture与IPictureDisp提供了与语言无关的接口,这个接口用来提供对位图(Bitmap)、图标(Icon)、图元文件(Metafile)的抽象,其中后者还实现了IDispatch接口以实现COM的自动化接口。总之,如果通过COM接口传输图像的话,可能会接触到这两个接口。

【二、使用AxHost实现与System.Drawing.Image的互转】

.NET在System.Windows.Forms下提供了一个叫AxHost的类来实现与ActiveX控件进行访问,不过这里用到的只是在AxHost里的protected的静态方法而已。由于是protected的方法,所以没有办法直接调用,好在AxHost不是密封的类,所以我们还可以通过集成AxHost来实现调用,例如以下的代码:

 using System.Drawing;
using System.Windows.Forms; public sealed class IPictureConverter : AxHost
{
private IPictureConverter() : base("") { } #region IPictureDisp
public static stdole.IPictureDisp ImageToIPictureDisp(Image image)
{
return (stdole.IPictureDisp)GetIPictureDispFromPicture(image);
} public static Image IPictureDispToImage(stdole.IPictureDisp pictureDisp)
{
return GetPictureFromIPictureDisp(pictureDisp);
}
#endregion #region IPicture
public static stdole.IPicture ImageToIPicture(Image image)
{
return (stdole.IPicture)GetIPictureFromPicture(image);
} public static Image IPictureToImage(stdole.IPicture picture)
{
return GetPictureFromIPicture(picture);
}
#endregion
}

【三、使用VB6 compatibility library实现互转】

除了AxHost,其实微软也提供了另外一个库提供托管的Image与IPicture等互转,那就是Microsoft.VisualBasic.Compatibility.dll,其中有一个叫Support的类提供了很多向后兼容的方法。对于IPicture或IPictureDisp的转换,我们可以写如下代码:

 using System.Drawing;
using Microsoft.VisualBasic.Compatibility.VB6; public static class IPictureConverter
{
#region IPictureDisp
public static stdole.IPictureDisp ImageToIPictureDisp(Image image)
{
return (stdole.IPictureDisp)Support.ImageToIPictureDisp(image);
} public static Image IPictureDispToImage(stdole.IPictureDisp pictureDisp)
{
return Support.IPictureDispToImage(pictureDisp);
}
#endregion #region IPicture
public static stdole.IPicture ImageToIPicture(Image image)
{
return (stdole.IPicture)Support.ImageToIPicture(image);
} public static Image IPictureToImage(stdole.IPicture picture)
{
return Support.IPictureToImage(picture);
}
#endregion
}

仔细看其实与上一段代码非常类似,本着好奇的态度,我们Relector一下这些方法实现的代码。

看起来两者几乎是一样的,不过有意思的是,虽然两者的很多方法如GetPICTDESCFromPicture等都不是同一个方法,甚至IPicture等接口都不是在一个库里定义的(AxHost是在System.Windows.Forms.UnsafeNativeMethods中定义的,而VB6 compatibility library则是在单独的一个stdole.dll中定义的),但是其调用的方法里执行的内容基本都相同,IPicture等接口也都是ComImport的同一个Guid,而两个方法实现的源头,更都是DllImport的oleaut32.dll,调用其中的“OleCreatePictureIndirect”方法,所以上述两种方法是完全一样的。

不过在4.0的CLR下,提供的Microsoft.VisualBasic.Compatibility.dll的版本为10.0.0.0,Support类以及相应的方法都被标记为过时的(Obsolete),所以编译的时候提示的警告也蛮让人恶心的(2.0的CLR下提供的8.0.0.0的dll没有这个问题),所以倒不妨采用第一种方法。

【四、Alpha通道的问题】

如果你的图片包含Alpha通道的话,上述转换可能会导致颜色有些问题,由于IPicture没有办法支持Alpha通道,所以妥协的办法只能是要么不用Alpha通道,要么在转换为IPicture前在图片底下垫上一个纯色的背景(比如对方程序中要显示图片的位置的背景),比如How to Convert a System.Drawing.Image to an IPictureDisp with Alpha Transparency这篇文章就是这么做的。

【相关链接】

  1. IPicture interface:http://msdn.microsoft.com/en-us/library/ms680761.aspx
  2. IPictureDisp interface:http://msdn.microsoft.com/en-us/library/ms680762.aspx
  3. Converting between IPictureDisp and System.Drawing.Image:http://blogs.msdn.com/b/andreww/archive/2007/07/30/converting-between-ipicturedisp-and-system-drawing-image.aspx

.NET中操作IPicture、IPictureDisp的小随笔的更多相关文章

  1. .NET中操作IPicture、IPictureDisp

    .NET中操作IPicture.IPictureDisp的小随笔   [题外话] 最近在做一个调用某实验仪器的程序,这个仪器提供了Windows上COM的接口.调用仪器的时候需要传输图片,提供的接口里 ...

  2. 在Firefox中操作iframe的一个小问题

    在做一个 Web 的打印功能时,需要将被打印的文档写到 iframe 的 document 中. <!doctype html> <html lang="en"& ...

  3. PHP中使用PDO操作事务的一些小测试

    关于事务的问题,我们就不多解释了,以后在学习 MySQL 的相关内容时再深入的了解.今天我们主要是对 PDO 中操作事务的一些小测试,或许能发现一些比较好玩的内容. 在 MyISAM 上使用事务会怎么 ...

  4. css小随笔(二)与通用样式

    51先在学校HTML5已经有半个多月了,然后这个星期做了一个京东的手机网站,接触到了通用样式,下面以京东的手机站为例 这两个就是京东手机站了的不同的两个板块,因为HTML5仅仅只是学完了基本标签跟cs ...

  5. VBA中操作XML

    OFFICE2007之后使用了OpenXml标准(伟大的改变),定制文本级的Ribbon可以通过修改压缩包内的xml文件来实现. 先学习一下VBA中操作XML的方法 先引用Microsoft XML ...

  6. SQL开发中容易忽视的一些小地方(一)

    原文:SQL开发中容易忽视的一些小地方(一) 写此系列文章缘由: 做开发三年来(B/S),发现基于web 架构的项目技术主要分两大方面: 第一:C#,它是程序的基础,也可是其它开发语言,没有开发语言也 ...

  7. SQL开发中容易忽视的一些小地方(六)

    原文:SQL开发中容易忽视的一些小地方(六) 本文主旨:条件列上的索引对数据库delete操作的影响. 事由:今天在博客园北京俱乐部MSN群中和网友讨论了关于索引对delete的影响问题,事后感觉非常 ...

  8. SQL开发中容易忽视的一些小地方( 三)

    原文:SQL开发中容易忽视的一些小地方( 三) 目的:这篇文章我想说说我在工作中关于in和union all 的用法. 索引定义 : 微软的SQL SERVER提供了两种索引:聚集索引(cluster ...

  9. 小随笔:利用Shader实现模型爆炸和沙粒化的效果

    0x00 前言 上一篇小随笔<小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果>中,我和大家聊了聊著名的斯坦福兔子和利用geometry shader实现的一些效果.这篇文章继续沿用 ...

随机推荐

  1. POJ 2991–Crane【线段树+几何】

    题意: 把手臂都各自看成一个向量,则机械手的位置正好是手臂向量之和.旋转某个关节,其实就是把关节到机械手之间的手臂向量统统旋转. 由于手臂很多,要每个向量做相同的旋转操作很费时间.这时就可以想到用线段 ...

  2. retrofit2的get和post

    get: 例: @GET("room/question_focus") Call<BaseResponseEntity> followQuestion(@Query(& ...

  3. echarts之tooltip-showContent

    当trigger:为'axis'时 tooltip : { trigger: 'axis', showContent:false } 当trigger:为'item'时 tooltip : { tri ...

  4. PDA固定资产条码管理系统软件-解决固定资产实物清查的瓶颈问题,大大提高清查效率

    固定资产管理系统是企业信息化管理中的一个重要组成部分,固定资产具有价值高,使用周期长.使用地点分散.管理难度大等特点.一个企业的良性发展,避免不了的要涉及到企业资产的有效管理.对于那些技术装备密集型的 ...

  5. 尽量用goto代替尾递归

    void PrintList(List L) { if(L!=Null) { PrintElement(L->Element); PrintLisr(L->Next); } } 所谓尾递归 ...

  6. 揭开Java IO流中的flush()的神秘面纱

    大家在使用Java IO流中OutputStream.PrintWriter --时,会经常用到它的flush()方法. 与在网络硬件中缓存一样,流还可以在软件中得到缓存,即直接在Java代码中缓存. ...

  7. 如何在Web引用中使用项目自定义的类

    这个是老架构了,不推荐现在这么用,维护一个老项目记录一下. 项目中WebService和客户端是在一个解决方案下,实体类是一个公用的Project,如果使用Web引用自动生成的类会缺少一些实体类定义的 ...

  8. Leetcode Palindrome Linked List

    Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) time ...

  9. HUAS_ACM 个人训练#4

    A 题目连接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=117542#problem/A 题意:给出n个单词(字符串),选出最长的字符 ...

  10. java基础2_运算符,选择语句

    算数运算符  +    相加  字符串的连接  正数 -    相减  负数 *    相乘 /    相除    10 / 3 ==> 3  两个操作数中精度最高的是int 结果也是int % ...