PDF 주석 작업
PDF 주석 작업
C++용 Aspose.PDF FOSS에서 PDF 주석은 Annotation 기본 클래스를 통해 표현되며, 구체적인 하위 유형(TextAnnotation, LinkAnnotation, HighlightAnnotation, FreeTextAnnotation, CircleAnnotation, WatermarkAnnotation, WidgetAnnotation 등)으로 이루어집니다. 각 페이지는 Page.Annotations()을 통해 주석을 제공하며, 이는 AnnotationCollection를 반환합니다. 이 가이드에서는 페이지에 주석을 추가하고, 반복 및 제거하는 방법, 기존 문서에서 주석을 읽는 방법, 링크 동작을 첨부하는 방법, 외관을 맞춤 설정하는 방법, 그리고 주석을 평탄화하는 방법을 다룹니다.
페이지에 주석 추가하기
구체적인 주석 인스턴스를 생성하고, Rectangle으로 위치를 지정한 뒤, AnnotationCollection.Add()을 사용해 페이지 컬렉션에 추가합니다. TextAnnotation는 페이지의 한 지점에 고정된 스티키 노트 형식 주석을 나타냅니다:
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>
#include <aspose/pdf/rectangle.hpp>
int main() {
Aspose::Pdf::Document doc("input.pdf");
auto& page = doc.Pages()[1];
Aspose::Pdf::Annotations::TextAnnotation note(doc);
note.Rect(Aspose::Pdf::Rectangle(100.0, 700.0, 200.0, 720.0, false));
note.Contents("Reviewed and approved");
page.Annotations().Add(note);
doc.Save("annotated.pdf");
}Annotation.Contents() / Contents(value)은 노트 텍스트를 가져오고 설정하며, Annotation.Rect() / Rect(value)은 페이지에서 주석의 위치를 지정합니다.
주석 반복 및 제거
AnnotationCollection은 개수 세기, 인덱스 접근, 포함 여부 확인, 값이나 인덱스로 제거를 지원합니다:
#include <aspose/pdf/document.hpp>
int main() {
Aspose::Pdf::Document doc("input.pdf");
auto& annotations = doc.Pages()[1].Annotations();
std::cout << "Annotation count: " << annotations.Count() << "\n";
for (int i = 0; i < annotations.Count(); ++i) {
std::cout << "Contents: " << annotations[i].Contents() << "\n";
}
if (annotations.Count() > 0) {
annotations.Delete(0); // remove by index
}
annotations.Clear(); // remove everything
}AnnotationCollection.Contains(annotation)와 Remove(annotation)은 특정 주석 참조에 대해 작동합니다; Delete(index)는 위치로 삭제하고, Delete(annotation)은 인덱스 없이 특정 주석을 삭제합니다. IsReadOnly()는 컬렉션을 수정할 수 있는지 여부를 보고합니다.
기존 문서에서 주석 읽기
문서를 로드하면 주석이 이미 채워져 있으며 아무 것도 추가하지 않고도 검사할 수 있습니다. Annotation.AnnotationType()는 서브타입(AnnotationType::Text, AnnotationType::Highlight, AnnotationType::Link, AnnotationType::FreeText, AnnotationType::FileAttachment, AnnotationType::Watermark 및 기타)을 보고합니다:
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/annotation_type.hpp>
int main() {
Aspose::Pdf::Document doc("annotated.pdf");
auto& annotations = doc.Pages()[1].Annotations();
for (int i = 0; i < annotations.Count(); ++i) {
auto& a = annotations[i];
if (a.AnnotationType() == Aspose::Pdf::Annotations::AnnotationType::Text) {
std::cout << "Note: " << a.Contents() << "\n";
}
}
}주석 순서와 서브타입은 저장/재로드 라운드 트립 동안 보존되므로, 문서를 로드한 후 Annotations()에 인덱싱하는 코드는 파일이 기록될 때 존재했던 동일한 순서를 확인합니다.
링크 주석 및 동작
LinkAnnotation은 페이지에 클릭 가능한 영역을 붙이고 활성화될 때 PdfAction을 디스패치합니다. NamedAction는 미리 정의된 네비게이션 대상로 이동하고, JavascriptAction은 ECMAScript 문자열을 실행하며, SubmitFormAction는 FileSpecification를 통해 URL에 폼 데이터를 전송합니다:
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/annotations/link_annotation.hpp>
#include <aspose/pdf/annotations/named_action.hpp>
#include <aspose/pdf/annotations/predefined_action.hpp>
#include <aspose/pdf/rectangle.hpp>
int main() {
Aspose::Pdf::Document doc;
auto page = doc.Pages().Add();
Aspose::Pdf::Annotations::LinkAnnotation link(
page, Aspose::Pdf::Rectangle(0.0, 0.0, 100.0, 20.0, false));
link.Action(Aspose::Pdf::Annotations::NamedAction(
Aspose::Pdf::Annotations::PredefinedAction::LastPage));
page.Annotations().Add(link);
doc.Save("linked.pdf");
}LinkAnnotation.Action(value)은 모든 PdfAction 서브타입을 받아 내부적으로 복제하므로 주석은 동작의 자체 복사본을 유지합니다. LinkAnnotation.Destination() / Destination(value)은 동작 대신 명시적인 네비게이션 대상을 설정하고, Highlighting() / Highlighting(value)는 링크 클릭 시 표시되는 시각적 피드백을 제어합니다.
주석 외관: 테두리, 플래그 및 색상
모든 Annotation는 Border와 AnnotationFlags의 비트필드, 그리고 외관을 렌더링하는 데 사용되는 Color을 노출합니다:
#include <aspose/pdf/annotations/border_style.hpp>
#include <aspose/pdf/annotations/annotation_flags.hpp>
#include <aspose/pdf/color.hpp>
// 'note' is an existing Annotation reference, e.g. from AnnotationCollection.
note.Border().Width(2);
note.Border().Style(Aspose::Pdf::Annotations::BorderStyle::Dashed);
note.Flags(Aspose::Pdf::Annotations::AnnotationFlags::Print);
note.Color(Aspose::Pdf::Color::Red());Border.Style()는 BorderStyle::Solid, Dashed, Beveled, Inset, 또는 Underline를 허용합니다. Border.Effect()은 또한 EffectIntensity()이(가) 강조 정도를 제어하는 BorderEffect::Cloudy 윤곽선을 지원합니다. AnnotationFlags는 비트필드이며 — Print, NoZoom, ReadOnly, LockedContents와 같은 값을 결합하여 주석이 표시 내용은 변경하지 않고 뷰어에서 어떻게 동작하는지 제어합니다.
주석 평탄화
단일 주석은 Annotation.Flatten()를 직접 호출하여 — 페이지 내용에 병합되고 비대화형으로 만들어지는 — 평탄화할 수 있습니다:
#include <aspose/pdf/document.hpp>
int main() {
Aspose::Pdf::Document doc("annotated.pdf");
auto& annotations = doc.Pages()[1].Annotations();
for (int i = 0; i < annotations.Count(); ++i) {
annotations[i].Flatten();
}
doc.Save("flattened.pdf");
}문서 전체에 걸친 주석 작업의 경우, PdfAnnotationEditor는 API 전반에 걸쳐 사용되는 공유 Facade 패턴을 따릅니다: BindPdf()로 소스 문서를 바인드하고, 하나 이상의 주석 작업을 적용한 다음, Save()으로 결과를 기록합니다:
#include <aspose/pdf/facades/pdf_annotation_editor.hpp>
int main() {
Aspose::Pdf::Facades::PdfAnnotationEditor editor;
editor.BindPdf("annotated.pdf");
editor.FlatteningAnnotations();
editor.Save("flattened.pdf");
}PdfAnnotationEditor.DeleteAnnotations()는 바인드된 문서에서 모든 주석을 제거합니다; DeleteAnnotations(annotType)은 제거를 단일 AnnotationType로 제한합니다. ImportAnnotationsFromXfdf(xfdfFile)와 ImportAnnotationsFromFdf(fdfFile)는 다른 PDF 뷰어에서 내보낸 주석 데이터를 로드합니다.
팁 및 모범 사례
- 항상
Document.Save()을 호출하기 전에 새로 만든 주석을Page.Annotations()에 추가하십시오 — 컬렉션에 추가되지 않은 주석은 출력 파일에 기록되지 않습니다. - 주석이 아직 존재하는지 확신이 서지 않을 경우
AnnotationCollection.Contains(annotation)를 사용해Remove()을 호출하십시오; 주석이 없을 때Remove()는 예외를 발생시키는 대신false을 반환합니다. - 신뢰할 수 없거나 제3자 PDF 파일에서 로드된 주석을 반복할 때 서브타입 동작에 대해 캐스팅하거나 분기하기 전에
Annotation.AnnotationType()를 확인하십시오. - 문서를 보관하기 전에
Annotation.Flatten()를 사용해 주석을 평탄화하세요(전체 문서의 경우PdfAnnotationEditor.FlatteningAnnotations()사용). 이렇게 하면 다른 도구의 검토자가 작성한 동일한 모습을 볼 수 있습니다. AnnotationFlags는 비트필드입니다 — 한 번에 하나의 플래그만 활성화될 수 있다고 가정하지 말고 열거형의 기본 정수 값과 플래그를 결합하십시오.
일반적인 문제
| 문제 | 원인 | 수정 |
|---|---|---|
| 저장 후 주석이 보이지 않음 | 주석은 생성되었지만 Page.Annotations()에 추가되지 않았습니다. | page.Annotations().Add(annotation)를 doc.Save()보다 먼저 호출하십시오. |
Remove()는 false를 반환합니다. | 전달된 주석 참조가 현재 컬렉션에 있는 항목과 일치하지 않습니다. | Contains()을 먼저 사용하거나, Delete(index)으로 인덱스를 지정해 제거하십시오. |
| 다시 로드한 후 잘못된 주석 유형 | 코드가 AnnotationType()을 확인하지 않고 특정 하위 유형을 가정했습니다. | 객체를 특정 하위 유형으로 처리하기 전에 Annotation.AnnotationType()에서 분기하십시오. |
| 링크 액션이 할당 후 설정되지 않은 것으로 보입니다. | 지역 PdfAction가 범위를 벗어났으며; LinkAnnotation.Action()은 원본 객체가 아니라 주석의 복제본을 반환합니다. | 원본 로컬 변수를 유지하는 대신 link.Action()을 통해 액션을 다시 읽어옵니다. |
PdfAnnotationEditor 연산은 효과가 없습니다. | BindPdf()가 호출되지 않았거나, 존재하지 않는 경로로 호출되었습니다 | BindPdf()이 성공했는지 확인한 뒤에 FlatteningAnnotations() 또는 DeleteAnnotations()를 호출하십시오 |
FAQ
PDF 페이지에 댓글 스타일 주석을 추가하려면 어떻게 해야 하나요?
대상 Document을(를) 사용해 TextAnnotation를 생성하고, Rect()와 Contents()을 설정한 다음 저장하기 전에 page.Annotations()에 추가하십시오.
내가 보고 있는 주석이 어떤 종류인지 어떻게 확인할 수 있나요?
Annotation.AnnotationType() 를 호출하면 AnnotationType 열거형 값이 반환되며, Text, Link, Highlight, FreeText, FileAttachment 또는 Watermark 중 하나입니다.
하나의 주석에 여러 플래그가 포함될 수 있나요?
예. AnnotationFlags 은 비트필드(Default, Invisible, Hidden, Print, NoZoom, ReadOnly, LockedContents 등)이며, 따라서 여러 플래그를 하나의 주석에 결합할 수 있습니다.
하나의 주석을 평탄화하는 것과 문서를 평탄화하는 것의 차이는 무엇인가요?
Annotation.Flatten() 은 단일 주석을 해당 페이지 내용에 병합합니다. PdfAnnotationEditor.FlatteningAnnotations() 은 (페이지 범위와 AnnotationType 로 선택적으로 범위를 지정하고, start, end, annotType 를 받는 오버로드를 통해) 전체 바인드된 문서를 한 번에 평탄화합니다.
문서에서 특정 유형의 모든 주석을 어떻게 제거하나요?
PdfAnnotationEditor.BindPdf() 로 문서를 바인드하고, 대상 AnnotationType 로 DeleteAnnotations(annotType) 을 호출한 뒤, 결과를 Save() 합니다.
API Reference 요약
| 클래스/메서드 | 설명 |
|---|---|
Annotation | 모든 PDF 주석 하위 유형에 대한 추상 기본 클래스 |
Annotation.Rect() / Rect(value) | 주석의 경계 사각형을 가져오거나 설정합니다. |
Annotation.Contents() / Contents(value) | 주석의 텍스트 내용을 가져오거나 설정합니다 |
Annotation.AnnotationType() | 이 주석에 대한 AnnotationType 열거형 값을 반환합니다 |
Annotation.Flags() / Flags(value) | Get 또는 set AnnotationFlags 비트필드 |
Annotation.Border() / Border(value) | 주석의 Border를 가져오거나 설정합니다. |
Annotation.Color() / Color(value) | 주석의 표시 Color를 가져오거나 설정합니다 |
Annotation.Flatten() | 이 주석을 페이지 내용에 병합하여 상호 작용할 수 없게 만듭니다 |
AnnotationCollection | 페이지에 있는 주석들의 순서가 지정된 컬렉션이며, Page.Annotations()에 의해 반환됩니다 |
AnnotationCollection.Add(annotation) / Add(annotation, considerRotation) | 컬렉션에 주석을 추가합니다 |
AnnotationCollection.Count() | 컬렉션에 있는 주석의 수를 반환합니다 |
AnnotationCollection.Contains(annotation) | 컬렉션이 주어진 주석을 보유하고 있는지 보고합니다 |
AnnotationCollection.Remove(annotation) | 특정 주석을 제거합니다; 찾지 못하면 false을 반환합니다 |
AnnotationCollection.Delete(index) / Delete(annotation) | 인덱스 또는 참조를 통해 주석을 제거합니다 |
AnnotationCollection.Clear() | 컬렉션에서 모든 주석을 제거합니다 |
TextAnnotation | 스티키 노트 스타일 주석, Open() 및 Icon() (TextIcon) 포함 |
LinkAnnotation | 클릭 가능한 영역이 Action() / Action(value)를 통해 PdfAction을(를) 디스패치합니다 |
LinkAnnotation.Destination() / Destination(value) | 명시적 탐색 대상을 가져오거나 설정합니다. |
HighlightAnnotation | 텍스트 범위에 강조 색상을 표시합니다 |
FreeTextAnnotation | 텍스트 호출을 표시합니다; Justification(), DefaultAppearanceObject(), Callout()를 통해 구성됩니다 |
CircleAnnotation | 주석의 사각형 내에 타원을 그립니다 |
WatermarkAnnotation | 오버레이 주석에 Opacity() / Opacity(value) 접근자를 사용 |
WidgetAnnotation | 폼 필드 외관 주석에 ReadOnly(), Required(), Exportable(), DefaultAppearance() 사용 |
NamedAction | 미리 정의된 네비게이션 동작(PredefinedAction enum)을 LinkAnnotation에 연결할 수 있음 |
JavascriptAction | Script() / GetECMAScriptString()를 통해 ECMAScript 문자열을 실행 |
SubmitFormAction | 폼 데이터를 FileSpecification URL에 Url() / Url(value)를 통해 전송합니다 |
Border | 주석 경계선: Width(), Style() (BorderStyle), Effect() (BorderEffect) |
PdfAnnotationEditor | 문서 전체 주석 가져오기, 수정, 평탄화 및 삭제를 위한 파사드 |
PdfAnnotationEditor.FlatteningAnnotations() | 바인드된 문서 전체에 주석을 평탄화합니다 |
PdfAnnotationEditor.DeleteAnnotations(annotType) | 주어진 AnnotationType에 대한 모든 주석을 삭제합니다 |
PdfAnnotationEditor.ImportAnnotationsFromXfdf(xfdfFile) | XFDF 파일에서 주석을 가져옵니다 |