返回介绍

10.2 使用 wxBitmap 编程

发布于 2025-03-08 15:26:47 字数 8290 浏览 0 评论 0 收藏 0

你可以使用 wxBitmap 来作下面的事情:

  1. 通过设备上下文将其画在一个窗口上。
  2. 在某些类(比如 wxBitmapButton, wxStaticBitmap, and wxToolBar) 中将其作为一个图片标签。
  3. 使用其作为双缓冲区(在将某个图形绘制到屏幕上之前先绘制在一块缓冲区上)。

某些平台(特别是 windows 平台) 上限制了系统中 bitmap 资源的数目,因此如果你需要使用很多的 bitmap,你最好使用 wxImage 类来保存它们,而只在使用的时候将其转化成 bitmap。

在讨论怎样创建 wxBitmap 之前,让我们先来讨论一下几个主要的函数(如下表所示)

wxBitmap代表一个 bitmap,可以通过指定宽度和高度,或者指定另外一个 bitmap,或者指定一个 wxImage,XPM 数据(char**), 原始数据(char[]), 或者一个指定类型的文件名的方式来创建。
ConvertToImage转换成一个 wxImage,保留透明部分。
CopyFromIcon从一个 wxIcon 创建一个 wxBitmap。
Create从图片数据或者一个给定的大小创建一个 bitmap。
GetWidth, GetHeight返回图片大小。
Getdepth返回图片颜色深度。
GetMask, SetMask返回绑定的 wxMask 对象或者 NULL。
GetSubBitmap将位图其中的某一部分创建为一个新的位图。
LoadFile, SaveFile从某种支持格式的文件加载或者保存到文件里。
Ok如果 bitmap 的数据已经具备则返回 True。

创建一个 wxBitmap

可以通过下面的几个途径来创建一个 wxBitmap 对象。

你可以直接通过默认的构造函数创建一个不包含数据的 bitmap,不过你几乎不能用这个 bitmap 作任何事情,除非你调用 Create 或者 LoadFile 或者用另外一个 bitmap 赋值以便使其拥有具体的 bitmap 数据。

你还可以通过指定宽度和高度的方法创建一个位图,这种情况下创建的位图将被填充以随机的颜色,你需要在其上绘画以便更好的使用它,下面的代码演示了怎样创建一个 200x100 的图片并且将其的背景刷新为白色。

// 使用当前的颜色深度创建一个 200x100 的位图
wxBitmap bitmap(200, 100,  -1);
// 创建一个内存设备上下文
wxMemoryDC dc;
// 将创建的图片和这个内存设备上下文关联
dc.SelectObject(bitmap);
// 设置背景颜色
dc.SetBackground(*wxWHITE_BRUSH);
// 绘制位图背景
dc.Clear();
// 解除设备上下文和位图的关联
dc.SelectObject(wxNullBitmap);

你也可以从一个 wxImage 对象创建一个位图,并且保留这个 image 对象的颜色遮罩或者 alpha 通道:

// 加载一幅图像
wxImage image(wxT("image.png"), wxBITMAP_TYPE_PNG);
// 将其转换成 bitmap
wxBitmap bitmap(image);

通过 CopyFromIcon 函数可以通过图标文件创建一个 bitmap:

// 加载一个图标
wxIcon icon(wxT("image.xpm"), wxBITMAP_TYPE_XPM);
// 将其转换成位图
wxBitmap bitmap;
bitmap.CopyFromIcon(icon);

或者你可以通过指定类型的方式从一个图片文件直接加载一个位图:

