要实现将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下仍会显示不透明背景