鱼C论坛

 找回密码
 立即注册
查看: 532|回复: 5

c++打印mat图

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

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

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

x
在C++ MFC里,怎样将一个Mat图按指定的X和Y坐标以及宽度、高度、dpi打印到系统打印机
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-10 09:37:09 | 显示全部楼层
在C++ MFC中打印一个`Mat`图像到系统打印机,可以按照以下步骤进行:

1. **初始化OpenCV和MFC环境:**
   确保你已经配置好OpenCV库,并能在MFC项目中使用。

2. **将`Mat`图像转换为适合MFC打印的格式:**
   将图像转换为DIB(Device Independent Bitmap),这个格式便于在MFC中进行打印。

3. **设置打印文档:**
   创建一个`CPrintDialog`对象,让用户选择打印机和设置参数。

4. **启动打印监视:**
   使用`CDC`类来管理打印任务。

5. **绘制图像:**
   将图像绘制到打印设备的上下文(DC)。你需要使用到`CDC::StretchDIBits`或类似的函数来指定位置、宽度和高度。

6. **结束打印:**
   使用`CDC::EndDoc()`函数来完成打印任务。

这里是一个简化的代码示例,帮助你理解如何实现上述步骤:

  1. void CYourClass::PrintImage(const cv::Mat& image, int x, int y, int width, int height, int dpi)
  2. {
  3.     // Step 1: 转换Mat到DIB
  4.     cv::Mat bgr;
  5.     cvtColor(image, bgr, cv::COLOR_BGR2BGRA);  // 确保类型正确

  6.     // Step 2: 创建DIB位图信息
  7.     BITMAPINFO bitmapInfo = {0};
  8.     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  9.     bitmapInfo.bmiHeader.biWidth = bgr.cols;
  10.     bitmapInfo.bmiHeader.biHeight = -bgr.rows;  // 图像倒转
  11.     bitmapInfo.bmiHeader.biPlanes = 1;
  12.     bitmapInfo.bmiHeader.biBitCount = 32;
  13.     bitmapInfo.bmiHeader.biCompression = BI_RGB;

  14.     // Step 3: 打印对话框和打印环境设置
  15.     CPrintDialog printDlg(FALSE);
  16.     if (printDlg.DoModal() == IDCANCEL) return;
  17.     CDC dc;
  18.     dc.Attach(printDlg.GetPrinterDC());
  19.     dc.m_bPrinting = TRUE;

  20.     CString strTitle;
  21.     strTitle.LoadString(AFX_IDS_APP_TITLE);
  22.     DOCINFO di;
  23.     ::ZeroMemory(&di, sizeof(DOCINFO));
  24.     di.cbSize = sizeof(DOCINFO);
  25.     di.lpszDocName = strTitle;

  26.     BOOL bPrintingOK = dc.StartDoc(&di);  // 开始打印任务

  27.     // Step 4: 绘制图片
  28.     dc.StartPage();

  29.     SetStretchBltMode(dc, HALFTONE);
  30.     dc.StretchDIBits(x, y, width, height, 0, 0, bgr.cols, bgr.rows,
  31.                      bgr.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);

  32.     // Step 5: 结束打印任务
  33.     dc.EndPage();
  34.     dc.EndDoc();
  35.     dc.Detach();

  36. }
复制代码


请注意,这段代码需要根据具体的项目环境稍作调整。确保安装并配置好OpenCV库,并在MFC项目属性中正确设置路径和依赖项。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-10 09:51:14 | 显示全部楼层
提示以下错误
错误        C2039        "StretchDIBits": 不是 "CDC" 的成员
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-10 09:51:26 | 显示全部楼层
cxnet 发表于 2024-10-10 09:51
提示以下错误
错误        C2039        "StretchDIBits": 不是 "CD ...


