现在的位置: 首页 > 综合 > 正文

用gdi+将内存位图文件保存为其它格式的图片

2013年10月21日 ⁄ 综合 ⁄ 共 3564字 ⁄ 字号 评论关闭

一个任务中需要将内存中的图片bmp文件,保存为png格式的图片,上网google了一下,找到一篇文章,介绍可以用gdi+将内存文件保存为其它格式的图片文件,参见《使用GDI+在内存中转换图片类型》,
作者:芦伟。在vc知识库网站上的,url:http://www.vckbase.com/document/viewdoc/?id=1177。参考了这篇文章,写个测试程序,源代码如下,在vc6.0下进行试验,将tmp.bmp转成newimg.png格式文件,效果不错,而且文件大小明显变小了。

 

这是调用函数,从本地读取tmp.bmp文件到内存中,然后绑定到cmemfile对象上,并且创建了newimg文件的cfile对象,打开这个文件(注意:原作者介绍的函数的输出对象仍然是cmemfile,而我需要在本地保存这个文件,所以用了cfile直接替换)

void CMybmpView::myconvbmp()
{
    CFile     file; 
    file.Open("temp.bmp", CFile::modeReadWrite,NULL); 

    BYTE*   buffer=(BYTE*)   malloc(file.GetLength()); 
    file.Read(buffer,file.GetLength()); 
   
    CMemFile   memfile; 
    memfile.Attach(buffer,file.GetLength(),1024); 
    memfile.SetLength(file.GetLength()); 
   

    CFile imgf;
    if(!imgf.Open("newimg.png", CFile::modeCreate | CFile::modeWrite))
        return;

    MBmpToMImage(memfile, imgf, "png");
    imgf.Close();
}

 

这个函数是将内存bmp转换成png的函数,这是转换主要实现部分,我没有太仔细研究这段代码,目前能实现转换功能。

 

BOOL CMybmpView::MBmpToMImage(CMemFile& cbfBmp, CFile& cbfImage, CString strType)
{
    int iBmpSize = cbfBmp.GetLength();
    HGLOBAL hMemBmp = GlobalAlloc(GMEM_FIXED, iBmpSize);
    if (hMemBmp == NULL) return FALSE;
    IStream* pStmBmp = NULL;
    CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp);
    if (pStmBmp == NULL)
    {
        GlobalFree(hMemBmp);
        return FALSE;
    }
    BYTE* pbyBmp = (BYTE *)GlobalLock(hMemBmp);
    cbfBmp.SeekToBegin();
    cbfBmp.Read(pbyBmp, iBmpSize);
   
    Image* imImage = NULL;
    imImage = Image::FromStream(pStmBmp, FALSE);
    if (imImage == NULL)
    {
        GlobalUnlock(hMemBmp);
        GlobalFree(hMemBmp);
        return FALSE;
    }
    USES_CONVERSION;
    CLSID clImageClsid;
   
    GetImageCLSID(A2W(("image/"+strType).GetBuffer(0)), &clImageClsid);
   
    HGLOBAL hMemImage = GlobalAlloc(GMEM_MOVEABLE, 0);
    if (hMemImage == NULL)
    {
        pStmBmp->Release();
        GlobalUnlock(hMemBmp);
        GlobalFree(hMemBmp);
        if (imImage != NULL) delete imImage;
        return FALSE;
    }
    IStream* pStmImage = NULL;
    CreateStreamOnHGlobal(hMemImage, TRUE, &pStmImage);
    if (pStmImage == NULL)
    {
        pStmBmp->Release();
        GlobalUnlock(hMemBmp);
        GlobalFree(hMemBmp);
        GlobalFree(hMemImage);
        if (imImage != NULL) delete imImage;
        return FALSE;
    }   
   
    imImage->Save(pStmImage, &clImageClsid);
    if (pStmImage == NULL)
    {
        pStmBmp->Release();
        pStmImage->Release();
        GlobalUnlock(hMemBmp);
        GlobalFree(hMemBmp);
        GlobalFree(hMemImage);
        if (imImage != NULL) delete imImage;
        return FALSE;
    }
    LARGE_INTEGER liBegin = {0};
    pStmImage->Seek(liBegin, STREAM_SEEK_SET, NULL);
    BYTE* pbyImage = (BYTE *)GlobalLock(hMemImage);
    cbfImage.SeekToBegin();
    cbfImage.Write(pbyImage, GlobalSize(hMemImage));
   
    if (imImage != NULL) delete imImage;
   
    pStmBmp->Release();
    pStmImage->Release();
    GlobalUnlock(hMemBmp);
    GlobalUnlock(hMemImage);
    GlobalFree(hMemBmp);
    GlobalFree(hMemImage);
    return TRUE;
}

 

这个函数同样是在网站上找的代码,是上面函数用到的

int CMybmpView::GetImageCLSID(const   WCHAR*   format,   CLSID*   pCLSID) 
{  
    //得到格式为format的图像文件的编码值,访问该格式图像的COM组件的GUID值保存在pCLSID中 
    UINT num  = 0; 
    UINT size = 0; 

    ImageCodecInfo* pImageCodecInfo = NULL; 
    GetImageEncodersSize(&num,   &size); 
   
    if(size == 0) 
        return FALSE;   //   编码信息不可用 
   
    //分配内存 
    pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); 
    if(pImageCodecInfo == NULL) 
        return FALSE;   //   分配失败 
   
    //获得系统中可用的编码方式的所有信息 
    GetImageEncoders(num, size, pImageCodecInfo); 
   
    //在可用编码信息中查找format格式是否被支持 
    for(UINT i = 0; i < num; ++i) 
    {
        //MimeType:编码方式的具体描述 
        if(wcscmp(pImageCodecInfo[i].MimeType, format) == 0) 
        { 
            *pCLSID = pImageCodecInfo[i].Clsid; 
            free(pImageCodecInfo); 
            return TRUE; 
        } 
    } 

    free(pImageCodecInfo); 
    return FALSE; 
}

抱歉!评论已关闭.