文章目录
GDI和GDI+GDIplus的介绍和使用介绍GDI+库,使用GDI+读取图像文件
获取显示区域绘图句柄hdc创建GDI+绘图对象,并通过GDI+绘图对象的`DrawImag`方法显示图像。关闭GDI+最简单示例代码(25行)
GDI 和 GDI+
GDI是Graphics Device Interface的缩写,意为图形设备接口。它的主要任务是负责系统与绘图程序之间的信息交换以及处理所有Windows程序的图形输出。利用GDI提供的众多功能,您可以轻松地在屏幕、打印机和其他输出设备上输出图形、文本等操作。 GDI使程序员能够将应用程序的输出转换为硬件设备的输出,而不必担心硬件设备和设备驱动程序。实现了程序开发人员与硬件设备的隔离,极大的方便了开发工作。
GDI+(Graphics Device Interface plus)是windows 2000年后开发的新技术。GDI+是一组通过C++类实现的应用程序编程接口。 GDI+ 是以前版本的 GDI 的继承者。出于兼容性原因,Windows XP 仍然支持以前版本的 GDI。然而,在开发新的应用程序时,开发人员应该使用GDI+来满足图形输出需求,因为GDI+与以前的Windows版本不兼容。 GDI在此版本中进行了优化,并添加了许多新功能。
作为图形设备接口,GDI+允许应用程序开发人员输出屏幕和打印机信息,而无需考虑特定显示设备的细节。它们只需要调用GDI+库输出的类的一些方法即可完成图形操作。确实通过这些方法将绘图工作交给了具体的设备驱动程序。 GDI+ 将图形硬件和应用程序相互隔离。这使得开发人员可以非常轻松地编写与设备无关的应用程序。
VC++6.0,诞生于1998年,支持GDI编程。但默认情况下不支持 GDI+。用户需要安装新的Windows SDK。不过VC 2010版本直接支持GDI+编程。
GDI仅支持读取bmp等少数图像格式,而GID+支持大多数常见图像格式(如jpg、png、tif、gif等)。为了方便多种格式图像文件的读取和显示,下面实验以VS2010为开发平台,讲解如何使用GDI+读取图像文件并在控制台窗口中显示。 (关于如何使用MFC在新窗口或对话框窗口中应用GDI+的文章有很多,本文不再赘述)。
【注】VS2010绿色版请参见:VS2010绿色版下载
GDIplus介绍及使用
GDI+ 库简介
要使用GDI+,您需要导入gdiplus.h并链接到gdiplus.lib库。 GDI+ 函数位于命名空间 Gdiplus 中,也必须使用 using namespace Gdiplus; 来引入。否则,需要在GDI+函数前添加Gdiplus::前缀。
#包括
#pragma comment(lib,"gdiplus.lib")
//#define ULONG_PTR ULONG
使用命名空间Gdiplus;
【注】:在VC6中编译时,如果ULONG_PTR ULONG未定义,可以添加
#define ULONG_PTR ULONG
因为GDI+是WIndows Platform SDK的一部分,而不是MFC的一部分,并且SDK中ULONG_PTR的定义与MFC中的定义冲突,所以出现这个问题。
使用GDI+读取图像文件
然后,在主程序中使用GdiplusStartup函数启动GDI+:
GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
通过FromFile打开图像文件。
Image* pImage = Image::FromFile(L"wtclablogo.png");
也可以这样:
Image* pImage = new Image(L"testfile.jpg");
其中L"testfile.jpg"将字符串转换为宽字符。因为Image类只接受宽字符串WCHAR。
【注】以下函数也可用于将字符串 char * 转换为宽字符串类型 WCHAR。
WCHAR * charToWCHAR(char *s) {
int w_nlen = MultiByteToWideChar(CP_ACP, 0, s, -1, NULL, 0);
WCHAR *ret;
ret = (WCHAR*)malloc(sizeof(WCHAR)*w_nlen);
memset(ret, 0, sizeof(ret));
MultiByteToWideChar(CP_ACP, 0, s, -1, ret, w_nlen);
返回ret;
}
例如,要从main函数的命令行参数(argv[1]中设置)读取文件名,需要进行以下转换:
WCHAR * 文件名;
文件名 =charToWCHAR(argv[1]);
图像* pImage = 新图像(文件名);
获取显示区域绘图句柄hdc
extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow ();
主(){
HWND hWnd = GetConsoleWindow();
HDC hdc = GetDC(hWnd);
}
创建 GDI+ 绘图对象
构造Graphics对象并将其绑定到显示区域hdc。 (这里没有使用双缓冲)
图形图形(hdc);
通过GDI+绘图对象的DrawImag方法显示图像
最后通过Graphics对象的DrawImage方法在屏幕上进行绘制。其中,使用pImage->GetWidth()和pImage->GetHeight()来获取图像的宽度和高度(像素数)。
graphics.DrawImage(pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight());
关闭GDI+
可以在程序执行结束时关闭GDI+(在控制台窗口程序中,可以不关闭而退出)
GdiplusShutdown( m_gdiplusToken );
最简单的示例代码(25行)
本例读取一张png图片,放大2倍后显示。
#包括
#包括
#包括
#pragma comment(lib,"gdiplus.lib")
extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow ();
使用命名空间Gdiplus;
int main() {
Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
HWND hWnd = GetConsoleWindow();
HDC hdc = GetDC(hWnd);
图像* pImage = Image::FromFile(L"wtclablogo.png");
if ((pImage==NULL)||(pImage->GetLastStatus()!=Ok))
{
如果(pImage)
{
printf("无法打开图片");
删除pImage;
pImage = NULL;
}
返回FALSE;
}
图形图形(hdc);
graphics.DrawImage(pImage, 0, 0, pImage->GetWidth()*2, pImage->GetHeight()*2);
返回0;
}
以上代码可以在VS2010和VC++6(辅以GDI+)集成环境下编译。运行结果如下:
从运行结果来看,wtclablogo.png图片的透明部分也能正确显示。
【注】对于gif格式等多帧组成的图像,VS2010版本自带的GDI+只能支持帧分析。因此,下面读取gif图像的实验必须在VS2010中编译。
为了图像显示后能够重绘刷新,可以使用while循环(Ctrl+C退出)结合Sleep函数来实现,如上一篇文档所述。
同时(正确){
graphics.DrawImage(pImage, 0, 0, pImage->GetWidth()*2, pImage->GetHeight()*2);
睡眠(100);
}
完整代码:
#包括
#包括
#包括
#pragma comment(lib,"gdiplus.lib")
extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow ();
使用命名空间Gdiplus;
int main() {
Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
HWND hWnd = GetConsoleWindow();
HDC hdc = GetDC(hWnd);
图像* pImage = Image::FromFile(L"wtclablogo.png");
if (!pImage) {
printf("无法打开图片");
返回-1;
}
图形图形(hdc);
同时(正确){
graphics.DrawImage(pImage, 0, 0, pImage->GetWidth()*2, pImage->GetHeight()*2);
睡眠(100);
}
GdiplusShutdown( m_gdiplusToken );//关闭GDI+,可略此句
返回0;
}
首先解释以下两个名词(仅供参考,可跳过)
JPEG=联合摄影专家组(Joint Photographic Experts Group),是第一个国际图像压缩标准。 JPEG图像压缩算法不仅能够提供良好的压缩性能,而且具有较好的重建质量,广泛应用于图像和视频处理领域。人们日常遇到的.jpeg、.jpg等是指图像数据经过压缩编码后在介质上的存储形式,不能与JPEG压缩标准混淆。 (百度百科)
IJG 是一个非正式小组,编写并分发广泛使用的免费 JPEG 图像压缩库。第一个版本于 1991 年 10 月 7 日发布。 (http://www.sychzs.cn/)
本文将重点介绍IJG提供的JPEG图像压缩/解压缩库的编译和初步使用。
首先从IJG网站http://www.sychzs.cn/下载源代码。编辑本文时发布的版本是版本 9a
编译
我们要在Visual Studio 2010环境下编译,编译目标是libjpeg.lib
1。下载www.sychzs.cn并解压
2。将 www.sychzs.cn 文件的内容复制到新文件 jconfig.h
3。编辑www.sychzs.cn文件的内容
由于机器配置等原因,.mak文件路径可能会有所不同
? ? ?
以上截图为测试机上的文件路径(Windows 7 Professional 64位)
C:\ Program Files(x86)\ Microsoft SDKs \ Windows \ v7.0A \ Include \ Win32.Mak
4。编译
开始菜单-->VS2010工具-->VS命令提示符
切换到源码所在目录
键入命令 nmake /f www.sychzs.cn nodebug=1
nodebug开关(=1打开)表示以release模式编译
几秒后,编译完成
生成的目标是libjpeg.lib
5。使用
复制以下4个文件
其中jconfig.h是第2步修改的,jmorecfg.h是一些更详细的配置,jpeglib.h是库引用语句
使用时只需将上述头文件和库文件添加到工程中即可。
示例
以下是一个简单的JPEG文件读取(解压)示例
#包括
#include "jpeglib.h"
#pragma comment(lib,"libjpeg.lib")
#pragma warning(disable:4996)
typedef 无符号字符 BYTE;
int main(void)
{
printf("输入jpeg文件路径:");
char szFileName[256] = { 0 };
scanf("%s", szFileName);
jpeg_decompress_struct cinfo;
jpeg_error_mgr jerr;
// 第 1 步:标准错误
cinfo.err = jpeg_std_error(&jerr);
// 第 2 步:创建
jpeg_create_decompress(&cinfo);
文件* pf = fopen(szFileName, "rb");
if (pf != NULL)
{
// 第三步:IO
jpeg_stdio_src(&cinfo, pf);
// 第 4 步:标题
jpeg_read_header(&cinfo, TRUE);
长字节 = cinfo.image_width*cinfo.image_height*cinfo.num_components;
printf("分配%d字节内存:",bytes);
BYTE* 数据 = 新 BYTE[字节];
if(数据!= NULL)
{
printf("好的。\n准备解压图片...\n");
// 第 5 步:开始
jpeg_start_decompress(&cinfo);
JSAMPROW row_pointer[1];
// 第 6 步:读取扫描
while (cinfo.output_scanline < cinfo.output_height)
{
row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline - 1)*cinfo.image_width*cinfo.num_components];
jpeg_read_scanlines(&cinfo, row_pointer, 1);
}
// 第 7 步:完成
jpeg_finish_decompress(&cinfo);
// 用
做某事// 这里是字节数据[]
//然后松开
删除[]数据;
}
其他
{
printf("失败。\n");
}
// 第 8 步:摧毁
jpeg_destroy_decompress(&cinfo);
fclose(pf);
printf("JPEG解压完成。\n");
}
其他
{
printf("无法打开\'%s\'\n", szFileName);
}
printf("按 ENTER 继续...");
getchar();
getchar();
返回0;
}
某次运行结果截图(拍摄了1920*1080 JPG格式图片进行测试)
原创文章、博文地址
http://www.sychzs.cn/fengyhack/article/details/42239807
转载于:https://www.sychzs.cn/fengyhack/p/10603586.html
今天的测试程序需要简单的按钮图片加载,并且图片是在VS之外编辑和替换的。第一次编译时出现错误。
这种错误很少见。
我尝试修改原始图像,例如更改格式、更改位图深度等,但没有成功。
直接从其他地方复制新镜像覆盖,然后用VS重新导入资源即可解决问题。
?