声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 4622|回复: 9

[C/C++] VC中显示灰度图的问题

[复制链接]
发表于 2010-11-18 17:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
vc中有一数组 a[152][200] 存放的是16进制数
怎么样显示出灰度图?
回复
分享到:

使用道具 举报

发表于 2010-11-18 20:12 | 显示全部楼层
查一下BMP图像的储存格式吧,我印象中不复杂。
先将要显示的图存成BMP文件在硬盘中,再用CBitmap类(这是MFC种做法)载入,或者直接用pictureBox空间的的Load()接口(这是.NET的做法)载入。
发表于 2010-11-18 20:48 | 显示全部楼层
本帖最后由 Rainyboy 于 2010-11-18 20:57 编辑

        给一个很久以前学习和使用过的类吧,是继承MFC框架中CBitMap类实现的一个CBitMapEx(MFC框架中的类都是这样,以C开头)类:头文件:BitMapEx.h
  1. // BitmapEx.h: interface for the CBitmapEx class.
  2. //
  3. //////////////////////////////////////////////////////////////////////

  4. #if !defined(AFX_BITMAPEX_H__5E661765_FB4A_4623_BC9F_261366D967C3__INCLUDED_)
  5. #define AFX_BITMAPEX_H__5E661765_FB4A_4623_BC9F_261366D967C3__INCLUDED_

  6. #if _MSC_VER > 1000
  7. #pragma once
  8. #endif // _MSC_VER > 1000

  9. class CBitmapEx : public CBitmap
  10. {
  11. public:
  12.         CBitmapEx();
  13.         virtual ~CBitmapEx();

  14.         BOOL LoadImage(LPCTSTR szFilename);
  15.         BOOL LoadBitmap(LPCTSTR szFilename);

  16.         void Draw(CDC* pDC,double init_x,double init_y);
  17. };

  18. #endif // !defined(AFX_BITMAPEX_H__5E661765_FB4A_4623_BC9F_261366D967C3__INCLUDED_)
复制代码
        .cpp文件BitMapEx.cpp
  1. // BitmapEx.cpp: implementation of the CBitmapEx class.
  2. //
  3. //////////////////////////////////////////////////////////////////////

  4. #include "stdafx.h"
  5. #include "ImageEx.h"
  6. #include "BitmapEx.h"
  7. #include <olectl.h>
  8. #include <ole2.h>

  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif

  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////

  17. CBitmapEx::CBitmapEx()
  18. {

  19. }

  20. CBitmapEx::~CBitmapEx()
  21. {
  22.         DeleteObject();
  23. }

  24. BOOL CBitmapEx::LoadBitmap(LPCTSTR szFilename)
  25. {
  26.         ASSERT(szFilename);
  27.         DeleteObject();

  28.         HBITMAP hBitmap = NULL;
  29.         hBitmap = (HBITMAP)::LoadImage(NULL, szFilename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
  30.         return Attach(hBitmap);
  31. }

  32. BOOL CBitmapEx::LoadImage(LPCTSTR szFilename)
  33. {
  34.         // Use IPicture stuff to use JPG / GIF files
  35.         IPicture* p;
  36.         IStream* s;
  37.         HGLOBAL hG;
  38.         void* pp;
  39.         FILE* fp;


  40.         // Read file in memory
  41.         fp = fopen(szFilename,"rb");
  42.         if (!fp)
  43.                 return FALSE;

  44.         fseek(fp,0,SEEK_END);
  45.         int len = ftell(fp);
  46.         fseek(fp,0,SEEK_SET);
  47.         hG = GlobalAlloc(GPTR,len);
  48.         if (!hG)
  49.         {
  50.                 fclose(fp);
  51.                 return FALSE;
  52.         }
  53.         pp = (void*)hG;
  54.         fread(pp,1,len,fp);
  55.         fclose(fp);

  56.         // Create an IStream so IPicture can
  57.         if (CreateStreamOnHGlobal(hG,false,&s) != S_OK )
  58.         {
  59.                 GlobalFree(hG);
  60.                 return FALSE;
  61.         }

  62.         OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);

  63.         if (!p)
  64.         {
  65.                 s->Release();
  66.                 GlobalFree(hG);
  67.                 return FALSE;
  68.         }
  69.         s->Release();
  70.         GlobalFree(hG);

  71.         HBITMAP hB = 0;
  72.         p->get_Handle((unsigned int*)&hB); // 返回GDI句柄的指针

  73.         // Copy the image. Necessary, because upon p's release,
  74.         // the handle is destroyed.
  75.         HBITMAP hBitmap = (HBITMAP)CopyImage(hB,IMAGE_BITMAP,0,0,LR_COPYRETURNORG);

  76.         p->Release();
  77.         Detach();

  78.         return Attach(hBitmap);
  79. }

  80. void CBitmapEx::Draw(CDC* pDC,double init_x,double init_y)
  81. {
  82.         HBITMAP hBitmap = (HBITMAP)*this;
  83.         if( hBitmap )
  84.         {
  85.                 CDC bitmapDC;
  86.                 if (bitmapDC.CreateCompatibleDC(pDC))
  87.                 {
  88.                         BITMAP bm;
  89.                         GetBitmap(&bm);
  90.                         CBitmap* pOldBmp = bitmapDC.SelectObject(this);
  91.                         pDC->BitBlt(init_x,init_y,bm.bmWidth,bm.bmHeight,&bitmapDC,0,0,SRCCOPY);
  92.                         bitmapDC.SelectObject(pOldBmp);
  93.                 }
  94.         }
  95. }
