鱼C论坛

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

图像打印问题

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

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

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

x
我想将一个大图像按图像宽度*100像素高分块加载然后将图像分块依次绘制到指定名称的打印机(比如HP Designjet T730),打印之前可以选择预览打印页面,调用打印机时不要弹出打印机对话框进行静默调用,另外需要设置打印机驱动的纸张为自定义纸张尺寸880mm * 1200mm纵向,打印分辨率为1200dpi,以及可以设置图案的打印位置,比如从纸张的左边和顶边10mm的位置开始打印(偶尔有些文件也需要图像横向居于纸张中间打印),我曾经尝试了使用lpDevMode->dmPosition.x和lpDevMode->dmPosition.y来指定图像的位置,但是使用它以后不管自定义纸张是多大,都会变成A4,图案打印不全,不知道为什么,请问这应该怎么做?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-11-16 09:42:53 | 显示全部楼层
要实现您描述的功能,涉及到多个步骤和细节,简述如下:

1. **图像分块**:使用编程语言或图像处理库(如Python的PIL/Pillow库)将大图像按照宽度*100像素的高分块。这可以通过循环切片图像实现。

2. **调用打印机进行静默打印**:这通常需要直接与打印机驱动进行交互,构建和发送打印任务,而不显示打印对话框。通常,操作系统和编程库提供的API可能满足需求。例如,在Windows中,可以使用`PrintDlgEx`函数进行配置和调用。打印任务需要编写代码来设置`DEVMODE`结构。

3. **设置自定义纸张尺寸和打印首选项**:通过`DEVMODE`结构,您可以设置纸张尺寸、分辨率和打印位置。需要注意的是:

   - `dmPaperWidth` 和 `dmPaperLength`: 用于定义自定义纸张尺寸。单位为1/10毫米。
   - `dmPrintQuality`: 用于设置分辨率。
   - `dmPosition.x` 和 `dmPosition.y`: 通常用于微调打印位置,但这可能依赖于驱动程序的支持和正确配置。如果不生效,需要查看驱动程序的文档或制造商指南。

4. **定位与居中打印**:计算打印起始位置。对于固定位置,直接输入偏移量即可;若需居中打印,计算如下:

    - 横向居中:`(纸张宽度 - 图像宽度) / 2`
    - 纵向居中:`(纸张高度 - 图像高度) / 2`

5. **调试与验证**:确保驱动正确安装,版本更新,查看制造商提供的接口文档。注意,有些属性在某些情况下可能依赖特定硬件支持。

6. **程序实现**:可选择C/C++、C#或Python等语言,根据语言特性选择相应库实现。例如,Python可以通过`win32print`模块进行高级打印机操作。

如此复杂的打印设置和管理需要对细节进行认真研究。参考具体API文档和打印机技术文档是关键。

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

使用道具 举报

 楼主| 发表于 2024-11-16 09:44:51 | 显示全部楼层
FishC 发表于 2024-11-16 09:42
要实现您描述的功能,涉及到多个步骤和细节,简述如下:

