2015-02-01 3 views
0

PDF 페이지의 내용을 임의의 각도로 회전해야하며 PDPage.setRotation (int) 명령은 90 도의 배수로 제한됩니다. 페이지 내용이 벡터 및 텍스트이므로 나중에 내용을 확대 할 수 있어야합니다. 즉, 해상도 손실로 인해 페이지를 이미지로 변환 할 수 없습니다.PDF 페이지의 내용을 임의의 각도로 회전하려면 어떻게해야합니까?

+2

페이지 수준에서이 작업을 수행 할 수 없습니다. 그러나 콘텐츠 스트림 수준에서 현재 변환 행렬을 변경하여, 즉 출력을하기 전에 회전 된 행렬 인스턴스를 CTM에 연결하여 순환 게재를 설정할 수 있습니다. –

+0

콘텐츠를 그리기 만하면됩니다 (예 :기존의 일반 초상화 또는 가로 페이지를 임의의 천사에서 새로운 일반 세로 또는 가로 페이지로 가져 가면 [여기] (http://stackoverflow.com/a/26299557/1729265)에 제시된 메커니즘을 사용할 수 있습니다. 반면에 페이지 자체가 임의의 각도로 회전 할 것으로 예상되면 @TilmanHausherr 및 Bruno를 믿을 수 있습니다. – mkl

+0

감사합니다. @mkl, 2014 년 10 월 및 현재 2.0.0 스냅 샷 게시 시점의 스냅 샷 간 API 변경을 허용 한 경우 – sdmorris

답변

5

의견에서 이미 내용이 예를 들어 인 것으로 표시되었습니다. 새로운 정규 초상화 또는 가로 페이지에 임의의 각도로 기존의 세로보기 또는 가로 페이지를 제공하면 in this answer이라는 메커니즘을 사용할 수 있습니다. 코드로

  1. 가 PDFBox 개발 2.0.0-SNAPSHOT 버전과
  2. 손에있는 상황에서 필요하지 않습니다 형태 xobjects을 사용합니다을이 요구되게

그래도 여기에 빠른 & 더러운 솔루션은 현재 정규 릴리스 1.8.8에서 xobjects 형식을 도입하지 않고 작동합니다.

이 방법

void transformPage(PDDocument document, PDPage page, AffineTransform at) throws IOException, COSVisitorException 
{ 
    PDRectangle cropBox = page.findCropBox(); 
    float xOffset = (cropBox.getUpperRightX() + cropBox.getLowerLeftX())/2f; 
    float yOffset = (cropBox.getUpperRightY() + cropBox.getLowerLeftY())/2f; 
    AffineTransform transform = AffineTransform.getTranslateInstance(xOffset, yOffset); 
    transform.concatenate(at); 
    transform.concatenate(AffineTransform.getTranslateInstance(-xOffset, -yOffset)); 

    PDPageContentStream stream = new PDPageContentStream(document, page, true, false); 
    stream.concatenate2CTM(transform); 
    stream.close(); 

    COSBase contents = page.getCOSDictionary().getDictionaryObject(COSName.CONTENTS); 
    if (contents instanceof COSStreamArray) 
    { 
     COSStreamArray contentsArray = (COSStreamArray) contents; 
     COSArray newArray = new COSArray(); 
     newArray.add(contentsArray.get(contentsArray.getStreamCount() - 1)); 

     for (int i = 0; i < contentsArray.getStreamCount() - 1; i++) 
     { 
      newArray.add(contentsArray.get(i)); 
     } 

     COSStreamArray newStreamArray = new COSStreamArray(newArray); 
     page.getCOSDictionary().setItem(COSName.CONTENTS, newStreamArray); 
    } 
} 

지정된 페이지에 지정된 변환을 적용한다. 유스 케이스를 손쉽게 (PDF 페이지의 내용을 회전시키기 위해) 변환을 변환에 포함 시키려면 변환을 위해 좌표계의 원점을 페이지의 중앙으로 이동해야합니다.

있어서 반 시계 방향 45 ° (PI/4, 수학적으로 정 회전 방향)으로 문서의 페이지를 회전이

try (InputStream sourceStream = getClass().getResourceAsStream("13.pdf")) 
{ 
    final PDDocument document = PDDocument.load(sourceStream); 
    final AffineTransform transform = AffineTransform.getRotateInstance(Math.PI/4); 

    List<PDPage> pages = document.getDocumentCatalog().getAllPages(); 

    for (PDPage page: pages) 
    { 
     transformPage(document, page, transform); 
    } 

    document.save("13-transformedPages.pdf"); 
} 

처럼 사용될 수있다.

2

ISO-32000-1 (PDF의 ISO 표준) 인 specifically Table 30 ("Entries in a page object")을 읽으십시오. 이는이 같은 Rotate 엔트리 (그대로 복사/붙여 넣기)를 정의

표시되거나 인쇄 될 때 페이지 시계 방향으로 회전되어야하는 각도의 수. ISO 표준은 표준 정상적으로 단어를 사용하는 경우에 반대 , 당신은 (규범 적 규칙을 직면한다 단어를 사용 할 때마다 0

: 값은 90 기본 값의 배수이어야한다) 추천을 받고 있습니다.

간단히 말해서 : PDF 사양에서 명시 적으로 금지 된 것을 요청하고 있습니다. PDF로는 요구 사항을 충족하는 것이 불가능합니다. 페이지의 오리엔테이션은 0, 90, 180 또는 270도입니다. 페이지를 회전하는 대신 페이지의 내용을 회전해야합니다.

+0

내 나쁜 소식 나는 그 페이지의 내용을 의미했다. 나는 그것을 반영하기 위해 질문을 바꿀 것이다. – sdmorris

+0

나는 iText 사람이다. 나는 PDF로 (그리고 iText를 사용하여) 컨텐트를 회전시키는 법을 알고 있지만, 필자의 적응 된 질문에 답하기에는 PdfBox에 익숙하지 않다. @TilmanHausherr에 설명 된대로 변환 행렬을 변경하는 메소드를 찾아야합니다. –

관련 문제