拆分 PDF 的关键函数是 PDDocInsertPages。

void PDDocInsertPages(PDDoc doc, ASInt32 mergeAfterThisPage, PDDoc doc2, ASInt32
startPage, ASInt32 numPages, ASUns16 insertFlags, ProgressMonitor progMon, void *
progMonClientData, CancelProc cancelProc, void *cancelProcClientData);

这个函数可以将一个 PDF 中的某几页插入到另一个 PDF 中。如果另一个 PDF 是个新建的空 PDF,那就实现了拆分 PDF 的目的。

示例主要代码:

#include <iostream>
#include "Wrapper.h"
#include "APDFLib.h"
using namespace std;

int main()
{
    APDFLib lib;
    if (lib.hasError())
    {
        lib.printError();
        return -1;
    }

    DURING

    const wchar_t* filename = LR"(d:\Temp\test.pdf)";
    WPDDoc doc(filename);
    int count = doc.GetNumPages();
    for (int i = 0; i < count; ++i)
    {
        WPDDoc page;
        page.InsertPages(PDLastPage, doc, i, 1, PDInsertThreads);

        wchar_t buffer[256] = { 0 };
        wsprintf(buffer, LR"(d:\Temp\aa\split_%d.pdf)", i + 1);
        PDSaveFlags saveFlags = PDSaveFull;
        page.Save(saveFlags, WASText(buffer));
    }

    HANDLER
    ASErrorCode errCode = ERRORCODE;
    char errStr[256] = { 0 };
    cerr << "Error: " << ASGetErrorString(errCode, errStr, 256) << endl;
    END_HANDLER

    return 0;
}

相关代码 Wrapper.h

#include <PDCalls.h>
#include <ASCalls.h>
#include <ASExtraCalls.h>
#include <DLExtrasCalls.h>
#include <PDFLExpT.h>
#include <PDFLCalls.h>

class WASText
{
public:
    WASText(const wchar_t* text)
        : m_text(nullptr)
    {
        m_text = ASTextFromUnicode((ASUTF16Val*)text, kUTF16HostEndian);
    }

    ~WASText()
    {
        if (m_text)
        {
            ASTextDestroy(m_text);
        }
    }

    operator ASText() const
    {
        return m_text;
    }

private:
    ASText m_text;
};

class WASPathName
{
public:
    WASPathName(const WASText& text)
        : m_path(nullptr)
    {
        m_path = ASFileSysCreatePathFromDIPathText(nullptr, text, nullptr);
    }

    ~WASPathName()
    {
        if (m_path)
        {
            ASFileSysReleasePath(nullptr, m_path);
        }
    }

    operator ASPathName() const
    {
        return m_path;
    }

private:
    ASPathName m_path;
};

class WPDDoc
{
public:
    WPDDoc()
        : m_doc(nullptr)
    {
        m_doc = PDDocCreate();
    }

    WPDDoc(const wchar_t* filename)
        : WPDDoc(WASPathName(filename))
    {
    }

    WPDDoc(const WASPathName& filename)
        : m_doc(nullptr)
    {
        m_doc = PDDocOpen(filename, nullptr, nullptr, false);
    }

    ~WPDDoc()
    {
        if (m_doc)
        {
            PDDocClose(m_doc);
        }
    }

    operator PDDoc() const
    {
        return m_doc;
    }

    size_t GetNumPages() const
    {
        return PDDocGetNumPages(m_doc);
    }

    void InsertPages(ASInt32 mergeAfterThisPage, WPDDoc doc2, ASInt32 startPage, ASInt32 numPages, ASUns16 insertFlags = PDInsertAll,
        ProgressMonitor progMon = nullptr, void* progMonClientData = nullptr, CancelProc cancelProc = nullptr, void* cancelProcClientData = nullptr)
    {
        PDDocAcquire(doc2);
        PDDocInsertPages(m_doc, mergeAfterThisPage, doc2, startPage, numPages, insertFlags, progMon, progMonClientData,
            cancelProc, cancelProcClientData);
    }

    void Save(
        PDSaveFlags saveFlags, WASPathName newPath, ASFileSys fileSys = nullptr, ProgressMonitor progMon = nullptr, void* progMonClientData = nullptr)
    {
        PDDocSave(m_doc, saveFlags, newPath, fileSys, progMon, progMonClientData);
    }

private:
    PDDoc m_doc;
};

APDFLib 参考官方例子。

Adobe PDF Library SDK 兼容性还是不太好,遇到有 PDF 出现“Unrecognized object name.”错误,无法拆分,但用福昕的 SDK 是可以拆的。

另外,如果 PDF 内有权限限制,不可以编辑, Adobe 的 SDK 会出现“This operation is not permitted.”错误,用福昕的 SDK 又是可以拆的;权限问题 Adobe 不给拆可以理解,但是否接受是另外一回事了。

发表回复

您的电子邮箱地址不会被公开。