鱼C论坛

 找回密码
 立即注册
查看: 442|回复: 7

图像打印不全

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

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

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

x
请帮我看一下我的这个代码,我是将一个1000mm宽,2000mm高,1200dpi的二值图通过按图像宽度和100像素高度分块加载后依次将分块图像绘制到打印机DC上进行打印,但始终只能打印到300多mm就是空白区域了,页面大小还是正常,就是后面就全是空白,没有内容,不知道为什么,而且我用这种方式打印出来的打印机缓存文件(*.spl)达到3.99G,而同一个图通过coreldraw加载打印出来的缓存文件只有300MB左右,不知道是什么原因


  1. void CMy001Dlg::OnBnClickedOk()
  2. {
  3.         cv::Mat image = cv::imread("605x780_P1_GRAY.tif", cv::IMREAD_UNCHANGED);
  4.         if (image.empty()) {
  5.                 AfxMessageBox(_T("无法加载图像!"));
  6.                 return;
  7.         }

  8.         int width = image.cols;
  9.         int height = image.rows;
  10.         int blockSize = 100;
  11.         HANDLE hPrinter = NULL;
  12.         BYTE* pPrinterInfo = NULL;
  13.         PRINTER_INFO_2* pInfo2 = NULL;
  14.         DEVMODE* pDevMode = NULL;
  15.         CDC printerDC;
  16.         int dpi = 1200;
  17.         CString strPrintDevice = _T("HP Designjet T730");

  18.         cv::Mat result = cv::Mat::zeros(height, width, image.type());//创建拼接大图尺寸

  19.         for (int y = 0; y < height; y += blockSize) {//按blackheight指定调试加载图像
  20.                 for (int x = 0; x < width; x += image.cols) {//按图像宽度分割加载
  21.                         int currentBlockHeight = std::min(blockSize, image.rows - y);

  22.                         cv::Rect roi(x, y, std::min(image.cols, width - x), std::min(blockSize, height - y));//定义切割矩形块区域
  23.                         cv::Mat block = image(roi);//按roi区域分割图像

  24.                         cv::Mat bgr;
  25.                         cv::cvtColor(block , bgr, cv::COLOR_BGR2BGRA);  // Make sure type is correct

  26.                         // Step 2: Create bitmap info
  27.                         BITMAPINFO bitmapInfo = { 0 };
  28.                         bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  29.                         bitmapInfo.bmiHeader.biWidth = bgr.cols;
  30.                         bitmapInfo.bmiHeader.biHeight = -bgr.rows;  // Flip image vertically
  31.                         bitmapInfo.bmiHeader.biPlanes = 1;
  32.                         bitmapInfo.bmiHeader.biBitCount = 32;
  33.                         bitmapInfo.bmiHeader.biCompression = BI_RGB;



  34.                         // 打开打印机
  35.                         LPWSTR ptName = strPrintDevice.GetBuffer();

  36.                         if (!OpenPrinter(ptName, &hPrinter, NULL)) {
  37.                                 AfxMessageBox(_T("打印机端口打开失败!"));
  38.                                 return;
  39.                         }


  40.                         // 获取打印机信息
  41.                         DWORD needed;
  42.                         GetPrinter(hPrinter, 2, NULL, 0, &needed);
  43.                         pPrinterInfo = new BYTE[needed];
  44.                         if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, &needed)) {
  45.                                 AfxMessageBox(_T("打印机信息获取失败!"));
  46.                                 delete[] pPrinterInfo;
  47.                                 ClosePrinter(hPrinter);
  48.                                 return;
  49.                         }

  50.                         pInfo2 = (PRINTER_INFO_2*)pPrinterInfo;
  51.                         int posX = 30; // 偏移位置
  52.                         int posY = 30;

  53.                         // 设置 DEVMODE
  54.                         pDevMode = (DEVMODE*)GlobalLock(pInfo2->pDevMode);

  55.                         if (pDevMode) {
  56.                                 // 设置自定义纸张
  57.                                 pDevMode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PRINTQUALITY | DM_PAPERSIZE;
  58.                                 pDevMode->dmPaperSize = DMPAPER_USER;
  59.                                 pDevMode->dmPaperWidth = width / dpi * 25.4 * 10;  // 1/10 mm
  60.                                 pDevMode->dmPaperLength = height / dpi * 25.4 * 10; // 1/10 mm LcinkRIP不能超过32740
  61.                                 pDevMode->dmPrintQuality = dpi; // DPI

  62.                                 // 释放 DEVMODE
  63.                                 GlobalUnlock(pInfo2->pDevMode);
  64.                         }

  65.                         // 创建和启动打印机上下文
  66.                         if (y == 0) {
  67.                                 // 准备 DOCINFO
  68.                                 DOCINFO docInfo;
  69.                                 memset(&docInfo, 0, sizeof(DOCINFO));
  70.                                 docInfo.cbSize = sizeof(DOCINFO);
  71.                                 docInfo.lpszDocName = _T("test");
  72.                                 docInfo.lpszOutput = NULL;

  73.                                 printerDC.Attach(CreateDC(NULL, pInfo2->pPrinterName, NULL, pDevMode));

  74.                                 printerDC.StartDoc(&docInfo);
  75.                                 printerDC.StartPage();
  76.                                 SetStretchBltMode(printerDC, HALFTONE);
  77.                                 ::StretchDIBits(printerDC, x + posX, y + posY, bgr.cols, bgr.rows, 0, 0, bgr.cols, bgr.rows,
  78.                                         bgr.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  79.                         }
  80.                         else {
  81.                                 SetStretchBltMode(printerDC, HALFTONE);
  82.                                 ::StretchDIBits(printerDC, x + posX, y + posY, bgr.cols, bgr.rows, 0, 0, bgr.cols, bgr.rows,
  83.                                         bgr.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  84.                         }
  85.                 }
  86.         }

  87.         printerDC.EndPage();
  88.         printerDC.EndDoc();
  89.         // 释放资源
  90.         delete[] pPrinterInfo;
  91.         printerDC.DeleteDC();
  92.         ClosePrinter(hPrinter);
  93. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-11-19 10:48:44 | 显示全部楼层
你的问题主要涉及打印过程中图像块处理和内存使用的问题。以下是一些可能的解决方案和改进建议:

1. 检查内存泄漏:
- 请确保在分配内存空间后及时释放。确保所有`new`和`GlobalLock`使用的对象都在适当的地方释放。你应该对`pPrinterInfo`申请的内存使用`delete[]`来释放。

2. 错误处理:
- 在代码中,每次调用`CreateDC`创建`printerDC`的时候,请检查返回值是否为空。如果`CreateDC`失败,`printerDC`将不被更新且可能导致后续操作失败。

3. 检查图像数据处理:
- 重新检查代码中`cvtColor`步骤,因为你使用的是二值图像,可能不需要`BGR到BGRA`的转换。确保图像像素格式与打印机的要求一致。

4. 调整文档和页面处理:
- `StartDoc`和`EndDoc`应该在整个图像处理之前和之后仅调用一次,而不是在每个块处理时。
- `StartPage`和`EndPage`应该是跨越每一个图像块的绘制周期,因此需要检查循环结构正确性。

[b]5. 修改缓存文件大小:[b]
- 大缓存文件通常表明传送给打印机的数据量过大,可能 due于图像格式或分辨率的缘故。尝试降低DPI(1200 DPI可能过高)来检查是否能缩小生成的`*.spl`文件大小。

6. 设置仅一次:
- 打印机的`DEVMODE`设置应在循环外完成一次,而不是在每个块循环中设置。

根据这些建议,对代码进行修改和测试,看问题是否得到解决。调整设置,控制内存使用并减少不必要的处理步骤,可以有效提高效率和效果。

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

使用道具 举报

 楼主| 发表于 2024-11-19 10:50:46 | 显示全部楼层
FishC 发表于 2024-11-19 10:48
你的问题主要涉及打印过程中图像块处理和内存使用的问题。以下是一些可能的解决方案和改进建议:

1. 检 ...

请帮我在我的代码基础上进行修改一下谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-19 11:02:50 | 显示全部楼层
cxnet 发表于 2024-11-19 10:50
请帮我在我的代码基础上进行修改一下谢谢


当然可以。下面是一些针对你代码的改进建议:

  1. void CMy001Dlg::OnBnClickedOk()
  2. {
  3.         cv::Mat image = cv::imread("605x780_P1_GRAY.tif", cv::IMREAD_UNCHANGED);
  4.         if (image.empty()) {
  5.                 AfxMessageBox(_T("无法加载图像!"));
  6.                 return;
  7.         }

  8.         int width = image.cols;
  9.         int height = image.rows;
  10.         int blockSize = 100;
  11.         HANDLE hPrinter = NULL;
  12.         BYTE* pPrinterInfo = NULL;
  13.         PRINTER_INFO_2* pInfo2 = NULL;
  14.         DEVMODE* pDevMode = NULL;
  15.         CDC printerDC;
  16.         int dpi = 1200;
  17.         CString strPrintDevice = _T("HP Designjet T730");

  18.         // 打开打印机
  19.         LPWSTR ptName = strPrintDevice.GetBuffer();
  20.         if (!OpenPrinter(ptName, &hPrinter, NULL)) {
  21.                 AfxMessageBox(_T("打印机端口打开失败!"));
  22.                 return;
  23.         }

  24.         // 获取打印机信息
  25.         DWORD needed;
  26.         GetPrinter(hPrinter, 2, NULL, 0, &needed);
  27.         pPrinterInfo = new BYTE[needed];  // 修正内存分配大小
  28.         if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, &needed)) {
  29.                 AfxMessageBox(_T("打印机信息获取失败!"));
  30.                 delete[] pPrinterInfo;
  31.                 ClosePrinter(hPrinter);
  32.                 return;
  33.         }

  34.         pInfo2 = (PRINTER_INFO_2*)pPrinterInfo;
  35.        
  36.         // 设置 DEVMODE
  37.         pDevMode = (DEVMODE*)GlobalLock(pInfo2->pDevMode);
  38.         if (pDevMode) {
  39.                 pDevMode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PRINTQUALITY | DM_PAPERSIZE;
  40.                 pDevMode->dmPaperSize = DMPAPER_USER;
  41.                 pDevMode->dmPaperWidth = width / dpi * 25.4 * 10;  // 1/10 mm
  42.                 pDevMode->dmPaperLength = height / dpi * 25.4 * 10;
  43.                 pDevMode->dmPrintQuality = dpi;
  44.                 GlobalUnlock(pInfo2->pDevMode);
  45.         }

  46.         printerDC.Attach(CreateDC(NULL, pInfo2->pPrinterName, NULL, pDevMode));
  47.         if (printerDC.m_hDC == NULL) {
  48.                 AfxMessageBox(_T("创建打印机DC失败!"));
  49.                 delete[] pPrinterInfo;
  50.                 ClosePrinter(hPrinter);
  51.                 return;
  52.         }

  53.         DOCINFO docInfo;
  54.         memset(&docInfo, 0, sizeof(DOCINFO));
  55.         docInfo.cbSize = sizeof(DOCINFO);
  56.         docInfo.lpszDocName = _T("test");

  57.         if (printerDC.StartDoc(&docInfo) < 0) {
  58.                 AfxMessageBox(_T("启动打印文档失败!"));
  59.                 delete[] pPrinterInfo;
  60.                 printerDC.DeleteDC();
  61.                 ClosePrinter(hPrinter);
  62.                 return;
  63.         }

  64.         for (int y = 0; y < height; y += blockSize) {
  65.                 printerDC.StartPage();
  66.                
  67.                 int currentBlockHeight = std::min(blockSize, height - y);
  68.                 cv::Rect roi(0, y, width, currentBlockHeight);
  69.                 cv::Mat block = image(roi);
  70.                 cv::Mat bgr;
  71.                 cv::cvtColor(block, bgr, cv::COLOR_GRAY2BGRA);

  72.                 BITMAPINFO bitmapInfo = {0};
  73.                 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  74.                 bitmapInfo.bmiHeader.biWidth = bgr.cols;
  75.                 bitmapInfo.bmiHeader.biHeight = -bgr.rows;
  76.                 bitmapInfo.bmiHeader.biPlanes = 1;
  77.                 bitmapInfo.bmiHeader.biBitCount = 32;
  78.                 bitmapInfo.bmiHeader.biCompression = BI_RGB;

  79.                 SetStretchBltMode(printerDC, HALFTONE);
  80.                 ::StretchDIBits(printerDC, 0, y, bgr.cols, bgr.rows, 0, 0, bgr.cols, bgr.rows,
  81.                         bgr.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);

  82.                 printerDC.EndPage();
  83.         }

  84.         printerDC.EndDoc();

  85.         delete[] pPrinterInfo;
  86.         printerDC.DeleteDC();
  87.         ClosePrinter(hPrinter);
  88. }
