Tutorial Anotasi Jarak Java: Cara menambahkan pengukuran ke gambar dengan GroupDocs

Dalam panduan komprehensif ini Anda akan menemukan cara menambahkan pengukuran ke gambar, PDF, dan jenis dokumen lainnya menggunakan GroupDocs.Annotation untuk Java. Baik Anda sedang membangun penampil CAD, alat tinjauan arsitektur, atau platform dokumentasi teknis, anotasi jarak memberikan pengguna Anda penggaris interaktif yang jelas dan dapat diandalkan. Pada akhir tutorial Anda akan memiliki solusi siap produksi yang menggambar pengukuran presisi, menyesuaikan tampilannya, dan terintegrasi mulus dengan basis kode Java Anda yang ada.

Cara menambahkan pengukuran ke gambar dalam Java?

Muat dokumen target dengan Annotator, buat DistanceAnnotation, konfigurasikan properti visualnya, tambahkan ke halaman yang diinginkan, dan akhirnya simpan file. Dalam hanya empat baris kode Anda mendapatkan penggaris yang berfungsi penuh yang dapat diedit oleh pengguna akhir di viewer yang kompatibel. Pendekatan ini bekerja untuk PDF, file Word, presentasi PowerPoint, lembar Excel, dan format gambar umum seperti PNG, JPEG, dan TIFF.

Jawaban Cepat

  • Apa cara termudah untuk menambahkan pengukuran ke gambar dalam Java? Gunakan kelas DistanceAnnotation dari GroupDocs.Annotation.
  • Format apa yang didukung? PDF, Word, PowerPoint, Excel, dan tipe gambar umum (PNG, JPEG, TIFF).
  • Apakah saya memerlukan lisensi untuk pengembangan? Versi percobaan gratis atau lisensi sementara dapat digunakan untuk pengujian; lisensi komersial diperlukan untuk produksi.
  • Bisakah saya menyesuaikan tampilan garis penggaris? Ya – Anda dapat mengatur warna, gaya, lebar, dan opasitas.
  • Bagaimana cara menghindari kebocoran memori? Selalu dispose instance Annotator atau gunakan try‑with‑resources.

Apa Itu Anotasi Jarak (Dan Mengapa Anda Membutuhkannya)?

Anotasi jarak adalah elemen visual interaktif yang menampilkan panjang yang diukur antara dua titik dalam dokumen. Mereka berfungsi seperti penggaris digital yang dapat ditempatkan di mana saja, diseret, dan diedit secara real time, memberikan pengguna umpan balik visual instan tanpa perhitungan manual.

Anotasi ini memberikan kejelasan visual, umpan balik interaktif, dan penampilan profesional pada dokumen teknis apa pun. Mereka sangat berharga untuk gambar arsitektur, skema teknik, pencitraan medis, dan denah properti real‑estate di mana dimensi yang tepat sangat penting.

Praktik Terbaik Pengukuran Dokumen

Sebelum Anda mulai menulis kode, ingatlah praktik terbukti berikut:

  1. Indeks halaman berbasis nolpageNumber = 0 mengacu pada halaman pertama, yang sesuai dengan model internal GroupDocs.Annotation.
  2. Warna kontras tinggi – Pilih warna penggaris yang menonjol pada latar belakang dokumen (misalnya, kuning cerah pada skema gelap).
  3. Penyesuaian opasitas – Opasitas 0.7 menyeimbangkan visibilitas dan detail di bawahnya; tingkatkan ke 1.0 untuk pengukuran yang sangat penting.
  4. Kelompokkan anotasi terkait – Gunakan balasan atau komentar untuk menjaga diskusi terorganisir di sekitar pengukuran tertentu.
  5. Dispose segera – Selalu panggil annotator.dispose() atau gunakan try‑with‑resources untuk membebaskan memori native, terutama saat menangani file besar.

Prasyarat: Apa yang Anda Butuhkan Sebelum Memulai

Persyaratan Lingkungan Pengembangan

  • Java Development Kit (JDK): Versi 8 atau lebih tinggi (JDK 11+ disarankan).
  • Maven atau Gradle: Contoh menggunakan Maven, tetapi dependensi yang sama bekerja dengan Gradle.
  • IDE: IDE Java apa saja (IntelliJ IDEA, Eclipse, VS Code, dll.) sudah cukup.

