page contents

C语言——图形库图像处理相关函数

C语言——图形库图像处理相关函数

一、IMAGE

图像对象。

class IMAGE(int width = 0, int height = 0);

公有成员:

int getwidth();

返回 IMAGE 对象的宽度,以像素为单位。

int getheight();

返回 IMAGE 对象的高度,以像素为单位。

operator =

实现 IMAGE 对象的直接赋值。该操作仅拷贝源图像的内容,不拷贝源图像的绘图环境。

示例:

以下局部代码创建 img1、img2 两个对象,之后加载图片 test.jpg 到 img1,并通过赋值操作将 img1 的内容拷贝到 img2:

IMAGE img1, img2;
loadimage(&img1, _T("test.jpg"));
img2 = img1;

以下局部代码创建 img 对象,之后加载图片 test.jpg,并将图片的宽高赋值给变量 w、h:

IMAGE img;
loadimage(&img, _T("test.jpg"));
int w, h;
w = img.getwidth();
h = img.getheight();

更多示例请参考 putimage 函数示例。

二、loadimage

这个函数用于从文件中读取图像。

// 从图片文件获取图像(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

图片资源名称。

返回值:

(无)

说明:

如果创建 IMAGE 对象的时候没有指定宽高,可以通过 Resize 函数设置。

对于没有设置宽高的 IMAGE 对象,执行 loadimage 会将其宽高设置为和读取的图片一样的尺寸。

示例:

// 完整示例:加载图片“D:\test.jpg”至绘图窗口
#include <graphics.h>
#include <conio.h>

// 主函数
int main()
{
	// 绘图环境初始化
	initgraph(640, 480);

	// 读取图片至绘图窗口
	loadimage(NULL, _T("D:\\test.jpg"));

	// 按任意键退出
	_getch();
	closegraph();
}
// 局部代码:加载图片“D:\test.jpg”至绘图窗口(MBCS 及 Unicode 自适应)
loadimage(NULL, _T("D:\\test.jpg"));
// 局部代码:加载“IMAGE”分类下的图像资源“Player”至 img 对象,并在屏幕的指定位置显示
IMAGE img;
loadimage(&img, _T("IMAGE"), _T("Player"));
putimage(100, 100, &img);    // 在另一个地方再次显示背景
// 局部代码:加载“IMAGE”分类下的图像资源 IDR_PLAYER 至 img 对象,并在屏幕的指定位置显示
IMAGE img;
loadimage(&img, _T("IMAGE"), MAKEINTRESOURCE(IDB_PLAYER));
putimage(100, 100, &img);    // 在另一个地方再次显示背景

三、saveimage

这个函数用于保存绘图内容至图片文件。

void saveimage(
	LPCTSTR strFileName,
	IMAGE* pImg = NULL
);

参数:

strFileName

指定文件名。文件名的扩展名表示保存的图片格式,支持 bmp / gif / jpg / png / tif 格式。已存在的文件将被覆盖。

pImg

指向 IMAGE 对象的指针。如果为 NULL,表示绘图窗口。

返回值:

(无)

示例:

以下示例保存绘图窗口的内容为 "D:\\test.bmp":

#include <graphics.h>
#include <conio.h>

int main()
{
	// 绘图环境初始化
	initgraph(640, 480);

	// 绘制图像
	outtextxy(100, 100, _T("Hello World!"));
	
	// 保存绘制的图像
	saveimage(_T("D:\\test.bmp"));

	// 按任意键退出
	_getch();
	closegraph();
}

四、getimage

这个函数用于从当前绘图设备中获取图像。

// 从当前绘图设备获取图像
void getimage(
    IMAGE* pDstImg,   // 保存图像的 IMAGE 对象指针
    int srcX,         // 要获取图像区域左上角 x 坐标
    int srcY,         // 要获取图像区域的左上角 y 坐标
    int srcWidth,     // 要获取图像区域的宽度
    int srcHeight     // 要获取图像区域的高度
);

参数:

 pDstImg

保存图像的 IMAGE 对象指针。

srcX

要获取图像区域的左上角 x 坐标。

srcY

要获取图像区域的左上角 y 坐标。

srcWidth

要获取图像区域的宽度。

srcHeight

 要获取图像区域的高度。

返回值:

(无)

示例:

请参考 putimage 函数示例。

五、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  // 三元光栅操作码(详见备注)
);

参数:

(详见各重载函数原型内的注释)

备注:

三元光栅操作码(即位操作模式),支持全部的 256 种三元光栅操作码,常用的几种如下:

DSTINVERT 绘制出的像素颜色 = NOT 屏幕颜色
MERGECOPY 绘制出的像素颜色 = 图像颜色 AND 当前填充颜色
MERGEPAINT 绘制出的像素颜色 = 屏幕颜色 OR (NOT 图像颜色)
NOTSRCCOPY 绘制出的像素颜色 = NOT 图像颜色
NOTSRCERASE 绘制出的像素颜色 = NOT (屏幕颜色 OR 图像颜色)
PATCOPY 绘制出的像素颜色 = 当前填充颜色
PATINVERT 绘制出的像素颜色 = 屏幕颜色 XOR 当前填充颜色
PATPAINT 绘制出的像素颜色 = 屏幕颜色 OR ((NOT 图像颜色) OR 当前填充颜色)
SRCAND 绘制出的像素颜色 = 屏幕颜色 AND 图像颜色
SRCCOPY 绘制出的像素颜色 = 图像颜色
SRCERASE 绘制出的像素颜色 = (NOT 屏幕颜色) AND 图像颜色
SRCINVERT 绘制出的像素颜色 = 屏幕颜色 XOR 图像颜色
SRCPAINT 绘制出的像素颜色 = 屏幕颜色 OR 图像颜色

