使用wxWidget中遇到的图片存储问题一二

1. 实验室中CCD的实际色阶为14位,获取的原始图像数据的每个值都存储在一个字中,即存储色阶16位,也就是说最高两位的数据一直为0,同时获取的图片信息仅仅是16色阶的灰度图,而采用wxWidget没有办法直接将16位的数值串保存为图片格式,如tiff格式,那么如何将16位的数值串以图片的形式进行保存呢?

    经过这么几天的折腾总算是找到了一条解决的途径,就是将16位的数值串转化为8为的数值串,也许你会很快的想到这么一个方法,nValue*max(uint8)/max(uint16);用来表示转化后的数值,不够还是得考虑一下CCD的实际色阶,由于是14位,因此可以采用这样的方式nValue*max(uint8)/max(uint14);不过由于我们对于图片的处理是直接对图片的原始数据进行处理,而转化只是图片在显示屏上显示的前提步骤,采用上述的方式虽然能够相对很准确的进行转化,但是需要花费一定的计算量,而通过近似的转化能够更快的进行这个转化过程,同时获取得到的图片依然具有较好的清晰度,下面细说一下我采用的方法:

   1: unsigned short nPicData16 = new unsigned short[nBufSize];   // nBufSize is the size to store pic
   2:  
   3: // to get the nPicData16
   4: // ..................
   5: // get the nPicData16
   6:  
   7: char *pcPicData8 = new char[nBufSize];
   8: for (size_t i = 0; i < nBufSize; ++i) {
   9:   pcPicData8[i] = (char)(nPicData16>>6);
  10: }
  11:  
  12:  

由于2^6在2^14中所占的比例较小因此可以采用这样的近似的方法。(这种方法具体有什么作用或是缺陷还没有细究,请各位看官给点看法

2. 顺利将14位数值串转化成为8为数值串后,尝试的使用下列方式进行图片保存,发现结果一片黑,数值都为0了:

   1: // 结果发现存储得到的save.bmp图是24b的
   2: wxBitmap bitmap(pcPicData8,1392,1040,8);
   3: bitmap.SaveFile(wxT("save.bmp"),wxBITMAP_TYPE_BMP);
   4:  

因此猜想wxWidget对直接获取的数据串进行保存时采用的rgb的模式进行保存,可能只会保存为24字节格式的图片,也就是想要将图片显示到屏幕上时,也应该采用24b的图片。不过wxWidget对于图片数据却能够读取8位的图片,但是再次采用上述的方式进行存储时,变成了32字节的了,(各位大虾知不知道有没有方法能够直接保存8位图的呢)。

于是采用了将这个8位的数值串分别赋值给R,G,B,用这种方式实现灰度图的创建,然后再进行保存,最终解决了问题。

   1: unsigned char *rgbData = new unsigned char[1392*1040*3];
   2: unsigned char *ptr1 = (unsigned char*) pcPicData8;
   3: unsigned char *ptr2 = rgbData;
   4: for (int i = 0; i < 1392*1040; ++i) {
   5:     *ptr2++ = *ptr1;   
   6:     *ptr2++ = *ptr1;
   7:     *ptr2++ = *ptr1++;
   8: }
   9: wxImage myImage(1392,1040,rgbData);
  10: myImage.SaveFile(wxT("save.bmp"),wxBITMAP_TYPE_BMP);

posted on 2012-06-26 17:51 钟谢伟 阅读(1865) 评论(12)  编辑 收藏 引用

评论

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 20:48 泡菜

貌似,wxWidget默认保存tiff为24位图(色阶8位)的

wxWidget底层调用的,子库为LibTIFF---一个开源C库;需要复杂实用,直接调用C API...不过这样很麻烦的.一般24位图足够实用了啊?

文中提到的"实验室中CCD的单个像素的分辨率为14位",有点没理解?指色阶14位,既32位图么??看着有点晕  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 20:53 泡菜

上面回复有点错误,特别纠正下,应该这样说:

文中提到的"实验室中CCD的单个像素的分辨率为14位",有点没理解?指色阶14位,既42位图么??看着有点晕

显卡一般实际输出为32位图(24位图上加了个透明通道,色阶还是8位的),个别支持48位图(色阶16位),例如DP口,可这是通过抖动/差值实现的,没啥实际意义  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 21:03 钟谢伟

@泡菜
那个专有的名词是dynamic range A/D——14bit,指的是模数转换范围,我理解可能表示实际色阶(文中说成单个像素的分辨率了,用词不够专业,不好意思),而数据存储中是以16位色阶存储,也就是说16位中最高的两位一直是0,而这个ccd只能够获取灰度图,也就是没有RGB信息,而wxWidget中没有简单的直接保存8位灰度图的方式,于是采用了文中说的方式。  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 21:29 泡菜

@钟谢伟
把代码变为下面这个看看,保存下来的图是否还是黑色的南??

1: // 结果发现存储得到的save.bmp图是24b的
2: wxBitmap bitmap(pcPicData8,1392,1040);
3: bitmap.SaveFile(wxT("save.bmp"),wxBITMAP_TYPE_BMP);  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 21:34 钟谢伟

@泡菜
是的,还是黑色的,尝试过了的  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 21:58 泡菜

static char pcPicData8[]= { 255 ,255 ,255 ,255 ,31,
255,255,255,31,255,255,255,31,255,255,255,
31,255,255,255,31,255,255,255,31,255,255,
255,31,255,255,255,31,255,255,255,25,243,
255,255,19,249,255,255,7,252,255,255,15,254,
255,255,31,255,255,255,191,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,
255 };

wxBitmap bitmap(pcPicData8,32,32);
bitmap.SaveFile(wxT("save.bmp"),wxBITMAP_TYPE_BMP);

很久没碰编程了,上面的代码在wxWidget下是能正常生成,并保存的.说明你的pcPicData8转化有问题,问题出在pcPicData8上.  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-26 22:24 泡菜

实验室硬件CCD咋样不清楚,整体代码也没看到,但感觉你对图像色阶的理解有点小问题;如果CCD是14位的(A/D),直接获得的数据得通过转换(抖动/插值)才能生成16位色阶的图片(48位图).....大多软件也不支持48位图的.

tiff不太清楚,但bmp、JPG最高支持24位图(8位色阶),也是wxWidget默认支持的;PNG好像本身格式支持48位图,可wxWidget默认也24位图,实际上目前,在PC上还没看到有完全支持48位图形的程序.
  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-27 11:32 钟谢伟

@泡菜
它是灰度图,所以没有48位之说。
你给出的例子是教程中的例子,能够正常生成,不过pcPicData8的长度是128,而32*32=1024,对于它是怎么实现的感到困惑。也许采用的是补零??
另外我转化存储的数据上传了  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-27 11:46 钟谢伟

@泡菜
晕啊,不知道怎么上传文件  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-27 13:09 泡菜

这是百度上,灰度图像解释:(针对RGB色彩空间来说)

完整的图像,是由红色绿色蓝色三个通道组成的。红色、绿色、蓝色三个通道的缩览图都是以灰度显示的。用不同的灰度色阶来表示“ 红,绿,蓝”在图像中的比重。通道中的纯白,代表了该色光在此处为最高亮度,亮度级别是255。

俺在加点...8位色阶数码图,实际上就是24位图片(另一种表述方法),RGB三坐标,每个坐标轴,分为256个刻度.例如(255,0,255)表示品红,(0,0,255)表示蓝色.图片上的每个像素点,就是这样描述出来的.

RGB色彩空间,是以RGB三个坐标建立起的"立方体","灰度级"指"立方体"的对角线.灰度图简单点理解,可以简单理解为,采用RGB色彩空间建立起来的图形.
所以灰度图,有48位图(16位色阶)的概念,只不过这个立方体相对8位色阶,更大而已,每个坐标的刻度从256级别,变大为65536级(2的16次方),可以表现65536*65536*65536种颜色;相对于8位色阶(24位图),256*256*256种颜色多得多尔

给你个连接自己看,虽然讲的不太详细
http://baike.baidu.com/view/1184366.htm

你对某些概念的确没搞清楚,不过只要想学就好办...

最后一贴,最终问题还是要靠自己解决....:)
  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-27 22:03 泡菜