1. **图像分块**:使用编程语言或图像处理库( ...

请帮我写一下具体的代码,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-16 09:45:01 | 显示全部楼层
cxnet 发表于 2024-11-16 09:44
请帮我写一下具体的代码,谢谢


实现这种高级功能需要调用操作系统的打印API,下面我将提供一个Python示例代码,运用`win32print`模块。需要注意,这里的代码是一个框架,仅用于展示如何设置基本属性和打印。在具体实现时,您需要根据实际情况调整代码。

  1. from PIL import Image
  2. import win32print
  3. import win32ui
  4. import win32con

  5. def print_image(image_path, printer_name):
  6.     # 打开图像
  7.     img = Image.open(image_path)
  8.    
  9.     # 打印机 Handle
  10.     printer_handle = win32print.OpenPrinter(printer_name)

  11.     try:
  12.         # 设置DEVMODE以配置打印机参数
  13.         devmode = win32print.GetPrinter(printer_handle, 2)['pDevMode']
  14.         
  15.         # 设置自定义纸张尺寸(880x1200 mm)
  16.         devmode.PaperWidth = 8800  # 1/10 mm
  17.         devmode.PaperLength = 12000  # 1/10 mm
  18.         
  19.         # 设置打印质量为1200dpi
  20.         devmode.PrintQuality = 1200
  21.         
  22.         # 关闭打印机对话框
  23.         devmode.Fields |= win32con.DM_PRINTQUALITY | win32con.DM_PAPERSIZE | win32con.DM_ORIENTATION

  24.         # 创建打印上下文
  25.         hdc = win32ui.CreateDC()
  26.         hdc.CreatePrinterDC(printer_name)
  27.         hdc.StartDoc(image_path)
  28.         hdc.StartPage()

  29.         # 图像缩放和位置计算(如果需要居中打印,调整这里的坐标值)
  30.         img_width, img_height = img.size
  31.         image_scale = 1200 / img_width
  32.         pos_x = 100  # 从左边10mm开始,1/10 mm
  33.         pos_y = 100  # 从上边10mm开始,1/10 mm

  34.         # 绘制图像
  35.         dib = ImageWin.Dib(img)
  36.         dib.draw(hdc.GetHandleOutput(), (pos_x, pos_y, pos_x + int(img_width * image_scale), pos_y + int(img_height * image_scale)))

  37.         # 结束任务
  38.         hdc.EndPage()
  39.         hdc.EndDoc()
  40.         hdc.DeleteDC()

  41.     finally:
  42.         # 关闭打印机
  43.         win32print.ClosePrinter(printer_handle)


  44. # 示例调用
  45. print_image("example.jpg", "HP Designjet T730")
复制代码


### 注意事项:
1. **环境要求**:这是Windows平台上的代码,`win32print`和`win32ui`需要在Python Win32 Extensions中使用。可以通过`pip install pywin32`安装。

2. **自定义设置**:注意DEVMODE的不同属性配置,操作可能因打印机驱动而不同。如果自定义纸张不起作用,请确保打印机驱动支持并正确安装。

3. **图像处理**:这里不包含图像分块的实现。在打印之前,根据您的需求可以用PIL库实现图像裁切。

4. **调试**:使用时可能需要根据实际硬件调试和适配。

如需深入定制或实现更多功能,请参考相关文档并结合所用平台进行深入开发。

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

使用道具 举报

 楼主| 发表于 2024-11-16 09:47:00 | 显示全部楼层
FishC 发表于 2024-11-16 09:45
实现这种高级功能需要调用操作系统的打印API,下面我将提供一个Python示例代码,运用`win32print`模块 ...

不好意思,我忘记告诉你我是用的C++ MFC写代码了,请麻烦帮我重写一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-16 09:47:17 | 显示全部楼层
cxnet 发表于 2024-11-16 09:47
不好意思,我忘记告诉你我是用的C++ MFC写代码了,请 ...


使用C++ MFC实现打印图像的复杂操作确实涉及到不少细节。以下是一段示例代码,演示如何设置打印机、打印图像时不弹出对话框,以及如何调整打印机设置,如纸张尺寸和分辨率。

这段代码仅是个基础框架,需根据您的具体环境和需求进行调整和完善:

  1. #include <afxwin.h>
  2. #include <winspool.h>

  3. void PrintImage(const CString& printerName, const CString& imagePath) {
  4.     // 打开打印机
  5.     HANDLE hPrinter;
  6.     if (!OpenPrinter(printerName.GetBuffer(), &hPrinter, NULL)) {
  7.         AfxMessageBox(_T("Unable to open printer."));
  8.         return;
  9.     }

  10.     // 获取打印机信息
  11.     DWORD needed;
  12.     GetPrinter(hPrinter, 2, NULL, 0, &needed);
  13.     BYTE* pPrinterInfo = new BYTE[needed];
  14.     if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, &needed)) {
  15.         AfxMessageBox(_T("Unable to get printer info."));
  16.         delete[] pPrinterInfo;
  17.         ClosePrinter(hPrinter);
  18.         return;
  19.     }

  20.     PRINTER_INFO_2* pInfo2 = (PRINTER_INFO_2*)pPrinterInfo;

  21.     // 设置 DEVMODE
  22.     DEVMODE* pDevMode = (DEVMODE*)GlobalLock(pInfo2->pDevMode);
  23.     if (pDevMode) {
  24.         // 设置自定义纸张
  25.         pDevMode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PRINTQUALITY;
  26.         pDevMode->dmPaperWidth = 8800;  // 1/10 mm
  27.         pDevMode->dmPaperLength = 12000; // 1/10 mm
  28.         pDevMode->dmPrintQuality = 1200; // DPI

  29.         // 释放 DEVMODE
  30.         GlobalUnlock(pInfo2->pDevMode);
  31.     }

  32.     // 准备 DOCINFO
  33.     DOCINFO docInfo;
  34.     memset(&docInfo, 0, sizeof(DOCINFO));
  35.     docInfo.cbSize = sizeof(DOCINFO);
  36.     docInfo.lpszDocName = _T("Image Print Job");
  37.     docInfo.lpszOutput = NULL;

  38.     // 创建和启动打印机上下文
  39.     CDC printerDC;
  40.     printerDC.Attach(CreateDC(NULL, pInfo2->pPrinterName, NULL, pDevMode));

  41.     if (printerDC.StartDoc(&docInfo) > 0) {
  42.         printerDC.StartPage();

  43.         // 加载图像
  44.         CImage image;
  45.         image.Load(imagePath);

  46.         // 打印图像
  47.         int posX = 100; // 偏移位置
  48.         int posY = 100;
  49.         image.Draw(printerDC.m_hDC, posX, posY);

  50.         printerDC.EndPage();
  51.         printerDC.EndDoc();
  52.     }

  53.     // 释放资源
  54.     delete[] pPrinterInfo;
  55.     printerDC.DeleteDC();
  56.     ClosePrinter(hPrinter);
  57. }

  58. // 示例调用
  59. PrintImage(_T("HP Designjet T730"), _T("path_to_image.jpg"));
复制代码


