鱼C论坛

 找回密码
 立即注册
查看: 159|回复: 3

图片打印问题

[复制链接]
发表于 2024-10-11 09:48:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我在使用C++ MFC Opencv分块读取一个比较大的图片时,虽然能够正常分块读入,但是在打印Mat图片时,如果直接打印拼接后的大图就会失败,所以我想怎样才能分块打印并且能打印在一张纸上无缝拼接,另外,我原图片的分辨率是300dpi,但是用opencv加载图片后就会变成72dpi,所以图像的尺寸就会变大,打印到纸上比例也就变很大了,怎样才能让保持原图大小和dpi打印
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-10-11 09:50:33 | 显示全部楼层
要解决这个问题,我们可以从以下几个方面入手:

1. **分块打印并无缝拼接**:
   - 确保以相同的尺寸、比例裁剪和打印每个分块图像。
   - 打印时需要严格对齐各个分块,可以在每个分块之间留出微小边距,然后小心裁剪以确保无缝拼接。

2. **保持原图大小和dpi**:
   - OpenCV加载图像时的dpi信息可能会被忽略,通常OpenCV关注的是像素维度,而不是DPI。
   - 打印时要使用专业的打印软件或库(例如GDI+或打印驱动程序)来设置DPI,确保还原原始图像的物理尺寸。
   - 在拼接完成的大图上设置打印选项,手动调整图像大小以匹配原图在300dpi时的纸张尺寸。

3. **调整图像尺寸**:
   - 确定每个分块的尺寸后,可以手动在打印设置中调整,比如说图像宽度和高度,使其与300dpi图像的物理尺寸匹配。

在C++与MFC中,你可以使用`CDC`进行打印处理,结合设备管理器函数以精确地设置打印输出尺寸和DPI。如果直接用OpenCV处理,参考如下步骤:
cv::Mat image = cv::imread("path_to_image");

// 处理和分块操作...

// 设置打印比例为300 dpi
int printWidth = image.cols * 300 / 72; // 调整宽度
int printHeight = image.rows * 300 / 72; // 调整高度

// 调整后的 Print 函数
void printImage(const cv::Mat &img) {
    // 伪代码:涉及到具体的打印API
    // 例如 Win32 API 可以通过设置 DEVMODE 结构体中的 dpi 属性。
}

printImage(image);

请根据实际需求在细节上进行精细调整和处理。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-11 10:02:23 | 显示全部楼层
FishC 发表于 2024-10-11 09:50
要解决这个问题,我们可以从以下几个方面入手:

1. **分块打印并无缝拼接**:

我的意思是图太大根本无法打印,所以按图片的宽度和100像素的高度进行分块加载并分块打印到打印机,但是这些分块需要在打印纸上连续打印不能断开,所以StartDoc、StartPage函数只能执行一次,但中间的分块图像却要执行多次打印等所有的分块打印完成后再执行EndPage、EndDoc。请给个示例代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-11 10:02:37 | 显示全部楼层
cxnet 发表于 2024-10-11 10:02
我的意思是图太大根本无法打印,所以按图片的宽度和10 ...


要实现这个功能,你需要在整个打印过程中仅使用一次 `StartDoc()` 和 `EndDoc()`,而在打印每个分块时使用 `StartPage()` 和 `EndPage()`。以下是一个简单示例,展示如何在 MFC 中实现分块打印:
#include <afxwin.h>
#include <opencv2/opencv.hpp>

void PrintImage(const cv::Mat &largeImage, CDC* pDC)
{
    // 假设分块宽度为图像宽度,高度为100像素
    int blockHeight = 100;
    int imageWidth = largeImage.cols;
    int imageHeight = largeImage.rows;
    int numBlocks = (imageHeight + blockHeight - 1) / blockHeight; // 计算分块数量

    DOCINFO di;
    ::ZeroMemory(&di, sizeof(DOCINFO));
    di.cbSize = sizeof(DOCINFO);
    di.lpszDocName = _T("Image Print");

    // 开始打印工作
    if (pDC->StartDoc(&di) > 0) {
        for (int i = 0; i < numBlocks; ++i) {
            pDC->StartPage(); // 开始新的一页

            // 计算当前分块的起始位置和高度
            int startY = i * blockHeight;
            int currentBlockHeight = std::min(blockHeight, imageHeight - startY);
            
            // 从大图中截取当前分块
            cv::Mat block = largeImage(cv::Rect(0, startY, imageWidth, currentBlockHeight));

            // 将OpenCV的Mat转换为适合打印的位图
            BITMAPINFOHEADER bmInfoHeader;
            // ... 填充bmInfoHeader的信息,根据block来设置
            // ... 将block数据转换为DIB或HBITMAP

            // 打印分块图像
            // 例如:使用 StretchDIBits 或 StretchBlt

            pDC->EndPage(); // 结束当前页
        }

        pDC->EndDoc(); // 结束打印文档
    }
}

### 说明:

- **列坐标和宽度设置**:代码中我们根据图片的实际宽度和分块的高度设置了矩形 `Rect`,这样就在打印过程中分块进行循环读取。
- **`StartPage()` 和 `EndPage()`**:每个分块在打印过程中是作为一页来处理,但是由于我们没有实际输出到纸上,而是输出到打印设备内存中,最终展现时是连续的。
- **图像转换**:在打印过程中,通常需要将 `cv::Mat` 转换成位图格式,通过 `StretchDIBits` 或 `StretchBlt` 打印出来。

这个示例提供了基本的思路和框架,但实际应用中,细节会根据具体的图像设置以及打印设备的要求进行调整,比如实际的DPI设置、颜色格式转换等。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-21 20:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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