soui中apng 图像解码器解码图片后像素格式研究
2015-12-29 13:01
411 查看
soui是一个非常牛逼的界面库,里面对图片透明有着很好的支持,这也是我喜欢soui的一个重要原因。soui中不仅可以设置主窗口半透明,而且还可以设置soui子窗口半透明,两者的设置都非常的简单。只需要在xml中设置下属性就好了。
但我一直好奇,透明技术是如何实现的。看了下soui的源码,在渲染引擎为gdi模式下,透明实现用了UpdateLayeredWindow和AlphaBlend技术,两者都有一个共同的BLENDFUNCTION 参数,这个结构体对透明有着重要的影响。
前几天在msdn上面找到了一个Alpha Blending a Bitmap(Windows)的一段 代码,下面是该原文地址的连接:
然后在相同文件下把 _DoDecode()函数替换如下:
int SImgX_PNG::_DoDecode(APNGDATA *pData)
{
if(!pData) return 0;
m_pngData = pData;
int nWid = m_pngData->nWid;
int nHei = m_pngData->nHei;
//swap rgba to bgra and do premultiply
BYTE *p=m_pngData->pdata;
int pixel_count = nWid * nHei * m_pngData->nFrames;
for (int i=0; i < pixel_count; ++i) {
BYTE a = p[0];
BYTE t = p[0];
if (a)
{
BYTE k = p[0];
p[0] = p[3];
p[3] = k;
k = p[1];
p[1] = p[2];
p[2] = k;
p[0] = p[0] * t/255;
p[1] = p[1]*t/255;
p[2] = p[2] * t/255;
}else
{
memset(p,0,4);
}
p += 4;
}
p=m_pngData->pdata;
m_pImgArray = new SImgFrame_PNG[m_pngData->nFrames];
for(int i=0;i<m_pngData->nFrames;i++)
{
m_pImgArray[i].Attach(p,nWid,nHei,m_pngData->pDelay?m_pngData->pDelay[i]:0);
p += nWid*nHei*4;
}
return m_pngData->nFrames;
} 编译运行也可以显示正常效果,这里就说明了apng解码出来的argb格式在内存中地址从低到高依次是b,g,r,a,这样跟msdn描述的就一样了,实在还不相信的话,可以在debug模式下面看内存数据的变化,这同样也可以发现这一点。
但我一直好奇,透明技术是如何实现的。看了下soui的源码,在渲染引擎为gdi模式下,透明实现用了UpdateLayeredWindow和AlphaBlend技术,两者都有一个共同的BLENDFUNCTION 参数,这个结构体对透明有着重要的影响。
前几天在msdn上面找到了一个Alpha Blending a Bitmap(Windows)的一段 代码,下面是该原文地址的连接:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183353%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396[/code]
在注释里面我发现了这样一句话:msdn意思是说32位位图像素格式是0xaarrggbb格式的。我尝试修改了像素值发现确实是这样。// in top window area, constant alpha = 50%, but no source alpha // the color format for each pixel is 0xaarrggbb // set all pixels to blue and set source alpha to zero
soui中还有一个非常牛逼的地方就是,支持多种图像解码模块,比如stb,wic,apng,gdi+,我发现除了用gdi+解码图像时用的是argb格式外,其他三种解码模块都不是argb格式,而是bgra格式。这让我很疑惑。比如下面这个是apng解码时的部分代码:int SImgX_PNG::_DoDecode(APNGDATA *pData) { if(!pData) return 0; m_pngData = pData; int nWid = m_pngData->nWid; int nHei = m_pngData->nHei; //swap rgba to bgra and do premultiply BYTE *p=m_pngData->pdata; int pixel_count = nWid * nHei * m_pngData->nFrames; for (int i=0; i < pixel_count; ++i) { BYTE a = p[3]; BYTE t = p[0]; if (a) { p[0] = (p[2] *a)/255; p[1] = (p[1] * a)/255; p[2] = (t * a)/255; }else { memset(p,0,4); } p += 4; } p=m_pngData->pdata; m_pImgArray = new SImgFrame_PNG[m_pngData->nFrames]; for(int i=0;i<m_pngData->nFrames;i++) { m_pImgArray[i].Attach(p,nWid,nHei,m_pngData->pDelay?m_pngData->pDelay[i]:0); p += nWid*nHei*4; } return m_pngData->nFrames; }
但msdn上面说的像素格式应该是0xaarrggbb的,咋一看好看soui中解码的bgra跟msdn上面说的不一样,刚开始我也是这么认为,后来发现是对的。如下是我进行的试验:
查看了下apng的文档,发现apng是支持直接解码成argb格式的,在decoder-apng.cpp中的 APNGDATA* loadPng(IPngReader* pSrc)函数中的 png_read_update_info 下面加入以下代码,这里就将图片格式解析成了argb。
if (png_ptr_read->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_swap_alpha(png_ptr_read);
然后在相同文件下把 _DoDecode()函数替换如下:
int SImgX_PNG::_DoDecode(APNGDATA *pData)
{
if(!pData) return 0;
m_pngData = pData;
int nWid = m_pngData->nWid;
int nHei = m_pngData->nHei;
//swap rgba to bgra and do premultiply
BYTE *p=m_pngData->pdata;
int pixel_count = nWid * nHei * m_pngData->nFrames;
for (int i=0; i < pixel_count; ++i) {
BYTE a = p[0];
BYTE t = p[0];
if (a)
{
BYTE k = p[0];
p[0] = p[3];
p[3] = k;
k = p[1];
p[1] = p[2];
p[2] = k;
p[0] = p[0] * t/255;
p[1] = p[1]*t/255;
p[2] = p[2] * t/255;
}else
{
memset(p,0,4);
}
p += 4;
}
p=m_pngData->pdata;
m_pImgArray = new SImgFrame_PNG[m_pngData->nFrames];
for(int i=0;i<m_pngData->nFrames;i++)
{
m_pImgArray[i].Attach(p,nWid,nHei,m_pngData->pDelay?m_pngData->pDelay[i]:0);
p += nWid*nHei*4;
}
return m_pngData->nFrames;
} 编译运行也可以显示正常效果,这里就说明了apng解码出来的argb格式在内存中地址从低到高依次是b,g,r,a,这样跟msdn描述的就一样了,实在还不相信的话,可以在debug模式下面看内存数据的变化,这同样也可以发现这一点。
相关文章推荐
- winform异型不规则界面设计的实现方法
- Android中设置只有程序第一次运行才显示的界面实现思路
- hta 实现的五子棋界面
- android开发之欢迎界面的小例子
- C#中载入界面的常用方法
- android编程实现局部界面动态切换的方法
- Android判断现在所处界面是否为home主桌面的方法
- Android编程实现泡泡聊天界面实例详解(附源码)
- android 引导界面的实现方法
- VC 界面库皮肤库相关信息珍藏
- Android中界面实现全屏显示的两种方式
- 简单做出不丑设计
- extmail 界面修改
- QT程序启动界面的使用
- The Book of Qt 4 翻译: 2.2 界面和处理逻辑的分离
- 软件界面交互和易用性改进总结
- WP7界面设计与交互指南中英译本(附下载)
- 微软发布Windows Phone 7技术预览版(多图)(1)
- wxpython笔记
- 修改SecureCRT终端的Home和End功能键