cxnet 发表于 2025-9-29 08:01:33

矢量文件转图片问题

在C++ MFC中,我想将 *.ps、*.pdf、*.eps等矢量格式的文件快速转为指定分辨率和尺寸的高质量Mat图像(其中PDF文件会内嵌部份字体),请帮我写一段代码。

FishC 发表于 2025-9-29 08:02:59

在C++ MFC中将矢量文件转换为Mat图像,可以使用Ghostscript库进行处理。以下是示例代码:


#include <opencv2/opencv.hpp>
#include <windows.h>

// 使用Ghostscript转换矢量文件到图像
cv::Mat VectorToMat(const CString& inputFile, int dpi = 300, int width = 0, int height = 0)
{
    CString tempFile = _T("temp_output.png");
    CString gsCommand;
   
    // 构建Ghostscript命令
    if(width > 0 && height > 0)
    {
      gsCommand.Format(_T("gswin64c -dNOPAUSE -dBATCH -dSAFER -sDEVICE=png16m -r%d -g%dx%d -sOutputFile=\"%s\" \"%s\""),
            dpi, width, height, tempFile, inputFile);
    }
    else
    {
      gsCommand.Format(_T("gswin64c -dNOPAUSE -dBATCH -dSAFER -sDEVICE=png16m -r%d -sOutputFile=\"%s\" \"%s\""),
            dpi, tempFile, inputFile);
    }
   
    // 执行Ghostscript命令
    STARTUPINFO si = {sizeof(si)};
    PROCESS_INFORMATION pi;
    CreateProcess(NULL, gsCommand.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
   
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
   
    // 读取生成的图像文件
    cv::Mat result = cv::imread(CStringA(tempFile).GetString());
   
    // 删除临时文件
    DeleteFile(tempFile);
   
    return result;
}

// 使用示例
void ConvertExample()
{
    // 转换PDF文件为300DPI的1920x1080图像
    cv::Mat image = VectorToMat(_T("input.pdf"), 300, 1920, 1080);
   
    if(!image.empty())
    {
      // 处理图像...
      cv::imshow("Result", image);
      cv::waitKey(0);
    }
}


使用前需要:

1. 安装Ghostscript(确保 gswin64c.exe 在系统路径中)
2. 配置OpenCV库
3. 包含必要的头文件

主要参数说明:
- dpi:输出图像分辨率
- width/height:输出图像尺寸(为0时保持原比例)
- 支持格式:PS、PDF、EPS等Ghostscript支持的矢量格式

注意:Ghostscript会自动处理嵌入字体,确保输出图像中的文字正确显示。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

cxnet 发表于 2025-9-29 08:15:48

FishC 发表于 2025-9-29 08:02
在C++ MFC中将矢量文件转换为Mat图像,可以使用Ghostscript库进行处理。以下是示例代码:




有没有不安装Ghostscript的转换方法?因为我看很多图像RIP软件是在没安装Ghostscript的前提下就将各种矢量文件转换成图像了

FishC 发表于 2025-9-29 08:16:53

cxnet 发表于 2025-09-29 08:15
FishC 发表于 2025-9-29 08:02
在C++ MFC中将矢量文 ...

可以使用Ghostscript DLL直接调用,避免安装完整软件。以下是使用gsdll32.dll的方案:


#include <windows.h>
#include "ierrors.h"
#include "iapi.h"
#include <opencv2/opencv.hpp>

// 定义Ghostscript函数指针
typedef int (GSDLLAPI *PGSEXECUTE)(void *instance, const char *command);
typedef int (GSDLLAPI *PGSNEW)(void **pinstance, void *caller_handle);
typedef int (GSDLLAPI *PGSDELETE)(void *instance);
typedef int (GSDLLAPI *PGSSETARGS)(void *instance, int argc, char **argv);

class CVectorConverter {
private:
    HMODULE m_hGsDll;
    void* m_gsInstance;
    PGSNEW m_pgsNew;
    PGSDELETE m_pgsDelete;
    PGSEXECUTE m_pgsExecute;
    PGSSETARGS m_pgsSetArgs;

public:
    CVectorConverter() : m_hGsDll(NULL), m_gsInstance(NULL) {}
   
    ~CVectorConverter() {
      Cleanup();
    }
   
    bool Initialize(const CString& dllPath = _T("gsdll32.dll")) {
      m_hGsDll = LoadLibrary(dllPath);
      if (!m_hGsDll) return false;
      
      m_pgsNew = (PGSNEW)GetProcAddress(m_hGsDll, "gsapi_new_instance");
      m_pgsDelete = (PGSDELETE)GetProcAddress(m_hGsDll, "gsapi_delete_instance");
      m_pgsExecute = (PGSEXECUTE)GetProcAddress(m_hGsDll, "gsapi_execute");
      m_pgsSetArgs = (PGSSETARGS)GetProcAddress(m_hGsDll, "gsapi_set_args");
      
      if (!m_pgsNew || !m_pgsDelete || !m_pgsExecute) {
            FreeLibrary(m_hGsDll);
            return false;
      }
      
      return (m_pgsNew(&m_gsInstance, NULL) == 0);
    }
   
    cv::Mat ConvertToImage(const CString& inputFile, int dpi = 300,
                        int width = 0, int height = 0) {
      if (!m_gsInstance) return cv::Mat();
      
      CString tempFile = _T("temp_output.png");
      CStringA tempFileA(tempFile);
      CStringA inputFileA(inputFile);
      
      // 构建Ghostscript参数
      const char* args[] = {
            "gswin32c",
            "-dNOPAUSE",
            "-dBATCH",
            "-dSAFER",
            "-sDEVICE=png16m",
            CStringA().Format("-r%d", dpi),
            width > 0 && height > 0 ?
                CStringA().Format("-g%dx%d", width, height) : "-dUseCropBox",
            CStringA().Format("-sOutputFile=%s", tempFileA.GetString()),
            inputFileA.GetString(),
            NULL
      };
      
      int argc = 8; // 参数数量
      if (m_pgsSetArgs(m_gsInstance, argc, (char**)args) == 0) {
            if (m_pgsExecute(m_gsInstance) == 0) {
                cv::Mat result = cv::imread(tempFileA.GetString());
                DeleteFile(tempFile);
                return result;
            }
      }
      
      return cv::Mat();
    }
   
    void Cleanup() {
      if (m_gsInstance && m_pgsDelete) {
            m_pgsDelete(m_gsInstance);
            m_gsInstance = NULL;
      }
      if (m_hGsDll) {
            FreeLibrary(m_hGsDll);
            m_hGsDll = NULL;
      }
    }
};

// 使用示例
void ConvertVectorFile() {
    CVectorConverter converter;
    if (converter.Initialize(_T("gsdll32.dll"))) {
      cv::Mat image = converter.ConvertToImage(_T("input.pdf"), 300, 1920, 1080);
      if (!image.empty()) {
            // 处理图像...
      }
    }
}


使用步骤:

1. 从Ghostscript官网下载DLL文件包
2. 将以下文件放在可执行文件目录:

[*] gsdll32.dll (或gsdll64.dll)
[*] gsdll32.lib
[*] gs文件夹(包含字体和资源)


3. 在项目中包含头文件:
ierrors.h 和 iapi.h

优点:

[*] 无需安装Ghostscript
[*] 程序可独立分发
[*] 转换速度快
[*] 支持所有Ghostscript支持的格式


注意事项:

[*] 确保DLL版本与项目架构匹配(32/64位)
[*] 资源文件路径需要正确配置
[*] 多线程环境下需要适当的同步


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

python大牢 发表于 2025-9-29 19:38:09

thanks
页: [1]
查看完整版本: 矢量文件转图片问题