前几天写程序需要将DIB(设备无关位图)格式的图片在WPF 程序中显示出来,在网上查了一些资料和代码,记录下来以便以后参考。

设备有关位图主要是显卡在显存中保存的图片格式,显卡就是从显存里面将要显示的图片数据直接打印到显示器上,这样不仅节省了系统内存的空间,还大大节省了从内存把图片数据搬到显存的时间—因为显卡芯片可以实现一些指令,直接操作显存中的图片。所以设备有关位图的格式不是固定的,是由显卡制造商自由决定的,这也就意味着我们没有办法直接操作DDB格式图片的每一个像素。

如果保存在硬盘的图片格式是以DDB格式保存的话,那就意味着你使用一个显卡保存的图片不能在使用不同型号的显卡的机器上打开—因为不同显卡制造商使用的DDB的格式不一样。为了解决这个问题,在很久以前,微软的GDI系统就提供了DIB(设备无关位图),相当于一种中间格式,在显示DIB图片的之前,GDI先将DIB位图转换成显卡能够理解的DDB格式—当然这一系列的操作都是由显卡的指令完成的。

在WPF和Winform的世界里,大家针对图片的编程相对来说都比较舒服,因为.NET Framework提供了简化的API帮你隐藏了这些细节,所有你需要做的就是:

WPF:

var image = new Image();

image.Source = new BitmapImage(new Uri("some image.jpg"));

Winform:

var image = System.Drawing.Image.FromFile("some image.jpg");

恩,看起来很美,但问题是,因为微软的函数库实在是太多了,强大如.NET这种类库也有考虑不周的时候,WPF并没有公开的API直接从DIB格式的图片中生成BitmapImage实例。为什么有的时候我们需要直接操作DIB格式的图片呢?例如你需要从剪贴板里面拿一个图片出来,而把图片放置到剪贴板的程序有可能并不是.NET程序,而是古老的OLE程序或者Win32程序,这些老古董经常喜欢在剪贴板里面放两个格式的图片,一个是DIB格式的,另外一个可能是支持IDataObject的接口—这个接口怎么实现又是仁者见仁,智者见智的事情。这个时候,你就发现你必须要处理DIB格式的图片;另外一种情况就是拖拉操作,因为拖拉操作中数据源和接受数据的程序有可能不是同一个程序,例如,你从一个OLE程序里面拖拉一个图片到WPF程序里。

根据MSDN,DIB图片的格式如下图所示:

下面的代码是我从网上搜到的关于如何从DIB格式生成BitmapImage实例的代码:

private System.Drawing.Bitmap CreateBitmapFromDib(Stream dib)

{

BinaryReader reader = new BinaryReader(dib);

int headerSize = reader.ReadInt32();

int pixelSize = (int)dib.Length - headerSize;

int fileSize = 14 + headerSize + pixelSize;

MemoryStream bmp = new MemoryStream(fileSize);

BinaryWriter writer = new BinaryWriter(bmp);

// 1. 把位图的一些元数据写进去,下面这几次Write相当于填写Win32的

// BITMAPFILEHEADER结构

writer.Write((byte)'B');

writer.Write((byte)'M');

writer.Write(fileSize);

writer.Write((int)0);

writer.Write(14 + headerSize);

// 2. 把DIB位图中的像素矩阵拷贝出来到我们指定的MemoryStream里。

// 因为我们要从MemoryStream里面生成System.Drawing.Bitmap对象

// 然后再颇为曲折地从Bitmap对象生成WPF的BitmapImage对象

dib.Position = 0;

byte[] data = new byte[(int)dib.Length];

dib.Read(data, 0, (int)dib.Length);

writer.Write(data, 0, (int)data.Length);

// 3. 生成Bitmap对象—这个是Winform里面的Bitmap对象

bmp.Position = 0;

return new System.Drawing.Bitmap(bmp);

}

上面那一段代码也相当于下面的C++代码,从MFC的实例代码里面找到的:

HDIB WINAPI ReadDIBFile(CFile& file)

{

BITMAPFILEHEADER bmfHeader;

UINT nBitsSize;

HDIB hDIB;

LPSTR pDIB;

/*

* get length of DIB in bytes for use when reading

*/

nBitsSize = (UINT)file.GetLength();

/*

* Go read the DIB file header and check if it's valid.

*/

if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))

return NULL;

if (bmfHeader.bfType != DIB_HEADER_MARKER)

return NULL;

/*

* Allocate memory for DIB

*/

hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)nBitsSize);

if (hDIB == 0)

{

return NULL;

}

pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

/*

* Go read the bits.

*/

if (file.Read(pDIB, nBitsSize - sizeof(BITMAPFILEHEADER)) !=

nBitsSize - sizeof(BITMAPFILEHEADER) )

{

::GlobalUnlock((HGLOBAL) hDIB);

::GlobalFree((HGLOBAL) hDIB);

return NULL;

}

::GlobalUnlock((HGLOBAL) hDIB);

return hDIB;

}

得到System.Drawing.Bitmap实例以后,就可以通过下面的函数来创建BitmapImage对象了:

private BitmapSource BitmapToImageSource(System.Drawing.Bitmap bitmap)

{

BitmapSource destination;

IntPtr hBitmap = bitmap.GetHbitmap();

BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromEmptyOptions();

destination = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, sizeOptions);

