2013-01-14 3 views
3

일반 RGB 색상의 PDF 세트가 있습니다. 이들은 파일 크기를 줄이기 위해 8 비트로 변환하면 도움이됩니다. PDF에서 비 래스터 요소를 유지하면서이 작업을 수행 할 수있는 API 또는 도구가 있습니까?실용적인 PDF 이미지를 8 비트로 변환

답변

2

이것은 재미 있습니다. PDF 래스터 라이저와 함께 atalasoft dotImage와 dotPdf는 이것을 할 수 있습니다 (면책 조항 : 저는 Atalasoft에서 일하고 대부분의 PDF 도구를 작성했습니다). 내가 관리하는 ImageSource 사용하는 거라고,

List<int> GetCandidatePages(Stream pdf, string password) 
{ 
    List<int> retVal = new List<int>(); 
    using (PageCollection pages = new PageCollection(pdf, password)) { 
     for (int i=0; i < pages.Count; i++) { 
      if (pages[i].SingleImageOnly()) 
       retVal.Add(i); 
     } 
    } 
    pdf.Seek(0, SeekOrigin.Begin); // restore file pointer 
    return retVal; 
} 

다음, 나는 8 비트 이미지로 선회, 만 페이지를 래스터 싶지만, 효율적으로 일을 계속 : I 후보 페이지를 찾아 처음 시작할 것 물론 메모리 :

public class SelectPageImageSource : RandomAccessImageSource { 
    private List<int> _pages; 
    private Stream _stm; 

    public SelectPageImageSource(Stream stm, List<int> pages) 
    { 
     _stm = stm; 
     _pages = pages; 
    } 

    protected override ImageSourceNode LowLevelAcquire(int index) 
    { 
     PdfDecoder decoder = new PdfDecoder(); 
     _stm.Seek(0, SeekOrigin.Begin); 
     AtalaImage image = PdfDecoder.Read(_stm, _pages[index], null); 
     // change to 8 bit 
     if (image.PixelFormat != PixelFormat.Pixel8bppIndexed) { 
      AtalaImage changed = image.GetChangedPixelFormat(PixelFormat.Pixel8bppIndexed); 
      image.Dispose(); 
      image = changed; 
     } 
     return new FileReloader(image, new PngEncoder()); 
    } 
    protected override int LowLevelTotalImages() { return _pages.Count; } 

} 

다음이에서 새 PDF를 작성해야합니다

public void Make8BitImagePdf(Stream pdf, Stream outPdf, List<int> pages) 
{ 
    PdfEncoder encoder = new PdfEncoder(); 
    SelectPageImageSource source = new SelectPageImageSource(pdf, pages); 
    encoder.Save(outPdf, source, null); 
} 

다음은 당신이 새로운 사람과 원래의 페이지를 교체해야합니다

public void ReplaceOriginalPages(Stream pdf, Stream image8Bit, Stream outPdf, List<int> pages) 
{ 
    PdfDocument docOrig = new PdfDocument(pdf); 
    PdfDocument doc8Bit = new PdfDocument(image8Bit); 
    for (int i=0; i < pages.Count; i++) { 
     docOrig.Pages[pages[i]] = doc8Bit[i]; 
    } 
    docOrig.Save(outPdf); // this is your final 
} 

이렇게하면 원하는대로 할 수 있습니다. 덜 이상적인 점은 이미지 페이지가 래스터 화 된 것이므로 원하는 것은 아닐 것입니다. 좋은 점은 래스터 라이 제이션만으로 출력을 생성하는 것이 쉽지만 원본 이미지의 해상도가 아닐 수도 있다는 것입니다. 이 작업을 수행 할 수 있지만 SingleImageOnly 페이지에서 이미지를 추출한 다음 픽셀 형식을 변경해야한다는 점에서 훨씬 더 많은 작업이 필요합니다. 이 문제는 SingleImageOnly가 이미지가 전체 페이지에 맞는지 의미하지 않으며 이미지가 특정 위치에 놓여 있음을 의미하지 않습니다. PixelFormat 변경 (사실, 변경 전) 이외에도 페이지의 이미지를 이미지 자체에 배치하는 데 사용되는 행렬을 적용하고 적절한 여백 세트와 원본 페이지 크기를 사용하여 PdfEncoder를 사용하려고합니다 이미지가 있어야합니다. 이 모든 것은 잘리고 건조되었지만 상당한 양의 코드입니다.

