精华内容
下载资源
问答
  • 位图

    千次阅读 2006-04-01 19:12:00
    如何创建位图(VC版)这篇文章介绍了一种创建位图的方法以及如何在位图中绘图并保存成为位图文件。位图本质上是视频图像的内存表示,它做为windows的一种资源可以用于很多场合,被几乎所有的绘图软件所支持。象图标、...

        如何创建位图(VC版)

    这篇文章介绍了一种创建位图的方法以及如何在位图中绘图并保存成为位图文件。位图本质上是视频图像的内存表示,它做为windows的一种资源可以用于很多场合,被几乎所有的绘图软件所支持。象图标、墙纸、图形、图像都可以以位图的形式来存储。在这里我们讨论的位图是属于DIB(device-independent-bitmap)文件格式,我们称之为与设备环境(在这里可以称为显示设备)无关的位图。位图文件可以分为三部分来组成(有些人把它分为四部分):
    一、    文件头(BITMAPFILEHEADER):
    我们看文件头的数据结构:
    typedef struct tagBITMAPFILEHEADER {
    WORD    bfType;// 用来指定文件类型,其值必须为BM即:0x424d。
    DWORD   bfSize;//以字节为单位指定位图文件的大小。
    WORD    bfReserved1;//保留,但其值必须为0。
    WORD    bfReserved2; //保留,但其值必须为0。
    DWORD   bfOffBits;///以字节为单位的从文件头到位图数据的偏移量
    } BITMAPFILEHEADER;
    二、    位图信息(BITMAPINFO):
    我们看位图信息的数据结构:
          typedef struct tagBITMAPINFO {
            BITMAPINFOHEADER bmiHeader;/*信息头结构,包含位图的尺寸和颜色格式。对于不同系统版本,我们有不同的信息头结构版本:BITMAPINFOHEADER用于NT3.51及老的版本, BITMAPV4HEADER用于NT4.0和WIN95版本,BITMAPV5HEADER用于NT5.0和WIN98版本。*/
            RGBQUAD    bmiColors[1];///调色板结构,用来存放颜色的。常以数组(也常常称///为调色表)形式出现。
    } BITMAPINFO
          
    我们看信息头结构BITMAPINFOHEADER:
         typedef struct tagBITMAPINFOHEADER{
                DWORD  biSize; ///此结构所需要的字节数。
                LONG   biWidth; ///以像素为单位的位图的宽度。
                LONG   biHeight; ///以像素为单位的位图的高度。见详细说明一。
                WORD   biPlanes; ///指定目标设备的平面数,目前这个值必须设置为1。
                WORD   biBitCount ///指定每个像素点所需要的位的个数。见详细说明二。
                DWORD  biCompression; ///指定压缩的类型。见详细说明三。
                DWORD  biSizeImage; ///以字节位单位的图像大小。见详细说明四。
                LONG   biXPelsPerMeter;///以像素/米为单位来说明水平分辨率。
                LONG   biYPelsPerMeter; ///以像素/米为单位来说明垂直分辨率。
                DWORD  biClrUsed; ///规定了位图中使用调色表索引的数目。一般此值为0,///表示可使用所有的颜色索引。
                DWORD  biClrImportant; ///指定调色表的一个索引,这个索引所代表的颜色///将做为显示位图需要的很重要的颜色。如果0代表所///有索引。
    } BITMAPINFOHEADER;
    详细说明一:
        如果这个高度值是正数(>0),这个位图的原点坐标位于左下角(意味着位图的方向是倒的),如果是负数,这个位图的原点坐标位于左上角(意味着位图的方向是正的)。
    详细说明二:
        这个值指定了在位图中一个像素点用多少个位(bit)来表示。位数必须是下面值的一种:
    1、    0。意味着jpeg格式。只能够在win98,NT5.0或更高的版本上使用。
    2、    1。每个像素点需要一个位。两种颜色,缺省的是黑色和白色。在这种情况下,位图数据中的每一个位表示一个像素。如果这个位是0,那么这个像素就用调色板表的第一个索引所对应的颜色值来表示;如果这个位是1,那么这个像素就用调色表中的第二个索引所对应的颜色值来表示。
    3、    4。每个像素点需要四个位。最多有十六种颜色。每一个像素可以用在调色表中从0到15的索引所对应的颜色值来表示。举例来讲,在位图数据种的第一个字节如果是0x1F,那么这两个像素的第一个像素所包含的颜色在调色表中由索引值为1的索引所代表的颜色组成;而第二个像素所包含的颜色在调色表中由索引值为15的索引所代表的颜色组成。
              4、8。每个像素点需要八个位。最多有256种颜色。每一个像素可以用在调色表中从0到255的索引所对应的颜色值来表示。因为8个位即为一个字节,所以每个像素点由单个字节组成。举例而言,在位图数据中如果有某一个数据为OxFF,那么这个像素点所包含的颜色在调色表中由索引值为255的索引所代表的颜色组成。
              8、16。用两个字节(16bit)来表示一个像素点。最多有65536(2^16)种颜色。如果biCompression的值是BI_RGB,那么BITMAPINFO 的bmiColors成员须为NULL值。红、绿、蓝三基色都用5个位(bit)来表示,这三基色的位的顺序为:0(不用)00000(红)00000(绿)00000(蓝),即由小到大分别为蓝、绿、红。
              9、24。用24个位来表示一个像素点。 最多有16777216(2^24)种颜色。BITMAPINFO 的bmiColors成员必须为NULL值。在位图数据中,每三个字节一组用来表示一个像素点。
              10、32。用32个位表示一个像素点。最多有4294967296(2^32)种颜色。如果biCompression的值是BI_RGB,那么BITMAPINFO 的bmiColors成员须为NULL值。
    详细说明三:
         压缩仅仅对于倒向(左下角坐标的位图)的位图有效。可以有下面的选择:
    1、    BI_RGB:不压缩的格式。
    2、    BI_RLE8:8位每像素点的RLE格式。
    3、    BI_RLE4:4位每像素点的RLE格式。
    4、    BI_BITFIELDS:位图不压缩,对于16位和32位位图有效。
    5、    BI_JPEG:对于win98、NT5.0或较高的版本有效。指示这个图像是一个JPEG的文件格式。
       详细说明四:
              如果是BI_RGB格式,其值可以设为零。如果biCompressionshi是JBI_JPEG,则:其值指的是jpeg图像缓冲的大小。
    我们看调色板结构RGBQUAD:

    typedef struct tagRGBQUAD {
          BYTE    rgbBlue; ///指定蓝色的深度
          BYTE    rgbGreen; ///指定绿色的深度
          BYTE    rgbRed; ///指定红色的深度
          BYTE    rgbReserved; ///保留,暂时不用
    } RGBQUAD;

    第三部分(DATA CONTENT):
         这部分存放位图的图像数据。
    仅仅创建一个位图,大部分情况不是我们编程的目的,在位图中绘出我们所需要的东西,才是我们真正需要的。WINDOWS提供了专门的绘图对象如画刷(填充颜色)、画笔(画点、线)及其它的GDI对象如:字体、矩形等等。有了这些对象我们就可以在位图中画出自己想要的图,并保存为位图文件。生成一个位图文件,大体上可以分为以下几个步骤:
    一、    根据自己的需要初始化位图信息结构BITMAPINFO,同时建立设备环境(显示设备环境)和与此设备环境逻辑兼容的内存设备环境。内存设备环境对我们很重要,在本文中几乎所有的绘图操作都是针对它而言的。还好windows提供了CreateCompatibleDC这个函数,用它可以建立内存设备环境对象。
    二、    建立自己的位图对象或位图句柄(可以利用CreateDIBSection函数),并将其选进(或者说关联到)内存设备环境上,以后我们就可以通过内存设备环境来对位图操作了。
    三、    建立自己需要的绘图工具,如画刷、画笔并选择它们的颜色。以及其它所需要的GDI对象如字体、矩形等等。
    四、    通过内存设备环境选择自己将要用的绘图工具,要选择绘图工具(对象)SelectObject这个函数(或者说成员)是我们最佳的选择。
    五、    利用绘图工具开始绘图,如画线,画点、画矩形、画圆等等,以及填充某些区域。在这个过程中我们可以根据需要更换自己不同颜色的画笔和画刷。这好像一个画家当他画太阳时用红色的画笔,然后用红色的画刷去填充,画蓝天时就用蓝色的画笔,然后用蓝色的画刷去填充。
    六、    当所有的绘图操作完成以后,开始对位图进行保存,因此我们要建立和初始化位图文件头结构BITMAPFILEHEADER,为建立一个位图文件做准备。当然需要保存的文件格式必须严格按照位图(bmp)的文件格式,即:文件头、位图信息和图像数据。对于图像数据我们可以通过位图数据的入口指针(由函数CreateDIBSection的第四个参数*ppvBits
    确定)来获得。

    下面给出一个完整的实例函数(仅供参考),在VC5.0上编译通过,其目的用来绘出某一股票的指数K线图(在内存设备环境上),并将其保存为位图文件(可以在本人个人信息中看到生成的图片)。
    void CImage::MakeIndex(TIndex *pIndex,TDate &pDate,const TCHAR *pchTitle,int iDays,int iRectWidth)
    {
        //* Create a file about bmp and Create BITMAPINFOHEADER First.
        LPBITMAPINFO lpbmih = new BITMAPINFO;
        lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        lpbmih->bmiHeader.biWidth = m_iWidth;
        lpbmih->bmiHeader.biHeight = m_iHeight;
        lpbmih->bmiHeader.biPlanes = 1;
        lpbmih->bmiHeader.biBitCount = g_iPixel;
        lpbmih->bmiHeader.biCompression = BI_RGB;
        lpbmih->bmiHeader.biSizeImage = 0;
        lpbmih->bmiHeader.biXPelsPerMeter = 0;
        lpbmih->bmiHeader.biYPelsPerMeter = 0;
        lpbmih->bmiHeader.biClrUsed = 0;
        lpbmih->bmiHeader.biClrImportant = 0;

        //* Create Data for bmp
        HDC hdc,hdcMem;
        HBITMAP hBitMap = NULL;
        CBitmap *pBitMap = NULL;
        CDC *pMemDC = NULL;
        BYTE *pBits;
        CBrush brWhite,brBlack;

        hdc = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
        hdcMem = CreateCompatibleDC(hdc);
        hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_PAL_COLORS,(void **)&pBits,NULL,0);
        pBitMap = new CBitmap;
        pBitMap->Attach(hBitMap);
        pMemDC = new CDC;
        pMemDC->Attach(hdcMem);
        pMemDC->SelectObject(pBitMap);
        brWhite.CreateSolidBrush(RGB(255,255,255));
        brBlack.CreateSolidBrush(RGB(0,0,0));

        //* Clear First and draw coordinate with gray.
        pMemDC->FillRect(CRect(0,0,m_iWidth,m_iHeight),&brWhite);
        int iGray = RGB(192,192,192),iDrakGray = RGB(128,128,128),iDateHeight = 11;    //* Color Gray and eg.2002-3-8's and 2-11M's and MinIndex's and MaxIndex's Height.
        int iSpaceLine = 12;    //* The space with two lines of bottom.
        int iTitleHeight;        //* eg.上海A股's Height.
        TEXTMETRIC ptm;

        CRect rect;
        CPen newPenDot(PS_DASH,1,iDrakGray);
        CPen penDrakGray(PS_SOLID,1,iDrakGray);
        CPen penGray(PS_SOLID,1,iGray);
        GetTextMetrics(hdcMem,&ptm);
        iTitleHeight = ptm.tmHeight;
        
    pMemDC->SelectObject(&penDrakGray);
        //* Draw K line for Index.
        int iOffsetClose = -1;
        for(int i=0; i<iDays; i++)
        {
            if(pIndex[i].fOpen <= pIndex[i].fClose)    //* 阳线
            {
                //* Up-shadow line.
                pMemDC->MoveTo(pIndex[i].iDay,pIndex[i].fClose);    //* iRectWidth equate 2
                pMemDC->LineTo(pIndex[i].iDay,pIndex[i].fHigh);
                
                //* Entity of white
                pMemDC->Rectangle(pIndex[i].iDay - iRectWidth,pIndex[i].fOpen,pIndex[i].iDay + iRectWidth,pIndex[i].fClose);
                
                //* Bottom-shadow line.
                pMemDC->MoveTo(pIndex[i].iDay,pIndex[i].fOpen);
                pMemDC->LineTo(pIndex[i].iDay,pIndex[i].fLow);
                //* Draw Volume.
                pMemDC->SelectObject(&penDrakGray);
                pMemDC->Rectangle(pIndex[i].iDay - iRectWidth,m_iHeight - iDateHeight,pIndex[i].iDay + iRectWidth,pIndex[i].iVolume);
                pMemDC->SelectStockObject(BLACK_PEN);
            }
            else    //* 阴线
            {
                //* Up-shadow line.
                pMemDC->MoveTo(pIndex[i].iDay,pIndex[i].fOpen);
                pMemDC->LineTo(pIndex[i].iDay,pIndex[i].fHigh);
                
                //* Entity of black.
                rect.SetRect(pIndex[i].iDay - iRectWidth,pIndex[i].fClose,pIndex[i].iDay + iRectWidth,pIndex[i].fOpen);
                pMemDC->FillRect(rect,&brBlack);
            //* Draw Vloume.
                rect.SetRect(pIndex[i].iDay - iRectWidth,m_iHeight - iDateHeight,pIndex[i].iDay + iRectWidth,pIndex[i].iVolume);
                pMemDC->FillRect(rect,&brBlack);
            }
        }
        //* Save to File.And Create BITMAPFILEHEADER.
        BITMAPFILEHEADER bmfh;
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
        *((char *)&bmfh.bfType) = 'B';
        *(((char *)&bmfh.bfType) + 1) = 'M';
        bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
        bmfh.bfSize = bmfh.bfOffBits + (m_iWidth * m_iHeight) * g_iPixel / 8;

        TCHAR szBMPFileName[32];
        int iBMPBytes = m_iWidth * m_iHeight * g_iPixel / 8;
        strcpy(szBMPFileName,m_szFileName);
        CFile file;
        if(file.Open(szBMPFileName,CFile::modeWrite | CFile::modeCreate))
        {
            file.Write(&bmfh,sizeof(BITMAPFILEHEADER));
            file.Write(&(lpbmih->bmiHeader),sizeof(BITMAPINFOHEADER));
            file.Write(pBits,iBMPBytes);
            file.Close();
        }

        pMemDC->DeleteDC();
        delete pMemDC;
        delete pBitMap;
        delete lpbmih;
    }

     

    ————————————————————————

    有编程经验的程序员都知道:要使应用程序的界面美观不可避免的要使用大量位图。现在流行的可视化编程工具对位图的使用提供了很好的支持,被称为三大可视化开发工具的VB、VC、Delphi通过封装位图对象对位图使用提供了很好的支持:VB提供了两个功能很强的对象:PictureBox及Image,通过使用它们,装载、显示位图变得非常容易。Delphi中也提供了一个位图对象:TImage,它的功能与用法与VB中的Image类似。在VC中通过使用设备相关类CDC与GDI对象类CBitmap来完成位图的操作。

    然而在VC中使用CBitmap类必须将BMP位图装入资源中,然后通过类 CBitmap的成员函数使用它,在通过CDC类的成员函数操作它。这样做有两点缺陷:将位图装入资源导致可执行文件增大,不利于软件发行;只能使用资源中有限的位图,无法选取其它位图。而且BMP位图文件是以DIB(设备无关位图)方式保存,BMP位图装入资源后被转换为DDB(设备相关位图),类CBitmap就是对一系列DDB操作的API函数进行了封装,使用起来有一定的局限性,不如DIB可以独立于平台特性。

    要弥补使用资源位图的两点不足,就必须直接使用BMP位图文件。VC的示例中提供了一种方法读取并显示BMP位图文件,但使用起来相当的麻烦。首先使用API函数GlobalAlloc分配内存并创建HDIB位图句柄,所有操作只能直接读写内存,然后通过StrechDIBits及SetDIBsToDevice函数来显示于屏幕上,操作起来费时费力。

    因此笔者通过研究类CBitmap的封装与DIB结构,使用Win32中提供的新函数,建立了一个专用于操作BMP文件的类,而且完全仿照类CBitmap的实现:从类CGdiObject派生,新类的所有接口与类CBitmap 的部分接口完全相同。这样对于习惯使用CBitmap类接口用法的程序员来说两者的接口在使用上没有什么分别。

    首先我们先简单介绍一下DIB的结构。DIB位图既可以存在于内存,也可以以文件形式保存在磁盘上(BMP文件)。所有DIB都包含两部分信息:位图信息(BITMAPINFO),包括位图信息头和颜色表;位图数据。对于内存中DIB的只要有上述两部分就行,而对于DIB文件则还要加上位图文件头。
    其次,Win32中提供了一个新函数CreateDIBSection,通过它可以创建一个存储DIB位的内存区域,既可以执行相应的GDI操作,又可以直接通过指向DIB位区域的指针方位DIB位区域。这是一个非常有用的函数,通过它我们可以用DIB替代DDB。

    在了解了相应的知识后,我们可以自己由类CGdiObject派生一个操作BMP文件的类:CBitmapFile。

    在自己编写类时有两点值得注意:

    在BitmapFile.h文件中定义类CBitmapFile,首先必须声明类CBitmapFile是从类CGdiObject中公有派生。然后在类中首先使用宏DECLARE_DYNAMIC(CBitmapFile)表明新类的最高父类是类CObject,是符合MFC的类库规范。紧接着宏DECLARE_DYNAMIC的是声明静态函数FromHandle,这两个声明必须放在类定义的最前面。  
    在BitmapFile.cpp文件中类的成员函数的实现前加上IMPLEMENT_DYNAMIC(CBitmapFile,CGdiObject);表明类CBitmapFile直接派生于类CGdiObject。  
    在类CBitmapFile的声明中有三个函数与类Cbitmap中的定义稍有不同:

    在类CbitmapFile中LoadBitmap函数的参数是LPCTSTR型,保存的是BMP文件的文件名。  
    在类CbitmapFile中CreateBitmap函数的参数中少了参数nPlanes,在函数内部默认为1。  
    在类CbitmapFile中CreateBitmapIndirect函数的参数中多了参数lpBits,它指向指定位图DIB位的内存区域。  
    在成员函数中最重要的是函数CreateBitmapIndirect和函数LoadBitmap:

    在函数CreateBitmapIndirect中使用函数CreateDIBSection创建了一个以兼容DC为基础的HBITMAP句柄,并用继承自类CGdiObject 的函数Attach把它与类CGdiObject的句柄m_hObject关联起来。然后将指定位图的DIB位图数据拷贝到由函数CreateDIBSection创建的DIB位的内存区域。  
    在函数LoadBitmap中首先从指定文件名的文件中读取以结构BITMAPFILEHEADER为大小的数据块,然后由文件头标志判断文件是否为BMP位图文件,然后由BITMAPFILEHEADER中bfSize保存的文件大小与文件的真实大小比较文件是否有损坏,再由BITMAPFILEHEADER中bfOffBits与BITMAPFILEHEADER结构大小相减计算出位图信息头和颜色表一共的大小,动态申请一块空间保存位图信息头和颜色表信息,再由BITMAPFILEHEADER中bfSize与bfOffBits相减计算出DIB位图数据的大小,动态申请一块空间保存DIB位图数据,最后调用成员函数CreateBitmapIndirect来创建DIB位图。  
    在应用程序的OnPaint()事件中绘制DIB位图的方法与使用类CBitmap时绘制位图的方法完全相同,但有一点要注意的是由于CDC类没有提供返回新类CBitmapFile指针类型的将DIB位图选入内存的SelectObject函数,所以在使用SelectObject时要将返回类型强制转换为CbitmapFile *类型。

    至此,关于新类CBitmapFile编写中的一些要点和使用时一些要注意的问题就介绍这么多了。

    展开全文
  • 概述 这篇的标题更确切的说应该叫位图画刷,这样才好和前几篇对应起来。在Direct2D中,位图的渲染也是通过画刷来实现的。 Direct2D中并没有直接操作位图的接口,...从文件创建WIC位图 由WIC位图创建D2D位图 使...

     

    概述

    这篇的标题更确切的说应该叫位图画刷,这样才好和前几篇对应起来。在Direct2D中,位图的渲染也是通过画刷来实现的。

    Direct2D中并没有直接操作位图的接口,而是借助WIC(Windows Image Component)来完成的。今天我们来看看如何在Direct2D中加载并显示位图。这个方法可以用来渲染背景。基本步骤如下。

    • 从文件创建WIC位图
    • 由WIC位图创建D2D位图
    • 使用D2D绘制位图

    在开始之前,首先简要介绍一下WIC

    什么是WIC?

    WIC全称是Windows Image Component,是一套扩展的API,用来处理数字图像,它是基于COM组件的。该API包含非常丰富的图像处理函数,比如

    • 内置对于标准web image格式的解码支持
    • 内置对于标准metadata格式的支持
    • 广泛的像素格式支持
    • 高色度支持,包含30位扩展,30位及48位高精度像素格式
    • 对于图像解码,像素格式及元数据格式的扩展框架支持

    WIC包含的组件及每个组件中的接口如下图所示。

    在这里,我们只要知道WIC能够处理图像即可,比如位图操作。关于WIC的详细信息,大家可以看看MSDN的介绍。

    具体步骤

    从文件创建WIC位图

    给定一个图像文件,我们首先使用WIC函数将其读入内存,并创建一个WIC类型的位图。

    首先我们需要创建一个解码器,因为图片是经过编码的,为了能显示图片,我们首先需要将其解码,创建解码器需要使用函数CreateDecoderFromFilename,该函数返回一个解码器指针。稍后的操作都通过这个指针来完成,关于这个函数的详细介绍,可以参考MSDN,这里不再赘述。

    然后,利用创建好的解码器来获取图片的帧,我么这里只要第一帧,因为图片只有一帧,但是对于视频文件来说,就有许多帧了。代码如下:在这里,uri即图片文件名。

    复制代码
    HRESULT LoadBitmapFromFile(
                               ID2D1RenderTarget *pRenderTarget,
                               IWICImagingFactory *pIWICFactory,
                               PCWSTR uri,
                               UINT destinationWidth,
                               UINT destinationHeight,
                               ID2D1Bitmap **ppBitmap
                               )
    {
        HRESULT hr = S_OK;
    
        IWICBitmapDecoder *pDecoder = NULL;
        IWICBitmapFrameDecode *pSource = NULL;
        IWICStream *pStream = NULL;
        IWICFormatConverter *pConverter = NULL;
        IWICBitmapScaler *pScaler = NULL;
    
        hr = pIWICFactory->CreateDecoderFromFilename(
            uri,
            NULL,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
            );
        if (SUCCEEDED(hr))
        {
    
            // Create the initial frame.
            hr = pDecoder->GetFrame(0, &pSource);
        }
    复制代码

    然后创建converter,负责对位图进行后续的格式转换。

    if (SUCCEEDED(hr))
    {
        hr = pIWICFactory->CreateFormatConverter(&pConverter);
    }

    接下来则要判断图像是否被放大或者缩小了,比如一个图片的原始尺寸是100 x 100,但是我们程序中要以 200 x 200的方式去显示,那么相当于将图片放大了一倍,图片的显示尺寸通过参数来指定,而实际尺寸则是通过分析图片文件得到。如果图片有缩放,那么需要从新生成图片的数据文件,如果没有,那么直接进行下一步即可。代码如下:

    复制代码
    // If a new width or height was specified, create an
    // IWICBitmapScaler and use it to resize the image.
    if (destinationWidth != 0 || destinationHeight != 0)
    {
        UINT originalWidth, originalHeight;
        hr = pSource->GetSize(&originalWidth, &originalHeight);
        if (SUCCEEDED(hr))
        {
            if (destinationWidth == 0)
            {
                FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight);
                destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth));
            }
            else if (destinationHeight == 0)
            {
                FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth);
                destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight));
            }
    
            hr = pIWICFactory->CreateBitmapScaler(&pScaler);
            if (SUCCEEDED(hr))
            {
                hr = pScaler->Initialize(
                    pSource,
                    destinationWidth,
                    destinationHeight,
                    WICBitmapInterpolationModeCubic
                    );
            }
            if (SUCCEEDED(hr))
            {
                hr = pConverter->Initialize(
                    pScaler,
                    GUID_WICPixelFormat32bppPBGRA,
                    WICBitmapDitherTypeNone,
                    NULL,
                    0.f,
                    WICBitmapPaletteTypeMedianCut
                    );
            }
        }
    }
    复制代码

    由WIC位图创建D2D位图

    调用函数CreateBitmapFromWicBitmap可以由一个WIC位图创建一个D2D位图,代码如下:

    复制代码
    if (SUCCEEDED(hr))
    {
        // Create a Direct2D bitmap from the WIC bitmap.
        hr = pRenderTarget->CreateBitmapFromWicBitmap(
            pConverter,
            NULL,
            ppBitmap
            );
    }
    复制代码

    上面这些代码有个特点,就是要时刻判断前一次函数调用的返回值,只有前面的操作成功了,才进行下一步操作。这是很好的编程习惯。

    最后,需要做一些清理工作,由于WIC是基于COM的,所以,需要手动释放COM对象,代码如下:

    SAFE_RELEASE(pDecoder);
    SAFE_RELEASE(pSource);
    SAFE_RELEASE(pStream);
    SAFE_RELEASE(pConverter);
    SAFE_RELEASE(pScaler);

    SAFE_RELEASE是一个宏定义

    #define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;}

    使用D2D绘制位图

    这一步就很简单了,绘制位图和绘制其他几何图形几乎没有区别。首先是将render target清空为指定颜色,也就是背景色,然后调用render target的接口DrawBitmap来绘制位图,这个函数需要指定位图的尺寸,所以之前还需要获取位图的大小。注意绘制代码要放在BeginDraw和EndDraw之间。

    复制代码
    void DrawBitmap()
    {
        CreateD2DResource(g_Hwnd) ;
    
        pRenderTarget->BeginDraw() ;
    
        // Clear background color to dark cyan
        pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
        D2D1_SIZE_F size = pBitmap->GetSize() ;
        D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f) ;
    
        // Draw bitmap
        pRenderTarget->DrawBitmap(
            pBitmap,
            D2D1::RectF(
            upperLeftCorner.x,
            upperLeftCorner.y,
            upperLeftCorner.x + size.width,
            upperLeftCorner.y + size.height)
            ) ;
    
        HRESULT hr = pRenderTarget->EndDraw() ;
        if (FAILED(hr))
        {
            MessageBox(NULL, "Draw failed!", "Error", 0) ;
    
            return ;
        }
    }
    复制代码

    最后,来一张效果图,这是微软的游戏 4 Elements 2 的截图,大家一同欣赏一下。这是我平生购买的第一款游戏,值得纪念一下。

    展开全文
  • 只需将任何图片放置在编辑器中,使用opendialog或拖放图片,选择区域并使用[>]按钮创建位图即可。 之后,生成bootres.dll文件,它将位于一个临时文件夹(位于AppData内部)中。 准备就绪后,应用它,它将要求您...
  • 本演练演示如何Windows 演示基础 (WPF) 自定义控件创建工具箱图标。...为控件的工具箱图标创建自定义位图文件。 在设计时测试控件的图标。 完成本演练后,您将了解如何为自定义控件创建工具箱图标。


    本演练演示如何为 Windows 演示基础 (WPF) 自定义控件创建工具箱图标。 将自定义控件添加到工具箱时,该图标将显示在控件的名称旁边。

    在本演练中,您将执行下列任务:

    • 创建一个 WPF 自定义控件库项目。

    • 为控件的工具箱图标创建自定义位图文件。

    • 在设计时测试控件的图标。

    完成本演练后,您将了解如何为自定义控件创建工具箱图标。

    Note Note

    显示的对话框和菜单命令可能会与“帮助”中的描述不同,具体取决于您现用的设置或版本。 若要更改设置,请在“工具”菜单上选择“导入和导出设置” 有关更多信息,请参见 Visual Studio 设置

    您需要以下组件来完成本演练:

    • Visual Studio 2010.

    若要为控件创建自定义工具箱图标,请将一个图像作为嵌入资源添加到控件的项目中。

    创建自定义工具箱图标

    1. 使用 Visual Basic 或 Visual C# 新建一个名为 CustomControlWithToolboxIcon 的 WPF 自定义控件库项目。

      CustomControl1 的代码在“代码编辑器”中打开。

    2. “项目”菜单中选择“添加新项”

      “添加新项”对话框打开。

    3. “添加新项”对话框中,选择“常规”类别。

    4. 在模板列表中,选择“位图文件”,将新文件命名为 CustomControl1.Icon.bmp,然后单击“添加”

      将打开图像编辑器。

    5. 在“属性”窗口中,将位图的“颜色”属性设置为 24 bit

    6. 使用图像编辑器工具在位图中绘制图像。 有关更多信息,请参见 图标的图像编辑器

    7. “解决方案资源管理器”中,选择 CustomControl1.Icon.bmp。

    8. 在“属性”窗口中,将“生成操作”属性设置为“嵌入的资源”

    9. 生成解决方案。

      有关更多信息,请参见 工具箱图标

    通过将 CustomControl1 添加到工具箱来测试您的自定义工具箱图标。

    测试工具箱图标

    1. 使用 Visual Basic 或 Visual C# 在解决方案中添加一个名为 TestApplication 的新 WPF 应用程序项目。

      MainWindow.xaml 将在 WPF Designer中打开。 在“工具箱”中,“CustomControl1”出现在“CustomControlWithToolboxIcon Controls”选项卡中。

      带自定义控件的工具箱
    2. 在“工具箱”中,右击“CustomControl1”并选择“删除”

    3. 在出现的消息框中,单击“确定”

      “CustomControl1”将从“工具箱”中移除。

    4. 在“工具箱”中,右击要向其中添加控件的控件组,然后从上下文菜单中选择“选择项”

      “选择工具箱项”对话框随即打开。

    5. “选择工具箱项”对话框中,单击“WPF 组件”选项卡。 有关更多信息,请参见选择工具箱项, WPF 元素

    6. 单击“浏览”,并导航到 CustomControlWithToolboxIcon 项目的 bin\Debug 文件夹。

    7. “打开”对话框中,选择 CustomControlWithToolboxIcon.dll,然后单击“打开”

      CustomControlWithToolboxIcon 程序集的详细信息显示在“选择工具箱项”对话框中。 您的自定义图标显示在“CustomControl1”组框中。

    8. 单击“确定”

      “CustomControl1”连同其对应的图标显示在“工具箱”中。

      自定义工具箱图标
    展开全文
  • 下面就和大家具体谈谈如何在VB中建立和使用资源文件。  首先,我们先了解一下...一般来说,都是在图像编辑器中创建位图,然后再将该位图添加到资源文件中。  图标:图标是类似于位图的小图像,然而,虽然...
       下面就和大家具体谈谈如何在VB中建立和使用资源文件。

       首先,我们先了解一下windows应用程序中一般经常使用的资源:

       位图:位图是用于创建应用程序用户界面的图像。例如,用户可以工具栏按钮创建一套位图,也可以创建在其它窗口上显示的位图。一般来说,都是在图像编辑器中创建位图,然后再将该位图添加到资源文件中。

       图标:图标是类似于位图的小图像,然而,虽然位图可以具有任意大小的尺寸,但是图标却小得多,通常为16*16像素或32*32像素。图标使用的很多方法与位图一样。然而,图标通常被用作代表最小化应用程序的图象、代表应用程序文档类型的图像和其它类型的应用系统。

       字符串表:就是指文本串的一个表格,通常来说字符串用来显示菜单命令的提示、对话框中和消息框中显示的信息。要访问串表格中的文本串,需引用串的ID,它与定义表格的源文件中的串相联系。

       光标:光标是代表鼠标在屏幕上的位置的图像。尽管windows 系统定义和许多类型的光标,但用户也可以创建自己需要的光标。

       定制资源:定制资源是用户想存储在其应用程序资源文件中的任何类型的数据。这些数据可以是文本文件或二进制文件,用户可以用任何喜欢的方式定制资源。资源文件只是作为存储区域。创建了定制资源,可以避免必须从磁盘文件中加载数据,因为数据随资源文件一起加载。

       对话框:对话框的资源定义包括样式标志(控制对话框外观及行为的值)以及对话框中含控件的大小和位置。

       菜单栏:用户应用程序的菜单栏也可以在资源文件中定义。可以在资源文件中指定命令和命令的ID,以用命令在菜单中的位置。

       加速器:加速器也称为热键。它们是用户快速选取命令时所按下的键,使用热键时,不必在应用程序的菜单中寻找命令。加速器在一个表格中定义,这个表将按键与命令资源的ID联系起来。

       那么在VB开发环境中如何使用这些资源呢?

       1、添加资源文件编辑器,

       启动VB6.0的IDE集成环境,新建一个工种。点选菜单“Add -Ins”下的“Add -in Manager”,在弹出的对话框的列表框中选择“VB Resource (RES) Editor”,单击“OK“后退出对话框。这样在“Tools”菜单栏中就有一项“Resource Editor”了。打开这个工具就可以进行资源文件的编辑了。

       2、编辑资源文件

       在资源编辑器中编辑资源文件非常简单。它可是编辑我们在上面先提到的位图、图标、光标、字符串及定制资源五种类型的资源,如图1所示:

       在进行编辑时,点击相应的图标就可以添加资源了。

       编辑资源的方法也很容易,以添加图片为例看一看添加位图的方法:点击添加位图按钮,在弹出的对话框中选择一个位图文件,单击“OK”后,位图的添加就完成了,在这里要注意属性按钮,点击它以后,可以选择请语言版本并输入资源的ID号,这个ID号是标识一类资源的唯一编号,必须记住资源的ID号,以使在应用程序中调用。编辑好资源后,关闭资源编辑器,资文件自动加入新建的工种内。另外,也必须将资源文件保存。其它资源的编辑方法也大体上一样。

       3、使用资源文件,在应用程序中调用资源文件与直接使用资源基本上是一致的。对了,在一个工种中只能保存一个资源文件,在使用资源文件之前,请必须保证资源已经加入到资源文件中了。

       调用资源文件中资源的函数有:

       LoadResString 返回一个文本字符串。语法:LoadResString(index) index必需是一个整数,它用来指定资源文件中数据的标识符(即经常提到的ID号),如果ID号为1的资源保留给应用程序图标。

       LoadResPicture 用以从资源 (.res) 文件装载位图、图标或光标。它的语法:

       LoadResPicture(index, format)

       LoadResPicture 函数的语法包含下列部分:

       参数 描述

       index 一个整数或字符串,它用来指定资源文件中数据的标识

       符 (ID) 。ID标识符为 1 的资源保留给应用程序的图标。

       format 必需的。一个数值或常数,如下列“设值"中所描述的,

       指定返回数据的格式。

       用于 format 的设置值有:

       常数 值 描述

       vbResBitmap 位数 0 位图资源

       vbResIcon 图标 1 图标资源

       vbResCursor 2 光标资源

       说明:可以使用 LoadResPicture 函数代替对存储在 Form 或控件的 Picture 属性中的图形的引用。

       LoadResData 返回一个Byte数组,用以从资源 (.res) 文件装载若干可能类型的数据。语法为:

       LoadResData(index, format)

       LoadResData 函数的语法包含下列部分:

       部分 描述

       index 必需的。一个整数或字符串,它用来指定资源文件中数据的标识

       符 (ID)。ID 标识为 1 的资源保留给应用程序的图标。

       Format 必需的。一个数值,它用来按照下列“设置值"中的描述,指定返

       回数据的原始格式。该数值也可以是用户定义资源的字符串名。

       设置值 用于 format 的设置值有:

       设置值 描述

       1 光标资源

       2 位图资源

       3 图标资源

       4 菜单资源

       5 对话框

       6 字符串资源

       7 字体目录资源

       8 字体资源

       9 加速键表

       10 用户定义资源

       12 群组光标

       14 群组图标

       说明:LoadResData 从资源文件装载的数据可以达到 64K。

       最后我们用一个简单的例子来说明这几个函数的用法:

       (1)建立一个窗体,在窗体上放置三个按钮,一个图片框用来显示图片、图标。其属性如图2所示。

       按照前面讲述的方法添加资源文件编辑器并建立工程文件,里面包含一个字符串,位图、图标、光标和一个自定义的资源。

       程序代码如下所示:

       Private Sub cmdLoadData_Click()

       Dim tt As Byte

       End Sub

       Private Sub cmdLoadPicture_Click()

       picTest.Picture = LoadResPicture(101, 1)

       ''如何为0表示位图,为2表示光标

       End Sub

       Private Sub cmdLoadstring_Click()

       Dim str As String

       str = LoadResString(101)

       MsgBox str

       End Sub

    转载于:https://www.cnblogs.com/wyfandy/archive/2008/08/10/1264588.html

    展开全文
  • 使用imwrite将图像数据导出为位图文件,指定要创建的变量名和输出文件名。如果在文件名中包含扩展名,imwrite将尝试从中推断所需的文件格式。例如,文件扩展名.bmp指定微软Windows位图格式。您还可以显式地将格式...
  • 所附的例子添加一个定制的属性页,使用它你可以编辑文件对象的创建,修改和最后访问时间. -------------------------------------------------------------------------------- 第七节-如何编写自画上下文...
  • 所附的例子添加一个定制的属性页,使用它你可以编辑文件对象的创建,修改和最后访问时间. -------------------------------------------------------------------------------- 第七节-如何编写自画上下文...
  • 您将了解如何使用C#为Windows应用程序创建动态的用户界面和图形输出。本书使用了大量以C#编写的客户应用程序示例来展示常用技术,并且在最佳编程实践方面给出了大量的实际建议。有了这本书,您很快就会成为C#编程的...
  • 您将了解如何使用C#为Windows应用程序创建动态的用户界面和图形输出。本书使用了大量以C#编写的客户应用程序示例来展示常用技术,并且在最佳编程实践方面给出了大量的实际建议。有了这本书,您很快就会成为C#编程的...
  • Microsoft C# Windows程序设计(上下册)

    热门讨论 2011-08-05 10:28:13
    11.2 位图文件格式 11.3 加载和绘制 11.4 图像信息 11.5 绘制图像 11.6 匹配矩形 11.7 旋转和剪切 11.8 显示部分图像 11.9 在图像上绘制 11.10 关于image类的更多内容 11.11 bitmap类 11.12 ...
  • 第8章 Windows文件操作和内存映射文件 264 8.1 文件操作 264 8.1.1 创建和读写文件 264 8.1.2 获取文件信息 268 8.1.3 常用文件操作 270 8.1.4 检查PE文件有效性的例子 272 8.1.5 MFC的支持(CFile类) ...
  • 7.3 创建和使用位图(3) 7.3 创建和使用位图(4) 7.3 创建和使用位图(5) 7.4 块传送操作(1) 7.4 块传送操作(2) 7.5 区域和路径 第8章 通用对话框 8.1 通用对话框简介 8.1 通用对话框简介(2) 8.1 通用...
  • 示例描述:本章学习Windows进程的创建和管理方法。 01_StartProcess 创建和结束进程。 02_RedirectStdio 用匿名管道获取控制台程序的输出。 03_CatchError 拦截并处理外部进程的错误。 04_SingleInstance ...
  • Windows系统不像DOS系统,它的应用程序界面是规范化的,统一的界面来自大量的系统界面控件,学习这些控件就等于学习如何编写Windows界面,下面的界面篇中的两章将探讨这方面的内容: 7.1 GDI原理(1) 7.1 GDI原理(2)...
  • "icl"文件中分离出icon (4KB) 85,iniedit.ZIP 如何编辑ini文件以及任何包含文本的windows文件 (6KB) 86,helpfile.ZIP 在vb中调用help文件并实现winhelp的关键字、主题等功能 (5KB) 87,split.ZIP ...
  • Visual C++编程技巧精选500例.pdf

    热门讨论 2012-09-01 15:01:50
    038 如何在文件对话框中预览位图文件? 039 如何从文件对话框中获取文件扩展名? 040 如何从文件对话框中获取文件标题? 041 如何获取文件对话框选择的多个文件? 042 如何在程序启动时弹出文件打开对话框? 第4章 标题栏...
  • 如何创建和使用一个无模式对话框 为什么使用CRichEditCtrl控件的对话框不能显示出来 如何改变控件的字体 如何限制编辑框的准许字符 如何防止Edit框中的Password被非法获取 如何设置ClistCtr控件为可以整栏选择并且有...
  • m_texture[i].LoadBitmap(fileName[i]) ) /**载入位图文件 */ { MessageBox(NULL,"装载位图文件失败!","错误",MB_OK); /**如果载入失败则弹出对话框 */ exit(0); } glGenTextures(1, &m_texture[i].ID)...
  • 23.如何在“文件”对话框中预览位图文件 24.如何创建一个文件“保存”对话框 25.如何在程序启动时弹出“文件”对话框 26.如何从“文件夹”对话框中选择文件夹 27.如何在“文件夹”对话框中新建文件夹 28.如何使用...
  • 如何在“文件”对话框中预览位图文件  24.如何创建一个文件“保存”对话框  25.如何在程序启动时弹出“文件”对话框  26.如何从“文件夹”对话框中选择文件夹  27.如何在“文件夹”对话框中新建...
  • VC++ 编程技巧

    2010-02-16 14:24:48
    17、如何创建一个字回绕的CEditView 4 18、通用控件的显示窗口 4 19、移动窗口 4 20、重置窗口的大小 4 21、如何单击除了窗口标题栏以外的区域使窗口移动 4 22、如何改变视窗的背景颜色 5 23、如何改变窗口标题 5 24...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 196
精华内容 78
关键字:

windows如何创建位图文件