vib_QQ 发表于 2010-11-18 17:54

VC中显示灰度图的问题

vc中有一数组 a 存放的是16进制数
怎么样显示出灰度图?

Rainyboy 发表于 2010-11-18 20:12

查一下BMP图像的储存格式吧,我印象中不复杂。
先将要显示的图存成BMP文件在硬盘中,再用CBitmap类(这是MFC种做法)载入,或者直接用pictureBox空间的的Load()接口(这是.NET的做法)载入。

Rainyboy 发表于 2010-11-18 20:48

本帖最后由 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);
      }
个人感觉挺好用的一个类,但愿能对你有用。


aaa0131106 发表于 2011-1-14 10:38

Rainyboy老大,您真是 太厉害了,研究方向是 结构动力学,但 热心助人,知识面宽广,佩服

Rainyboy 发表于 2011-1-14 13:13

回复 4 # aaa0131106 的帖子

哪里……这些都是简单的问题,能帮就帮帮,复杂的问题咱也没辙……
毕竟是门外汉,呵呵{:{02}:}

wqsong 发表于 2011-1-15 00:01

本帖最后由 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:09

本帖最后由 wqsong 于 2011-1-15 00:41 编辑

至于转化灰度图,其实就是一个简单的数学运算。调色板有三元色RGB三个数,假设用Gray代表灰度计算结果,从位图表读取出一个数据,简单地说就是这样一个过程:
[Gray] = [ R; G; B] * [变换矩阵]
这样就得到灰度数据了,然后显示。变换矩阵有很多种的,这个也可以自己设定。

一般不做图像处理的简单知道点就够了,想深入可以找本图形处理与分析的书看看。。。

Rainyboy 发表于 2011-1-15 10:28

本帖最后由 Rainyboy 于 2011-1-15 10:28 编辑

回复 6 # wqsong 的帖子

为什么还有“哀伤的”分割线呢?嘿嘿……

wqsong 发表于 2011-1-15 11:28

回复 8 # Rainyboy 的帖子

嗯分割线跟着心情走。。。嘻嘻

aaa0131106 发表于 2011-6-28 11:39

回复 5 # Rainyboy 的帖子

敬仰一下,哈哈
页: [1]
查看完整版本: VC中显示灰度图的问题