VC如何将资源中包含的位图释放成文件

转载自:http://hi.baidu.com/doubleuto/item/36738fa14e1753a828ce9dc0


一般的操作都是引入资源,这个是把资源导出。暂且学习下,没有找到合适的应用场景。

#ifndef __LOADRES_H__
#define __LOADRES_H__
BOOL FreeSource_1(LPCTSTR pszResName,LPCTSTR pszResType,LPCTSTR szFileName)   
{   
    BOOL bRet = TRUE;   
    HINSTANCE hInst = GetModuleHandle(NULL);  
    //判断指定的资源是否存在   
    HRSRC hResInfo = FindResource(hInst,pszResName,pszResType);   
    if(hResInfo == NULL)   
        return FALSE;  
    HANDLE hFile = NULL;   
    DWORD dwWritten = 0;  
    //调入指定的资源到内存   
    HGLOBAL hResData = LoadResource(hInst,hResInfo);   
    LPVOID pvResData = LockResource(hResData);   
    DWORD dwResSize = SizeofResource(hInst,hResInfo);  
    //创建目标文件并保存数据至文件   
    hFile = CreateFile(   
        szFileName,   
        GENERIC_WRITE,   
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,   
        NULL,   
        CREATE_ALWAYS,   
        FILE_ATTRIBUTE_HIDDEN, NULL   
    );  
    WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);  
    //释放有关内存资源   
    CloseHandle(hFile);   
    FreeResource(hResData);  
    return TRUE;  
} 
/*
    调用代码为:
FreeSource(MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP, "C:\\TEMP1.BMP");   
FreeSource(MAKEINTRESOURCE(IDR_JPG1), "JPG", "C:\\TEMP2.JPG"); 
FreeSource(MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP, "C:\\TEMP1.BMP");
FreeSource(MAKEINTRESOURCE(IDR_JPG1), "JPG", "C:\\TEMP2.JPG");

    奇怪的是,上述代码对自定义类型的资源,如GIF、JPEG甚至EXE都能正确释放,但对于BMP类型的却无能为力。虽然保存到了磁盘上,却无法打开,提示为格式错误!

    于是,我又自作聪明地使用流技术,把内存中的图像数据写回磁盘,代码如下:
*/
BOOL FreeSource_2(LPCTSTR pszResName,LPCTSTR pszResType,LPCTSTR szFileName)   
{   
    BOOL bRet = TRUE;   
    HINSTANCE hInst = GetModuleHandle(NULL);  
    //判断指定的资源是否存在   
    HRSRC hResInfo = FindResource(hInst,pszResName,pszResType);   
    if(hResInfo == NULL)return FALSE;  
    HANDLE hFile = NULL;   
    DWORD dwWritten = 0;  
    //直接保存自定义资源,如JPG、GIF、EXE等   
    if(pszResType != RT_BITMAP)   
    {   
        //使用LoadResource调入指定的资源到内存   
        HGLOBAL hResData = LoadResource(hInst,hResInfo);   
        LPVOID pvResData = LockResource(hResData);   
        DWORD dwResSize = SizeofResource(hInst,hResInfo);  
        //创建目标文件并保存数据至文件   
        hFile = CreateFile(   
            szFileName,   
            GENERIC_WRITE,    
            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,   
            NULL,   
            CREATE_ALWAYS,   
            FILE_ATTRIBUTE_HIDDEN,   
            NULL   
        );  
        WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);   
    
        //释放有关内存资源   
        CloseHandle(hFile);   
        FreeResource(hResData);   
    }   
    else //使用流技术保存BITMAP位图   
    {   
        //使用LoadBitmap调入指定的位图资源   
        HBITMAP hBitmap = LoadBitmap(hInst, pszResName);  
        if(hBitmap == NULL)return FALSE;  
        //创建一个IPicture接口的实例   
        PICTDESC ps;   
        IPicture* pIPic=NULL;  
        ps.cbSizeofstruct = sizeof(PICTDESC);   
        ps.picType = PICTYPE_BITMAP;   
        ps.bmp.hbitmap = hBitmap;   
        ps.bmp.hpal = NULL;   
        if(OleCreatePictureIndirect(&ps, IID_IPicture, TRUE,(LPVOID*)&pIPic) != ERROR_SUCCESS)   
        {   
            DeleteObject(hBitmap);   
            return FALSE;   
        }  
        //将IPicture接口实例中的数据写入流接口中   
        LONG lSize = 0;   
        IStream* pIStm = NULL;   
        CreateStreamOnHGlobal(NULL,TRUE,&pIStm);   
        if(pIPic->SaveAsFile(pIStm,TRUE,&lSize) != ERROR_SUCCESS)   
        {   
            pIPic->Release();   
            DeleteObject(hBitmap);   
            return FALSE;   
        }  
        //保存流接口中的数据   
        LARGE_INTEGER li;   
        li.HighPart = 0;   
        li.LowPart = 0;   
        ULARGE_INTEGER uli;   
        uli.HighPart = 0;   
        uli.LowPart = 0;   
        pIStm->Seek(li, STREAM_SEEK_SET, &uli);  
        //创建目标文件并循环读取流中的数据保存至文件   
        char buffer[1024];   
        hFile = CreateFile(   
            szFileName,   
            GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,   
            NULL,   
            CREATE_ALWAYS,   
            FILE_ATTRIBUTE_HIDDEN,   
            NULL);  
        DWORD dwRead = 1;   
        while(dwRead>0)   
        {   
            pIStm->Read(buffer, 1024, &dwRead);   
            if(dwRead > 0)   
                WriteFile(hFile, buffer, dwRead, &dwWritten, NULL);   
        }  
        //释放有关内存资源   
        CloseHandle(hFile);   
        DeleteObject(hBitmap);   
        pIPic->Release();   
        pIStm->Release();   
    }   
    return TRUE;   
}
/*
    果然不出所料,资源中所包含的位图被成功地保存到磁盘,并能被正确地打开了。于是我把代码给了朋友,算是完成了一个小任务。

    今天下午,突然想起第一个函数写成的文件总比源文件少14个字节,使用流技术会不会自动补全啊,于是对比了一下图片文件,意外发现生成的目标文件竟然比源文件多出了2倍多的字节,我顿时惊呆了。这是为什么呢?
14字节!14字节?我脑海里反复想到这个数字,因为按照常理,第一个函数便能正确运行的啊。第二函数虽然运行成功了,但文件大小又有了出入。这中间一定有鬼。
肯定是VC开发环境对BITMAP、ICON之类的资源作了手脚。
14字节!——这不正是位图文件头的结构大小吗?哦,也许是VC对位图资源忽略了文件头。于是赶快实验,便写了第三个函数,代码如下:
*/
BOOL FreeSource_3(LPCTSTR pszResName,LPCTSTR pszResType,LPCTSTR szFileName)   
{   
    BOOL bRet = TRUE;   
    HINSTANCE hInst = GetModuleHandle(NULL);  
    //判断指定的资源是否存在   
    HRSRC hResInfo = FindResource(hInst,pszResName,pszResType);   
    if(hResInfo == NULL)   
        return FALSE;  
    HANDLE hFile = NULL;   
    DWORD dwWritten = 0;   
    //调入指定的资源到内存   
    HGLOBAL hResData = LoadResource(hInst,hResInfo);   
    LPVOID pvResData = LockResource(hResData);   
    DWORD dwResSize = SizeofResource(hInst,hResInfo);  
    //创建目标文件并保存数据至文件   
    hFile = CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);   
    if(pszResType == RT_BITMAP)   
    {   
        //获得位图信息头   
        BITMAPINFOHEADER bmpInfoHdr;   
        CopyMemory(&bmpInfoHdr, pvResData, sizeof(BITMAPINFOHEADER));   
        //获得位图颜色表中RGBQUAD结构的个数   
        long nColorEntries;   
        switch(bmpInfoHdr.biBitCount)   
        {   
        case 1:   
            nColorEntries = 2;   
            break;   
        case 4:   
            nColorEntries = 16;   
            break;   
        case 8:   
            nColorEntries = 256;   
            break;   
        default:   
            nColorEntries = 0;   
        }   
        //根据位图信息头创建位图文件头   
        BITMAPFILEHEADER bmpFileHdr;   
        bmpFileHdr.bfType = 0x4d42; // 'BM'   
        bmpFileHdr.bfSize = sizeof(BITMAPINFOHEADER) + dwResSize;   
        bmpFileHdr.bfReserved1 = bmpFileHdr.bfReserved2 = 0;   
        bmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorEntries;   
        //写入位图文件头   
        WriteFile(hFile, &bmpFileHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);   
    }   
    WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);   
    //释放有关内存资源   
    CloseHandle(hFile);   
    FreeResource(hResData);   
    return TRUE;   
}; 
#endif


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值