注:
1. AND / OR / NOT / XOR 为布尔运算。
2. "屏幕颜色"指绘制所经过的屏幕像素点的颜色。
3. "图像颜色"是指通过 IMAGE 对象中的图像的颜色。
4. "当前填充颜色"是指通过 setfillcolor 设置的用于当前填充的颜色。
5. 查看全部的三元光栅操作码请点这里:三元光栅操作码

返回值:

(无)

示例:

以下局部代码将屏幕 (0,0) 起始的 100x100 的图像拷贝至 (200,200) 位置:

IMAGE img;
getimage(&img, 0, 0, 100, 100);
putimage(200, 200, &img);

六、GetWorkingImage

这个函数用于获取当前的绘图设备。

IMAGE* GetWorkingImage();

参数:

(无)

返回值:

返回指向当前绘图设备的指针。如果返回值为 NULL,表示当前绘图设备为绘图窗口。

示例:

(无)

七、rotateimage

这个函数用于旋转 IMAGE 中的绘图内容。

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。

返回值:

(无)

示例:

以下示例加载图片 "C:\\test.jpg" 并旋转 30 度 (PI / 6),然后显示在左上角:

#include <graphics.h>
#include <conio.h>

#define PI 3.1415926535

int main()
{
	// 绘图环境初始化
	initgraph(640, 480);

	// 定义图像
	IMAGE img1, img2;
	
	// 从文件加载图像
	loadimage(&img1, _T("C:\\test.jpg"));

	// 旋转图像 30 度 (PI / 6)
	rotateimage(&img2, &img1, PI / 6);
	
	// 显示旋转后的图像
	putimage(0, 0, &img2);

	// 按任意键退出
	_getch();
	closegraph();
}

八、SetWorkingImage

这个函数用于设定当前的绘图设备。

void SetWorkingImage(IMAGE* pImg = NULL);

参数:

pImg

绘图设备指针。如果为 NULL,表示绘图设备为默认绘图窗口。

返回值:

(无)

说明:

如果需要对某个 IMAGE 做绘图操作,可以通过该函数将其设置为当前的绘图设备,之后所有的绘图语句都会绘制在该 IMAGE 上面。将参数置为 NULL 可恢复对默认绘图窗口的绘图操作。

示例:

#include <graphics.h>
#include <conio.h>

int main()
{
	// 初始化绘图窗口
	initgraph(640, 480);

	// 创建 200x200 的 img 对象
	IMAGE img(200, 200);
	
	// 设置绘图目标为 img 对象
	SetWorkingImage(&img);
	// 以下绘图操作都会绘制在 img 对象上面
	line(0, 100, 200, 100);
	line(100, 0, 100, 200);
	circle(100, 100, 50);

	// 设置绘图目标为绘图窗口
	SetWorkingImage();
	// 将 img 对象显示在绘图窗口中
	putimage(220, 140, &img);

	// 按任意键退出
	_getch();
	closegraph();
}

九、Resize

这个函数用于调整指定绘图设备的尺寸。

void Resize(IMAGE* pImg, int width, int height);

参数:

pImg

指定要调整尺寸的绘图设备。如果为 NULL,则表示默认绘图窗口。

width

指定绘图设备的宽度。

height

指定绘图设备的高度。

返回值:

(无)

说明:

(无)

示例:

(无)

十、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 <conio.h>

int main()
{
	// 初始化绘图窗口
	initgraph(640, 480);

	// 获取指向显存的指针
	DWORD* pMem = GetImageBuffer();

	// 直接对显存赋值
	for(int i = 0; i < 640 * 480; i++)
		pMem[i] = BGR(RGB(0, 0, i * 256 / (640 * 480) ));

	// 使显存生效(注:操作指向 IMAGE 的显存不需要这条语句)
	FlushBatchDraw();

	// 按任意键退出
	_getch();
	closegraph();
}

十一、GetImageHDC

这个函数用于获取绘图设备句柄(HDC)。

HDC GetImageHDC(IMAGE* pImg = NULL);

参数:

pImg

绘图设备指针。如果为 NULL,表示默认的绘图窗口。

返回值:

返回绘图设备句柄(HDC)。

说明:

获取到的 HDC 句柄可以用在 Windows GDI 函数中。

每个 IMAGE 对象都有一个 HDC 句柄,可以通过 HDC 句柄实现对该 IMAGE 的 GDI 函数操作。在同一个 IMAGE 设备中,请勿混用 EasyX 绘图函数和 GDI 绘图函数。

如果获取默认绘图窗口的 HDC 句柄,那么执行 GDI 函数后并不会直接显示到屏幕上,请执行 FlushBatchDraw() 显示之前的 GDI 操作效果。

示例:

#include <graphics.h>
#include <conio.h>

int main()
{
	// 初始化绘图窗口
	initgraph(640, 480);


	// 获取默认绘图窗口的 HDC 句柄
	HDC hdc = GetImageHDC();

	// 执行 Windows GDI 绘图函数
	MoveToEx(hdc, 10, 10, NULL);
	LineTo(hdc, 100, 100);

	// 使之前的 Windows GDI 绘图生效
	FlushBatchDraw();


	// 创建大小为 200x200 的 img 对象
	IMAGE img(200, 200);

	// 获取该 img 对象的 HDC 句柄
	hdc = GetImageHDC(&img);

	// 执行 Windows GDI 绘图函数
	Ellipse(hdc, 0, 50, 199, 150);

	// 将 img 对象显示到绘图窗口上面
	putimage(100, 0, &img);


	// 按任意键退出
	_getch();
	closegraph();
}
  • 发表于 2021-10-06 16:56
  • 阅读 ( 1742 )
  • 分类:C/C++开发

0 条评论

请先 登录 后评论
小威
小威

64 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1471 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章