julianhille / MuhammaraJS

Muhammara a node module with c/cpp bindings to modify PDF with js for node or electron (based/replacement on/of galkhana/hummusjs)
Other
228 stars 46 forks source link

Editing FreeText annotation #385

Open LudvikWiejowski opened 4 months ago

LudvikWiejowski commented 4 months ago

Hello,

I created FreeText annotation, but now I need to edit it or remove it. In pdf-lib I used to do it via array of annotations, but don't know how to do it in muhammarajs.

I ended up with this piece of code, where I take existing annotation and try to edit it.

                        const contentObject = annotDict.queryObject('Contents');
                        var objectsContext = pdfWriter.getObjectsContext()
                        var result=objectsContext.startModifiedIndirectObject(annotObjectID);
                        var dictionaryContext=objectsContext.startDictionary();

                        //copyingContext.copyDirectObjectAsIs(annotDict);
                        //Object.keys(annotObject).forEach(key => {
                        //  dictionaryContext.writeKey(key);
                        //  copyingContext.copyDirectObjectAsIs(annotObject[key]);
                         //});

                        dictionaryContext.writeKey('Contents');
                        dictionaryContext.writeLiteralStringValue(annotContent+'\n'+annotationText);

                        pdfWriter.getObjectsContext().endDictionary(dictionaryContext);
                        pdfWriter.getObjectsContext().endIndirectObject();

Unfortunately, mentioned code is executed, by when I open PDF file, annotation is not visible, but I think it's there but I changed someting incorrectly.

Any ideas?

Thanks a lot.

julianhille commented 4 months ago

Can you write a Test in a fork and send it? Or add the file here

LudvikWiejowski commented 4 months ago

I'm sorry, It seems it was caused by already corrupted pdf, as I played with the library and learnt. Since then I do not see this problem anymore when using Recipe.annot function. Just is it possible to quickly remove Annotation or Annots key completely? Or do I have to go via pdfWriter and copy all the objects except Annots or specific annot? Thanks a lot.

julianhille commented 4 months ago

Im currently not aware of a simple way. But If you start implenting one or send me some Sample Code IT would be of great use.

LudvikWiejowski commented 4 months ago

In my case I need to include one annot only on the first page of invoice pdf, so I thought it will be easier to remove annotations completely and create a new instead of modifying it. But at the end I managed to modify it based on the lib/recipe/annotation.js file. When I'm thinking about deleteAnnotations function, I'm not sure what should be the parameter for annotation identification. ObjectID or array index, or annotation text? Here is I believe working function example.

` function deleteAnnotations(pageIndex, annotObjectID){

try{

    const pdfWriter = muhammara.createWriterToModify(localPdfPath);
    const copyingContext = pdfWriter.createPDFCopyingContextForModifiedFile();

    const pageID = copyingContext
        .getSourceDocumentParser()
        .getPageObjectID(pageIndex);

    const pageObject = copyingContext
        .getSourceDocumentParser()
        .parsePage(pageIndex)
        .getDictionary()
        .toJSObject();

    const objectsContext = pdfWriter.getObjectsContext();

    objectsContext.startModifiedIndirectObject(pageID);
    const modifiedPageObject = pdfWriter.getObjectsContext().startDictionary();
    Object.getOwnPropertyNames(pageObject).forEach((element) => {
    const ignore = ["Annots"];
    if (!ignore.includes(element)) {
        modifiedPageObject.writeKey(element);
        copyingContext.copyDirectObjectAsIs(pageObject[element]);
    }
    });

    modifiedPageObject.writeKey("Annots");
    objectsContext.startArray();

    if(annotObjectID){
        if (pageObject["Annots"] && pageObject["Annots"].toJSArray) {
            pageObject["Annots"].toJSArray().forEach((annot) => {
                if(annot.getObjectID()!==annotObjectID){
                    objectsContext.writeIndirectObjectReference(annot.getObjectID());
                }
            });
        }
    }

    objectsContext
        .endArray()
        .endLine()
        .endDictionary(modifiedPageObject)
        .endIndirectObject();

    pdfWriter.end();

}catch(error){
    console.log(error.message);
}

} `