### 代码说明:
1. **打开和检查打印机**:使用`OpenPrinter`和`GetPrinter`函数打开和检查打印机。
   
2. **设置打印机参数**:通过`DEVMODE`结构,控制纸张的宽度、高度分辨率等。记得检查`dmFields`字段,以确保需要更改的设置应用成功。

3. **创建打印机上下文**:`CreateDC`函数创建打印上下文,绘制图像。

4. **处理图像**:使用MFC的`CImage`类加载和绘制图像。

### 注意事项:
- **权限和驱动问题**:确保你有足够的权限访问打印机,且打印机驱动支持所有设置。
- **错误处理**: 本示例中没有完备的错误处理,请根据需要补充。
- **环境测试**:在不同的环境中,具体工作方式可能略有不同,请结合设备、驱动文档进行调试。

希望这些信息能帮助到你。如有更多问题或需求,请随时告知。

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

使用道具 举报

 楼主| 发表于 2024-11-16 14:38:31 | 显示全部楼层
FishC 发表于 2024-11-16 09:47
使用C++ MFC实现打印图像的复杂操作确实涉及到不少细节。以下是一段示例代码,演示如何设置打印机、打 ...

通过这个例子可以看出CImage比用Opencv打开的图片大很多而且速度相对很快,不知道可不可以直接将CImage二值图像做膨胀处理,而不使用Opencv库,如果可以请写个代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-16 14:38:46 | 显示全部楼层
cxnet 发表于 2024-11-16 14:38
通过这个例子可以看出CImage比用Opencv打开的图片大很 ...


在不使用OpenCV的情况下,我们可以利用`CImage`和GDI+进行基本的图像处理操作,如二值化和膨胀处理。由于MFC本身并没有直接提供图像膨胀的功能,我们需要手动实现这些操作。

下面是一个基于`CImage`的示例,演示如何实现简单的二值化和膨胀处理:

  1. #include <afxwin.h>
  2. #include <atlimage.h>

  3. // 二值化图像
  4. void BinarizeImage(CImage& image, BYTE threshold) {
  5.     for (int y = 0; y < image.GetHeight(); ++y) {
  6.         for (int x = 0; x < image.GetWidth(); ++x) {
  7.             COLORREF color = image.GetPixel(x, y);
  8.             BYTE gray = (GetRValue(color) + GetGValue(color) + GetBValue(color)) / 3;
  9.             
  10.             if (gray < threshold) {
  11.                 image.SetPixel(x, y, RGB(0, 0, 0));  // 黑
  12.             } else {
  13.                 image.SetPixel(x, y, RGB(255, 255, 255));  // 白
  14.             }
  15.         }
  16.     }
  17. }

  18. // 膨胀处理
  19. void DilateImage(CImage& image) {
  20.     CImage copy;
  21.     copy.Create(image.GetWidth(), image.GetHeight(), image.GetBPP());
  22.     image.BitBlt(copy.GetDC(), 0, 0, SRCCOPY);
  23.     copy.ReleaseDC();

  24.     for (int y = 1; y < image.GetHeight() - 1; ++y) {
  25.         for (int x = 1; x < image.GetWidth() - 1; ++x) {
  26.             COLORREF color = copy.GetPixel(x, y);
  27.             if (color == RGB(0, 0, 0)) {
  28.                 image.SetPixel(x-1, y, RGB(0, 0, 0));
  29.                 image.SetPixel(x+1, y, RGB(0, 0, 0));
  30.                 image.SetPixel(x, y-1, RGB(0, 0, 0));
  31.                 image.SetPixel(x, y+1, RGB(0, 0, 0));
  32.             }
  33.         }
  34.     }
  35. }

  36. int main() {
  37.     CImage image;
  38.     HRESULT hr = image.Load(_T("path_to_image.jpg"));
  39.     if (FAILED(hr)) {
  40.         AfxMessageBox(_T("Failed to load image."));
  41.         return -1;
  42.     }

  43.     // 二值化处理
  44.     BinarizeImage(image, 128);

  45.     // 膨胀处理
  46.     DilateImage(image);

  47.     // 保存结果图像
  48.     hr = image.Save(_T("path_to_modified_image.jpg"));
  49.     if (FAILED(hr)) {
  50.         AfxMessageBox(_T("Failed to save image."));
  51.         return -1;
  52.     }

  53.     return 0;
  54. }
复制代码


### 说明:
1. **二值化**:将图像转为灰度图,根据阈值(如128)设置像素为全黑或全白。

2. **膨胀处理**:对图像执行简单的膨胀操作,检查每个像素,如果是黑色,将其周围四个像素也设为黑色。

### 注意:
- 这是基本的操作,只能处理单一通道的图像,对于彩色复杂图像的处理可能需要更复杂的算法。
- 可以根据需要调整`BinarizeImage`中的阈值达到不同效果。

这段代码示例展示了如何不依赖OpenCV来进行CImage的基本图像处理。进行更复杂的图像操作会越来越复杂。希望这些信息能帮助到你,若有其他疑问或需求,请随时告知。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-10 00:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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