在WPF里面显示DIB图片格式的图形

眼前几上写序需要将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图片的格式如下图所示:

图片 1

 

下面的代码是自个儿自网上搜到的关于怎样从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;

}