Programmatically create annotations in Flutter

Nutrient Flutter SDK offers a few methods to programmatically get, add, and remove annotations. All of these methods use the Instant JSON format to represent annotations.

Method
Description
getAnnotations(int pageIndex, String type) Gets all annotations on the given page index of the given type. List of all supported annotation types.
getAllUnsavedAnnotations() Gets all the unsaved annotations from the entire document.
addAnnotation(dynamic jsonAnnotation) Adds the given annotation to the document.
removeAnnotation(dynamic jsonAnnotation) Removes the given annotation from the document. If the given annotation doesn’t exist, this method does nothing.

Getting all annotations

The example below shows how to get all annotations on the first page of the document:

dynamic allAnnotations = await pdfDocument.getAnnotations(0, 'all');
print(allAnnotations);

Removing all annotations

The example below shows how to remove an array of annotations from the document:

dynamic allAnnotations = await pdfDocument.getAnnotations(0, 'all');
print(allAnnotations);

// Make sure that at least one annotation exists in the document.
// Remove the first annotation.
await pdfDocument.removeAnnotation(allAnnotations[0]);
print(allAnnotations);

Adding annotations

The example below shows how to programmatically add an ink annotation:

// Create an annotation in the Instant JSON format.
dynamic annotationJSON = '''{
  "bbox": [18.4609375, 582.3333740234375, 431.6640625, 426.00003051757812],
  "blendMode": "normal",
  "createdAt": "2019-11-15T15:36:25Z",
  "creatorName": "PSPDFKit",
  "isDrawnNaturally": false,
  "lineWidth": 10,
  "lines": {
    "intensities": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
    "points": [[[271.6171875, 598], [266.93331909179688, 595.16668701171875], [259.71206665039062, 591.5833740234375], [255.27398681640625, 590.16668701171875], [248.65992736816406, 588.75], [244.59376525878906, 588.0030517578125], [239.75138854980469, 587.3333740234375], [234.60507202148438, 587.3333740234375], [229.98934936523438, 587.3333740234375], [225.3984375, 588.5908203125], [218.64601135253906, 588.75], [212.66595458984375, 588.75], [206.78047180175781, 590.16668701171875], [190.50941467285156, 591.5833740234375], [179.1796875, 593.75], [167.80718994140625, 595.16668701171875], [158.66848754882812, 596.5833740234375], [150.61857604980469, 598], [144.00840759277344, 600.125], [139.43266296386719, 600.125], [135.82032775878906, 601.54168701171875], [130.93865966796875, 604.41668701171875], [125.97789764404297, 607.9583740234375], [120.16405487060547, 609.6793212890625], [114.53083038330078, 612.2083740234375], [109.08804321289062, 614.375], [104.01295471191406, 616.29022216796875], [98.109375, 619.43707275390625], [92.337196350097656, 622.16668701171875], [87.625740051269531, 625.04168701171875], [82.543983459472656, 628.5833740234375], [77.507820129394531, 631.41668701171875], [71.68023681640625, 636.41668701171875], [68.25, 641.36651611328125], [63.281246185302734, 644.66424560546875], [58.289066314697266, 650.6976318359375], [54.0234375, 658.99774169921875], [49.0546875, 669.7379150390625], [42.656242370605469, 681.2083740234375], [37.6875, 694.83612060546875], [32.695316314697266, 707.46807861328125], [29.859375, 717.4583740234375], [28.429689407348633, 730.241943359375], [24.867185592651367, 742.06866455078125], [24.867185592651367, 753.7083740234375], [23.4609375, 768.94134521484375], [23.4609375, 782.875], [23.4609375, 799.98004150390625], [23.4609375, 814.16668701171875], [24.867185592651367, 828.375], [27, 841.2083740234375], [29.859375, 854], [32.695316314697266, 867.92138671875], [36.257816314697266, 880.78863525390625], [41.226566314697266, 893.8333740234375], [42.656242370605469, 904.97161865234375], [44.085941314697266, 913.21966552734375], [45.185382843017578, 919.41668701171875], [48.017143249511719, 928.0272216796875], [51.890621185302734, 937.18316650390625], [56.882816314697266, 946.41668701171875], [61.938720703125, 952.8333740234375], [64.687507629394531, 957.05609130859375], [70.581169128417969, 962.0833740234375], [78.143966674804688, 968.4583740234375], [86.742179870605469, 973.4583740234375], [96.703125, 979.875], [109.5, 984.125], [124.87102508544922, 989.0833740234375], [137.95753479003906, 992.66668701171875], [149.32032775878906, 995.5], [163.54685974121094, 999.04168701171875], [184.17189025878906, 1000.4583740234375], [209.76560974121094, 1001.9166870117188], [231.79685974121094, 1003.3333740234375], [250.99217224121094, 1003.3333740234375], [265.053955078125, 1003.3333740234375], [276.60940551757812, 1003.3333740234375], [287.2734375, 1001.9166870117188], [301.83041381835938, 1000.2388916015625], [317.83590698242188, 995.5], [333.4921875, 992.66668701171875], [345.98687744140625, 984.57415771484375], [355.52838134765625, 976.28839111328125], [366.91409301757812, 965.625], [384.67971801757812, 952.8333740234375], [401.74224853515625, 941.4583740234375], [414.5625, 932.2083740234375], [425.454345703125, 924.84600830078125], [432.32809448242188, 915.875], [436.59375, 901.6387939453125], [441.58590698242188, 881], [442.99221801757812, 854], [445.125, 830.54168701171875], [445.125, 807.79168701171875], [442.99221801757812, 788.7923583984375], [440.15625, 771.5], [435.16409301757812, 752.2916259765625], [430.19534301757812, 736.66668701171875], [427.35934448242188, 724.387451171875], [424.5, 715.0751953125], [420.96090698242188, 708.2083740234375], [415.96810913085938, 698.25], [410.59469604492188, 690.4583740234375], [406.734375, 682.9306640625], [403.17190551757812, 677.268798828125], [400.33590698242188, 671.87744140625], [395.66424560546875, 668.41668701171875], [389.95599365234375, 662.67138671875], [381.23092651367188, 657], [373.3125, 650.625], [366.91409301757812, 645.625], [360.19537353515625, 641.375], [354.17913818359375, 637.8333740234375], [349.00265502929688, 634.9583740234375], [345.44509887695312, 631.41668701171875], [339.6290283203125, 628.5833740234375], [334.68048095703125, 625.04168701171875], [330.84097290039062, 623.5833740234375], [325.87319946289062, 622.16668701171875], [319.62060546875, 620.75], [315.2069091796875, 618.625], [309.99786376953125, 618.6029052734375], [304.51095581054688, 617.2083740234375], [300.08163452148438, 617.2083740234375], [297.23440551757812, 616.544189453125], [292.9212646484375, 615.7916259765625], [287.88607788085938, 615.7916259765625], [283.19888305664062, 615.7916259765625], [277.85714721679688, 615.7916259765625], [273.72171020507812, 615.043701171875], [268.078125, 614.58349609375], [264.75930786132812, 615.7916259765625], [260.88003540039062, 615.7916259765625], [256.7109375, 615.7916259765625], [252.39967346191406, 617.2083740234375], [247.453125, 622.875], [243.87890625, 623.5833740234375], [239.98826599121094, 625.04168701171875]]]
  },
  "name": "ed9b4f2f-8178-4b69-9c50-bb59f820e10e",
  "opacity": 1,
  "pageIndex": 0,
  "strokeColor": "#2196F3",
  "type": "pspdfkit/ink",
  "updatedAt": "2019-11-15T15:36:25Z",
  "v": 1
}''';