本来说不回帖了,可感觉还是有些东西有点不知所以然,就把wxWidget的英文文档调出来看,发现俺上面的例子也有点理解错误

wxBitmap的其中一个构造函数为wxBitmap (const char bits[], int width, int height, int depth=1);英文说明
Creates a bitmap from the given array bits.
You should only use this function for monochrome bitmaps (depth 1) in portable programs: in this case the bits parameter should contain an XBM image.
For other bit depths, the behaviour is platform dependent: under Windows, the data is passed without any changes to the underlying CreateBitmap() API. Under other platforms, only monochrome bitmaps may be created using this constructor and wxImage should be used for creating colour bitmaps from static data.

其bits[]是XBM image,种基于ASCII编码的图像格式,不同于真彩色图,没采用RGB色彩空间,自然不能套用三原色的东西.
之前俺的例子是从一篇中文,文档里提取的,他没做详细描述,俺想当然的引用了,有点误导....俺承认 :(

特别提一下,wxImage,他的其中一个构造函数,wxImage (int width, int height, unsigned char *data, unsigned char *alpha, bool static_data=false);英文文档描述
Creates an image from data in memory.
If static_data is false then the wxImage will take ownership of the data and free it afterwards. For this, it has to be allocated with malloc.
Parameters:
width Specifies the width of the image.
height Specifies the height of the image.
data A pointer to RGB data ------------注意是RGB
alpha A pointer to alpha-channel data
static_data Indicates if the data should be free'd after use

注意到他与上面wxBitmap构造函数声明的不同了没? 在wxImage这个上面用,自然没问题

看样遇见问题还是老老实实,求助英文文档来的实际 :(

另,经过查文档,确认,wxWidget默认生成图像,的确是8位色阶,24位真彩的哦  回复  更多评论   

# re: 使用wxWidget中遇到的图片存储问题一二 2012-06-28 09:32 钟谢伟

@泡菜
额,一直看的是英文文档,却没有深究,想当然了,汗颜。
  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2012年7月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

常用链接

留言簿(1)

随笔档案

IT网站

My Friends

搜索

最新评论

阅读排行榜

评论排行榜