destination.Freeze();

return destination;

}

转载于:https://www.cnblogs.com/killmyday/archive/2010/02/19/1669346.html

在WPF里面显示DIB图片格式的图片相关推荐

  1. 论文排版——写毕业论文时图片格式问题,图片只显示一小部分,其他部分被上方文字覆盖

    写毕业论文时图片格式问题 写毕业论文时图片格式问题,图片只显示一小部分,其他部分被上放文字覆盖,如图所示: 这种情况出现的原因是论文内容部分一般要求的格式是宋体小四首行缩进行距固定值20磅,问题就在这 ...

  2. VB显示PNG等格式的图片

    VB利用GDI+技术显示PNG等格式图形又一方法,通过GDI+创建DC图形场景,然后将图形转入到StdPicture,再从StdPicture中将图形显示到Form窗口,为什么要将图形转入StdPic ...

  3. JPEG、GIF、PNG、BMP哪种图片格式的图片清晰一点

    BMP格式的图片是无损保存,质量最好. JPEG:是有损压缩 ,文件后辍名为".jpg"或".jpeg". GIF :是用于压缩具有单调颜色和清晰细节的图像(如 ...

  4. html文本文档加图片格式,以图片格式呈现的文档怎么编辑文字

    以图片格式呈现的文档怎么编辑文字 如今在工作当中,图形格式呈现的文档使用的还是比较多的,如果我们想要编辑以图片格式呈现的文档,那么应该怎么进行操作?以图片格式呈现的文档怎么编辑文字? 想要对图片格式呈 ...

  5. 如何选择正确的图片格式? 图片格式详细科普

    数字图片处理是指通过离线或在线资源(如编辑软件和网络应用程序)来处理图片.其转换过程旨在提高图片质量或从图片中提取更多信息.小编将详细介绍常见的图片格式以及如何进行图片格式转换方便查看,刚好对此有困惑 ...

  6. 电脑怎么改图片格式?图片转格式怎么转?

    ​如何实现图片格式在线转换?下面给大家推荐一款图片转格式工具,压缩图的改图片格式功能可以轻松转换图片格式,下面是具体的操作方法. 1.选择压缩图的转格式工具. 2.上传图片,选择所需要的格式类型. 3 ...

  7. 前端开发中常用的图片格式

    在我们的日常开发中.必不可少会使用很多种图片. 我们需要根据业务场景来选择所使用的图片类型. 这里我整理了一些常用图片类型.他们的优缺点以及建议的使用场景. 如何在计算机中显示一张图片 我们使用的计算 ...

  8. 前端开发中常用图片格式

    前端开发中常用图片格式 在我们的日常开发中.必不可少会使用很多种图片. 我们需要根据业务场景来选择所使用的图片类型. 这里我整理了一些常用图片类型.他们的优缺点以及建议的使用场景. 如何在计算机中显示 ...

  9. 【Android 安装包优化】WebP 图片格式兼容与性能 ( Android 中的 WebP 图片格式兼容问题 | Android 中的 WebP 图片格式性能 )

    文章目录 一.Android 中的 WebP 图片格式兼容问题 二.Android 中的 WebP 图片格式性能 三.参考资料 一.Android 中的 WebP 图片格式兼容问题 在 Android ...

最新文章

  1. redis的spring的xml配置
  2. 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 反射获取系统的 Element[] dexElements )
  3. BlogEngine.net 学习笔记(一)
  4. 数据结构:线性数据结构(2)-队列(栈,队列,deques, 列表)
  5. 25岁之后,你更应该逼自己系统性成长
  6. 每次请求刷新token的时间
  7. 无法读取内存属于错误吗_索佳全站仪错误信息讲解
  8. Android逆向系列之ARM语法篇
  9. 介绍几个图论和复杂网络的程序库 —— BGL,QuickGraph,igraph和NetworkX
  10. python连接微信运动_怎样读取微信运动数据接口?
  11. 【DOORS】产品功能介绍
  12. android 9图工具位子,Android自定义9宫格图片视图
  13. Matplotlib绘图笔记
  14. python查看字符串的编码格式_Python 3 查看字符编码方法
  15. 【Designing ML Systems】第 11 章 :机器学习的人性方面
  16. DSF框架使用(DAO、序列化、注解、服务接口、服务代理)
  17. 常用的个人电子邮箱有哪些?什么邮箱可以批量注册?哪个邮箱群发好用?
  18. 多个输入框失焦事件触发异常问题解决
  19. 新版神舟战神ZX9游戏本 评测
  20. matlab自带的sbs算法,SFS与SBS特征选择算法

热门文章

  1. 阿里云ECS利用密钥对ssh登录服务器
  2. Apache发布NetBeans 10.0,增强对JDK 11的支持
  3. 实用工具推荐:LICEcap(屏幕录制.gif)
  4. 浪潮科大讯飞Altera用OpenCL实现FPGA深度学习语音识别加速方案
  5. 酒店居然用大数据赚你钱?
  6. Android安全开发之WebView中的地雷
  7. NodeJs——(8)http.ServerRequest的过程
  8. -------------初识----------动态规划。--------------------------------------------
  9. Emacs-24.2 中很重要的几个函数--实现自定义语法高亮的关键
  10. struts config xml详细解释