复制代码


主要的修改与建议:
1. 修正了`pPrinterInfo`的内存分配大小。
2. 在循环外部处理了打印机的`DEVMODE`设置。
3. 确保`StartDoc`和`EndDoc`只调用一次。
4. 改正了颜色空间转换步骤,使其适应灰度图像。
5. 确保了`CreateDC`的结果检查。
6. 使用`delete[]`释放内存。

请根据测试结果进一步调整与优化其他设置。

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

使用道具 举报

 楼主| 发表于 2024-11-19 11:32:33 | 显示全部楼层
FishC 发表于 2024-11-19 11:02
当然可以。下面是一些针对你代码的改进建议:

如果按你现在修改的代码打印出来分块图片就会打印成多个页面上,我是要将这些图片打印在一张纸上,所以StartDoc和StartPage只能是在y==0时才能执行一次,当y>0时就不能再执行它们,否则它就会重新创建新的页面,而EndPage和EndDoc也只能在所有分块图片都打印到一张纸上以后才能执行它,至于delete[] pPrinterInfo它也只能出现在EndPage和EndDoc之后,如果在分块处理过程后执行它就会出错,所以请帮我修改成将所有分块图片打印到同一个页面上,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-19 11:40:37 | 显示全部楼层
cxnet 发表于 2024-11-19 11:32
如果按你现在修改的代码打印出来分块图片就会打印成多 ...


