利用GDI+实现gif图像背景透明

来源:互联网 发布:java. se有哪些内容 编辑:程序博客网 时间:2024/05/16 06:50

    要实现将GIF图像进行透明处理,需要调用三个函数, MakeTransparent函数为将图像数据进行透明处理的函数,GetEncoderClsid为获取clsid,StreamToByte为将流转换为byte数组的函数,

这三个函数的具体代码如下:

MakeTransparent(IStream * inStream, IStream ** outStream)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

//制作透明gif
Bitmap *image=Bitmap::FromStream(inStream);   

// 图象打开失败返回错误
if( image->GetLastStatus() != Ok ) {
return FALSE;
}
// 如果不是单帧的GIF则返回错误
GUID guidFormat;
Status status;
status = image->GetRawFormat( &guidFormat );
if( status != Ok || guidFormat != ImageFormatGIF ){
return FALSE;
}
if( image->GetPixelFormat() != PixelFormat8bppIndexed )
return FALSE;  // GIF 格式必须为PixelFormat8bppIndexed格式

UINT nCount = 0,nFrames;
nCount = image->GetFrameDimensionsCount();
GUID* pDimensionIDs = new GUID[nCount];
image->GetFrameDimensionsList(pDimensionIDs, nCount);
nFrames = image->GetFrameCount(&pDimensionIDs[0]);
delete []pDimensionIDs;
// 不是单帧的GIF则返回
if( nFrames != 1 ){
return FALSE;
}
// 通过改变pallete来设置透明色
BOOL bRet = FALSE;
UINT  palSize = image->GetPaletteSize();
COLORREF transColor;
transColor=RGB(255,255,255);
if( palSize > 0 )
{
ColorPalette* palette = (ColorPalette*)malloc(palSize);
status = image->GetPalette( palette , palSize );
for( UINT i =0; i<palette->Count; ++i ){
if( (palette->Entries[i] & 0x00FFFFFF ) == transColor)
palette->Entries[i] &= 0x00FFFFFF;
else
palette->Entries[i] |= 0xFF000000;
}
palette->Flags |= PaletteFlagsHasAlpha;
// 创建位图对象
Bitmap bitmap(image->GetWidth(),image->GetHeight(),PixelFormat8bppIndexed) ;
if( bitmap.GetLastStatus() != Ok ){
free(palette); palette = NULL;
return FALSE;
}
status = bitmap.SetPalette( palette );
// 将image中的点的索引拷贝到bitmap中
BitmapData  bitmapData,imageData;
Rect  rect(0, 0, image->GetWidth(), image->GetHeight());
status = bitmap.LockBits( &rect,ImageLockModeWrite,PixelFormat8bppIndexed,&bitmapData);
if( status == Ok )
{
status = image->LockBits( &rect,ImageLockModeRead,PixelFormat8bppIndexed,&imageData );
if( status == Ok )
{
BYTE *pixels,*pixelsNew;
if (imageData.Stride > 0)
pixels = (BYTE*) imageData.Scan0;
else
pixels = (BYTE*) imageData.Scan0 + imageData.Stride*(image->GetHeight()-1);
UINT stride = abs(imageData.Stride);
pixelsNew = (BYTE*)bitmapData.Scan0;

for(UINT row = 0; row < image->GetHeight(); ++row)
{
for(UINT col = 0; col < image->GetWidth(); ++col)
{    
UINT      i8BppPixel = row * stride + col;
pixelsNew[i8BppPixel] = pixels[i8BppPixel];
}
}
CLSID gifClsid;
int ret=GetEncoderClsid( L"image/gif",&gifClsid );
if( ret != -1 )
bRet = bitmap.Save(*outStream , &gifClsid)==Ok;
image->UnlockBits( &imageData );
}
bitmap.UnlockBits( &bitmapData );
}
free(palette); palette = NULL;
}
return S_OK;
}


GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
UINT num= 0;
UINT size= 0;
ImageCodecInfo* pImageCodecInfo= NULL;
GetImageEncodersSize(&num, &size);
if(size== 0)
{
return -1;
}
pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo== NULL)
{
return -1;
}
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j=0; j< num; ++j)
{
if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
{
*pClsid= pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}


StreamToByte(IStream *InStream, BYTE* ImageBuff, DWORD* dwSize)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

//获得与流对应的内存句柄
HGLOBAL hMem;
GetHGlobalFromStream(InStream,&hMem);
DWORD streamSize =GlobalSize(hMem); 
if (ImageBuff == NULL || *dwSize < streamSize)
{
*dwSize = streamSize;
return S_OK;
}
BYTE *pbyBmp = (BYTE *)GlobalLock(hMem);
memcpy_s(ImageBuff,*dwSize,pbyBmp, streamSize);
::GlobalUnlock(hMem); 

return S_OK;
}


调用这个三个函数实现图像背景透明处理的操作代码如下:

//位图保存到流
CLSID encoderClsid;
psl->GetEncoderClsid(L"image/gif",&encoderClsid);
IStream *pStream = NULL;
HRESULT iRet = CreateStreamOnHGlobal(NULL,TRUE,&pStream);
Status sRet = pBitmap->Save(pStream,&encoderClsid,NULL);
//生成透明印章图像
IStream *bStream = NULL;
HRESULT bRet = CreateStreamOnHGlobal(NULL,TRUE,&bStream);
BOOL mret=psl->MakeTransparent(pStream,&bStream);
//将流转换成字节数组
BYTE * picBuff=NULL;
DWORD picBuffSize = 0;
BOOL stRet=psl->StreamToByte(bStream,picBuff,&picBuffSize);
picBuff = new BYTE[picBuffSize + 1];
memset(picBuff, 0x00, picBuffSize+1);
stRet=psl->StreamToByte(bStream,picBuff,&picBuffSize);


本代码经实际操作,在WIN7下可行,但在xp下仍会显示不透明背景


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 脚趾头磨了个泡怎么办 脚趾头起了大泡怎么办 脚上有脚气起水泡很痒怎么办 脚底有水泡很痒怎么办 脚底磨得起泡了怎么办 脚底有水泡很疼怎么办 脚底硬皮走路疼怎么办 上火鼻子上长脓包怎么办 鼻子上总是长脓包怎么办 孕妇脚上长水泡很痒怎么办 脚气有水泡很痒怎么办 脚又痒又脱皮怎么办 手指出水泡很痒怎么办 鼻子里上火长泡怎么办 鼻子又干又痒怎么办 眼皮长了小水泡怎么办 眼皮上长了个泡怎么办 眼皮上长了粉刺怎么办 上眼皮又肿又疼怎么办 眼皮长了个痘怎么办 手指上小水泡痒怎么办 阴茎长了一个泡怎么办 干活累的腰疼怎么办 手长白色的小泡怎么办 全身长水泡很痒怎么办 自吸泵声音大怎么办 索尼镜头盖丢了怎么办 15-45镜头盖丢了怎么办 手机镜头盖丢了怎么办 三星微单镜头盖怎么办 大胸走路容易抖怎么办 哎呦该怎么办是什么歌 老婆想爆我菊花怎么办 衣服泡了一晚上怎么办? 来大姨妈了该怎么办 耳机戴不住总掉怎么办 眼睛被辣椒辣了怎么办 电信光猫复位后怎么办 电信光猫重置了怎么办 u盘无法安全弹出怎么办 u盘不能安全弹出怎么办