우리의 PDF 생성 API를 사용할 수도있는 또 다른 방법이 있습니다. 문서를 열고 8 비트 문서로 이미지 리소스를 교체하는 작업이 포함됩니다. 이것은 또한 할 수 있지만, 완전히 사소하지는 않습니다. 당신이 뭔가를 할 것이다 :

public void ReplaceImageResources(Stream pdf, Stream outPdf, List<int> pages) 
{ 
    PdfGeneratedDocument doc = new PdfGeneratedDocument(pdf); 
    doc.Resources.Images.Compressors.Insert(0, new AtalaImageCompressor()); 

    foreach (int page in pages) { 
     // GetSinglePageImage uses PageCollection, as above, to 
     // pull a single image from the page (no need to use the matrix) 
     // then converts it to 8 bpp indexed and returns it or null if it 
     // is already 8 bpp indexed (or 4bpp or 1bpp). 
     using (AtalaImage image = GetSinglePageImage(pdf, page)) { 
      if (image == null) continue; 
      foreach (string resName in doc.Pages[page].ImportedImages) { 
       doc.Resources.Images.Remove(resName); 
       doc.Resources.Images.Add(resName, image); 
       break; 
      } 
     } 
    } 
    doc.Save(outPdf); 
} 

내가 말했듯이,이 까다 롭습니다 - PDF 파일 생성 제품군은 전체 천에서 새로운 PDF 파일을 만들거나 미래에 (기존 PDF에 새 페이지를 추가하기 위해 만들어진, 우리가 원하는 전체 편집 추가). 그러나 PDF는 모든 이미지를 리소스 문서로 관리하며 이러한 리소스를 완전히 대체 할 수 있습니다. 더 쉽게 작업 할 수 있도록 AtalaImage 객체를 처리하고 기존 이미지 리소스를 제거하고 새 이미지 리소스로 대체하는 ImageCompressor를 Image 리소스 컬렉션에 추가합니다.

이제는 자신의 제품에 대해 이야기 할 때 어떤 공급 업체가 볼 수없는 것을 할 것입니다. 여러 단계에서 비판적으로 보겠습니다. 첫째, 그것은 아주 싸구려가 아닙니다. 죄송합니다. 가격을 볼 때 스티커 충격을받을 수는 있지만 가격에는 정직한 직원의 기술 지원이 포함됩니다.

iTextPdf Sharp 또는 Bit Miracle의 Docotic PDF 라이브러리 또는 Tall Components PDF 라이브러리를 사용하면이 작업을 많이 수행 할 수 있습니다. 후자의 두 사람도 비용이 들었습니다. 비트 기적의 엔지니어들은 꽤 도움이된다는 것을 입증했으며 여기에서 볼 수 있습니다 (HI!). 어쩌면 그들은 당신을 도울 수 있습니다.iTextPdfSharp는 옳은 일을하기 위해 PDF 스펙을 이해할 필요가 있거나, 가비지를 출력 할 가능성이 높다는 점에서 문제가 있습니다. PDF 파일을 iTextPdfSharp를 사용하여 자신의 라이브러리와 나란히 실험 해 보았습니다. 에 대한 공통점은에 대한 PDF 사양 수정에 대한 심층적 인 지식이 필요합니다. 저의 고수준 툴에서 PDF 스펙을 알 필요가 없으며 나쁜 PDF 작성에 대해 걱정할 필요가 없도록 의사 결정을했습니다.

비슷한 일을하는 코드베이스에는 분명히 다른 여러 도구가 있다는 사실을 특히 좋아하지 않습니다. PageCollection은 역사적인 이유로 PDF 래스터 라이저의 일부입니다. PdfDocument는 페이지를 조작하기 위해 엄격하게 만들어졌으며 메모리로 가볍고 인색합니다. PdfGeneratedDocument는 페이지 내용을 조작/생성하기 위해 만들어졌습니다. PdfDecoder는 기존 PDF에서 래스터 이미지를 생성합니다. PdfEncoder는 이미지에서 이미지 전용 PDF를 생성합니다. 이 모든 명백하게 겹치는 틈새 도구를 보유하는 것은 매우 어려울 수 있지만, 그들과 서로의 관계는 논리적입니다.

관련 문제