gpt4 book ai didi

pdf - 实用地将PDF图像转换为8位

转载 作者:行者123 更新时间:2023-12-01 14:44:54 25 4
gpt4 key购买 nike

我有一组标准RGB颜色的PDF。他们将受益于转换为8位以减小文件大小。是否有任何API或工具可以让我在保留PDF中的非栅格元素的同时做到这一点?

最佳答案

这很有趣。带有PDF Rasterizer和dotPdf的Atalasoft dotImage可以做到这一点(免责声明:我为Atalasoft工作,并编写了大多数PDF工具)。我首先要找到候选页面:

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位图像,但是为了保持效率,我将使用ImageSource来很好地管理内存:
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将其所有图像作为 资源来管理,并且可以完全替换这些资源。为了使生活更轻松,我们将ImageCompressor添加到处理AtalaImage对象的Image资源集合中,并删除现有的图像资源并将其替换为新的资源。

现在,我要做的事情是您在谈论他们自己的产品时可能看不到任何供应商做的事情-我将在多个层面上批评它。首先,它并不便宜。抱歉。当您查看价格时,您可能会受到贴纸的震撼,但价格包括来自工作人员的技术支持,这是首屈一指的。

您可以使用iTextPdf Sharp或Bit Miracle的Docotic PDF库或Tall Components PDF库来完成很多工作。后两者也要花钱。 Bit Miracle的工程师被证明是非常有用的,您很可能会在这里看到他们(HI!)。也许他们也可以帮助您。 iTextPdfSharp存在问题,因为您确实需要了解PDF规范才能做正确的事情,否则您可能会输出垃圾PDF-我已经与iTextPdfSharp并排进行了自己的库,并发现了许多需要深入了解PDF规范才能解决的常见任务的难点。我试图在高级工具中做出决定,以使您不需要了解PDF规范,也不必担心创建不良的PDF。

我不特别喜欢这样的事实,即我们的代码库中有几种明显不同的工具可以执行类似的操作。由于历史原因,PageCollection是我们的PDF光栅化器的一部分。 PdfDocument严格用于处理页面,并尝试使其轻巧且带有内存小巧。 PdfGeneratedDocument用于处理/创建页面内容。 PdfDecoder用于从现有PDF生成光栅图像。 PdfEncoder用于从图像生成仅图像的PDF。所有这些显然重叠的利基工具可能令人生畏,但是它们之间以及它们之间的关系都有逻辑。

关于pdf - 实用地将PDF图像转换为8位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14322033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com