// 从文件加载
wxBitmap bitmap(wxT("picture.png", wxBITMAP_TYPE_PNG);
if (!bitmap.Ok())
{
    wxMessageBox(wxT("Sorry, could not load file."));
}

wxBitmap 可以加载所有的可以被 wxImage 加载的图片类型,使用的则是各个平台定义的针对特定类型的加载方法.最常用的图片格式比如"PNG, JPG,BMP 和 XPM"等在各个平台上都支持读取和保存操作,不过你需要确认你的 wxWidgets 在编译的时候已经打开了对应的支持。

目前支持的图形类型处理函数如下表所示:

wxBMPHandler用来加载 windows 位图文件。
wxPNGHandler用来加载 PNG 类型的文件.这种文件支持透明背景以及 alpha 通道。
wxJPEGHandler用来支持 JPEG 文件
wxGIFHandler因为版权方面的原因,仅支持 GIF 格式的加载。
wxPCXHandler用来支持 PCX. wxPCXHandler 会自己计算图片中颜色的数目,如果没有超过 256 色,则采用 8bits 颜色深度,否则就采用 24 bits 颜色深度。
wxPNMHandler用来支持 PNM 文件格式. 对于加载来说 PNM 格式可以支持 ASCII 和 raw RGB 两种格式.但是保存的时候仅支持 raw RGB 格式。
wxTIFFHandler用来支持 TIFF。
wxIFFHandler用来支持 IFF 格式。
wxXPMHandler用来支持 XPM 格式。
wxICOHandler用来支持 windows 平台图标文件。
wxCURHandler用来支持 windows 平台光标文件。
wxANIHandler用来支持 windows 平台动画光标文件。

在 Mac OS X 平台上,还可以通过指定 wxBITMAP_TYPE_PICT_RESOURCE 来加载一个 PICT 资源。

如果你希望在不同的平台上从不同的位置加载图片,你可以使用 wxBITMAP 宏,如下所示:

#if !defined(__WXMSW__) && !defined(__WXPM__)
#include "picture.xpm"
#endif
wxBitmap bitmap(wxBITMAP(picture));

这将使得程序在 windows 和 OS/2 平台上从资源文件中加载图片,而在别的平台上,则从一个 picture_xpm 变量中加载 xpm 格式的图片,因为 XPM 在所有的平台上都支持,所以这种使用方法并不常见。

设置一个 wxMask

每个 wxBitmap 对象都可以指定一个 wxMask,所谓 wxMask 指的是一个单色图片用来指示原图中的透明区域.如果你要加载的图片中包含透明区域信息(比如 XPM,PNG 或者 GIF 格式),那么 wxMask 将被自动创建,另外你也可以通过代码创建一个 wxMask 然后调用 SetMask 函数将其和对应的 wxBitmap 对象相关连.你还可以从 wxBitmap 对象创建一个 wxMask,或者通过给一个 wxBitmap 对象指定一种透明颜色来创建一个 wxMask 对象。

下面的代码创建了一个拥有透明色的灰阶位图 mainBitmap,它的大小是 32x32 象素,原始图形从 imageBits 数据创建,遮罩图形从 maskBits 创建,遮罩中 1 代表不透明,0 代表透明颜色。

static char imageBits[] = { 255, 255, 255, 255, 31,
  255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255,
  31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255,
  255, 31, 255, 255, 255, 31, 255, 255, 255, 25, 243,
  255, 255, 19, 249, 255, 255, 7, 252, 255, 255, 15, 254,
  255, 255, 31, 255, 255, 255, 191, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255 };
static char maskBits[] = { 240, 1, 0, 0, 240, 1,
  0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1,
  0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 255, 31, 0, 0, 255,
  31, 0, 0, 254, 15, 0, 0, 252, 7, 0, 0, 248, 3, 0, 0,
  240, 1, 0, 0, 224, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0 };
wxBitmap mainBitmap(imageBits, 32, 32);
wxBitmap maskBitmap(maskBits, 32, 32);
mainBitmap.SetMask(new wxMask(maskBitmap));

XPM 图形格式

在使用小的需要支持透明的图片(比如工具栏上的小图片或者 notebook 以及树状控件上的小图片) 的时候,wxWidgets 的程序员通常偏爱使用 XPM 格式,它的最大的特点是采用 C/C++语言的语法,既可以被程序动态加载,也可以直接编译到可执行代码中去,下面是一个例子:

// 你也可以用 #include "open.xpm"
static char *open_xpm[] = {
/* 列数 行数 颜色个数 每个象素的字符个数 */
"16 15 5 1",
"  c None",
". c Black",
"X c Yellow",
"o c Gray100",
"O c #bfbf00",
/* 象素 */
"                ",
"          ...   ",
"         .   . .",
"              ..",
"  ...        ...",
" .XoX.......    ",
" .oXoXoXoXo.    ",
" .XoXoXoXoX.    ",
" .oXoX..........",
" .XoX.OOOOOOOOO.",
" .oo.OOOOOOOOO. ",
" .X.OOOOOOOOO.  ",
" ..OOOOOOOOO.   ",
" ...........    ",
"                "
};
wxBitmap bitmap(open_xpm);

正如你看到的那样,XPM 是使用字符编码的.在图片数据前面,有一个调色板区域,使用字符和颜色对应的方法,颜色既可以用标准标识符表示,也可以用 16 进制的 RGB 值表示,使用关键字 None 来表示透明区域.尽管在 windows 系统上,XPM 并不被大多数的图形处理工具支持,不过你还是可以通过一些工具把 PNG 格式转换成 XPM 格式,比如 DialogBlocks 自带的 ImageBlocks 工具,或者你可以直接使用 wxWidgets 编写一个你自己的转换工具。

使用位图绘画

使用位图绘画的方式有两种,你可以使用内存设备上下文绑定一个位图,然后使用 wxDC::Blit 函数,也可以直接使用 wxDC:: DrawBitmap 函数,前者允许你使用位图的一部分进行绘制.在两种方式下,如果这个图片支持透明或者 alpha 通道,你都可以通过将最后一个参数指定为 True 或者 False 来打开或者关闭透明支持。

这两种方法的用法如下:

// Draw a bitmap using a wxMemoryDC
wxMemoryDC memDC;
memDC.SelectObject(bitmap);
// Draw the bitmap at 100, 100 on the destination DC
destDC.Blit(100, 100,                         // Draw at (100, 100)
    bitmap.GetWidth(), bitmap.GetHeight(),    // Draw full bitmap
    & memDC,                                  // Draw from memDC
    0, 0,                                     // Draw from bitmap origin
    wxCOPY,                                   // Logical operation
    true);                                    // Take mask into account
memDC.SelectObject(wxNullBitmap);
// Alternative method: use DrawBitmap
destDC.DrawBitmap(bitmap, 100, 100, true);

第五章,"绘画和打印"中对使用 bitmap 绘画有更详细的描述。

打包位图资源

如果你曾是一个 windows 平台的程序员,你可能习惯从可执行文件的资源部分加载一幅图片,当然在 wxWidgets 中也可以这样作,你只需要指定一个资源名称一个资源类型 wxBITMAP_TYPE_BMP_RESOURCE,不过这种作法是平台相关的.你可能更倾向于使用另外一种平台无关的解决方案。

一个可移植的方法是,你可以将你用到的所有数据文件,包括 HTML 网页,图片或者别的任何类型的文件压缩在一个 zip 文件里,然后你可以用 wxWidgets 提供的虚拟文件系统对加载这个 zip 文件的其中任何一个或几个文件,如下面的代码所示:

// 创建一个文件系统
wxFileSystem*fileSystem = new wxFileSystem;
wxString archiveURL(wxT("myapp.bin"));
wxString filename(wxT("myimage.png"));
wxBitmapType bitmapType = wxBITMAP_TYPE_PNG;
// 创建一个 URL
wxString combinedURL(archiveURL + wxString(wxT("#zip:")) + filename);
wxImage image;
wxBitmap bitmap;
// 打开压缩包中的对应文件
wxFSFile* file = fileSystem->OpenFile(combinedURL);
if (file)
{
    wxInputStream* stream = file->GetStream();

    // Load and convert to a bitmap
    if (image.LoadFile(* stream, bitmapType))
        bitmap = wxBitmap(image);

    delete file;
}
delete fileSystem;
if (bitmap.Ok())
{
    ...
}

更多关于虚拟文件系统的信息请参考第 14 章:文件和流操作。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文