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

VC++实现屏幕截图并保存为BMP:深入Windows GDI与位图文件格式 屏幕截图是计算机图形处理中的基础功能,其核心原理涉及操作系统对显示缓冲区的访问与像素数据的获取。在Windows平台上,这一过程主要通过图形设备接口(GDI)实现,它提供了访问屏幕设备上下文和操作位图的核心API。理解GDI的工作原理,对于开发屏幕录制、界面自动化测试等工具具有重要技术价值。本文聚焦于使用Visual C++和原生Windows API,详细解析如何通过GetDC、BitBlt等函数捕获屏幕像素,并遵循BMP文件格式规范,将原始数据保存为标准位图文件。文中深入探讨了设备上下文管理、内存位图操 阅读详情

一个任务中需要将内存中的图片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; 
}

SAP GUI 经典事务在 Fiori Launchpad 中的穿越之道:原理、配置与实践指南 在许多企业的 S/4HANA 或 ECC 系统里,经典 SAP GUI 事务依旧承载着关键业务。如何把这些老将自然地嵌入到 Fiori Launchpad,让用户在统一入口里无缝切换新旧 UI,是项目中经常遇到的主题。本文结合社区博文、官方文档与实际项目经验,系统梳理这一过程的技术原理、配置步骤、性能优化以及常见坑点,并给出贴近中国读者的案例解析与改进建议。阅读完毕,你将不仅知道怎么做,还会理解。 阅读详情

相关推荐

Zotero on Mac: 高效文献管理与引用指南

本文为Mac用户提供了一份全面的Zotero高效文献管理与引用指南。从安装配置、文献收集管理、PDF深度阅读与笔记,到在Word中无缝插入引用和生成参考文献,详细讲解了核心工作流。同时推荐了ZotFile、Better BibTeX等必备插件,并介绍了利用同步与WebDAV实现跨设备无缝衔接的方法,助力研究者构建个人数字知识库,极大提升学术研究效率。

weixin_29281941的博客 1176

c语言gdi 保存图片,GDI+中从内存读取图片/保存图片到内存

要给项目中增加一个新的模块,需要先在服务器端做一些图片处理相关的工作。本来,对图片做一些诸如ALPHA混合旋转缩放的操作,在游戏客户端应该是很容易的事。但是这事要在服务器做,就不得不引入一些第三方库。反正我们的服务器运行于WINDOWS下,这里又需要处理JPG图片的加载,我就考虑到了GDI+。在这之前对GDI+没有过任何接触。直接翻了MSDN,还好居然有个一系列的usage。GDI+的Image本...

weixin_30953203的博客 800

三菱PLC FX3U温度控制系统案例

U0\G100是平均次数的设置,设置为100个数据取平均,这样数据显示更加稳定,通道1的数据显示再U0\G10里面,温度模块的数据对应是0~150°输出0~10V,对应到0~10000的数据10000是150°的66.667倍,因此把数据传送到D0后转换成浮点数,再去除以66.667,就得到实际的温度了,数据存放到D2。触摸屏软件使用EBpro软件,设计界面如下,右边的是温度的实时曲线图,左边的是温度报警表,当当前温度超过了报警温度这种时,就会在这个表格上显示对应对应的报警。(1)实时显示温度值;

u010670857的博客 4058

GDI+(图像的显示和保存)

题目要求:   编写一个window应用程序,分别利用Bitmap类和PictureBox控件实现显示,保存图像的功能。  输入代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using S

汉南最後の読書人 2809

易智联LM401模块学习(四)——双串口收发

串口的发送和接受有三种方式,分别是阻塞发送和接收(轮询)、中断方式发送和接收、DMA方式发送和接收。这里我使用阻塞+中断的方式实现双串口通信。简单的串口收发。

weixin_46046597的博客 990

新手别怕!用嘉立创EDA从零画一块ESP8266最小系统板(附完整PCB源文件)

本文详细指导新手如何使用嘉立创EDA从零开始设计ESP8266最小系统板,涵盖原理图绘制、PCB布局、布线技巧及设计验证等关键步骤。通过实战案例和实用技巧,帮助读者快速掌握PCB设计基础,轻松打造自己的物联网开发板,并附完整PCB源文件供参考。

weixin_28716769的博客 618

2. GDI+图像的加载和保存

