C++에서 PDF 주석 작업하기
Aspose.PDF FOSS for C++는 모든 PDF 주석을 공통 Annotation 기본 클래스의 서브클래스로 표현하고, Page::Annotations()가 반환하는 AnnotationCollection을 통해 페이지상의 주석을 노출합니다. 이 가이드는 TextAnnotation을 사용하여 페이지에 일반 텍스트 메모 주석과 스타일이 적용된 주석을 추가하고, 문서를 저장한 뒤 다시 열어 주석을 읽어들인 후 하나를 제거합니다. 라이브러리는 CMake 프로젝트에 서브디렉터리 종속성으로 통합되며, 패키지 레지스트리 설치 단계가 없습니다.
단계별 가이드
1단계: 패키지 설치
라이브러리를 CMake 서브디렉터리로 추가하고 정적 라이브러리 타깃을 링크합니다:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)최소 프로그램으로 툴체인 및 링크 단계가 올바르게 해결되는지 확인합니다:
#include <aspose/pdf/document.hpp>
#include <iostream>
int main() {
Aspose::Pdf::Document doc;
std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}pages: 0를 출력하는 성공적인 빌드는 라이브러리가 링크되었음을 확인시켜 줍니다.
2단계: 필요한 클래스 가져오기
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/page_collection.hpp>
#include <aspose/pdf/rectangle.hpp>
#include <aspose/pdf/color.hpp>
#include <aspose/pdf/annotations/annotation.hpp>
#include <aspose/pdf/annotations/annotation_collection.hpp>
#include <aspose/pdf/annotations/annotation_type.hpp>
#include <aspose/pdf/annotations/annotation_flags.hpp>
#include <aspose/pdf/annotations/border.hpp>
#include <aspose/pdf/annotations/border_style.hpp>
#include <aspose/pdf/annotations/text_annotation.hpp>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Annotations;3단계: 문서를 만들고 페이지 추가
새 문서를 만들고 그에 페이지를 추가합니다. PageCollection::Add()은(는) 새로 추가된 Page을(를) 반환합니다:
Document doc;
Page page = doc.Pages().Add();4단계: 페이지에 텍스트 주석 추가
TextAnnotation은(는) 포스트잇 스타일 주석으로 표시됩니다. 이를 소유하는 Document에서 생성하고, Rect()로 위치를 설정하고, Contents()으로 메시지를 지정한 다음, 페이지의 AnnotationCollection에 추가합니다:
TextAnnotation note{doc};
note.Rect(Rectangle(100.0, 700.0, 200.0, 720.0, false));
note.Contents("Reviewed and approved.");
page.Annotations().Add(note);5단계: 두 번째 주석을 색상, 테두리 및 플래그로 스타일링
Annotation은(는) 또한 Color(), Border(), Flags()을(를) 노출합니다. Flags()는 AnnotationFlags 비트 필드를 받습니다 — 값을 비트 OR 연산으로 결합하여 한 번에 여러 플래그를 설정합니다:
TextAnnotation flagged{doc};
flagged.Rect(Rectangle(100.0, 600.0, 300.0, 650.0, false));
flagged.Contents("Needs follow-up");
flagged.Color(Color::FromRgb(220, 20, 20));
flagged.Flags(AnnotationFlags::Print | AnnotationFlags::ReadOnly);
flagged.Border().Width(2);
flagged.Border().Style(BorderStyle::Dashed);
page.Annotations().Add(flagged);6단계: 문서 저장
Save()가 실행될 때까지 디스크에 아무 것도 기록되지 않습니다:
doc.Save("annotated.pdf");단계 7: PDF를 다시 열고 주석을 읽습니다
저장된 파일을 다시 열고 첫 페이지의 AnnotationCollection를 다시 읽습니다. AnnotationCollection은 0부터 시작하며, Count()는 해당 페이지에 포함된 주석 수를 보고합니다:
Document reopened("annotated.pdf");
auto& annots = reopened.Pages()[1].Annotations();
std::cout << "Annotation count: " << annots.Count() << "\n";
for (int i = 0; i < annots.Count(); ++i) {
const auto& a = annots[i];
if (a.AnnotationType() == AnnotationType::Text) {
std::cout << "Text annotation: " << a.Contents() << "\n";
}
}단계 8: 주석을 제거하고 다시 저장합니다
AnnotationCollection::Delete(index)는 0부터 시작하는 위치를 기준으로 주석을 제거합니다. 첫 번째 주석을 삭제하고 결과를 새 파일에 저장합니다:
annots.Delete(0);
reopened.Save("annotated-cleaned.pdf");일반적인 문제 및 해결 방법
호출한 후 저장된 PDF에 아무 변화가 없습니다 Annotations().Add()
두 가지가 여기서 흔히 잘못됩니다. 첫째, PageCollection은 1 기반(doc.Pages()[1]이 첫 페이지)이고 AnnotationCollection는 0 기반(annots[0]이 첫 주석)입니다 — 두 인덱싱 방식을 혼동하면 잘못된 객체를 조작하게 됩니다. 둘째, Document::Save()가 주석이 추가된 후에 실제로 실행되는지 확인하십시오; 그때까지는 디스크에 아무 것도 기록되지 않습니다.
AnnotationCollection 인덱싱 또는 Delete(index) throws std::out_of_range
유효한 인덱스는 0부터 Count() - 1까지입니다. 음수 인덱스이거나 Count()와 같거나 큰 인덱스를 전달하면 설계상 std::out_of_range가 발생합니다. 루프나 조회를 제한하려면 먼저 Count()를 호출하십시오.
Remove() returns false 같은 주석에 대해 두 번째로 호출할 때
이는 오류가 아닙니다. Remove()은 주석이 bool으로 찾아지고 제거되었는지 보고합니다; 이미 사라진 주석에 다시 호출하면 아무 작업도 수행하지 않으며 false를 반환합니다. Remove()이 항상 성공한다고 가정하지 말고 반환 값을 확인하십시오.
새로운 값을 설정하면 AnnotationFlags 값이 이미 설정한 플래그를 지웁니다
Flags(value)은 전체 플래그 세트를 교체합니다 — 이전 값과 병합되지 않습니다. 단일 플래그를 추가하거나 삭제하려면 먼저 현재 플래그를 읽고 비트 연산자로 결합하십시오, 예를 들어 플래그를 추가하려면 a.Flags(a.Flags() | AnnotationFlags::Print), 나머지는 그대로 두고 하나의 플래그만 삭제하려면 a.Flags(a.Flags() & ~AnnotationFlags::Print)를 사용합니다.
자주 묻는 질문
Annotation, TextAnnotation 및 다른 주석 하위 유형 간의 관계는 무엇입니까?
Annotation은 공통 기본 클래스입니다. TextAnnotation 및 다른 구체적인 주석 유형은 각각 하나의 PDF 주석 하위 유형에 대해 이를 특수화하며, 기본 클래스의 Rect(), Contents(), Color(), Flags(), Border() 접근자를 공유합니다.
주석은 전체 문서에 적용되나요, 아니면 한 페이지에만 적용되나요?
각 페이지는 해당 페이지의 Annotations() 메서드가 반환하는 고유한 AnnotationCollection을 가지고 있습니다. 주석은 항상 추가된 페이지에만 적용되며, 전체 문서 전체에 적용되지 않습니다.
페이지에 있는 주석 수를 어떻게 셀 수 있나요?
Page::Annotations()가 반환하는 AnnotationCollection에 대해 Count()을 호출하세요.
주석이 동시에 인쇄 가능하고 읽기 전용일 수 있나요?
예. AnnotationFlags은 비트 필드이므로 비트 OR 연산자로 값을 결합하면 됩니다. 예를 들어 AnnotationFlags::Print | AnnotationFlags::ReadOnly.
AnnotationCollection에서 주석을 삭제하면 디스크에 있는 PDF 파일에서도 제거됩니까?
Document::Save()가 실행된 후에만. Delete(), Remove(), Clear()는 메모리 컬렉션만 수정합니다 — 문서를 저장할 때까지 디스크상의 PDF는 변경되지 않습니다.