鱼C论坛

 找回密码
 立即注册
12
返回列表 发新帖
楼主: cxnet

C++图像保存问题

[复制链接]
 楼主| 发表于 6 天前 | 显示全部楼层
FishC 发表于 2024-11-15 12:51
`HPDF_LoadRawImageFromMem` 是一个加载原始图像数据到 PDF 的方式,但直接调用这个函数可能需要用到 l ...

用它HPDF_LoadRawImageFromMem可以正常转成HPDF_Image可以正常输出PDF文件,不过如果我想在同一个页面上添加多张图片应该怎样做呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
FishC 发表于 2024-11-15 13:51
要在同一个页面上添加多张图片,可以通过多次调用 `HPDF_Page_DrawImage` 函数来实现。在绘制每张图像 ...

我是直接将一个图片按图片宽度*100像素的高度分块加载到Mat然后依次把分块添加到PDF图片上,不是多个不同文件的图片
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
FishC 发表于 2024-11-15 13:58
要将一个大图片按块分割并依次放入PDF页面上,可以逐块读取图像数据并绘制到同一个PDF页面。你需要不断 ...

这样拼好的图片有些问题,它是从图片底部开始分割插入到页面上方了,所以顺序拼接反了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-21 16:55

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表