复制代码


实际中如何使用?


1,在欲显示图像的窗口声明私有变量:
  1.         CBitmapEx m_BitmapEx_11;
  2.         CBitmapEx m_BitmapEx_12;
复制代码
2,想要载入图像的时候(多半对应于某个事件(菜单项的单击、按钮的单击)响应函数):

  1. void CImageExView::OnReadImage()
  2. {

  3.         CString strFileName11("11.bmp");
  4.         CString strFileName12("12.bmp");

  5.         m_BitmapEx_11.LoadImage(strFileName11);
  6.         BITMAP bm11;
  7.         m_BitmapEx_11.GetBitmap(&bm11);

  8.         m_BitmapEx_12.LoadImage(strFileName12);
  9.         BITMAP bm12;
  10.         m_BitmapEx_12.GetBitmap(&bm12);

  11.         CSize sz(bm11.bmWidth + bm12.bmWidth, bm11.bmHeight + bm12.bmHeight);
  12.         SetScrollSizes(MM_TEXT, sz);

  13.         Invalidate();
  14.         
  15. }
复制代码
3,当然,要想Invalidate()强制重绘的时候也重绘咱们的图像,得改写相应窗口的OnDraw函数,看这里:
  1. void CImageExView::OnDraw(CDC* pDC)
  2. {
  3.         CImageExDoc* pDoc = GetDocument();
  4.         ASSERT_VALID(pDoc);
  5.         // TODO: add draw code for native data here
  6. m_BitmapEx_11.Draw(pDC,0,0);
  7.                 BITMAP bm11;
  8.                 m_BitmapEx_11.GetBitmap(&bm11);
  9.                 m_BitmapEx_12.Draw(pDC,bm11.bmWidth,0);
  10.         }
复制代码

个人感觉挺好用的一个类,但愿能对你有用。


评分

1

查看全部评分

发表于 2011-1-14 10:38 | 显示全部楼层
Rainyboy  老大,您真是 太厉害了,研究方向是 结构动力学,但 热心助人,知识面宽广,佩服
发表于 2011-1-14 13:13 | 显示全部楼层
回复 4 # aaa0131106 的帖子

哪里……这些都是简单的问题,能帮就帮帮,复杂的问题咱也没辙……
毕竟是门外汉,呵呵
发表于 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,使用一个字符数组定义读取文件头,其他信息按照各部分结构读取即可。

  1. #include <stdio.h>
  2. main()
  3. {
  4. char datarea[14];
  5. FILE *fp = fopen("a.bmp", "rb");
  6. fread(datarea, 14, 1, fp);
  7. printf("%c%c\n%u\n%u\n", datarea[0], datarea[1], *(unsigned *)(datarea+2), *(unsigned *)(datarea+10));
  8. }
复制代码
运行结果:
run.png
文件属性:
attribute.png
由于Demo中使用的图是真彩图,调色板24字节固定,文件中无需定义调色板。所以会发现数据区的偏移量是54,也就是紧接着文件头和文件信息。

至于具体怎么显示,这是另一回事,和显示设备有关,一般都会提供一些显示设备的工具类。
发表于 2011-1-15 00:09 | 显示全部楼层
本帖最后由 wqsong 于 2011-1-15 00:41 编辑

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

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

评分

1

查看全部评分

发表于 2011-1-15 10:28 | 显示全部楼层
本帖最后由 Rainyboy 于 2011-1-15 10:28 编辑

回复 6 # wqsong 的帖子

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

点评

赞成: 5.0
To ChaChing:这哥们要毕业,因此连分割线都哀伤了(好文艺……)  发表于 2011-1-15 11:41
赞成: 5
why? 哀伤的?  发表于 2011-1-15 11:10
发表于 2011-1-15 11:28 | 显示全部楼层
回复 8 # Rainyboy 的帖子

嗯  分割线跟着心情走。。。嘻嘻
发表于 2011-6-28 11:39 | 显示全部楼层
回复 5 # Rainyboy 的帖子

敬仰一下,哈哈
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-5-3 11:58 , Processed in 0.117340 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表