Sample code for 30+ languages & platforms
PureBasic Requires Chilkat v11.7.0+

Remove a PDF's Old Revisions

See more PDF Optimization Examples

Demonstrates dropOldRevisions. A PDF that has been edited and saved several times carries every earlier revision: the superseded objects are still in the file, reachable through the older cross-reference sections. The audit reports them as "oldRevisions", and dropping them is often the single largest saving in a real document. Dropping them requires a full rewrite, which is why it invalidates existing digital signatures.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkFileAccess.pb"
IncludeFile "CkJsonObject.pb"
IncludeFile "CkPdf.pb"

Procedure ChilkatExample()

    success.i = 0

    ;  This example requires the Chilkat API to have been previously unlocked.
    ;  See Global Unlock Sample for sample code.

    ;  The PDF used in this example is available at grand_canyon_hiking_guide.pdf

    pdf.i = CkPdf::ckCreate()
    If pdf.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkPdf::ckLoadFile(pdf,"qa_data/pdf/grand_canyon_hiking_guide.pdf")
    If success = 0
        Debug CkPdf::ckLastErrorText(pdf)
        CkPdf::ckDispose(pdf)
        ProcedureReturn
    EndIf

    ;  How much of this file is superseded revisions?
    json.i = CkJsonObject::ckCreate()
    If json.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    jsonOut.i = CkJsonObject::ckCreate()
    If jsonOut.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkPdf::ckOptimize(pdf,"audit",json,jsonOut)
    If success = 0
        Debug CkPdf::ckLastErrorText(pdf)
        CkPdf::ckDispose(pdf)
        CkJsonObject::ckDispose(json)
        CkJsonObject::ckDispose(jsonOut)
        ProcedureReturn
    EndIf

    Debug "fileSize:     " + Str(CkJsonObject::ckIntOf(jsonOut,"fileSize"))
    Debug "oldRevisions: " + Str(CkJsonObject::ckIntOf(jsonOut,"usage.oldRevisions.bytes"))

    ;  Drop them, and nothing else, so that the saving is attributable.
    CkJsonObject::ckUpdateBool(json,"compressUncompressed",0)
    CkJsonObject::ckUpdateBool(json,"recompressFlate",0)
    CkJsonObject::ckUpdateBool(json,"replaceLegacyFilters",0)
    CkJsonObject::ckUpdateBool(json,"imagePredictors",0)
    CkJsonObject::ckUpdateBool(json,"dedupeStreams",0)
    CkJsonObject::ckUpdateBool(json,"dedupeObjects",0)
    CkJsonObject::ckUpdateBool(json,"removeUnreferenced",0)
    CkJsonObject::ckUpdateBool(json,"removeUnusedResources",0)
    CkJsonObject::ckUpdateBool(json,"removeUnusedLayers",0)
    CkJsonObject::ckUpdateBool(json,"coalesceContent",0)
    CkJsonObject::ckUpdateBool(json,"tidyContent",0)
    CkJsonObject::ckUpdateBool(json,"subsetFonts",0)
    CkJsonObject::ckUpdateBool(json,"dropOldRevisions",1)

    success = CkPdf::ckOptimize(pdf,"optimize",json,jsonOut)
    If success = 0
        Debug CkPdf::ckLastErrorText(pdf)
        CkPdf::ckDispose(pdf)
        CkJsonObject::ckDispose(json)
        CkJsonObject::ckDispose(jsonOut)
        ProcedureReturn
    EndIf

    success = CkPdf::ckWriteFile(pdf,"qa_output/grand_canyon_one_revision.pdf")
    If success = 0
        Debug CkPdf::ckLastErrorText(pdf)
        CkPdf::ckDispose(pdf)
        CkJsonObject::ckDispose(json)
        CkJsonObject::ckDispose(jsonOut)
        ProcedureReturn
    EndIf

    ;  The saving is an estimate: what the old revisions occupied is known exactly, but the writer
    ;  decides the final layout.  Measure the written file for the real number.
    fac.i = CkFileAccess::ckCreate()
    If fac.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    Debug "bytesSaved (reported): " + Str(CkJsonObject::ckIntOf(jsonOut,"bytesSaved"))
    Debug "written file:          " + Str(CkFileAccess::ckFileSize(fac,"qa_output/grand_canyon_one_revision.pdf"))


    CkPdf::ckDispose(pdf)
    CkJsonObject::ckDispose(json)
    CkJsonObject::ckDispose(jsonOut)
    CkFileAccess::ckDispose(fac)


    ProcedureReturn
EndProcedure