parent
d474e03345
commit
ad28a1d547
@ -0,0 +1,219 @@
|
|||||||
|
#include "PDFReader.h" // 引入 PDFReader 头文件
|
||||||
|
#include <sstream> // 处理字符串流
|
||||||
|
#include <regex> // 使用正则表达式
|
||||||
|
#include <iterator> // 迭代器支持
|
||||||
|
#include <vector> // 使用动态数组
|
||||||
|
#include <GL/glut.h> // OpenGL 用于渲染 PDF
|
||||||
|
#include <cstring> // 处理 C 风格字符串
|
||||||
|
|
||||||
|
// 构造函数: 打开 PDF 文件
|
||||||
|
PDFReader::PDFReader(const std::string& filepath) {
|
||||||
|
// 以二进制模式打开文件
|
||||||
|
file.open(filepath, std::ios::binary);
|
||||||
|
|
||||||
|
// 检查文件是否成功打开
|
||||||
|
if (!file) {
|
||||||
|
// 输出错误信息
|
||||||
|
std::cerr << "无法打开 PDF 文件: " << filepath << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 析构函数: 关闭 PDF 文件
|
||||||
|
PDFReader::~PDFReader() {
|
||||||
|
// 检查文件是否仍然打开
|
||||||
|
if (file.is_open()) {
|
||||||
|
|
||||||
|
// 关闭文件
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 JPEG (DCTDecode) 图片
|
||||||
|
void PDFReader::extractImages() {
|
||||||
|
// 如果文件未打开,直接返回
|
||||||
|
if (!file.is_open()) return;
|
||||||
|
|
||||||
|
// 将文件指针移动到文件开头
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
// 存储读取的行数据
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
// 逐行读取 PDF 文件内容
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
// 检测 JPEG 图片标识符
|
||||||
|
if (line.find("/DCTDecode") != std::string::npos) {
|
||||||
|
// 输出发现信息
|
||||||
|
std::cout << "发现 JPEG (DCTDecode) 图片" << std::endl;
|
||||||
|
|
||||||
|
// 存储 JPEG 图片的二进制数据
|
||||||
|
std::vector<unsigned char> imageData;
|
||||||
|
// 缓冲区用于存储文件数据
|
||||||
|
char buffer[1024];
|
||||||
|
// 逐块读取文件
|
||||||
|
while (file.read(buffer, sizeof(buffer))) {
|
||||||
|
// 将数据存入 imageData
|
||||||
|
imageData.insert(imageData.end(), buffer, buffer + file.gcount());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 libjpeg 解析 JPEG 图片
|
||||||
|
struct jpeg_decompress_struct cinfo; // JPEG 解压缩结构体
|
||||||
|
|
||||||
|
// JPEG 错误管理
|
||||||
|
struct jpeg_error_mgr jerr;
|
||||||
|
|
||||||
|
// 绑定错误管理器
|
||||||
|
cinfo.err = jpeg_std_error(&jerr);
|
||||||
|
|
||||||
|
// 初始化 JPEG 解压缩对象
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
|
||||||
|
// 设定解码数据来源
|
||||||
|
jpeg_mem_src(&cinfo, imageData.data(), imageData.size());
|
||||||
|
// 读取 JPEG 头部信息
|
||||||
|
jpeg_read_header(&cinfo, TRUE);
|
||||||
|
// 开始解压
|
||||||
|
jpeg_start_decompress(&cinfo);
|
||||||
|
|
||||||
|
// 输出图片尺寸
|
||||||
|
std::cout << "JPEG 图片尺寸: " << cinfo.output_width << "x" << cinfo.output_height << std::endl;
|
||||||
|
|
||||||
|
// 结束解压
|
||||||
|
jpeg_finish_decompress(&cinfo);
|
||||||
|
// 释放资源
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 FlateDecode (压缩流)
|
||||||
|
void PDFReader::parseFlateDecode() {
|
||||||
|
// 如果文件未打开,直接返回
|
||||||
|
if (!file.is_open()) return;
|
||||||
|
|
||||||
|
// 存储压缩数据
|
||||||
|
std::vector<unsigned char> compressedData;
|
||||||
|
// 存储读取的行数据
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
// 将文件指针移动到文件开头
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
// 逐行读取 PDF 文件内容
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
// 检测 FlateDecode 标识符
|
||||||
|
if (line.find("/FlateDecode") != std::string::npos) {
|
||||||
|
// 输出发现信息
|
||||||
|
std::cout << "发现 FlateDecode (压缩流)" << std::endl;
|
||||||
|
|
||||||
|
// 缓冲区用于存储压缩数据
|
||||||
|
char buffer[1024];
|
||||||
|
// 逐块读取文件
|
||||||
|
while (file.read(buffer, sizeof(buffer))) {
|
||||||
|
// 存入 compressedData
|
||||||
|
compressedData.insert(compressedData.end(), buffer, buffer + file.gcount());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 zlib 解压缩数据
|
||||||
|
std::vector<unsigned char> uncompressedData(compressedData.size() * 4); // 预分配缓冲区
|
||||||
|
|
||||||
|
// 初始化 zlib 流结构体
|
||||||
|
z_stream strm = { 0 };
|
||||||
|
// 设定输入数据
|
||||||
|
strm.next_in = compressedData.data();
|
||||||
|
// 设定输入数据大小
|
||||||
|
strm.avail_in = compressedData.size();
|
||||||
|
// 设定输出缓冲区
|
||||||
|
strm.next_out = uncompressedData.data();
|
||||||
|
// 设定输出缓冲区大小
|
||||||
|
strm.avail_out = uncompressedData.size();
|
||||||
|
|
||||||
|
// 初始化解压
|
||||||
|
inflateInit(&strm);
|
||||||
|
// 执行解压
|
||||||
|
inflate(&strm, Z_FINISH);
|
||||||
|
// 结束解压
|
||||||
|
inflateEnd(&strm);
|
||||||
|
|
||||||
|
|
||||||
|
// 输出解压后大小
|
||||||
|
std::cout << "解压后数据大小: " << strm.total_out << " 字节" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 PDF 表格
|
||||||
|
void PDFReader::parseTables() {
|
||||||
|
|
||||||
|
// 如果文件未打开,直接返回
|
||||||
|
if (!file.is_open()) return;
|
||||||
|
|
||||||
|
// 存储读取的行数据
|
||||||
|
std::string line;
|
||||||
|
// 逐行读取 PDF 文件内容
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
// 检测表格标识符
|
||||||
|
if (line.find("/Table") != std::string::npos) {
|
||||||
|
// 输出发现信息
|
||||||
|
std::cout << "发现 PDF 表格" << std::endl;
|
||||||
|
|
||||||
|
// 存储表格数据
|
||||||
|
std::vector<std::vector<std::string>> tableData;
|
||||||
|
// 读取表格内容
|
||||||
|
while (std::getline(file, line) && line.find("endtable") == std::string::npos) {
|
||||||
|
// 存储当前行数据
|
||||||
|
std::vector<std::string> row;
|
||||||
|
// 使用字符串流分割数据
|
||||||
|
std::stringstream ss(line);
|
||||||
|
// 存储单元格数据
|
||||||
|
std::string cell;
|
||||||
|
|
||||||
|
|
||||||
|
// 以空格分割单元格
|
||||||
|
while (std::getline(ss, cell, ' ')) {
|
||||||
|
// 存入行数据
|
||||||
|
row.push_back(cell);
|
||||||
|
}
|
||||||
|
// 存入表格数据
|
||||||
|
tableData.push_back(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 输出表格行数
|
||||||
|
std::cout << "表格数据解析完成,共 " << tableData.size() << " 行" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenGL 渲染 PDF 页面
|
||||||
|
display() {
|
||||||
|
// 清空缓冲区
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
// 设置颜色(红色)
|
||||||
|
glColor3f(1.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
// 开始绘制四边形
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
// 左下角
|
||||||
|
glVertex2f(-0.5f, -0.5f);
|
||||||
|
// 右下角
|
||||||
|
glVertex2f(0.5f, -0.5f);
|
||||||
|
// 右上角
|
||||||
|
glVertex2f(0.5f, 0.5f);
|
||||||
|
// 左上角
|
||||||
|
glVertex2f(-0.5f, 0.5f);
|
||||||
|
|
||||||
|
glEnd(); // 结束绘制
|
||||||
|
|
||||||
|
glFlush(); // 刷新显示
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFReader::renderPDF() {
|
||||||
|
int argc = 1;
|
||||||
|
char* argv[1] = { (char*)"PDFRenderer" };
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_SINGLE);
|
||||||
|
glutInitWindowSize(500, 500);
|
||||||
|
glutCreateWindow("PDF 页面渲染");
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutMainLoop();
|
||||||
|
}
|
Loading…
Reference in new issue