GDI只提供了加载和保存BMP图像的方法,对于现代化UI显示显然是不够的。GDI+提供了常用图像格式(BMP/TIFF/JPG/PNG/GIF等)的加载和保存,基于编码器/解码器的设计有利于进一步扩展,但是也存在一些坑,本文就这些加以详细说明,并给出一个封装类,可用于实际生产环境使用。

文洲的专栏 1667

Whisper 模型在嘈杂环境中的表现:降噪与增强技术

本报告系统分析了OpenAI Whisper模型在嘈杂环境中的表现机制,重点揭示其内在降噪能力的技术边界,并结合语音增强(SE)、时频分析等前沿技术提出优化方案。内容覆盖从基础概念(如噪声类型对ASR的影响)到理论框架(模型架构与数学形式化),再到实际应用(端到端部署策略)的全链路分析,同时通过案例研究与可视化工具(如梅尔频谱对比图)降低复杂概念的认知门槛。核心结论指出:Whisper的多语言预训练虽提升了泛化性,但在低信噪比(SNR<5dB)场景下需结合前端降噪或联合训练技术以突破性能瓶颈。

AI 原生应用开发的博客 488

GDI+ 在窗口显示内存图片

bool CTest::ShowImage(CWnd *pWnd, PBYTE pbImgData, int iImgDataLen) { if (pWnd == NULL || pbImgData == NULL || iImgDataLen < 1) { return false; } // 创建流 IStream *p

friendan的专栏 3552

优快云 2

2

qq_62260432的博客 5236

华为OD机试双机位C卷:流量波峰 (C/C++/Py/Java/Js/Go)

华为OD机试双机位C卷 流量波峰,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 流量波峰。

qq_45776114的博客 2445

GDI+ 保存HDC为位图文件

//GDI+为图片的加载、存储,屏蔽了内部编解码、压缩解压缩等的具体细节,给程序员带来了极大的方便 //目前版本的GDI+支持bmp jpeg gif tiff png等几种格式 //下面的程序基本思路是先将目标DC上的内容存到内存BITMAP //再使用GDI+Bitmap::FromHBITMAP加载内存位图,并保存成文件 //此版本在Win32和MFC环境下测试通过 // //使用GDI+ 保存HDC为位图文件 #include <rpc.h> #in...

yaowang107的博客 3842

Python爬虫实战:使用最新技术爬取GitHub Trending项目

本文将详细介绍如何使用Python最新技术栈构建一个高效的GitHub Trending爬虫。我们将使用异步请求库httpx、HTML解析库parsel、数据存储方案以及反反爬技术,完整实现一个能够稳定获取GitHub Trending数据的爬虫系统。文章包含5000余字详细教程,从环境搭建到代码实现,再到数据处理和存储,最后部署运行,提供全方位指导。GitHub Trending页面展示了GitHub上当前最受欢迎的项目,对于开发者了解技术趋势、发现优秀项目非常有价值。

2201_76125261的博客 736

使用GDI+ 保存HDC为位图文件

//GDI+为图片的加载、存储,屏蔽了内部编解码、压缩解压缩等的具体细节,给程序员带来了极大的方便 //目前版本的GDI+支持bmp jpeg gif tiff png等几种格式 //下面的程序基本思路是先将目标DC上的内容存到内存BITMAP //再使用GDI+Bitmap::FromHBITMAP加载内存位图,并保存成文件 //此版本在Win32和MFC环境下测试通过 // //使

zgl7903的专栏 6889

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

gdi+保存图片

首先,在StdAfx.h中静态调用diplus.lib,即由编译系统完成对DLL的加载,应用程序结束时卸载DLL的编码。如下: #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #include "GdiPlus.h" using namespace Gdiplus; #pragma comment(lib, "

sha_jinhao的专栏 1225

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

使用GDI+在内存中转换图片类型

<br />使用GDI+在内存中转换图片类型<br />作者:卢伟<br />微软新推出的GDI+功能强大,本文仅对图片转换加以讨论,不足之处请大家指出,本人QQ: 394777271 。<br />图片类型的转换支持:bmp、dib、png、gif、jpeg/jpg、tiff、emf等<br />以下是详细步骤。<br />首先在StdAfx.h中静态调用diplus.lib,即由编译系统完成对DLL的加载,应用程序结束时卸载DLL的编码。如下:<br />#ifndef ULONG_PTR<br />#

创业轨迹 1137

在内存绘图并保存为图片格式

1、保存为BMP图片格式 //将内存绘制的图保存为 HBITMAP,调用时可以按照尺寸只截取整个绘图区域的一部分 HBITMAP CopyDCToBitmap(HDC hScrDC, LPRECT lpRect) {  HDC hMemDC;  // 屏幕和内存设备描述表  HBITMAP hBitmap,hOldBitmap;  // 位图句柄  int nX, nY,

denghubu的专栏 6838

MFC中的GDI/GDI+和双缓冲绘图

1、GDI概述   GDI在全称是Graphics Device Interface,即图形设备接口。是图形显示与实际物理设备之间的桥梁。         GDI使得用户无需关心具体设备的细节,而只需在一个虚拟的环境(即逻辑设备)中进行操作。它的桥梁作用体现在:      (1)用户通过调用GDI函数将逻辑空间的操作转化为具体针对设备驱动程序的调用。      为实现图形设

Invoker's Tower 8084

GDI+ 制作透明图片

1:制作透明图片文件;       GDI+ 支持32位位图文件,所以自然就支持图片透明了;        首先:建立一个32位位图文件在内存中,将文件刷新为透明格式;        其次:在这个内存32位位图文件上作图;        最后:保存这个32位位图文件为指定格式的图片: 例子如下:在透明位图文件上作图,然后保存问题png格式文件: #include using nam

chinabinlang的专栏 8852

BMP与JPG图片格式的互相转换

近天要用到bmp与jpg之间互想转换,在网上查看了许多资料,如jpeglib,cximage,zlib,最后找到了GDI+利用流来转换,此方法最简单,可以实现在文件->文件,文件->内存,内存->内存,内存->文件保存,对于网络传送图片非常实用,通常320*240*24b的225k的BMP转成JPG后大约15.6K,压缩比15:1. 转换逻辑如下: 1.载入bmp或jpg文件,取得文件数据大小

lu1012123053的专栏 9033

Gdi+绘制半透明文字并保存为透明背景图片

透明、半透明原理:看画刷的颜色,Color的第一个参数指定透明值,范围0-255,0全透明,255不透明 1.新建MFC工程,名为newtou 2.添加头文件 #include using namespace Gdiplus; #pragma comment(lib, "Gdiplus") //Gdi+初始化 GdiplusStartupInput gdip

kevin的博客 5193

android保存透明图片格式,Android-加载透明PNG图片变黑的问题

png和jpg作为两种最常用的图片格式,首先我们要知道他们的区别:1.从一般图片的外观上来说,他们是无法直接判断的2.从文件大小上来说,同样一张图png肯定比jpg的大3.通过查资料咱们可以发现,png即可移植网络图形格式,也是一种位图文件存储格式,可以进行无损压缩。而jpg是我们最常见的图片格式了,图片占用存储较少,但是也牺牲了图片质量。总结为一句话是两者最大的区别是有损和无损。而出现加载透明p...

weixin_30020909的博客 1011

重温WIN32 API ------ 窗口上绘制位图文件

1 基本思路做界面仿真时,经常需要在窗口上贴图,随着图片数量的增多,通过资源文件中添加位图的方式会变得越来越不可控。所以本着“资源与程序分离“的原则,还是使用外部位图文件更加清晰明了。那么如何管理位图的贴图位置呢?如果写死到程序代码中,则又会导致耦合行过高的问题。容易想到解决方法有两个,一是使用一个单独的xml文件来记录图片文件名称和贴图位置的关系,二是直接把贴图位置信息包含进位图文件的文件名中。

smstong的成长轨迹 9630

GDI+ 保存图片

郑重提示:本代码是一个DLL供C#调用,使用CLI编写,但是原理是一样的。           首先获取到图片数据Buffer(不包含文件头和图片头),然后将之写入图片文件。 // 这是主 DLL 文件。 #include "stdafx.h" using namespace System; using namespace System::Runtime::InteropServices;

志汉天涯~!~Day Day Up~ 982
上一篇: 用内存位图的数据流创建cximage对象
下一篇: Flex4 AdvanceDataGrid去掉排序中竖线
secondfloor
博客等级 码龄18年 2粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值