用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; 
}

保姆级教程:用Anaconda+PyCharm搞定YOLOv8本地部署(附避坑指南) 本文提供了一份详细的YOLOv8本地部署指南,涵盖Anaconda环境配置、PyCharm集成到模型部署的全过程。特别针对国内开发者需求,整合了镜像加速和常见报错解决方案,帮助快速完成目标检测模型的本地部署与实战应用。 阅读详情

相关推荐

从DBC到ARXML:用RTA-CAR7实现车载通信协议栈自动化生成全流程

本文详细介绍了如何利用ETAS RTA-CAR7工具链,特别是ISOLAR-A和RTA-BSW ConfGen,实现从车载通信DBC文件到AUTOSAR ARXML系统描述文件,再到基础软件(BSW)协议栈代码的自动化生成全流程。该流程通过深度配置、信号路由、PDU复用及规则定制,大幅提升开发效率与一致性,是应对现代汽车电子复杂网络开发的关键实践。

brandy的博客 220

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

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

weixin_30953203的博客 800

5G时代必知:LDPC与Polar码实战解析(附MATLAB仿真代码)

本文深入解析5G时代核心信道编码技术LDPC码与Polar码的原理差异及性能表现,通过MATLAB仿真代码展示其在实际通信系统中的应用。LDPC码适用于大数据块高速传输,而Polar码在小数据块低时延场景表现优异,帮助开发者优化5G系统设计。

sugar的博客 642

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

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

汉南最後の読書人 2809

Qt入门教程【基础控件篇】QLineEdit输入框

QLineEdit输入框

小鱼酱的博客 3261

Android11原生设置屏幕亮由Gamma变化改为线性变化

从Android9 开始屏幕亮度调解变成非线性变化,这样的话就会出现 之前亮度变化很小,到后面时变化亮度很快; 修改为线性变化,只需要修改 ./frameworks/base/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache L

Android 4923

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

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

文洲的专栏 1667

机器人控制算法九之 位姿描述与空间变换

机器人控制算法九之 位姿描述与空间变换

yohnyang的博客 1029

GDI+ 在窗口显示内存图片

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

friendan的专栏 3552

基于STM32、HAL库的AD7124-8BCPZ模数转换器ADC驱动程序设计

/ 配置0: 使用内部参考电压(2.5V),增益128,双极性。// 配置通道0: AIN0+和AIN1-,使用配置0和滤波器0。// 100ms采样间隔。// 转换为电压值(使用内部2.5V参考电压)// 构造读命令: 最高位为1表示读,接下来7位是寄存器地址。// 构造写命令: 最高位为0表示写,接下来7位是寄存器地址。// 配置滤波器0: 输出数据率50Hz,后置滤波器4。

corlin6688的博客 528

基于Keil软件实现对射式红外传感器计次 (江协科技HAL库)

用HAL库复现江协科技,让嵌入式学习之路更顺畅。

2401_82728381的博客 798

GDI+ 保存HDC为位图文件

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

yaowang107的博客 3842

把 LangGraph 当“工作流引擎”用:与传统 BPM 的差异与融合策略

首先,我们来回顾一下有限状态机(FSM)的基本定义——一个 FSM 可以用一个五元组MQΣδq0FMQΣδq0​FQQQ有限状态集合,包含 FSM 所有可能的状态;Σ\SigmaΣ有限输入字母表,包含 FSM 所有可能的输入;δ\deltaδ状态转移函数,定义了 FSM 从当前状态q∈Qq \in Qq∈Q接收输入σ∈Σσ∈Σ后,转移到的下一个状态q′∈Qq' \in Qq′∈Q,即δQ×Σ→QδQ×Σ→Q。

AI 原生应用开发的博客 227

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

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

zgl7903的专栏 6889

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

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

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

使用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

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

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

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、付费专栏及课程。

余额充值