`HPDF_LoadRawImageFromMem` 是一个加载原始图像数据到 PDF 的方式,但直接调用这个函数可能需要用到 l ...
用它HPDF_LoadRawImageFromMem可以正常转成HPDF_Image可以正常输出PDF文件,不过如果我想在同一个页面上添加多张图片应该怎样做呢? cxnet 发表于 2024-11-15 13:51
用它HPDF_LoadRawImageFromMem可以正常转成HPDF_Image ...
要在同一个页面上添加多张图片,可以通过多次调用 `HPDF_Page_DrawImage` 函数来实现。在绘制每张图像时,可以指定不同的位置和大小,以便在页面上布置图像。
下面是一个简单的示例,展示如何在同一页面上绘制多张图像:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <hpdf.h>
void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data) {
std::cerr << "Error: " << error_no << ", detail: " << detail_no << std::endl;
}
void saveImagesAsPDF(const std::vector<cv::Mat>& images, const std::string& pdfFileName) {
HPDF_Doc pdf = HPDF_New(error_handler, nullptr);
if (!pdf) {
std::cerr << "Failed to create PDF document" << std::endl;
return;
}
HPDF_Page page = HPDF_AddPage(pdf);
HPDF_Page_SetWidth(page, 595); // A4 Width in points
HPDF_Page_SetHeight(page, 842); // A4 Height in points
float ypos = 700; // Starting y-position in points
for (const auto& image : images) {
cv::Mat rgb_image;
cv::cvtColor(image, rgb_image, cv::COLOR_BGR2RGB); // Convert BGR to RGB
// Create a raw image buffer
HPDF_UINT width = rgb_image.cols;
HPDF_UINT height = rgb_image.rows;
HPDF_UINT size = width * height * 3; // 3 bytes per pixel for RGB
const HPDF_BYTE* raw_data = rgb_image.ptr();
// Load the raw image data into the PDF document
HPDF_Image pdf_image = HPDF_LoadRawImageFromMem(pdf, raw_data, width, height, HPDF_CS_DEVICE_RGB, 8);
// Draw the image on the PDF page
float xpos = 50; // x-position in points
HPDF_Page_DrawImage(page, pdf_image, xpos, ypos, width / 2, height / 2); // Scale image to fit
ypos -= (height / 2) + 20; // Move y-position down for next image
if (ypos < 0) break; // Avoid drawing outside the page
}
HPDF_SaveToFile(pdf, pdfFileName.c_str());
HPDF_Free(pdf);
}
int main() {
// Load your images using OpenCV
std::vector<cv::Mat> images;
images.push_back(cv::imread("image1.png"));
images.push_back(cv::imread("image2.png"));
// Save images to PDF
saveImagesAsPDF(images, "output.pdf");
return 0;
}
### 说明:
- **位置调整**:在 `HPDF_Page_DrawImage` 函数中,通过 `xpos` 和 `ypos` 来控制图像在页面上的位置。
- **尺寸调整**:通过调整 `width / 2` 和 `height / 2` 参数,控制输出图像的大小,以适应页面。
- **页面项格式**:在纸张的单位中,通常使用点(points)作为单位。比如A4大小的页面为 595 x 842 点。
- **循环绘制**:通过循环,将每次图像绘制到页面上,并在绘制完一张图像后调整位置以绘制下一张图像。调整 `ypos` 以确保不会超过页面。例如,根据图像数量或总空间调整到新页面。
这样,您就可以在一个 PDF 页面上对多张图像进行灵活定位。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-11-15 13:51
要在同一个页面上添加多张图片,可以通过多次调用 `HPDF_Page_DrawImage` 函数来实现。在绘制每张图像 ...
我是直接将一个图片按图片宽度*100像素的高度分块加载到Mat然后依次把分块添加到PDF图片上,不是多个不同文件的图片 cxnet 发表于 2024-11-15 13:58
我是直接将一个图片按图片宽度*100像素的高度分块加载 ...
要将一个大图片按块分割并依次放入PDF页面上,可以逐块读取图像数据并绘制到同一个PDF页面。你需要不断更新图像绘制的位置坐标。下面是一个完整的示例,说明如何处理这个任务:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <hpdf.h>
void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data) {
std::cerr << "Error: error_no=" << error_no << ", detail_no=" << detail_no << std::endl;
}
void saveMatAsPDF(const cv::Mat& image, const std::string& pdfFileName, int blockHeight) {
HPDF_Doc pdf = HPDF_New(error_handler, nullptr);
if (!pdf) {
std::cerr << "Error creating PDF document" << std::endl;
return;
}
HPDF_Page page = HPDF_AddPage(pdf);
HPDF_Page_SetWidth(page, static_cast<HPDF_REAL>(image.cols));
HPDF_Page_SetHeight(page, static_cast<HPDF_REAL>(image.rows));
int y_offset = 0;
for (int y = 0; y < image.rows; y += blockHeight) {
int currentBlockHeight = std::min(blockHeight, image.rows - y);
cv::Mat block = image.rowRange(y, y + currentBlockHeight);
// Convert the current block to raw RGB data
cv::Mat block_rgb;
cv::cvtColor(block, block_rgb, cv::COLOR_GRAY2RGB);
// Create a HPDF_Image from the raw data
HPDF_Image pdf_image = HPDF_LoadRawImageFromMem(pdf,
block_rgb.data,
block_rgb.cols,
block_rgb.rows,
HPDF_CS_DEVICE_RGB,
8);
// Draw the image block to the PDF page
HPDF_Page_DrawImage(page, pdf_image, 0, y_offset, block_rgb.cols, block_rgb.rows);
y_offset += currentBlockHeight;
}
HPDF_SaveToFile(pdf, pdfFileName.c_str());
HPDF_Free(pdf);
}
int main() {
// Load an example image
cv::Mat image = cv::imread("example.tif", cv::IMREAD_GRAYSCALE);
if (image.empty()) {
std::cerr << "Error loading image" << std::endl;
return -1;
}
// Create a PDF with each block of the image
saveMatAsPDF(image, "output.pdf", 100);
return 0;
}
### 关键步骤:
1. **错误处理器**: 处理libharu的错误信息。
2. **加载图像**: 使用OpenCV加载大图像,并将其分割为小块。
3. **创建PDF文档**: 利用libharu新建PDF文档和页面。
4. **逐块绘制**: 在PDF页面上逐块绘制图像。
5. **正确处理颜色**: 确保将灰度图像转换为RGB,因为libharu的`HPDF_LoadRawImageFromMem`需要RGB格式。
运行这个脚本将创建一个PDF文件,依次添加分块后的每个图块。这样做有效处理了即便是大图像,因为你无需将完整图像都临时保存在内存中。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-11-15 13:58
要将一个大图片按块分割并依次放入PDF页面上,可以逐块读取图像数据并绘制到同一个PDF页面。你需要不断 ...
这样拼好的图片有些问题,它是从图片底部开始分割插入到页面上方了,所以顺序拼接反了 cxnet 发表于 2024-11-15 14:11
这样拼好的图片有些问题,它是从图片底部开始分割插入 ...
要正确地将图像从上到下分块并按照顺序插入PDF页面,您需要在绘制每一块时计算正确的y坐标。因为在PDF坐标系中,(0,0)通常位于页面的左下角,而图像数据通常是从左上角开始的。因此,调整绘制的y坐标是至关重要的。
请参考以下代码示例,它将图像按照正确的上下顺序分块并绘制到PDF页面中:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <hpdf.h>
void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data) {
std::cerr << "ERROR: error_no=" << error_no << ", detail_no=" << detail_no << std::endl;
}
void saveMatAsPDF(const cv::Mat& image, const std::string& pdfFileName, int blockHeight) {
HPDF_Doc pdf = HPDF_New(error_handler, nullptr);
if (!pdf) {
std::cerr << "Failed to create PDF object." << std::endl;
return;
}
HPDF_SetCompressionMode(pdf, HPDF_COMP_ALL);
HPDF_Page page = HPDF_AddPage(pdf);
HPDF_Page_SetWidth(page, image.cols);
HPDF_Page_SetHeight(page, image.rows);
for (int y = 0; y < image.rows; y += blockHeight) {
int actualBlockHeight = std::min(blockHeight, image.rows - y);
cv::Rect roi(0, y, image.cols, actualBlockHeight);
cv::Mat subImg = image(roi);
// Create a raw image from the sub-region
HPDF_Image pdf_image = HPDF_LoadRawImageFromMem(
pdf, subImg.data, subImg.cols, subImg.rows, HPDF_CS_DEVICE_GRAY, 8);
if (!pdf_image) {
std::cerr << "Failed to load image sub-region." << std::endl;
continue;
}
// Draw the image at the correct position, note the PDF coordinates
HPDF_Page_DrawImage(page, pdf_image, 0, image.rows - (y + actualBlockHeight), image.cols, actualBlockHeight);
}
HPDF_SaveToFile(pdf, pdfFileName.c_str());
HPDF_Free(pdf);
}
int main() {
cv::Mat image = cv::imread("large_image.tif", cv::IMREAD_GRAYSCALE);
if (image.empty()) {
std::cerr << "Image not found or unable to open." << std::endl;
return -1;
}
saveMatAsPDF(image, "output.pdf", 100);// Adjust blockHeight as needed
return 0;
}
### 代码说明:
1. **图像分块**:通过循环,遍历图像的每个垂直块,将其逐块绘制到页面。
2. **y坐标处理**:每次绘制子图像时,使用 `image.rows - (y + actualBlockHeight)` 计算正确的y坐标,以确保图片从上到下按顺序添加。
3. **HPDF_LoadRawImageFromMem**:这个函数用于将图像数据直接加载为PDF图像对象。
4. **首选构建**:确保 `libhpdf`、`opencv` 包括文件和库文件已正确链接。根据项目设置调整路径。
请根据你的开发环境和库的实际位置修改路径和链接设置。通过这个方法,图像应该会按照正确的顺序从上到下绘制到PDF中。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
1
[2]