了解了你的需求,下面是修改后的代码,确保所有分块图像都被打印在同一个页面上:

  1. void CMy001Dlg::OnBnClickedOk()
  2. {
  3.         cv::Mat image = cv::imread("605x780_P1_GRAY.tif", cv::IMREAD_UNCHANGED);
  4.         if (image.empty()) {
  5.                 AfxMessageBox(_T("无法加载图像!"));
  6.                 return;
  7.         }

  8.         int width = image.cols;
  9.         int height = image.rows;
  10.         int blockSize = 100;
  11.         HANDLE hPrinter = NULL;
  12.         BYTE* pPrinterInfo = NULL;
  13.         PRINTER_INFO_2* pInfo2 = NULL;
  14.         DEVMODE* pDevMode = NULL;
  15.         CDC printerDC;
  16.         int dpi = 1200;
  17.         CString strPrintDevice = _T("HP Designjet T730");

  18.         // 打开打印机
  19.         LPWSTR ptName = strPrintDevice.GetBuffer();
  20.         if (!OpenPrinter(ptName, &hPrinter, NULL)) {
  21.                 AfxMessageBox(_T("打印机端口打开失败!"));
  22.                 return;
  23.         }

  24.         // 获取打印机信息
  25.         DWORD needed;
  26.         GetPrinter(hPrinter, 2, NULL, 0, &needed);
  27.         pPrinterInfo = new BYTE[needed];  // 修正内存分配大小
  28.         if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, &needed)) {
  29.                 AfxMessageBox(_T("打印机信息获取失败!"));
  30.                 delete[] pPrinterInfo;  // 确保删除动态分配的内存
  31.                 ClosePrinter(hPrinter);
  32.                 return;
  33.         }

  34.         pInfo2 = (PRINTER_INFO_2*)pPrinterInfo;
  35.        
  36.         // 设置 DEVMODE
  37.         pDevMode = (DEVMODE*)GlobalLock(pInfo2->pDevMode);
  38.         if (pDevMode) {
  39.                 pDevMode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PRINTQUALITY | DM_PAPERSIZE;
  40.                 pDevMode->dmPaperSize = DMPAPER_USER;
  41.                 pDevMode->dmPaperWidth = width / dpi * 25.4 * 10;  // 1/10 mm
  42.                 pDevMode->dmPaperLength = height / dpi * 25.4 * 10;
  43.                 pDevMode->dmPrintQuality = dpi;
  44.                 GlobalUnlock(pInfo2->pDevMode);
  45.         }

  46.         printerDC.Attach(CreateDC(NULL, pInfo2->pPrinterName, NULL, pDevMode));
  47.         if (printerDC.m_hDC == NULL) {
  48.                 AfxMessageBox(_T("创建打印机DC失败!"));
  49.                 delete[] pPrinterInfo;
  50.                 ClosePrinter(hPrinter);
  51.                 return;
  52.         }

  53.         DOCINFO docInfo;
  54.         memset(&docInfo, 0, sizeof(DOCINFO));
  55.         docInfo.cbSize = sizeof(DOCINFO);
  56.         docInfo.lpszDocName = _T("test");
  57.         if (printerDC.StartDoc(&docInfo) < 0) {
  58.                 AfxMessageBox(_T("启动打印文档失败!"));
  59.                 delete[] pPrinterInfo;
  60.                 printerDC.DeleteDC();
  61.                 ClosePrinter(hPrinter);
  62.                 return;
  63.         }

  64.         printerDC.StartPage();  // 在页循环外启动页面

  65.         for (int y = 0; y < height; y += blockSize) {
  66.                 int currentBlockHeight = std::min(blockSize, height - y);
  67.                 cv::Rect roi(0, y, width, currentBlockHeight);
  68.                 cv::Mat block = image(roi);
  69.                 cv::Mat bgr;
  70.                 cv::cvtColor(block, bgr, cv::COLOR_GRAY2BGRA);

  71.                 BITMAPINFO bitmapInfo = {0};
  72.                 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  73.                 bitmapInfo.bmiHeader.biWidth = bgr.cols;
  74.                 bitmapInfo.bmiHeader.biHeight = -bgr.rows;
  75.                 bitmapInfo.bmiHeader.biPlanes = 1;
  76.                 bitmapInfo.bmiHeader.biBitCount = 32;
  77.                 bitmapInfo.bmiHeader.biCompression = BI_RGB;

  78.                 SetStretchBltMode(printerDC, HALFTONE);
  79.                 ::StretchDIBits(printerDC, 0, y, bgr.cols, bgr.rows, 0, 0, bgr.cols, bgr.rows,
  80.                         bgr.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  81.         }

  82.         printerDC.EndPage();
  83.         printerDC.EndDoc();

  84.         delete[] pPrinterInfo;
  85.         printerDC.DeleteDC();
  86.         ClosePrinter(hPrinter);
  87. }
