VC中显示灰度图的问题
vc中有一数组 a 存放的是16进制数怎么样显示出灰度图?
查一下BMP图像的储存格式吧,我印象中不复杂。
先将要显示的图存成BMP文件在硬盘中,再用CBitmap类(这是MFC种做法)载入,或者直接用pictureBox空间的的Load()接口(这是.NET的做法)载入。 本帖最后由 Rainyboy 于 2010-11-18 20:57 编辑
给一个很久以前学习和使用过的类吧,是继承MFC框架中CBitMap类实现的一个CBitMapEx(MFC框架中的类都是这样,以C开头)类:头文件:BitMapEx.h
// BitmapEx.h: interface for the CBitmapEx class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BITMAPEX_H__5E661765_FB4A_4623_BC9F_261366D967C3__INCLUDED_)
#define AFX_BITMAPEX_H__5E661765_FB4A_4623_BC9F_261366D967C3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CBitmapEx : public CBitmap
{
public:
CBitmapEx();
virtual ~CBitmapEx();
BOOL LoadImage(LPCTSTR szFilename);
BOOL LoadBitmap(LPCTSTR szFilename);
void Draw(CDC* pDC,double init_x,double init_y);
};
#endif // !defined(AFX_BITMAPEX_H__5E661765_FB4A_4623_BC9F_261366D967C3__INCLUDED_) .cpp文件BitMapEx.cpp
// BitmapEx.cpp: implementation of the CBitmapEx class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ImageEx.h"
#include "BitmapEx.h"
#include <olectl.h>
#include <ole2.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBitmapEx::CBitmapEx()
{
}
CBitmapEx::~CBitmapEx()
{
DeleteObject();
}
BOOL CBitmapEx::LoadBitmap(LPCTSTR szFilename)
{
ASSERT(szFilename);
DeleteObject();
HBITMAP hBitmap = NULL;
hBitmap = (HBITMAP)::LoadImage(NULL, szFilename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
return Attach(hBitmap);
}
BOOL CBitmapEx::LoadImage(LPCTSTR szFilename)
{
// Use IPicture stuff to use JPG / GIF files
IPicture* p;
IStream* s;
HGLOBAL hG;
void* pp;
FILE* fp;
// Read file in memory
fp = fopen(szFilename,"rb");
if (!fp)
return FALSE;
fseek(fp,0,SEEK_END);
int len = ftell(fp);
fseek(fp,0,SEEK_SET);
hG = GlobalAlloc(GPTR,len);
if (!hG)
{
fclose(fp);
return FALSE;
}
pp = (void*)hG;
fread(pp,1,len,fp);
fclose(fp);
// Create an IStream so IPicture can
if (CreateStreamOnHGlobal(hG,false,&s) != S_OK )
{
GlobalFree(hG);
return FALSE;
}
OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);
if (!p)
{
s->Release();
GlobalFree(hG);
return FALSE;
}
s->Release();
GlobalFree(hG);
HBITMAP hB = 0;
p->get_Handle((unsigned int*)&hB); // 返回GDI句柄的指针
// Copy the image. Necessary, because upon p's release,
// the handle is destroyed.
HBITMAP hBitmap = (HBITMAP)CopyImage(hB,IMAGE_BITMAP,0,0,LR_COPYRETURNORG);
p->Release();
Detach();
return Attach(hBitmap);
}
void CBitmapEx::Draw(CDC* pDC,double init_x,double init_y)
{
HBITMAP hBitmap = (HBITMAP)*this;
if( hBitmap )
{
CDC bitmapDC;
if (bitmapDC.CreateCompatibleDC(pDC))
{
BITMAP bm;
GetBitmap(&bm);
CBitmap* pOldBmp = bitmapDC.SelectObject(this);
pDC->BitBlt(init_x,init_y,bm.bmWidth,bm.bmHeight,&bitmapDC,0,0,SRCCOPY);
bitmapDC.SelectObject(pOldBmp);
}
}
}
实际中如何使用?
1,在欲显示图像的窗口声明私有变量: CBitmapEx m_BitmapEx_11;
CBitmapEx m_BitmapEx_12;2,想要载入图像的时候(多半对应于某个事件(菜单项的单击、按钮的单击)响应函数):
void CImageExView::OnReadImage()
{
CString strFileName11("11.bmp");
CString strFileName12("12.bmp");
m_BitmapEx_11.LoadImage(strFileName11);
BITMAP bm11;
m_BitmapEx_11.GetBitmap(&bm11);
m_BitmapEx_12.LoadImage(strFileName12);
BITMAP bm12;
m_BitmapEx_12.GetBitmap(&bm12);
CSize sz(bm11.bmWidth + bm12.bmWidth, bm11.bmHeight + bm12.bmHeight);
SetScrollSizes(MM_TEXT, sz);
Invalidate();
}3,当然,要想Invalidate()强制重绘的时候也重绘咱们的图像,得改写相应窗口的OnDraw函数,看这里:
void CImageExView::OnDraw(CDC* pDC)
{
CImageExDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
m_BitmapEx_11.Draw(pDC,0,0);
BITMAP bm11;
m_BitmapEx_11.GetBitmap(&bm11);
m_BitmapEx_12.Draw(pDC,bm11.bmWidth,0);
}
个人感觉挺好用的一个类,但愿能对你有用。
Rainyboy老大,您真是 太厉害了,研究方向是 结构动力学,但 热心助人,知识面宽广,佩服 回复 4 # aaa0131106 的帖子
哪里……这些都是简单的问题,能帮就帮帮,复杂的问题咱也没辙……
毕竟是门外汉,呵呵{:{02}:} 本帖最后由 wqsong 于 2011-1-15 00:40 编辑
简单说一下BMP图片的文件格式,就当狗尾续貂了。
总的来看bmp文件由四部分构成,分别是:文件头,文件信息,调色板,数据区。
文件头:
字节 含义
0-1 文件类型魔数
2-5 文件总长度
6-9 保留位
10-13 数据区域偏移
文件信息:
字节 含义
14-17 信息头字节数
18-21 图像的宽度
22-25 图像的高度
26-27 目标设备编号
28-29 像素点所占位数
30-33 文件是否压缩,不压缩为0
34-37 位图表字节数
38-41 目标设备的水平分辨率
42-45 目标设备的垂直分辨率
46-49 图像用到颜色数
50-53 图像中重要的颜色数
调色板:
和位图像素点所占位数(28-29)有关,需要分别定义。
数据区域:
从文件信息的位图表字节数(34-37)读取,块大小使用调色板定义的大小。
============================哀伤的分割线============================
知道这样的格式就可以读取文件,定义三个结构体,来读取这些信息,这里就不具体定义了。
写一段不规范的Demo,使用一个字符数组定义读取文件头,其他信息按照各部分结构读取即可。
#include <stdio.h>
main()
{
char datarea;
FILE *fp = fopen("a.bmp", "rb");
fread(datarea, 14, 1, fp);
printf("%c%c\n%u\n%u\n", datarea, datarea, *(unsigned *)(datarea+2), *(unsigned *)(datarea+10));
}运行结果:
文件属性:
由于Demo中使用的图是真彩图,调色板24字节固定,文件中无需定义调色板。所以会发现数据区的偏移量是54,也就是紧接着文件头和文件信息。
至于具体怎么显示,这是另一回事,和显示设备有关,一般都会提供一些显示设备的工具类。
本帖最后由 wqsong 于 2011-1-15 00:41 编辑
至于转化灰度图,其实就是一个简单的数学运算。调色板有三元色RGB三个数,假设用Gray代表灰度计算结果,从位图表读取出一个数据,简单地说就是这样一个过程:
[Gray] = [ R; G; B] * [变换矩阵]
这样就得到灰度数据了,然后显示。变换矩阵有很多种的,这个也可以自己设定。
一般不做图像处理的简单知道点就够了,想深入可以找本图形处理与分析的书看看。。。
本帖最后由 Rainyboy 于 2011-1-15 10:28 编辑
回复 6 # wqsong 的帖子
为什么还有“哀伤的”分割线呢?嘿嘿…… 回复 8 # Rainyboy 的帖子
嗯分割线跟着心情走。。。嘻嘻 回复 5 # Rainyboy 的帖子
敬仰一下,哈哈
页:
[1]