在MFC应用程序中,你不能直接调用`CDC::StretchDIBits`,因为`StretchDIBits`是Windows API函数,而不是`CDC`类的成员函数。你需要获取设备上下文的句柄,然后使用Windows API函数来进行操作。下面是一个修正过的代码示例:

  1. void CYourClass::PrintImage(const cv::Mat& image, int x, int y, int width, int height, int dpi)
  2. {
  3.     // Step 1: Convert Mat to DIB format
  4.     cv::Mat bgr;
  5.     cv::cvtColor(image, bgr, cv::COLOR_BGR2BGRA);  // Make sure type is correct

  6.     // Step 2: Create bitmap info
  7.     BITMAPINFO bitmapInfo = { 0 };
  8.     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  9.     bitmapInfo.bmiHeader.biWidth = bgr.cols;
  10.     bitmapInfo.bmiHeader.biHeight = -bgr.rows;  // Flip image vertically
  11.     bitmapInfo.bmiHeader.biPlanes = 1;
  12.     bitmapInfo.bmiHeader.biBitCount = 32;
  13.     bitmapInfo.bmiHeader.biCompression = BI_RGB;

  14.     // Step 3: Print dialog and get printer DC
  15.     CPrintDialog printDlg(FALSE);
  16.     if (printDlg.DoModal() == IDCANCEL) return;
  17.     CDC dc;
  18.     dc.Attach(printDlg.GetPrinterDC());
  19.     dc.m_bPrinting = TRUE;

  20.     CString strTitle;
  21.     strTitle.LoadString(AFX_IDS_APP_TITLE);
  22.     DOCINFO di;
  23.     ::ZeroMemory(&di, sizeof(DOCINFO));
  24.     di.cbSize = sizeof(DOCINFO);
  25.     di.lpszDocName = strTitle;

  26.     BOOL bPrintingOK = dc.StartDoc(&di);  // Start print job

  27.     // Step 4: Draw the image
  28.     dc.StartPage();

  29.     // Use Windows API (HDC)
  30.     HDC hdc = dc.GetSafeHdc();
  31.     SetStretchBltMode(hdc, HALFTONE);
  32.     ::StretchDIBits(hdc, x, y, width, height, 0, 0, bgr.cols, bgr.rows,
  33.                     bgr.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);

  34.     // Step 5: End the print job
  35.     dc.EndPage();
  36.     dc.EndDoc();
  37.     dc.Detach();
  38. }
复制代码


确保所有的依赖库如OpenCV已正确配置,并根据你的实际项目环境调整代码。使用Windows API处理位图数据时,要确保各个参数设置正确,以避免图像方向错误或颜色显示不正确。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-10 10:36:47 | 显示全部楼层
打印时        dc.StartDoc(&di);  // Start print job
报错
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-10 10:37:00 | 显示全部楼层
cxnet 发表于 2024-10-10 10:36
打印时        dc.StartDoc(&di);  // Start print job
报错


在使用`dc.StartDoc(&di);`时,如果报错,可能原因是`DOCINFO`结构体没有正确初始化,或者其他打印机相关设置不对。以下是使用`CDC`进行打印操作的常用步骤以及错误检查:

1. **确保正确初始化`DOCINFO`结构体:**

  
  1. DOCINFO di;
  2.    ::ZeroMemory(&di, sizeof(DOCINFO));
  3.    di.cbSize = sizeof(DOCINFO);
  4.    di.lpszDocName = _T("Your Document Name");
复制代码


   确保变量`di`的成员变量`cbSize`和`lpszDocName`已经正确设置。

2. **打印环境设置:**

   确保你已经从框架中获取了有效的打印设备上下文`CDC`对象。通常,它可以从`CPrintDialog`的`GetPrinterDC()`或其他打印相关功能中获取。

  
  1. HDC hdcPrinter = printDialog.GetPrinterDC();
  2.    CDC dc;
  3.    dc.Attach(hdcPrinter);
复制代码


3. **启动打印文档:**

   在启动打印作业之前,确保任何打印设备相关的错误(如关闭的打印机或未安装的驱动程序)已经处理。

4. **错误检查:**

   在调用`StartDoc`时可以使用一些错误检查来捕捉产生的问题:

  
  1. if (dc.StartDoc(&di) <= 0) {
  2.        // Handle the error, for example output an error message
  3.        AfxMessageBox(_T("Failed to start document."));
  4.        return;
  5.    }
复制代码


5. **打印流程:**
   
   确保按照`StartDoc`,`StartPage`,`EndPage`,`EndDoc`的顺序调用。

示例代码:

  1. // Get the printer device context
  2. CPrintDialog printDialog(FALSE);
  3. if (printDialog.DoModal() == IDOK) {
  4.     CDC dc;
  5.     dc.Attach(printDialog.GetPrinterDC());

  6.     // Initialize DOCINFO structure
  7.     DOCINFO di;
  8.     ::ZeroMemory(&di, sizeof(DOCINFO));
  9.     di.cbSize = sizeof(DOCINFO);
  10.     di.lpszDocName = _T("Your Document Name");

  11.     if (dc.StartDoc(&di) > 0) {
  12.         dc.StartPage();

  13.         // Perform drawing operations here
  14.         // For example: dc.TextOut(0, 0, _T("Hello, Printer!"));

  15.         dc.EndPage();
  16.         dc.EndDoc();
  17.     } else {
  18.         AfxMessageBox(_T("Failed to start document."));
  19.     }

  20.     dc.DeleteDC();
  21. }
复制代码


通过以上步骤,你应该能够成功启动打印任务。如果仍然遇到问题,可以检查输出错误信息,并确保打印机驱动和设备正常。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-10 07:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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