使用GDI+保存带Alpha通道的图像
bool ImageUtil :: CreateGdiplusBmpFromHBITMAP_Alpha ( HBITMAP hBmp , Gdiplus :: Bitmap ** bmp )
{
BITMAP bitmap ;
GetObject ( hBmp , sizeof ( BITMAP ), & bitmap );
if ( bitmap . bmBitsPixel != 32)
{
return false ;
}
Gdiplus :: Bitmap * pWrapBitmap = Gdiplus :: Bitmap :: FromHBITMAP ( hBmp , NULL );
if ( pWrapBitmap )
{
Gdiplus :: BitmapData bitmapData ;
Gdiplus :: Rect rcImage (0, 0, pWrapBitmap -> GetWidth (), pWrapBitmap -> GetHeight ());
pWrapBitmap -> LockBits (& rcImage , Gdiplus :: ImageLockModeRead , pWrapBitmap -> GetPixelFormat (), & bitmapData );
* bmp = new Gdiplus :: Bitmap ( bitmapData . Width , bitmapData . Height , bitmapData . Stride , PixelFormat32bppARGB , ( BYTE *) bitmapData . Scan0 );
pWrapBitmap -> UnlockBits (& bitmapData );
delete pWrapBitmap ;
return true ;
}
return false ;
}
Gdiplus :: Bitmap * ImageUtil :: CreateBitmapFromHBITMAP ( IN HBITMAP hBitmap )
{
BITMAP bmp = { 0 };
if ( 0 == GetObject ( hBitmap , sizeof ( BITMAP ), ( LPVOID )& bmp ) )
{
return FALSE ;
}
// Although we can get bitmap data address by bmp.bmBits member of BITMAP
// which is got by GetObject function sometime,
// we can determine the bitmap data in the HBITMAP is arranged bottom-up
// or top-down, so we should always use GetDIBits to get bitmap data.
BYTE * piexlsSrc = NULL ;
LONG cbSize = bmp . bmWidthBytes * bmp . bmHeight ;
piexlsSrc = new BYTE [ cbSize ];
BITMAPINFO bmpInfo = { 0 };
// We should initialize the first six members of BITMAPINFOHEADER structure.
// A bottom-up DIB is specified by setting the height to a positive number,
// while a top-down DIB is specified by setting the height to a negative number.
bmpInfo . bmiHeader . biSize = sizeof ( BITMAPINFOHEADER );
bmpInfo . bmiHeader . biWidth = bmp . bmWidth ;
bmpInfo . bmiHeader . biHeight = bmp . bmHeight ; // 正数,说明数据从下到上,如未负数,则从上到下
bmpInfo . bmiHeader . biPlanes = bmp . bmPlanes ;
bmpInfo . bmiHeader . biBitCount = bmp . bmBitsPixel ;
bmpInfo . bmiHeader . biCompression = BI_RGB ;
HDC hdcScreen = CreateDC ( L "DISPLAY" , NULL , NULL , NULL );
LONG cbCopied = GetDIBits ( hdcScreen , hBitmap , 0, bmp . bmHeight ,
piexlsSrc , & bmpInfo , DIB_RGB_COLORS );
DeleteDC ( hdcScreen );
if ( 0 == cbCopied )
{
delete [] piexlsSrc ;
return FALSE ;
}
// Create an GDI+ Bitmap has the same dimensions with hbitmap
Bitmap * pBitmap = new Bitmap ( bmp . bmWidth , bmp . bmHeight , PixelFormat32bppPARGB );
// Access to the Gdiplus::Bitmap's pixel data
BitmapData bitmapData ;
Rect rect (0, 0, bmp . bmWidth , bmp . bmHeight );
if ( Ok != pBitmap -> LockBits (& rect , ImageLockModeRead ,
PixelFormat32bppPARGB , & bitmapData ) )
{
delete ( pBitmap );
return NULL ;
}
BYTE * pixelsDest = ( BYTE *) bitmapData . Scan0 ;
int nLinesize = bmp . bmWidth * sizeof ( UINT );
int nHeight = bmp . bmHeight ;
// Copy pixel data from HBITMAP by bottom-up.
for ( int y = 0; y < nHeight ; y ++ )
{
// 从下到上复制数据,因为前面设置高度时是正数。
memcpy_s (
( pixelsDest + y * nLinesize ),
nLinesize ,
( piexlsSrc + ( nHeight - y - 1) * nLinesize ),
nLinesize );
}
// Copy the data in temporary buffer to pBitmap
if ( Ok != pBitmap -> UnlockBits (& bitmapData ) )
{
delete pBitmap ;
}
delete [] piexlsSrc ;
return pBitmap ;
}
bool ImageUtil::SavePng( HBITMAP hBmp, LPCTSTR lpszFilePath )
{
DIBSECTION dibsection;
int nBytes = ::GetObject( hBmp, sizeof( DIBSECTION ), &dibsection ); Gdiplus::Bitmap* bitmap = 0; if(nBytes != sizeof(DIBSECTION) || dibsection.dsBm.bmBitsPixel != 32)
{
// Bitmap with plate or non-ARGB(32bpp)
bitmap = Gdiplus::Bitmap::FromHBITMAP(hBmp);
}
else
{
int width, height, bits_per_pixel, pitch;
LPVOID bits; width = dibsection.dsBmih.biWidth;
height = abs( dibsection.dsBmih.biHeight );
bits_per_pixel = dibsection.dsBmih.biBitCount;
pitch = (((width*bits_per_pixel)+31)/32)*4; //计算行宽,四字节对齐 ATL::CImage::ComputePitch
bits = dibsection.dsBm.bmBits; if( dibsection.dsBmih.biHeight > 0 )
{
bits = LPBYTE( bits )+((height-1)*pitch);
pitch = -pitch;
} bitmap = new Gdiplus::Bitmap(width, height, pitch, PixelFormat32bppARGB, static_cast< BYTE* >(bits ));
} bool ret = false;
CLSID clsid = GetGdiplusEncoderClsid(NULL, &Gdiplus::ImageFormatPNG);
if(clsid != CLSID_NULL)
{
ret = (Gdiplus::Ok == bitmap->Save(lpszFilePath, &clsid, NULL));
}
delete bitmap;
return ret;
}
使用GDI+保存带Alpha通道的图像的更多相关文章
- 使用GDI+保存带Alpha通道的图像(续)
之前结合网上的一些代码及ATL::CImage的实现,自己写了一个将HBITMAP以PNG格式保存到文件到函数.见上一篇日记. 不过,后来换了个环境又发现了问题,昨天和今天上午把<Windows ...
- 带Alpha通道的色彩叠加问题
css3的rgba色彩模式.png/gif图片的alpha通道.canvas的rgba色彩模式.css3的阴影.css3的opacity属性等等,这些应用在网页中,有意无意间,我们的页面多了许多半透明 ...
- Unity 播放 带 alpha 通道的视频(Video Player组件)
孙广东 2017.6.18 http://blog.csdn.NET/u010019717 通常是 .webm类型文件!!!!! 你可以下载这个文件到本地: Http://tsubakit1.s ...
- 如何基于纯GDI实现alpha通道的矢量和文字绘制
今天有人在QQ群里问GDI能不能支持带alpha通道的线条绘制? 大家的答案当然是否定的,很多人推荐用GDI+. 一个基本的图形引擎要包括几个方面的支持:位图绘制,文字绘制,矢量绘制(如矩形,线条). ...
- 什么是Alpha通道?
图像处理(Alpha通道,RGB,...)祁连山(Adobe 系列教程)****的UI课程 一个也许很傻的问题,在图像处理中alpha到底是什么? Alpha通道是计算机图形学中的术语,指的是特别的 ...
- Alpha通道
Alpha通道是计算机图形学中的术语,指的是特别的通道,意思是“非彩色”通道,主要是用来保存选区和编辑选区.真正让图片变透明的不是Alpha 实际是Alpha所代表的数值和其他数值做了一次运算 为 ...
- ImagXpress中如何修改Alpha通道方法汇总
ImagXpress支持处理Alpha通道信息来管理图像的透明度,Alpha通道支持PNG ,TARGA和TIFF文件,同时还支持BMP和ICO文件.如果说保存的图像样式不支持Alpha通道,就将会丢 ...
- PIE SDK Alpha通道数据渲染
1. 功能简介 在计算机图形学中,一个RGB颜色模型的真彩图形,用由红.绿.蓝三个色彩信息通道合成的,每个通道用了8位色彩深度,共计24位,包含了所有彩色信息.为实现图形的透明效果,采取在图形文件的 ...
- 使用opencv为没有透明通道的图像加入透明通道
在图像处理中,我们经常需要处理带透明通道的图片,比如为图片或视频添加水印,为图片或视频添加字幕.贴图等.然而,我们的素材图片未必总是带有透明通道.比如,素材的背景本该透明的地方,却是黑色和白色.有时, ...
随机推荐
- js判断是否是移动端(触摸屏)或者是PC
js代码: console.log("ontouchstart" in window); 手机web浏览器,chrome模拟手机.手机APP会返回true, pc端(非手机模拟状态 ...
- 20165210 《网络对抗技术》week1 exp0 kali安装与配置
20165210 <网络对抗技术>week1 exp0 kali安装与配置 1. 安装过程: 从kali官网上下载如下图所示: 下载完成后打开VMware 点击创建新的虚拟机 弹出新虚拟机 ...
- 【这些年】Linux C/C++软件开发用过的工具
这些年一直从事Linux下C/C++软件开发,学习工作中用到了不少开发工具,一直想做个总结,却总是因为这个原因那个原因,未能动笔.趁今天天气凉爽,空气清新,花点儿功夫,做一个小结啦,防止以 ...
- angularjs 定时器 销毁
angular.module('app', []) .controller('ItemController', function($scope, $interval) { // store the i ...
- IOS开发Block详细用法
Block简介: ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数 ...
- python之List排序
sorted() #coding:utf-8 #sorted Ascending 升序 L = [12,23,43,3,65,34,21,3645] print(sorted(L)) >> ...
- GCD基础
一.GCD介绍 1.what is GCD? Grand Central Dispatch 中枢调度器.用很简单的方式实现了极为复杂繁琐的多线程编程.异步执行任务的技术之一. 2.GCD存在于li ...
- SPOJ Favorite Dice(数学期望)
BuggyD loves to carry his favorite die around. Perhaps you wonder why it's his favorite? Well, his d ...
- object references an unsaved transient instance【异常】
[异常提示] TransientObjectException: object references an unsaved transient instance -save the transient ...
- daemon Thread
1.概念 守护进程(daemon)是指在UNIX或其他多任务操作系统中在后台执行的电脑程序,并不会接受电脑用户的直接操控.此类程序会被以进程的形式初始化.守护进程程序的名称通常以字母“d”结尾:例如, ...