Prasyarat Pengetahuan

Anda seharusnya sudah nyaman dengan:

  • Konsep inti Java (kelas, objek, metode).
  • Menambahkan pustaka eksternal melalui Maven/Gradle.
  • I/O file dasar dan penanganan path.

Dokumen Uji

Siapkan beberapa file contoh:

  • Satu atau lebih halaman PDF.
  • Gambar PNG/JPEG/TIFF untuk pengujian berbasis raster.
  • File CAD opsional jika Anda ingin bereksperimen dengan gambar teknik.

Menyiapkan GroupDocs.Annotation untuk Java

Mengintegrasikan GroupDocs.Annotation sangat mudah. Di bawah ini kami tunjukkan koordinat Maven yang perlu Anda tambahkan ke proyek Anda.

Integrasi Maven

Tambahkan konfigurasi berikut ke file pom.xml Anda:

```xml
<repositories>
   <repository>
      <id>repository.groupdocs.com</id>
      <name>GroupDocs Repository</name>
      <url>https://releases.groupdocs.com/annotation/java/</url>
   </repository>
</repositories>
<dependencies>
   <dependency>
      <groupId>com.groupdocs</groupId>
      <artifactId>groupdocs-annotation</artifactId>
      <version>25.2</version>
   </dependency>
</dependencies>

### Memahami Persyaratan Lisensi

GroupDocs.Annotation menawarkan tiga model lisensi:

1. **Free Trial** – Ideal untuk evaluasi; mencakup semua fitur dengan batas penggunaan minor.  
2. **Temporary License** – Menghapus batasan percobaan untuk pengembangan dan pengujian.  
3. **Commercial License** – Penggunaan penuh fitur, siap produksi tanpa batas.

Mulailah dengan percobaan gratis, kemudian tingkatkan setelah Anda siap untuk produksi.

### Inisialisasi Dasar

Kelas `Annotator` adalah titik masuk untuk semua operasi anotasi. Ia memuat dokumen, menyediakan API pengeditan, dan menulis hasil kembali ke disk.

```java
```java
import com.groupdocs.annotation.Annotator;

// Initialize annotator with the input file path
final Annotator annotator = new Annotator("YOUR_DOCUMENT_DIRECTORY/input.pdf");

**Pro Tip:** Bungkus `Annotator` dalam blok try‑with‑resources atau panggil `dispose()` secara eksplisit untuk menghindari kebocoran memori native.

## Panduan Implementasi Langkah demi Langkah

Sekarang mari kita jalani alur kerja lengkap yang siap produksi untuk menambahkan anotasi jarak.

### Langkah 1: Buat Balasan Interaktif (Opsional Namun Disarankan)

Balasan memungkinkan kolaborator melampirkan komentar langsung ke pengukuran, mengubah penggaris sederhana menjadi utas diskusi.

```java
```java
import com.groupdocs.annotation.models.Reply;
import java.util.ArrayList;
import java.util.Calendar;

Reply reply1 = new Reply();
reply1.setComment("First comment");
reply1.setRepliedOn(Calendar.getInstance().getTime());

Reply reply2 = new Reply();
reply2.setComment("Second comment");
reply2.setRepliedOn(Calendar.getInstance().getTime());

ArrayList<Reply> replies = new ArrayList<>();
replies.add(reply1);
replies.add(reply2);

**Kapan menggunakan balasan:** Dalam siklus tinjauan multi‑pengguna, ketika Anda perlu menjelaskan mengapa dimensi dipilih atau meminta klarifikasi dari rekan tim.

### Langkah 2: Konfigurasikan Anotasi Jarak Anda

Kelas `DistanceAnnotation` adalah objek tingkat atas GroupDocs.Annotation yang mewakili pengukuran penggaris. Anda dapat menyesuaikan geometri, gaya visual, dan pesan yang terlampir.

`Rectangle` mendefinisikan kotak pembatas anotasi pada halaman. `PenStyle` mengenumerasi gaya garis seperti solid, dash, dan dot.

```java
```java
import com.groupdocs.annotation.models.Rectangle;
import com.groupdocs.annotation.models.PenStyle;
import com.groupdocs.annotation.models.annotationmodels.DistanceAnnotation;

DistanceAnnotation distance = new DistanceAnnotation();
distance.setBox(new Rectangle(200, 150, 200, 30)); // Set the annotation's position and size
distance.setCreatedOn(Calendar.getInstance().getTime()); 
distance.setMessage("This is a distance annotation");
distance.setOpacity(0.7);
distance.setPageNumber(0); 
distance.setPenColor(65535);
distance.setPenStyle(PenStyle.DOT);
distance.setPenWidth((byte) 3);

distance.setReplies(replies); // Attach replies

**Opsi konfigurasi utama**  
- `setBox()` – Menetapkan persegi panjang pembatas anotasi pada halaman.  
- `setOpacity()` – Mengontrol transparansi (`0.0` = tidak terlihat, `1.0` = sepenuhnya opaque).  
- `setPenColor()` – Warna RGB untuk garis pengukuran.  
- `setPenStyle()` – Gaya garis (`DOT`, `DASH`, `SOLID`).  
- `setPenWidth()` – Ketebalan garis dalam poin.

### Langkah 3: Terapkan Anotasi dan Simpan

Setelah anotasi siap, tambahkan ke dokumen dan simpan perubahan.

```java
```java
annotator.add(distance);
annotator.save("YOUR_OUTPUT_DIRECTORY/output.pdf");
annotator.dispose();

**Penting:** Selalu panggil `dispose()` setelah menyimpan, terutama saat memproses banyak dokumen dalam pekerjaan batch.

## Contoh Kerja Lengkap

Menggabungkan semuanya, berikut contoh lengkap end‑to‑end yang memuat PDF, menambahkan anotasi jarak, dan menyimpan hasilnya.

```java
```java
import com.groupdocs.annotation.Annotator;
import com.groupdocs.annotation.models.Reply;
import com.groupdocs.annotation.models.Rectangle;
import com.groupdocs.annotation.models.PenStyle;
import com.groupdocs.annotation.models.annotationmodels.DistanceAnnotation;
import java.util.ArrayList;
import java.util.Calendar;

public class DistanceAnnotationExample {
    public static void main(String[] args) {
        try (Annotator annotator = new Annotator("input.pdf")) {
            // Create replies for the annotation
            ArrayList<Reply> replies = new ArrayList<>();
            Reply reply = new Reply();
            reply.setComment("Measurement verified by engineering team");
            reply.setRepliedOn(Calendar.getInstance().getTime());
            replies.add(reply);

            // Configure the distance annotation
            DistanceAnnotation distance = new DistanceAnnotation();
            distance.setBox(new Rectangle(100, 100, 300, 50));
            distance.setCreatedOn(Calendar.getInstance().getTime());
            distance.setMessage("Wall length: 12 feet");
            distance.setOpacity(0.8);
            distance.setPageNumber(0);
            distance.setPenColor(0xFF0000); // Red color
            distance.setPenStyle(PenStyle.SOLID);
            distance.setPenWidth((byte) 2);
            distance.setReplies(replies);

            // Add and save
            annotator.add(distance);
            annotator.save("output_with_distance_annotation.pdf");
            
            System.out.println("Distance annotation added successfully!");
        } catch (Exception e) {
            System.err.println("Error adding distance annotation: " + e.getMessage());
        }
    }
}

Jalankan potongan kode, buka file output di viewer PDF apa pun yang mendukung anotasi, dan Anda akan melihat penggaris berfungsi penuh siap untuk interaksi.

## Kasus Penggunaan Umum dan Aplikasi Dunia Nyata

Memahami di mana anotasi jarak bersinar membantu Anda memutuskan cara menyematkannya dalam produk Anda.

### Dokumentasi Teknis dan Manual
- Sorot dimensi komponen dalam panduan perakitan.  
- Tampilkan zona clearance dalam manual instalasi.  
- Sediakan pengukuran referensi cepat untuk daftar periksa kontrol kualitas.  

### Proyek Arsitektur dan Teknik
- Tampilkan ukuran ruangan pada denah.  
- Indikasikan jarak elemen struktural.  
- Tandai jarak saluran utilitas dan clearance keselamatan.  

### Aplikasi Medis dan Ilmiah
- Ukur struktur anatomi dalam gambar radiologi.  
- Tambahkan bar skala ke slide mikroskopi.  
- Dokumentasikan dimensi spesimen dalam laporan penelitian.  

### Real Estate dan Manajemen Properti
- Visualisasikan batas lahan dan garis properti.  
- Tampilkan dimensi ruangan untuk listing.  
- Indikasikan ukuran tempat parkir dan pengukuran lansekap.  

## Memecahkan Masalah Umum

Bahkan contoh yang ditulis dengan baik dapat mengalami kendala. Di bawah ini masalah paling umum dan cara mengatasinya.

### Masalah: "File not found" atau Masalah Path
**Gejala:** Exception dilempar saat membuat `Annotator`.  
**Solusi:** Gunakan path absolut selama pengembangan, verifikasi file ada, dan pastikan proses memiliki izin baca.

```java
```java
// Better path handling
String inputPath = new File("documents/input.pdf").getAbsolutePath();
final Annotator annotator = new Annotator(inputPath);

### Masalah: Anotasi Tidak Terlihat
**Gejala:** Kode berjalan tanpa error, tetapi tidak ada penggaris yang muncul.  
**Penyebab umum:** Indeks halaman salah (ingat halaman mulai dari 0), anotasi ditempatkan di luar kanvas yang terlihat, atau opasitas terlalu rendah.

**Perbaikan cepat:**

```java
```java
distance.setPageNumber(0); // First page
distance.setOpacity(1.0);  // Fully opaque
distance.setBox(new Rectangle(50, 50, 200, 30)); // Visible position

### Masalah: Masalah Memori dengan Dokumen Besar
**Gejala:** `OutOfMemoryError` atau kinerja lambat pada file ratusan halaman.  
**Solusi:**  
- Dispose setiap instance `Annotator` segera setelah selesai.  
- Proses dokumen secara berurutan bukan memuat semuanya sekaligus.  
- Tingkatkan heap JVM (`-Xmx4g` atau lebih tinggi) untuk input yang sangat besar.

```java
```java
// Good practice - use try-with-resources
try (Annotator annotator = new Annotator("large-document.pdf")) {
    // Your annotation code here
} // Automatic disposal

### Masalah: Kesalahan Terkait Lisensi
**Gejala:** Peringatan tentang batasan percobaan atau kegagalan validasi lisensi.  
**Solusi:**  
- Pastikan path file lisensi benar dan file dapat dibaca.  
- Pastikan versi lisensi cocok dengan versi pustaka GroupDocs.Annotation yang Anda gunakan.  
- Verifikasi bahwa lisensi sementara belum kedaluwarsa.

## Tips Optimasi Kinerja

Saat Anda beralih dari prototipe ke produksi, ingat pertimbangan kinerja berikut.

### Praktik Terbaik Manajemen Memori
- **Selalu dispose**: Lebih baik gunakan try‑with‑resources atau `dispose()` eksplisit.  
- **Operasi batch**: Kelompokkan banyak perubahan anotasi dalam satu sesi `Annotator` untuk mengurangi overhead.  
- **Profiling**: Gunakan profiler Java (VisualVM, YourKit) untuk memantau penggunaan memori native.

### Optimasi Pemrosesan File
- **Cache dokumen yang sering diakses** di memori saat hanya baca.  
- **Lebih pilih PDF** daripada gambar resolusi tinggi untuk rendering lebih cepat; PDF rata‑rata 30‑40 % lebih kecil untuk konten visual yang sama.  
- **Sesuaikan resolusi gambar**: Turunkan skala gambar sumber hingga maksimum 150 DPI kecuali diperlukan fidelitas lebih tinggi.

### Pertimbangan Pemrosesan Konkuren
Jika layanan Anda memproses banyak file secara paralel, ikuti aturan berikut:

```java
```java
// Example of efficient batch processing
public void processMultipleDocuments(List<String> filePaths) {
    for (String path : filePaths) {
        try (Annotator annotator = new Annotator(path)) {
            // Add multiple annotations per document
            addDistanceAnnotation(annotator, config1);
            addDistanceAnnotation(annotator, config2);
            // Save once with all annotations
            annotator.save(getOutputPath(path));
        }
    }
}

- Setiap thread harus menginstansiasi `Annotator` masing‑masing.  
- Gunakan thread pool terbatas untuk menghindari kehabisan sumber daya sistem.  
- Pantau penggunaan CPU dan heap di bawah beban; skalakan secara horizontal jika diperlukan.

## Opsi Konfigurasi Lanjutan

Setelah Anda menguasai dasar, jelajahi fitur lanjutan ini untuk menyempurnakan anotasi Anda.

### Opsi Styling Kustom
```java
```java
// Advanced pen styling
distance.setPenStyle(PenStyle.DASH_DOT);
distance.setPenWidth((byte) 4);
distance.setPenColor(0x00FF00); // Hex color codes work too

// Custom opacity for different emphasis levels
distance.setOpacity(0.6); // Subtle background measurements
// vs
distance.setOpacity(1.0); // Prominent foreground measurements

Anda dapat mendefinisikan objek `Pen` kustom, menerapkan isian gradien, atau bahkan menyematkan penanda SVG di ujung garis penggaris.

### Penempatan Dinamis
```java
```java
// Calculate position based on document dimensions or content
Rectangle dynamicBox = calculateOptimalPosition(documentWidth, documentHeight);
distance.setBox(dynamicBox);

Manfaatkan koordinat relatif halaman sehingga anotasi secara otomatis berpindah posisi ketika dokumen di-zoom atau diputar.

### Anotasi Kondisional
```java
```java
// Add annotations based on document content or user preferences
if (document.getType() == DocumentType.ARCHITECTURAL_PLAN) {
    distance.setMessage("Room dimension");
    distance.setPenStyle(PenStyle.SOLID);
} else if (document.getType() == DocumentType.ENGINEERING_DRAWING) {
    distance.setMessage("Component spacing");
    distance.setPenStyle(PenStyle.DOT);
}

Tambahkan logika yang hanya membuat anotasi jarak ketika kondisi tertentu terpenuhi (mis., ketika komponen melebihi ambang toleransi).

## Integrasi dengan Sistem Lain

Anotasi jarak tidak terisolasi—mereka secara alami cocok dalam ekosistem manajemen dokumen yang lebih luas.

### Integrasi Basis Data
`AnnotationRecord` adalah model data kustom untuk menyimpan metadata anotasi dalam basis data.

```java
```java
// Save annotation details to database
AnnotationRecord record = new AnnotationRecord();
record.setDocumentId(documentId);
record.setAnnotationType("distance");
record.setMeasurement(distance.getMessage());
record.setCreatedDate(distance.getCreatedOn());

Simpan metadata anotasi (penulis, timestamp, nilai pengukuran) dalam basis data relasional untuk pelaporan dan pencarian.

### Integrasi Aplikasi Web
`DistanceAnnotationRequest` adalah DTO yang membawa parameter anotasi dari klien ke server.

```java
```java
@PostMapping("/documents/{id}/annotations/distance")
public ResponseEntity<String> addDistanceAnnotation(
    @PathVariable String id,
    @RequestBody DistanceAnnotationRequest request) {
    // Process the annotation request
    // Return success/failure response
}

Ekspos endpoint REST yang menerima file, menambahkan anotasi jarak berdasarkan payload JSON, dan mengembalikan dokumen beranotasi.

### Integrasi Penyimpanan Cloud
```java
```java
// Download from cloud, process, upload result
byte[] documentBytes = cloudStorageService.download(documentPath);
// Process with GroupDocs.Annotation
byte[] annotatedDocument = processAnnotations(documentBytes);
cloudStorageService.upload(outputPath, annotatedDocument);

Baca dan tulis file langsung dari AWS S3, Azure Blob Storage, atau Google Cloud Storage menggunakan SDK masing‑masing, lalu berikan stream ke `Annotator`.

## Pertanyaan yang Sering Diajukan

**Q: Format dokumen apa yang mendukung anotasi jarak?**  
A: GroupDocs.Annotation mendukung PDF, dokumen Word, presentasi PowerPoint, spreadsheet Excel, dan format gambar umum (PNG, JPEG, TIFF, BMP). Fitur ini berfungsi konsisten di semua lebih dari 50 format yang didukung.

**Q: Bisakah saya menyesuaikan tampilan garis pengukuran?**  
A: Tentu saja! Anda memiliki kontrol penuh atas warna pena, gaya garis (solid, dotted, dashed), lebar garis, dan opasitas. Anda juga dapat mendefinisikan simbol ujung khusus untuk standar teknik khusus.

**Q: Bagaimana saya menangani pengukuran dalam satuan yang berbeda?**  
A: Anotasi itu sendiri menampilkan teks yang Anda setel pada properti `message`. Lakukan konversi satuan apa pun (mis., inci ↔ milimeter) dalam kode Java Anda sebelum menetapkan pesan.

**Q: Bisakah pengguna berinteraksi dengan anotasi jarak setelah ditambahkan?**  
A: Ya. Pada viewer yang kompatibel (GroupDocs.Viewer, Adobe Acrobat, atau viewer web Anda sendiri), pengguna dapat mengklik, menyeret, dan mengedit penggaris. Balasan dan komentar tetap terlampir pada pengukuran untuk tinjauan kolaboratif.

**Q: Apa dampak kinerja menambahkan banyak anotasi?**  
A: Menambahkan hingga beberapa ratus anotasi per dokumen memiliki dampak yang dapat diabaikan (< 5 % beban CPU). Ketika Anda melebihi 1.000 anotasi, waktu pemuatan mungkin meningkat sedikit, tetapi perpustakaan tetap stabil dan responsif.

## Kesimpulan dan Langkah Selanjutnya

Anda kini memiliki peta jalan lengkap yang siap produksi untuk **cara menambahkan pengukuran** ke gambar dan dokumen lain dalam Java menggunakan GroupDocs.Annotation. Dengan memanfaatkan anotasi jarak, Anda dapat mengubah gambar statis menjadi aset interaktif dan kaya data yang meningkatkan kolaborasi dan mengurangi kesalahan.

**Poin penting**
- Anotasi jarak menyediakan pengukuran visual yang presisi di lebih dari 50 format file.  
- Implementasinya singkat: muat, konfigurasikan, tambahkan, simpan.  
- Kinerja kuat untuk dokumen berukuran menengah; ikuti tips manajemen memori untuk file besar.  
- Titik integrasi (DB, REST, cloud) memungkinkan Anda menyematkan anotasi ke dalam alur kerja apa pun.

### Langkah Selanjutnya yang Direkomendasikan
1. **Prototipe**: Kloning contoh lengkap, jalankan pada PDF atau gambar Anda sendiri, dan verifikasi penggaris muncul sesuai harapan.  
2. **Jelajahi tipe anotasi lain**: Anotasi highlight, teks, dan stempel dapat melengkapi pengukuran jarak.  
3. **Bangun UI**: Rancang antarmuka drag‑and‑drop yang memungkinkan pengguna akhir menempatkan penggaris langsung di browser atau klien desktop.  
4. **Rencanakan skala**: Jika Anda mengharapkan ribuan pengguna bersamaan, terapkan strategi thread‑pool dan pantau penggunaan heap seperti dijelaskan di bagian kinerja.

**Terakhir Diperbarui:** 2026-06-16  
**Diuji Dengan:** GroupDocs.Annotation 25.2 untuk Java  
**Penulis:** GroupDocs  

**Sumber Daya Terkait:**
- [Dokumentasi GroupDocs.Annotation](https://docs.groupdocs.com/annotation/java/) - Dokumentasi API yang komprehensif  
- [Referensi API](https://reference.groupdocs.com/annotation/java/) - Referensi metode dan kelas yang detail  
- [Halaman Unduhan](https://releases.groupdocs.com/annotation/java/) - Versi terbaru dan catatan rilis  
- [Forum Dukungan](https://forum.groupdocs.com/c/annotation/) - Dukungan komunitas dan diskusi  
- [Opsi Pembelian](https://purchase.groupdocs.com/buy) - Informasi lisensi komersial  
- [Percobaan Gratis](https://releases.groupdocs.com/annotation/java/) - Coba sebelum membeli  
- [Lisensi Sementara](https://purchase.groupdocs.com/temporary-license/) - Lisensi evaluasi diperpanjang  

## Tutorial Terkait
- [Cara menambahkan panah ke PDF dengan Java – Tutorial Lengkap & Praktik Terbaik](/annotation/java/graphical-annotations/add-arrow-annotations-java-groupdocs/)  
- [Java PDF Image Annotation - Tutorial Lengkap GroupDocs](/annotation/java/image-annotations/annotate-pdfs-java-groupdocs-image-annotations/)  
- [Edit PDF Annotations Java - Tutorial Lengkap GroupDocs](/annotation/java/annotation-management/groupdocs-annotation-java-modify-pdf-annotations/)