本文基于minigui3.0.12版本
一、接口方法
//加载图像内容bitmap到内存bmp句柄
int GUIAPI LoadBitmapFromFile (HDC hdc, PBITMAP bmp, const char* file_name);
//释放bmp句柄
void GUIAPI UnloadBitmap (PBITMAP bmp);
//加载bitmap到framebuffer;
BOOL GUIAPI FillBoxWithBitmap (HDC hdc, int x, int y, int w, int h,
const BITMAP *bmp);
使用方式
PBITMAP bg_bmp = NULL; //新建一个bitmap句柄
bg_bmp = (PBITMAP)malloc(sizeof(BITMAP)); //为句柄分配存储空间
LoadBitmapFromFile(HDC_HANDLER, bg_bmp,"filename.png"); //加载图像像素到bitmap
FillBoxWithBitmap (HDC_HANDLER,0,0,100,100,bg_bmp); //绘制到(0,0,100,100)的位置,改接口带缩放功能
UnloadBitmap (bg_bmp);//释放bitmap空间
二、内部详细代码流程
2.1、解码过程
LoadBitmapFromFile
get_extension(file_name) //获取图片文件后缀名
MGUI_RWFromFile(file_name, "rb") //打开文件保存fp,保存读写方法fops到MG_RWops
LoadBitmapEx(hdc, bmp, area, ext); //开始解码并根据fb像素格式保存转换后的像素内容到bmp
获得图片的fp、后缀名、以及读写文件的方法函数接下来继续分析LoadBitmapEx 在这里会根据图片的像素格式解码为对应的rgb格式的数据比如ARGB8888或者RGB888等格式后再转换为屏幕fb的像素格式最后存储到bitmap以方便后面进行读取显示。
不同的图片有不同的解码函数保存在
BITMAP_TYPE_INFO bitmap_types [MAX_BITMAP_TYPES] =
{
{ "gif", __mg_init_gif, __mg_load_gif, __mg_cleanup_gif, NULL, __mg_check_gif },
{ "png", __mg_init_png, __mg_load_png, __mg_cleanup_png, NULL, __mg_check_png },
}
LoadBitmapEx
LOAD_BITMAP_INFO info;
info.hdc = hdc;
info.bmp = bmp; //将bmp存放到bitmap info
LOAD_MYBITMAP_INFO* load_info;
load_info = InitMyBitmapSL(area, ext, &my_bmp, pal); //将解码函数方法放到load_info中
type = get_image_type(ext) //获取后缀名对应的解码函数数组指针对应上面的bitmap_types 数组
load_info->type_info = bitmap_types + type; //获取png图片的解码函数方法init load等
load_info->type_info->init (area, my_bmp, pal); //png init方法读取文件头信息保存到load_info->init_info
my_bmp->bits = malloc (my_bmp->pitch); //分配行长空间给中间存储bitmap结构mybitmap用以后续逐行读取解码后的图片像素内容
init_bitmap_from_mybmp (hdc, bmp, &my_bmp, pal, TRUE); //为bitmap分配存储空间并分配alpha像素存储的空间
pdc = dc_HDC2PDC (hdc); //获取设备绘制上下文
bmp->bmBitsPerPixel = pdc->surface->format->BitsPerPixel; //根据屏幕fb定制bitmap的像素位数32 24等
bmp->bmBytesPerPixel = pdc->surface->format->BytesPerPixel; //根据屏幕fb定制bitmap的像素字节数4,3等
size = GAL_GetBoxSize (pdc->surface, my_bmp->w, my_bmp->h, &bmp->bmPitch); //根据屏幕fb及图片宽高来确定bitmap存储空间大小
bmp->bmBits = malloc (alloc_all?size:bmp->bmPitch) //分配存储空间
if (my_bmp->flags & MYBMP_ALPHA && my_bmp->depth == 32)
bmp->bmAlphaMask = calloc(1, size); //分配存储alpha空间
LoadMyBitmapSL (area, load_info, &my_bmp, cb_load_bitmap_sl, &info); //逐行解码并存储解码后数据到bitmap
info->type_info->load (area, info->init_info, my_bmp, cb, context);//png解碼函數
__mg_load_png
png_read_row(info->png_ptr, rp, NULL); //读取一行png解码后的数据
if (cb && !p) cb(context, my_bmp, i); //调用回调cb_load_bitmap_sl
cb_load_bitmap_sl(void* context, MYBITMAP* my_bmp, int y)
compilergba_bitmap_sl (info->hdc, dst_bits, dst_alpha_mask, my_bmp);
pixel = GAL_MapRGBA (pdc->surface->format, rgb.r, rgb.g, rgb.b, rgb.a); //将像素放到int pixel
dst = _mem_set_pixel (dst, bpp, pixel); //根据bpp放到bitmap里
2.2 显示过程
FillBoxWithBitmap (HDC hdc, int x, int y, int w, int h, const BITMAP* bmp)
_begin_fill_bitmap (hdc, x, y, w, h, bmp, &fill_info); //计算填充区域信息
_fill_bitmap (pdc, bmp, &fill_info);
_dc_fillbox_bmp_clip (pdc, &fill_info->dst_rect, (BITMAP*)bmp); //不缩放的情况下调用该函数
GAL_PutBox (pdc->surface, rect, bmp); //开始填充
GAL_IntersectRect //计算重叠的填充区域 仅计算重绘的区域
dstrow = (Uint8 *)dst->pixels + my_dstrect.y * dst->pitch + my_dstrect.x * dst->format->BytesPerPixel; //目的framebuffer
srcrow = (Uint8 *)box->bmBits + off_y * box->bmPitch + off_x * box->bmBytesPerPixel; //源bitmap
_PutBoxAlpha (dst, dstrow, srcrow, w, h, box); //根据h高度一行行进行拷贝采用DUFFS_LOOP8拷贝
_end_fill_bitmap (pdc, bmp, &fill_info); //拷贝完成后更新到真实framebuffer进行显示
__mg_leave_drawing (pdc);
kernel_ShowCursorForGDI (TRUE, pdc);
GAL_UpdateRect (cur_pdc->surface, prc->left, prc->top, RECTWP(prc), RECTHP(prc)); //调用硬件tde 进行局部更新。
如果一开始就给了真实的framebuffer那后面的局部区域更新就不用调用了。