使用GDI+、文件和目录和打印API,批量将图片按文件名分组打包成PDF

代码写了两个小时,速度太慢(包括学习文档的时间)。

我接到一个同学的求助,她需要将 389 个图片文件按照文件名分组,每一组再扫描成PDF。图片文件大概长这样:

D:\pic2pdf>dir *.jpg
 驱动器 D 中的卷是 Data
 卷的序列号是 ####-####

 D:\pic2pdf 的目录

2025/02/19  09:34           388,171 2025####J02_回函扫描件_01.jpg
2025/02/19  09:34           416,678 2025####J02_回函扫描件_02.jpg
2025/02/19  09:34           414,120 2025####J02_回函扫描件_03.jpg
2025/02/19  09:34           380,703 2025####J02_回函扫描件_04.jpg
2025/02/19  09:34           216,506 2025####J02_回函扫描件_05.jpg
2025/02/19  09:34           243,285 2025####J02_回函扫描件_06.jpg
2025/02/19  09:34           216,857 2025####J02_回函扫描件_07.jpg
2025/02/19  09:34           388,839 2025####A01_回函扫描件_01.jpg
2025/02/19  09:34           384,575 2025####A01_回函扫描件_02.jpg

省略其余的输出. . .

             389 个文件    119,463,114 字节
               0 个目录 1,361,840,406,528 可用字节

D:\pic2pdf>

最终想要的输出类似于:

2025####J02.pdf
2025####A01.pdf

它们分别有 7 页、2 页。

我第一反应就是,Windows 系统默认不是有个虚拟的打印机嘛?名叫 “Microsoft Print to PDF”。所以我就想以编程的方式,使用 strchr 函数,识别文件名中的下划线,然后切分出序列号部分。由于所有页码都以固定的 2 位编码,所以顺序遍历目录下的图片文件即可。识别序列号后,发现和之前的序列号不一致,或者扫描结束,都应该输出一份文档(EndDoc)。

#include <stdio.h>
#include <Windows.h>
#include <gdiplus.h>
#include <string.h>
using namespace Gdiplus;
#pragma comment(lib, "Gdiplus.lib")
enum {
	IDLEN=30,
	FNAME=IDLEN+5,//.pdf
};

int main(void) {
	GdiplusStartupInput gsi;
	ULONG_PTR tok;
	GdiplusStartup(&tok,&gsi,nullptr);
	HDC print=CreateDCA("WINSPOOL","Microsoft Print to PDF",nullptr,nullptr);

	SetCurrentDirectoryA("D:\\pic2pdf");
	WIN32_FIND_DATAW fd;
	HANDLE hf=FindFirstFileW(L"*.jpg",&fd);
	if (hf) {
		puts("找到了jpg文件");

		wchar_t f[FNAME];
		wchar_t* p=wcschr(fd.cFileName,L'_');
		wcsncpy(f,fd.cFileName,p-fd.cFileName);
		wcscpy(p-fd.cFileName+f,L".pdf");

		DOCINFOW doc{};
		doc.cbSize=sizeof doc;
		doc.lpszDocName=doc.lpszOutput=f;
		StartDocW(print,&doc);
		StartPage(print);
		Graphics g(print);

		while (true) {
			Image img(fd.cFileName);
			g.DrawImage(&img,0,0);
			EndPage(print);

			if (FindNextFileW(hf,&fd)) {
				wchar_t f1[FNAME];
				p=wcschr(fd.cFileName,L'_');
				wcsncpy(f1,fd.cFileName,p-fd.cFileName);
				wcscpy(p-fd.cFileName+f1,L".pdf");
				if (wcscmp(f,f1)) {
					EndDoc(print);
					wprintf(L"%s\n",f);
					wcscpy(f,f1);
					StartDocW(print,&doc);
				}
			} else {
				EndDoc(print);
				wprintf(L"%s\n",f);
				break;
			}
		};
	}
	return 0;
}

参考资料:

将 GDI+ 输出发送到打印机 - Win32 apps | Microsoft Learn

加载和显示位图 - Win32 apps | Microsoft Learn

简单的 Win32 文件和目录 API —— 重命名文件_windows另存为自动重命名 api-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄铎彦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值