当前位置: 首页 > news >正文

如何从文件读取显示位图?

如何从文件读取显示位图?
自己总结的,感觉有些书上说得不清楚!直接拷贝到View类中的OnDraw()函数中即可

一.MFC中如何从文件读取显示位图
1.新建一个CDC对象dc,dc的成员函数直接根据pDC(已经跟当前窗口关联了)创建一个内存DC,在内存DC中选入CBitmap,然后通过BitBlt把内存DC的东西显示
CDC dc;
CBitmap m_bitmap;
dc.CreateCompatibleDC (pDC)
HBITMAP hBitmap=(HBITMAP)LoadImage(NULL,"d:\\skagon.bmp",IMAGE_BITMAP,
0,0,LR_LOADFROMFILE);
m_bitmap.Attach (hBitmap);
BITMAP bm;
m_bitmap.GetBitmap (&bm);
dc.SelectObject (&m_bitmap);
pDC->BitBlt (0,0,bm.bmWidth ,bm.bmHeight ,&dc,0,0,SRCCOPY);

2.创建一个CClientDC(跟当前窗口关联),然后再新建一个新的CDC指针,指针的成员函数去:根据当前的CClientDC创建内存DC,在内存DC中选入CBitmap,然后通过BitBlt把内存DC的东西显示
CClientDC dc(this);
CDC * ddc = new CDC;
CBitmap bitmap;
ddc->CreateCompatibleDC(&dc);
bitmap.m_hObject=(HBITMAP)LoadImage(NULL,"d:\\skagon.bmp",IMAGE_BITMAP,
0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
ddc->SelectObject(bitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt (0,0,rect.right,rect.bottom,ddc,0,0,SRCCOPY);

3.和'1'的步骤大致一样,不过这里是用CBitmap.m_hObject变量去关联获取的句柄。而不是CBitmap.Attach()函数
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap bitmap;
bitmap.m_hObject=(HBITMAP)LoadImage(NULL,"d:\\skagon.bmp",IMAGE_BITMAP,
0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
dc.SelectObject(bitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt (0,0,rect.right,rect.bottom,&dc,0,0,SRCCOPY);

4.从文件中载入内存,获得“bmp文件头指针&数据指针&宽&高”4个信息即可在View类中得OnDraw()函数中显示出来。
CFile dibFile("d:\\skagon.bmp",CFile::modeRead);
BYTE *pDib=new BYTE[dibFile.GetLength()];
dibFile.Read((void*)pDib,dibFile.GetLength());
BITMAPINFO * m_pBitmapInfo = (BITMAPINFO*)(pDib+14);
BITMAPINFOHEADER * m_pBitmapInfoHeader = (BITMAPINFOHEADER*)(pDib+14);
BYTE * m_pData = (pDib + 1078);
::StretchDIBits( pDC->m_hDC, 0, 0, m_pBitmapInfoHeader->biWidth, m_pBitmapInfoHeader->biHeight, 0, 0, 
m_pBitmapInfoHeader->biWidth, m_pBitmapInfoHeader->biHeight,
m_pData, m_pBitmapInfo, DIB_RGB_COLORS, SRCCOPY );
//其中,pDC->m_hDC也可以更改为pDC->GetSafeHdc(),因为GetSafeHdc()的返回值就是m_hDC

二,SDK中如何从文件读取显示位图
(1)对于需要调色板的图,要想正确地显示,必须根据bmp文件,产生逻辑调色板。产生的方法是:
①为逻辑调色板指针分配内存,大小为逻辑调色板结构(LOGPALETTE)长度加NumColors个PALETTENTRY大小
(调色板的每一项都是一个PALETTEENTRY结构);
②填写逻辑调色板结构的头pPal->palNumEntries = NumColors; pPal->palVersion = 0x300;
③从文件中读取调色板的RGB值,填写到每一项中;
④产生逻辑调色板:hPalette=CreatePalette(pPal)。

(2)产生位图(BITMAP)句柄,该项工作由函数CreateDIBitmap来完成。

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData,(LONG)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);

CreateDIBitmap的作用是产生一个和Windows设备无关的位图。该函数的第一项参数为设备上下文句柄。如果位图用到了调色板,要在调用CreateDIBitmap之前将逻辑调色板选入该设备上下文中,产生hBitmap后,再把原调色板选入该设备上下文中,并释放该上下文;
第二项为指向BITMAPINFOHEADER的指针;第三项就用常量CBM_INI,不用考虑;
第四项为指向调色板的指针;
第五项为指向BITMAPINFO(包括BITMAPINFOHEADER,调色板,及实际的图象数据)的指针;
第六项就用常量DIB_RGB_COLORS,不用考虑。

上面提到了设备上下文,相信编过Windows程序的读者对它并不陌生,这里再简单介绍一下。Windows操作系统统一管理着诸如显示,打印等操作,将它们看作是一个个的设备,每一个设备都有一个复杂的数据结构来维护。所谓设备上下文就是指这个数据结构。然而,我们不能直接和这些设备上下文打交道,只能通过引用标识它的句柄(实际上是一个整数),让Windows去做相应的处理。产生的逻辑调色板句柄hPalette和位图句柄hBitmap要在处理WM_PAINT消息时使用,这样才能在屏幕上显示出来,处理过程如下面的程序。

HDC hDC,hMemDC;
PAINTSTRUCT ps;
case WM_PAINT:
{
hDC = BeginPaint(hwnd, &ps); //获得屏幕设备上下文
if (hBitmap) //hBitmap一开始是NULL,当不为NULL时表示有图
{
hMemDC = CreateCompatibleDC(hDC); //建立一个内存设备上下文
if (hPalette) //有调色板
{ //将调色板选入屏幕设备上下文
SelectPalette (hDC, hPalette, FALSE);
//将调色板选入内存设备上下文
SelectPalette (hMemDC, hpalette, FALSE);
RealizePalette (hDC);
}
//将位图选入内存设备上下文
SelectObject(hMemDC, hBitmap);
//显示位图
BitBlt(hDC, 0, 0, bi.biWidth, bi.biHeight, hMemDC, 0, 0, SRCCOPY);
//释放内存设备上下文
DeleteDC(hMemDC);
}
//释放屏幕设备上下文
EndPaint(hwnd, &ps);
break;
}

在上面的程序中,我们调用CreateCompatibleDC创建一个内存设备上下文。SelectObject函数将与设备无关的位图选入内存设备上下文中。然后我们调用BitBlt函数在内存设备上下文和屏幕设备上下文中进行位拷贝。由于所有操作都是在内存中进行,所以速度很快。

转载于:https://www.cnblogs.com/wkjs/archive/2006/04/30/2008584.html

相关文章:

  • yii2 基本的增删改查
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • Linux随机生成密码的10种方法
  • 限制用户输入的方法
  • C++11 tuple的使用
  • 在VS2003中部署Crystal Report 10
  • 我的测试生活感悟2 - Art Of Unit Testing
  • 牛客---java练习
  • 今天晨跑了,呵呵
  • 素数
  • .net 简单实现MD5
  • Linux系统基础知识-嵌入式迅为4412开发板学习笔记
  • P2P 之 UDP穿透NAT的原理与实现
  • centos7 安装mysql
  • Redis(一):概述
  • Fastjson的基本使用方法大全
  • javascript数组去重/查找/插入/删除
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 创建一种深思熟虑的文化
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 利用jquery编写加法运算验证码
  • 两列自适应布局方案整理
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 入口文件开始,分析Vue源码实现
  • 微信公众号开发小记——5.python微信红包
  • nb
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #Linux(权限管理)
  • #宝哥教你#查看jquery绑定的事件函数
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (2015)JS ES6 必知的十个 特性
  • (初研) Sentence-embedding fine-tune notebook
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • . Flume面试题
  • .NET CLR基本术语
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题
  • @test注解_Spring 自定义注解你了解过吗?
  • [Android] 修改设备访问权限
  • [Angular] 笔记 6:ngStyle
  • [C++]STL之map
  • [CF543A]/[CF544C]Writing Code
  • [CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理
  • [Firefly-Linux] RK3568修改控制台DEBUG为普通串口UART
  • [Gamma]阶段测试报告
  • [HDOJ4911]Inversion
  • [ICCV2017]Neural Person Search Machines
  • [iOS]-NSTimer与循环引用的理解
  • [leetcode]_Symmetric Tree