风过无痕,生命如烟

每个人生下来都是天使,不过这个世界上也存在着恶魔。恶魔是天使变的,因为这个世界充满了诱惑。

导航

如何在vc中制作256色的16x16和32x32大小的彩色图标

本文摘自:http://www.vckbase.com/bbs/prime/viewprime.asp?id=372
在Windows的编程中,彩色图像的显示和处理一直是一个重要的课题,即使是在显
卡普遍支持真彩的今天,讨论256色位图的显示也是有意义的。通过对这一课题的讨论,
可以了解如何在VC5中实现装入图像,创建和使用调色板,以及最后将图像画出来。
    总的来说,要显示一幅256色的位图,首先应得到该图的有关信息,通过位图的颜
色表创建一个逻辑调色板,然后将这个调色板选入设备环境,实现这个调色板,最后将
位图用BitBlt函数拷贝到设备环境就可以了。
具体实现步骤如下:
1、装载位图并创建调色板。
    首先装入一幅位图,该位图既可以以资源的形式与程序绑在一起,也可以以文件
的形式从外部装入。然后将该位图与一个Cbitmap对象联系(Attach)起来。在这儿我
们应使用API函数LoadImage(),而不是CBitmap类的成员函数CBitmap::LoadBitmap(),
因为我们需要得到该位图的DIBSECTION结构,从这个结构中我们可以得到该位图的色彩
信息,从而建立一个与这些色彩相匹配的逻辑调色板。使用CBitmap::LoadBitmap()将
会失去我们所需的位图的色彩信息。
    得到位图后,下一步工作就是取得该位图的色彩信息。通过CBitmap:GetObject()
函数,我们可以访问DIBSECTION结构,从中得到位图的色彩数。一般来说,这些信息存
在于BITMAPINFOHEAD结构中,不过,作为DIBSECTION结构的一部分,BITMAPINFOHEAD有
时并未说明图像用了多少种颜色;碰到这种情况,我们可以看看图像的每一象素用了几
位(Bit)来描述颜色,如果是8位的话,因为8位二进制数可以表示256种不同的值,所
以该图像是256色的;同理,16Bit表明是64K色。得到了位图所用的颜色数,就可以创
建逻辑调色板了。色彩超过256色的位图是没有颜色表(Color Table)的,这时我们只用
简单地创建一个和设备环境兼容的半色调调色板(Halftone Palette)就行了,在半色调
调色板中包含着所有不同颜色的样本。这显然不是最佳解决方案,但却是最简单的。
    而对于颜色数小于或等于256的位图,我们就要从头建立一个新的调色板。先分配
足够的内存空间来装入图像的颜色表,颜色表可以利用API函数GetDIBColorTable获得;
然后再分配足够的内存给新建的逻辑调色板,将刚才得到的颜色表信息相应拷入新建调
色板中的palPalEntry域,并将PalVersion域设为0X300。创建了调色板后,应将窗口刷
新重画。在具体的实现上,我们定义了一个函数GetBitmapandPalette()来实现位图资
源的装入和逻辑调色板的创建,其功能实现框图如下(略)
函数具体实现如下:(程序)
    以上程序只是简单的从一个固定路径(e:\\project\\showimage\\bitmap1.bmp)
装入位图,读者可以将其功能扩充,如通过对话框选取等等,在此不多赘述。
    最后还要补充的一点是,如果要显示的位图是作为位图资源与程序联系在一起的,
对以上程序稍作修改即可显示出来,修改方法如下:
首先将GetBitmapandPalette()函数改为:
BOOL  GetBitmapandPalette(UINT nidresource,
CBitmap &bitmap, CPalette &pal,long *w,long *h)
其中nidresource是该位图的ID。
然后将GetBitmapandPalette()中的第一句改为:
    LPCTSTR lpszresourcename = (LPCTSTR)nidresource;
并将LoadImage函数改为:
HBITMAP hbmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
                          nidresourcename,IMAGE_BITMAP,0,0,
                         LR_CREATEDIBSECTION);
最后,在OnPaint函数中调用GetBitmapandPalette()时,将位图的ID通过
nidresource传入即可。

示例代码
BOOL GetBitmapandPalette(LPCTSTR lpszresource,
CBitmap &bitmap, CPalette &pal,long *w,long *h)
{
   LPCTSTR lpszresourcename = (LPCTSTR)lpszresource;
   HBITMAP hbmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
            lpszresourcename,IMAGE_BITMAP,0,0,      
               LR_LOADFROMFILE); //装入位图
   if( hbmp == NULL )
        return FALSE;
   bitmap.Attach( hbmp );
   // 将该位图与一个CBitmap对象联系起来
   DIBSECTION ds;
   BITMAPINFOHEADER &bminfo = ds.dsBmih;
   bitmap.GetObject( sizeof(ds), &ds );
   // 得到位图颜色数
   int ncolors = bminfo.biClrUsed ?
   bminfo.biClrUsed : 1 < <  bminfo.biBitCount;
   *w = bminfo.biWidth; //得到位图宽度值
   *h = bminfo.biHeight; //得到位图高度值
   CClientDC dc(NULL);  

   // 创建逻辑调色板
   if( ncolors  > 256 )
        pal.CreateHalftonePalette( &dc );
   else
   {
        // 颜色数 < = 256
        RGBQUAD *prgb = new RGBQUAD[ncolors];
        CDC memdc;
        memdc.CreateCompatibleDC(&dc);
        memdc.SelectObject( &bitmap );
        ::GetDIBColorTable( memdc, 0, ncolors, prgb );
        UINT nsize = sizeof(LOGPALETTE) +
          (sizeof(PALETTEENTRY) * ncolors);
        LOGPALETTE *plp = (LOGPALETTE *) new byte[nsize];
        plp- >palVersion = 0x300;
        plp- >palNumEntries = ncolors;
        for( int i=0; i< ncolors;i++)
        {
            plp- >palPalEntry[i].peRed = prgb[i].rgbRed;
            plp- >palPalEntry[i].peGreen = prgb[i].rgbGreen;
            plp- >palPalEntry[i].peBlue = prgb[i].rgbBlue;
            plp- >palPalEntry[i].peFlags = 0;
        }
        pal.CreatePalette( plp );
        delete[] plp;
        delete[] prgb;
   }
   return TRUE;
}

2.显示位图
在WM_PAINT消息的响应函数OnPaint()中实现。
void OnPaint()
{
   CPaintDC dc(this); // device context for painting
   // create a memory dc compatible with the paint dc
   CDC memdc;
   memdc.CreateCompatibleDC( &dc );
   CBitmap bitmap;
   CPalette palette;
   long nWidth;
   long nHeight;
     //调用该函数
   GetBitmapandPalette("e:\\project\\
     showimage\\bitmap1.bmp",bitmap,palette ,
     &nWidth,&nHeight);
   memdc.SelectObject( &bitmap );
   // select and realize the palette
   if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && palette.m_hObject != NULL )
   {
        dc.SelectPalette( &palette, FALSE );
        dc.RealizePalette();
   }

   //显示位图
   dc.BitBlt(0, 0, nWidth,nHeight, &memdc, 0, 0,SRCCOPY);

}

posted on 2006-01-19 09:05  hyamw  阅读(2108)  评论(2)    收藏  举报