0.图像处理相关函数与类型概览
您好,这里是limou3434,本次我将给您带来的是easyX的图像处理相关接口。
如果您感兴趣也可以看看我的其他内容。
函数或数据类型 | 描述 |
---|---|
IMAGE | 保存图像的对象。 |
loadimage | 读取图片文件。 |
putimage | 在当前绘图设备上绘制指定图像。 |
rotateimage | 旋转 IMAGE 中的绘图内容。 |
Resize | 调整指定绘图设备的尺寸。 |
getimage | 从当前绘图设备中获取图像。 |
saveimage | 保存绘图内容至图片文件。 |
SetWorkingImage | 设定当前绘图设备。 |
GetWorkingImage | 获取指向当前绘图设备的指针。 |
GetImageBuffer | 获取绘图设备的显示缓冲区指针。 |
GetImageHDC | 获取绘图设备句柄。 |
1.IMAGE:图像对象
图像类使用的是C++的class类关键字创建的,可以依靠图像类创建出图像对象。(您可以把class理解成升级版的struct,里面不仅有成员变量,还能放入成员函数)
class IMAGE(int width = 0, int height = 0);
//公有成员内的函数
//int getwidth():返回IMAGE对象的宽度,以像素为单位
//int getheight():返回IMAGE对象的高度,以像素为单位
//operator=:实现IMAGE对象的直接赋值。该操作仅拷贝源图像的内容,不拷贝源图像的绘图环境。这是赋值运算符重载,可以使得两个图像对象进行赋值操作
2.loadimage:读取图片文件
loadimage()是配合上述的对象使用的函数,该函数可以读取一个图片文件,并让IMAGE类型的指针指向该图片文件。该函数也有重载版本,有两种用法。
//从图片文件获取图像(bmp/gif/jpg/png/tif/emf/wmf/ico)
void loadimage(
IMAGE* pDstImg, //保存图像的IMAGE对象指针
LPCTSTR pImgFile, //图片文件名
int nWidth = 0, //图片的拉伸宽度
int nHeight = 0, //图片的拉伸高度
bool bResize = false //是否调整IMAGE的大小以适应图片
);
//从资源文件获取图像(bmp/gif/jpg/png/tif/emf/wmf/ico)
void loadimage(
IMAGE* pDstImg, //保存图像的IMAGE对象指针
LPCTSTR pResType, //资源类型
LPCTSTR pResName, //资源名称
int nWidth = 0, //图片的拉伸宽度
int nHeight = 0, //图片的拉伸高度
bool bResize = false //是否调整IMAGE的大小以适应图片
);
//参数
//pDstImg:保存图像的IMAGE对象指针。如果为NULL,表示图片将读取至绘图窗口
//pImgFile:图片文件名。支持bmp/gif/jpg/png/tif/emf/wmf/ico 格式的图片。gif格式的图片仅加载第一帧;gif与png均不支持透明
//nWidth:图片的拉伸宽度。加载图片后,会拉伸至该宽度。如果为0,表示使用原图的宽度
//nHeight:图片的拉伸高度。加载图片后,会拉伸至该高度。如果为0,表示使用原图的高度。
//bResize:是否调整IMAGE的大小以适应图片
//pResType:图片资源类型
//pResName:图片资源名称
//返回值
//无
2.1.图片格式
需要注意的是loadimage()支持大部分的图片格式:bmp、gif、jpg、png、tif、emf、wmf、ico。这里我整理了一下有关图片格式的相关内容供您查阅:
- BMP(Bitmap):
- 包含未经压缩的图像数据,文件大小较大。
- 支持多种颜色模式和图像深度。
- 适用于存储位图和图形编辑软件中的临时图像。
- GIF(Graphics Interchange Format):
- 使用LZW压缩算法来减小文件大小。
- 支持使用索引颜色的图像,最多仅支持256种颜色。
- 支持动画和透明背景。
- 适用于简单的图标、动画、线条图等具有明确边界和较少颜色的图像。
- JPG或JPEG(Joint Photographic Experts Group):
- 使用有损压缩算法以较小的文件大小存储图像。
- 支持全彩色图像和较高的图像质量。
- 不支持透明背景和动画。
- 适用于摄影、复杂图像和需要保持良好质量的图像。
- PNG(Portable Network Graphics):
- 使用无损压缩算法以较小的文件大小存储图像。
- 支持全彩色图像、透明背景和图像的部分alpha通道。
- 不支持动画。
- 适用于图标、图形设计、网页图像和需要保留透明度的图像。
- TIFF(Tagged Image File Format):
- 支持多种压缩算法,可以选择有损或无损压缩。
- 支持全彩色图像、多页文档和多帧动画。
- 文件大小较大,不适合网络传输。
- 适用于打印、出版业、医学图像等需要高质量图像和元数据的场景。
- EMF(Enhanced Metafile)和WMF(Windows Metafile):
- 为矢量图形格式,可缩放而不失真。
- EMF是Windows特定的增强型元文件格式,支持更多功能。
- WMF是旧版的Windows元文件格式。
- 适用于矢量图形、图表、图标、绘图程序等需要保持较好清晰度和编辑能力的场景。
- ICO(Icon):
- 用于存储图标文件,通常用于Windows操作系统。
- 支持多种尺寸的图标图像。
- 适用于自定义应用程序图标、网站图标等。
在上述图片格式中,您最需要了解的图片格式是GIF、PNG、JPG/JPEG,因为这是最常用的图片格式,其他仅作了解即可。
2.2.图像文件获取和资源文件获取的区别
从资源文件获取这个暂时还用不到,先跳过,这里先展示图像文件获取的例子:
#include <graphics.h>
#include <cstdio>
int main()
{
//绘图窗口初始化
initgraph(1000, 1000, EX_SHOWCONSOLE);
//读取图片至绘图窗口
loadimage(NULL, _T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg"), 0, 0, true);//这里填写您图片的路径即可
getchar();
//关闭绘图窗口
closegraph();
getchar();
return 0;
}
3.putimage:在当前绘图设备上绘制指定图像
我们可以通过loadimage()读取图片,然后存储到IMAGE类型的对象中,在后续需要输出图片的时候使用putimage()输出图片。
//绘制图像
void putimage(
int dstX, //绘制位置的x坐标
int dstY, //绘制位置的y坐标
IMAGE *pSrcImg, //要绘制的IMAGE对象指针
DWORD dwRop = SRCCOPY //三元光栅操作码
);
//绘制图像(指定宽高和起始位置)
void putimage(
int dstX, //绘制位置的x坐标
int dstY, //绘制位置的y坐标
int dstWidth, //绘制的宽度
int dstHeight, //绘制的高度
IMAGE *pSrcImg, //要绘制的IMAGE对象指针
int srcX, //绘制内容在IMAGE对象中的左上角 x 坐标
int srcY, //绘制内容在IMAGE对象中的左上角 y 坐标
DWORD dwRop = SRCCOPY //三元光栅操作码
);
这里的三元光栅操作码我们以后再谈……
//使用例子
#include <graphics.h>
#include <cstdio>
int main()
{
//绘图窗口初始化
int length = 1000;
int width = 1000;
initgraph(length, width, EX_SHOWCONSOLE);
//坐标轴修正
setaspectratio(1, -1);
setorigin(length / 2, width / 2);
//读取图片至绘图对象
IMAGE img1;
loadimage(
&img1,
_T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg")
);
putimage(0, 0, &img1);
getchar();
//关闭绘图窗口
closegraph();
return 0;
}
4.rotateimage:旋转IMAGE中的绘图内容
在上面的图片输出中我们可以看到,easyX库对图片方向的输出是有自己的默认规则的,想要选择只能通过rotateimage()来选择,而不能旋转图片文件。
void rotateimage(
IMAGE *dstimg,
IMAGE *srcimg,
double radian,
COLORREF bkcolor = BLACK,
bool autosize = false,
bool highquality = true
);
//参数
//dstimg:指定目标IMAGE对象指针,用来保存旋转后的图像
//srcimg:指定原IMAGE对象指针
//radian:指定旋转的弧度
//bkcolor:指定旋转后产生的空白区域的颜色。默认为黑色
//autosize:指定目标IMAGE对象是否自动调整尺寸以完全容纳旋转后的图像。默认为false
//highquality:指定是否采用高质量的旋转。在追求性能的场合请使用低质量旋转。默认为true
这个函数也比较简单,下面给您展示一下使用的例子:
//使用例子
#include <graphics.h>
#include <cstdio>
int main()
{
//绘图窗口初始化
int length = 1000;
int width = 1000;
initgraph(length, width, EX_SHOWCONSOLE);
//坐标轴修正
setaspectratio(1, -1);
setorigin(length / 2, width / 2);
//读取图片至绘图对象
IMAGE img1;
loadimage(
&img1,
_T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg")
);
putimage(0, 0, &img1);
getchar();
//旋转后
IMAGE img2;
rotateimage(&img2, &img1, 3.14/2);
putimage(-500, -500, &img2);
getchar();
//关闭绘图窗口
closegraph();
return 0;
}
5.Resize:调整指定绘图设备的尺寸
注意这里的调整尺寸指的是裁剪尺寸不是缩放后的尺寸。
void Resize(
IMAGE* pImg,
int width,
int height
);
//参数
//pImg:指定要调整尺寸的绘图设备。如果为NULL,则表示默认绘图窗口。
//width:指定绘图设备的宽度。
//height:指定绘图设备的高度。
//返回值
//无
下面以一个例子来说明:
//使用例子
#include <graphics.h>
#include <cstdio>
int main()
{
//绘图窗口初始化
int length = 1000;
int width = 1000;
initgraph(length, width, EX_SHOWCONSOLE);
//读取图片至绘图对象
IMAGE img1;
loadimage(
&img1,
_T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg")
);
putimage(0, 0, &img1);
getchar();
//调整好大小后
Resize(&img1, 500, 500);
putimage(100, 100, &img1);
getchar();
closegraph();
return 0;
}
6.getimage:从当前绘图设备中获取图像
这个函数可以实现在当前设备中裁剪图像区域并且实现复制图像区域的效果。
void getimage(
IMAGE* pDstImg, //保存图像的IMAGE对象指针
int srcX, //要获取图像区域左上角x坐标
int srcY, //要获取图像区域的左上角y坐标
int srcWidth, //要获取图像区域的宽度
int srcHeight //要获取图像区域的高度
);
下面就一个例子来演示这个函数的使用:
//使用例子
#include <graphics.h>
#include <cstdio>
int main()
{
//绘图窗口初始化
int length = 1000;
int width = 1000;
initgraph(length, width, EX_SHOWCONSOLE);
//读取图片至绘图对象
IMAGE img1;
loadimage(
&img1,
_T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg")
);
putimage(0, 0, &img1);
getchar();
//旋转后
IMAGE img2;
rotateimage(&img2, &img1, 3.14/2, WHITE);
putimage(0, 0, &img2);
getchar();
//复制区域的图像并且输出
IMAGE img3;
getimage(&img3, 200, 200, 300, 300);
putimage(0, 0, &img3);
getchar();
closegraph();
return 0;
}
因此上面这段代码的结果如下:
7.saveimage:保存绘图内容至图片文件
void saveimage(
LPCTSTR strFileName,
IMAGE* pImg = NULL
);
//参数
//strFileName:指定目标图片的文件名。图片类型由文件名的扩展名指定,支持bmp/gif/jpg/png/tif 格式。保存文件时,已存在的文件将被覆盖。
//pImg:指定源IMAGE对象的指针。如果为NULL,表示绘图窗口。
//返回值
//无
让我们尝试保存刚刚绘画得到的图像:
//使用例子
#include <graphics.h>
#include <cstdio>
int main()
{
//绘图窗口初始化
int length = 1000;
int width = 1000;
initgraph(length, width, EX_SHOWCONSOLE);
//读取图片至绘图对象
IMAGE img1;
loadimage(
&img1,
_T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg")
);
putimage(0, 0, &img1);
getchar();
//旋转后
IMAGE img2;
rotateimage(&img2, &img1, 3.14/2, WHITE);
putimage(0, 0, &img2);
getchar();
//复制区域的图像并且输出
IMAGE img3;
getimage(&img3, 200, 200, 300, 300);
putimage(0, 0, &img3);
getchar();
//保存图像
saveimage("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\img.jpg");
closegraph();
return 0;
}
8.SetWorkingImage:设定当前绘图设备
如需要对某个IMAGE做绘图操作,可以通过SetWorkingImage()将其设置为当前的绘图设备,之后所有的绘图语句都会绘制在该IMAGE上面。将参数置为 NULL 可恢复对默认绘图窗口的绘图操作。
void SetWorkingImage(IMAGE* pImg = NULL);
//参数
//pImg:绘图设备指针。如果为NULL,表示绘图设备为默认绘图窗口。
//返回值
//无
下面举一个例子来说明SetWorkingImage()的使用:
//使用例子
#include <graphics.h>
#include <cstdio> int main()
{
//绘图窗口初始化
int length = 1000;
int width = 1000;
initgraph(length, width, EX_SHOWCONSOLE); //读取图片至绘图对象
IMAGE img1;
loadimage( &img1, _T("C:\\Users\\DELL\\Desktop\\SummerHolidaysFile\\GSnakeEasyxProject\\testPicture2.jpg") );
putimage(0, 0, &img1);
getchar(); //以下绘图操作都会绘制在img1对象上面
line(0 + 100, 100, 200 + 100, 100);
line(100 + 100, 0, 100 + 100, 200);
circle(100 + 100, 100, 50); //设置绘图目标为img1对象
SetWorkingImage(&img1);
printf("img1\n");
getchar(); //设置绘图目标为绘图窗口
SetWorkingImage();
line(0, 100, 200, 100);
line(100, 0, 100, 200);
circle(100, 100, 50);
printf("绘图窗口\n");
getchar();
closegraph();
return 0;
}
9.GetWorkingImage:获取指向当前绘图设备的指针
IMAGE* GetWorkingImage();
//参数
//无
//返回值
//返回指向当前绘图设备的指针。如果返回值为NULL,表示当前绘图设备为绘图窗口。
10.GetImageBuffer:获取绘图设备的显示缓冲区指针
这个函数比较强大,能够做到很微小的像素改动。
DWORD* GetImageBuffer(IMAGE* pImg = NULL);
//参数
//pImg:绘图设备指针。如果为 NULL,表示默认的绘图窗口。
//返回值
//返回绘图设备的显示缓冲区指针。
获取到的显示缓冲区指针可直接读写。在显示缓冲区中每个点占用4个字节(显示缓冲区的大小=宽度×高度×4字节)。
像素点在显示缓冲区中按照从左到右、从上向下的顺序依次排列。
访问显示缓冲区请勿越界,否则会造成难以预料的后果。显示缓冲区中的每个点对应 RGBTRIPLE 类型的结构体:
struct RGBTRIPLE {
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
}
RGBTRIPLE在内存中的表示形式为:0xrrggbb (bb=蓝,gg=绿,rr=红),而常用的COLORREF在内存中的表示形式为:0xbbggrr。注意两者的红色和蓝色是相反的,请用BGR宏交换红色和蓝色。
如果操作绘图窗口的显示缓冲区,请在操作完毕后,执行 FlushBatchDraw() 使操作生效。
//使用例子
#include <graphics.h>
#include <windows.h>
#include <cstdio>
int main()
{
//初始化绘图窗口
initgraph(640, 480, EX_SHOWCONSOLE);
//获取指向显示缓冲区的指针
DWORD* pMem = GetImageBuffer();//不写默认为NULL(表示默认的绘图窗口)
//直接对显示缓冲区赋值
for (int i = 0; i < 640 * 480; i++)
{
pMem[i] = BGR(RGB(0, 0, i * 256 / (640 * 480)));
if (i % 1000 == 0)
{
Sleep(100);
}
}
//使显示缓冲区生效(注:操作指向IMAGE的显示缓冲区不需要这条语句)
FlushBatchDraw();
//在计算机图形编程中,
//我们经常需要将绘制的图形显示在屏幕上。
//而绘制图形是一个相对耗费资源的操作,
//如果每次绘制都立即显示在屏幕上,
//会导致频繁的图形刷新,
//可能会引起画面闪烁或者卡顿的问题。
//为了提高绘制的效率和流畅度,
//就引入了批量绘制的概念。
//FlushBatchDraw()的作用是将之前批量绘制的图形一次性地刷新到屏幕上。
//通俗地说,就好比是一个“提交”操作,
//你之前进行的所有绘制都会在调用FlushBatchDraw()后一起显示在屏幕上
//按任意键退出
getchar();
closegraph();
return 0;
}
11.GetImageHDC:获取绘图设备句柄
这个函数以后再来补充……