在VC5中显示256色位图

原创 2004年08月30日 01:37:00
在VC5中显示256色位图

  
 李欣 周学泳

在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()来实现位
图资源的装入和逻辑调色板的创建,其功能实现框图如下(略)

函数具体实现如下:

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 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);

}

以上程序只是简单的从一个固定路径(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传入即可。

MFC下256色BMP位图的保存

一、BMP位图的文件格式 BMP文件的数据按照从文件头开始的先后顺序分为四个部分: ◆ 位图文件头(bmp file header):  提供文件的格式、大小等信息 ◆ 位图信息头(bitmap...
  • qq_22531295
  • qq_22531295
  • 2017年02月22日 15:00
  • 439

用Qt来进行256色位图的转换

接着上次的一篇文章关于“在一个图片上写字并保存”,上次说到
  • prompty
  • prompty
  • 2016年12月30日 10:00
  • 749

MFC中位图显示函数

点击打开链接 理解分辨率 我们常说的屏幕分辨率为640×480,刷新频率为70Hz,意思是说每行要扫描640个象素,一共有480行,每秒重复扫描屏幕70次。   理解调色板 有一个长宽各...
  • rayna00
  • rayna00
  • 2016年06月20日 17:21
  • 629

MFC如何显示位图

1. 资源文件中加载 bmp 2.1. 静态加载图片  在属性下设置为如下即可 2.2 动态加载图片 其中要在控件中添加CStatic变量,并且属性设置为如下 ...
  • u011258240
  • u011258240
  • 2015年12月17日 09:51
  • 328

MFC---多种方式显示位图

一、控件方式1、将要显示的位图b.bmp放在res文件夹下 2、右键工程,选择“Insert”,选择Bitmap,这时工程中新添了Bitmap文件夹 3、右键Bitmap文件夹,选择“Import...
  • u012319493
  • u012319493
  • 2016年08月09日 20:08
  • 1582

BMP位图调色板

原文地址:http://blog.csdn.net/qsycn/article/details/7801145 BMP位图调色板是BMP位图文件的组成成分之一,调色板是单色(调色板中含有两种颜色,也就...
  • kkkkkkkkq
  • kkkkkkkkq
  • 2016年12月26日 20:11
  • 619

MFC中在视图窗口显示位图

本例将在单文档工程的视图窗口中显示一副位图,窗口的左边为原图,右边为放大后的位图。 本例的demo如下: 首先    在资源视图中插入一副位图,然后在Ondraw函...
  • u011619422
  • u011619422
  • 2014年12月07日 10:56
  • 1419

双缓冲显示位图

原理: 创建内存位图对象; 创建内存DC; 将位图对象选入到内存DC,便可以在内存DC中画图; 最后将内存DC中的图拷贝到窗口DC 在BOOL C***Dlg::OnEraseBkgnd(CDC*...
  • jiangqin115
  • jiangqin115
  • 2015年03月10日 09:37
  • 922

透明位图--SRCINVERT用法讲解

实现透明位图,有一个知识点必须要提前知道,那就是: 注意对于图片来说,只有纯黑RGB(0,0,0)为0,其余即使是RGB(0,0,1)也是1 如果一个单色位图向彩色位图转换,那么单色位...
  • u012513234
  • u012513234
  • 2015年04月23日 22:24
  • 804

位图文件读写综述

位图文件读写综述  转自:http://www.vckbase.com/index.php/wv/475 一、位图文件结构 1.位图文件头 2.位图信息 2.1位图信息头 2.2 颜色表 ...
  • chenjie863
  • chenjie863
  • 2013年11月23日 15:37
  • 1501
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在VC5中显示256色位图
举报原因:
原因补充:

(最多只允许输入30个字)