// Add the annotation to the document.
await pdfDocument.addAnnotation(annotationJSON);

// Get the annotations on the first page.
dynamic allAnnotations = await pdfDocument.getAnnotations(0, 'all');

// Print the annotations. This should contain the annotation added above.
print(allAnnotations);

Removing annotations

The example below shows how to programmatically remove an annotation:

// Get all annotations on the first page.
dynamic allAnnotations = await pdfDocument.getAnnotations(0, 'all');
print(allAnnotations);

// Remove the first annotation.
await pdfDocument.removeAnnotation(allAnnotations[0]);

Creating an image annotation

To create an image annotation in Flutter with Nutrient SDK, use the addAnnotation method with a JSON representation of the annotation.

  1. First, create a JSON object representing the image annotation. The image needs to be encoded as a base64 string within this JSON.

  2. Then, use the applyInstantJson method to add the annotation to your document.

Here’s an example of how to create and add an image annotation:

// Create an annotation in the Instant JSON format.
const imageAnnotationJson = {
  'annotations': [
    {
      'bbox': [
        167.8721923828125,
        380.95831298828125,
        249.99996948242188,
        250.00009155273438
      ],
      'createdAt': '2024-12-09T07:39:21Z',
      'creatorName': 'demo',
      'id': '01JEN5R3R96PNCG3956MGMMZ48',
      'imageAttachmentId':
          '303c4baa3d6adfcb12cd71e7060d6714850fa9c5404270fde637e43606352580',
      'name': '65dc5234-577b-4b8f-a60c-ecea64171d8b',
      'opacity': 1,
      'pageIndex': 0,
      'rotation': 0,
      'type': 'pspdfkit/image',
      'updatedAt': '2024-12-09T07:39:23Z',
      'v': 2
    }
  ],
  'attachments': {
    '303c4baa3d6adfcb12cd71e7060d6714850fa9c5404270fde637e43606352580': {
      'binary':
          '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',
      'contentType': 'image/jpeg'
    }
  },
  'format': 'https://pspdfkit.com/instant-json/v1',
  'pdfId': {
    'changing': 'aGa/7dtWOk4HPDunwZp7OA==',
    'permanent': 'J+h3K9erBwoHPDunwZp7OA=='
  }
};


// Add the annotation to the document.
     await pdfDocument?.applyInstantJson(const JsonEncoder()
                                .convert(imageAnnotationJson));

The best way to get the correct image annotation schema is to create an image annotation in the PDF viewer and export it as Instant JSON. Then, use this JSON as a template to create new image annotations programmatically.