复制代码


这个修改确保了整幅图像是在一个页面内打印完成的,而不需要在每个块打印时叫`StartPage`和`EndPage`。使得代码逻辑清晰,减少了不必要的页面操作,使其更高效。

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

使用道具 举报

 楼主| 发表于 2024-11-19 12:25:42 | 显示全部楼层
FishC 发表于 2024-11-19 11:40
了解了你的需求,下面是修改后的代码,确保所有分块图像都被打印在同一个页面上:

现在确实已经在一个版面了,但问题依然是图案只能绘制一部份,后面仍然是空白
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-19 12:26:00 | 显示全部楼层
cxnet 发表于 2024-11-19 12:25
现在确实已经在一个版面了,但问题依然是图案只能绘制 ...


如果图像只打印出一部分,而后面是空白,这可能与坐标计算、绘制方法或者纸张大小设置不当有关。以下是一些建议并在代码中进行了调整:

1. **纸张大小和DPI设置**:确保打印机的纸张大小足够,并且DPI设置正确。如果设置过高,可能会导致内存不足的问题。

2. **目标坐标调整**:确保`StretchDIBits`的目标坐标和尺寸正确,确保整个图像可以被正确定位打印。

3. **代码改进**:

  1. void CMy001Dlg::OnBnClickedOk()
  2. {
  3.         cv::Mat image = cv::imread("605x780_P1_GRAY.tif", cv::IMREAD_UNCHANGED);
  4.         if (image.empty()) {
  5.                 AfxMessageBox(_T("无法加载图像!"));
  6.                 return;
  7.         }

  8.         int width = image.cols;
  9.         int height = image.rows;
  10.         int blockSize = 100;
  11.         HANDLE hPrinter = NULL;
  12.         BYTE* pPrinterInfo = NULL;
  13.         PRINTER_INFO_2* pInfo2 = NULL;
  14.         DEVMODE* pDevMode = NULL;
  15.         CDC printerDC;
  16.         int dpi = 1200;
  17.         CString strPrintDevice = _T("HP Designjet T730");

  18.         // 打开打印机
  19.         LPWSTR ptName = strPrintDevice.GetBuffer();
  20.         if (!OpenPrinter(ptName, &hPrinter, NULL)) {
  21.                 AfxMessageBox(_T("打印机端口打开失败!"));
  22.                 return;
  23.         }

  24.         // 获取打印机信息
  25.         DWORD needed;
  26.         GetPrinter(hPrinter, 2, NULL, 0, &needed);
  27.         pPrinterInfo = new BYTE[needed];  // 修正内存分配大小
  28.         if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, &needed)) {
  29.                 AfxMessageBox(_T("打印机信息获取失败!"));
  30.                 delete[] pPrinterInfo;  // 确保删除动态分配的内存
  31.                 ClosePrinter(hPrinter);
  32.                 return;
  33.         }

  34.         pInfo2 = (PRINTER_INFO_2*)pPrinterInfo;
  35.        
  36.         // 设置 DEVMODE
  37.         pDevMode = (DEVMODE*)GlobalLock(pInfo2->pDevMode);
  38.         if (pDevMode) {
  39.                 pDevMode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PRINTQUALITY | DM_PAPERSIZE;
  40.                 pDevMode->dmPaperSize = DMPAPER_USER;
  41.                 pDevMode->dmPaperWidth = static_cast<int>(width / static_cast<double>(dpi) * 25.4 * 10);  // 1/10 mm
  42.                 pDevMode->dmPaperLength = static_cast<int>(height / static_cast<double>(dpi) * 25.4 * 10);
  43.                 pDevMode->dmPrintQuality = dpi;
  44.                 GlobalUnlock(pInfo2->pDevMode);
  45.         }

  46.         printerDC.Attach(CreateDC(NULL, pInfo2->pPrinterName, NULL, pDevMode));
  47.         if (printerDC.m_hDC == NULL) {
  48.                 AfxMessageBox(_T("创建打印机DC失败!"));
  49.                 delete[] pPrinterInfo;
  50.                 ClosePrinter(hPrinter);
  51.                 return;
  52.         }

  53.         DOCINFO docInfo;
  54.         memset(&docInfo, 0, sizeof(DOCINFO));
  55.         docInfo.cbSize = sizeof(DOCINFO);
  56.         docInfo.lpszDocName = _T("test");
  57.         if (printerDC.StartDoc(&docInfo) < 0) {
  58.                 AfxMessageBox(_T("启动打印文档失败!"));
  59.                 delete[] pPrinterInfo;
  60.                 printerDC.DeleteDC();
  61.                 ClosePrinter(hPrinter);
  62.                 return;
  63.         }

  64.         printerDC.StartPage();  // 在页循环外启动页面

  65.         for (int y = 0; y < height; y += blockSize) {
  66.                 int currentBlockHeight = std::min(blockSize, height - y);
  67.                 cv::Rect roi(0, y, width, currentBlockHeight);
  68.                 cv::Mat block = image(roi);

  69.                 BITMAPINFO bitmapInfo = {0};
  70.                 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  71.                 bitmapInfo.bmiHeader.biWidth = block.cols;
  72.                 bitmapInfo.bmiHeader.biHeight = -block.rows;
  73.                 bitmapInfo.bmiHeader.biPlanes = 1;
  74.                 bitmapInfo.bmiHeader.biBitCount = 8;  // 对于灰度图像
  75.                 bitmapInfo.bmiHeader.biCompression = BI_RGB;

  76.                 SetStretchBltMode(printerDC, HALFTONE);
  77.                 ::StretchDIBits(printerDC, 0, y, block.cols, block.rows, 0, 0, block.cols, block.rows,
  78.                         block.data, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  79.         }

  80.         printerDC.EndPage();
  81.         printerDC.EndDoc();

  82.         delete[] pPrinterInfo;
  83.         printerDC.DeleteDC();
  84.         ClosePrinter(hPrinter);
  85. }
复制代码


**改进点**:

1. 修正了内存分配`new BYTE[needed]`。
2. 将颜色转换去掉,因为是灰度图。
3. `StartDoc`和`EndDoc`只调用一次,确保所有块打印在同一页面。
4. 更新了纸张大小和DPI计算,确保设置的纸张大小正确。

确认以上更改并测试图像是否能够完整打印出来。同时,确保打印机设置也没有限制纸张的大小。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-9 23:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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