当前位置: 首页 > 知识库问答 >
问题:

将 PDF 页面从纵向更改为横向

魏康安
2023-03-14

给定一个包含纵向页面的现有 PDF 文件,我该如何以编程方式(使用 .NET)处理该文件,以便在横向页面上生成具有相同内容的新文件。

新页面应该充分利用可用的横向宽度。页面数量可能会增加,因为现有的纵向页面可能不适合一个横向页面。

背景故事:我们使用Google Sheets REST API来生成pdf文档。如果有很多列,文档可能会很宽。不幸的是,Google Drive REST API总是以纵向模式导出,并且不提供更改为横向模式的选项。

下面是我们需要处理的一个示例PDF文件:https://drive . Google . com/file/d/1 dvf 1 GD 7 zmdx 9 wjhsegebfpcvytjbn-uG/view?usp =共享

共有2个答案

宿楚青
2023-03-14

使用iTextSharp(iText for. Net v5.5.13)和PdfVeryDenseMergeToolPageVerticalAnalyzer类从这个问题(在"UPDATE 2"和"UPDATE 3"中,OP从接受的C#答案发布了他的Java解决方案的端口)如下所示:

List<PdfReader> Files = new List<PdfReader>();
Files.Add(new PdfReader(@"Example.pdf"));

PdfVeryDenseMergeTool tool = new PdfVeryDenseMergeTool(new RectangleReadOnly(595, 420), 18, 18, 10);

using (MemoryStream ms = new MemoryStream())
{
    tool.Merge(ms, Files);
    byte[] bytes = ms.ToArray();
    // bytes contains the result
} 

我得到一个五页的横向结果PDF,看起来像这样:

宫俊才
2023-03-14

您可以使用文档目录.pdf库来执行此操作。最简单的解决方案是将每个源页面转换为 XObject,然后将其缩放为横向并在多个目标页面上绘制。

以下是示例

using System.Linq;
using BitMiracle.Docotic.Pdf;

namespace SplitToMultiplePages
{
    public static class SplitToMultiplePages
    {
        public static void Main()
        {
            // NOTE: 
            // When used in trial mode, the library imposes some restrictions.
            // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
            // for more information.
            BitMiracle.Docotic.LicenseManager.AddLicenseData("temporary or permanent license key here");

            using (var src = new PdfDocument(@"Example.pdf"))
            {
                // Calculate common parameters based on the first page.
                // That makes sense when all pages have the same size, portrait orientation, and margins.
                PdfPage srcPage = src.Pages[0];
                PdfCollection<PdfTextData> words = srcPage.GetWords();

                double topMargin = words[0].Position.Y;
                double bottomMargin = srcPage.Height - words[words.Count - 1].Bounds.Bottom;
                double scale = srcPage.Height / srcPage.Width;
                const int BorderHeight = 1;

                // This sample shows how to convert existing PDF content in portrait orientation to landscape
                Debug.Assert(scale > 1);

                using (var dest = new PdfDocument())
                {
                    bool addDestPage = false;
                    double destPageY = topMargin;
                    for (int s = 0; s < src.PageCount; ++s)
                    {
                        if (s > 0)
                        {
                            srcPage = src.Pages[s];
                            words = srcPage.GetWords();
                        }

                        // skip empty pages
                        if (words.Count == 0)
                            continue;

                        // Get content of the source page, scale to landscape and draw on multiple pages
                        double textStartY = words[0].Bounds.Top;
                        double[] lineBottomPositions = words
                            .Select(w => (w.Bounds.Bottom - textStartY + BorderHeight) * scale)
                            .Distinct()
                            .ToArray();
                        double contentHeight = lineBottomPositions[lineBottomPositions.Length - 1];

                        PdfXObject xobj = dest.CreateXObject(srcPage);

                        double remainingHeight = contentHeight;
                        while (true)
                        {
                            PdfPage destPage = addDestPage ? dest.AddPage() : dest.Pages[dest.PageCount - 1];
                            destPage.Width = srcPage.Height;
                            destPage.Height = srcPage.Width;
                            double availableHeight = destPage.Height - destPageY - bottomMargin;
                            if (remainingHeight > availableHeight)
                                availableHeight = adjustToNearestLine(availableHeight, lineBottomPositions);

                            PdfCanvas destCanvas = destPage.Canvas;
                            destCanvas.SaveState();

                            destCanvas.TranslateTransform(0, destPageY);
                            destCanvas.AppendRectangle(new PdfRectangle(0, 0, destPage.Width, availableHeight), 0);
                            destCanvas.SetClip(PdfFillMode.Winding);

                            double y = -topMargin * scale - (contentHeight - remainingHeight);
                            destCanvas.DrawXObject(xobj, 0, y, xobj.Width * scale, xobj.Height * scale, 0);

                            destCanvas.RestoreState();

                            if (remainingHeight <= availableHeight)
                            {
                                // Move to next source page
                                addDestPage = false;
                                destPageY = remainingHeight + bottomMargin;
                                break;
                            }

                            // Need more pages in the resulting document
                            remainingHeight -= availableHeight;
                            addDestPage = true;
                            destPageY = topMargin;
                        }
                    }

                    // Optionally you can use Single Column layout by default
                    //dest.PageLayout = PdfPageLayout.OneColumn;

                    dest.Save("SplitToMultiplePages.pdf");
                }
            }
        }

        private static double adjustToNearestLine(double height, double[] lineHeights)
        {
            // TODO: Use binary search for better performance

            for (int i = lineHeights.Length - 1; i >= 0; --i)
            {
                double lh = lineHeights[i];
                if (height > lh)
                    return lh;
            }

            return lineHeights[0];
        }
    }
}

该样本产生以下结果:https://drive.google.com/file/d/1ITtV3Uw84wKd9mouV4kBpPoeWtsHlB9A/view?usp=sharing

根据您的要求,您也可以跳过除第一页以外的所有页面的标题。以下是这种情况的示例:

using System.Linq;
using BitMiracle.Docotic.Pdf;

namespace SplitToMultiplePages
{
    public static class SplitToMultiplePages
    {
        public static void Main()
        {
            // NOTE: 
            // When used in trial mode, the library imposes some restrictions.
            // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
            // for more information.
            BitMiracle.Docotic.LicenseManager.AddLicenseData("temporary or permanent license key here");

            using (var src = new PdfDocument(@"Example.pdf"))
            {
                // Calculate common parameters based on the first page.
                // That makes sense when all pages have the same size, portrait orientation, and margins.
                PdfPage srcPage = src.Pages[0];
                PdfCollection<PdfTextData> words = srcPage.GetWords();

                double topMargin = words[0].Position.Y;
                double bottomMargin = srcPage.Height - words[words.Count - 1].Bounds.Bottom;
                double scale = srcPage.Height / srcPage.Width;
                const int BorderHeight = 1;

                // This sample shows how to convert existing PDF content in portrait orientation to landscape
                Debug.Assert(scale > 1);

                using (var dest = new PdfDocument())
                {
                    bool addDestPage = false;
                    double destPageY = topMargin;
                    for (int s = 0; s < src.PageCount; ++s)
                    {
                        if (s > 0)
                        {
                            srcPage = src.Pages[s];
                            words = srcPage.GetWords();
                        }

                        // skip empty pages
                        if (words.Count == 0)
                            continue;

                        // Get content of the source page, scale to landscape and draw on multiple pages
                        double textStartY = words[0].Bounds.Top;
                        
                        // Skip the header line of all pages except first
                        if (s > 0)
                        {
                            double? firstDataRowY = words.Select(w => w.Bounds.Top).FirstOrDefault(y => y > textStartY);
                            if (!firstDataRowY.HasValue)
                                continue;

                            textStartY = firstDataRowY.Value;
                        }

                        double[] lineBottomPositions = words
                            .Select(w => (w.Bounds.Bottom - textStartY + BorderHeight) * scale)
                            .Distinct()
                            .ToArray();
                        double contentHeight = lineBottomPositions[lineBottomPositions.Length - 1];

                        PdfXObject xobj = dest.CreateXObject(srcPage);

                        double remainingHeight = contentHeight;
                        while (true)
                        {
                            PdfPage destPage = addDestPage ? dest.AddPage() : dest.Pages[dest.PageCount - 1];
                            destPage.Width = srcPage.Height;
                            destPage.Height = srcPage.Width;
                            double availableHeight = destPage.Height - destPageY - bottomMargin;
                            if (remainingHeight > availableHeight)
                                availableHeight = adjustToNearestLine(availableHeight, lineBottomPositions);

                            PdfCanvas destCanvas = destPage.Canvas;
                            destCanvas.SaveState();

                            destCanvas.TranslateTransform(0, destPageY);
                            destCanvas.AppendRectangle(new PdfRectangle(0, 0, destPage.Width, availableHeight), 0);
                            destCanvas.SetClip(PdfFillMode.Winding);

                            double y = -textStartY * scale - (contentHeight - remainingHeight);
                            destCanvas.DrawXObject(xobj, 0, y, xobj.Width * scale, xobj.Height * scale, 0);

                            destCanvas.RestoreState();

                            if (remainingHeight <= availableHeight)
                            {
                                // Move to the next source page
                                addDestPage = false;
                                destPageY = remainingHeight + bottomMargin;
                                break;
                            }

                            // Need more pages in the resulting document
                            remainingHeight -= availableHeight;
                            addDestPage = true;
                            destPageY = topMargin;
                        }
                    }

                    // Optionally you can use Single Column layout by default
                    //dest.PageLayout = PdfPageLayout.OneColumn;

                    dest.Save("SplitToMultiplePages.pdf");
                }
            }
        }

        private static double adjustToNearestLine(double height, double[] lineHeights)
        {
            // TODO: Use binary search for better performance

            for (int i = lineHeights.Length - 1; i >= 0; --i)
            {
                double lh = lineHeights[i];
                if (height > lh)
                    return lh;
            }

            return lineHeights[0];
        }
    }
}

“skip headers”示例的结果文件:https://drive . Google . com/file/d/1v 9 lpyiposknngheuzz 8 KD 3 xswmxgbjiz/view?usp =共享

 类似资料:
  • 我有一个从LibreOffice Writer导出的PDF文件。这里有一个例子。一些页面具有纵向,其他页面具有横向。我正在使用Linux,当我在evice或Foxit Reader中查看文件时,它会正确显示,即所有文本行都是水平的。它也可以在我的打印机上用A4纸正确打印:横向页面逆时针旋转90度,使文本行垂直。 问题是:文档将在另一台设备(出版商中)上打印,我被告知所有页面都必须具有纵向方向。我不

  • 问题内容: 我有一个PDFReader,其中包含横向模式的某些页面和纵向模式的其他页面。 我需要区分它们以进行一些处理…但是,如果我调用getOrientation或getPageSize,则该值始终是相同的(pagesize为595,方向为0)。 为什么横向页面的值没有不同? 我试图找到其他方法来检索页面宽度/方向,但没有任何效果。 这是我的代码: 谢谢 ! 问题答案: 解决: 用 代替

  • 问题内容: 我有一个PDFReader,其中包含横向模式的某些页面和纵向模式的其他页面。 我需要区分它们以进行一些处理…但是,如果我调用getOrientation或getPageSize,则该值始终是相同的(pagesize为595,方向为0)。 为什么横向页面的值没有不同? 我试图找到其他方法来检索页面宽度/方向,但没有任何效果。 这是我的代码: 谢谢 ! 问题答案: 解决: 用 代替

  • 问题内容: 我有一个移动Web应用程序,其无序列表包含多个列表项,每个li内都有一个超链接: …我的问题是如何格式化超链接,以使它们在iPhone上查看时不会改变大小,并且加速计从纵向切换为横向?现在,我将超链接的字体大小指定为14px,但是切换到横向时,它会炸裂到20px。我希望字体大小保持不变。这是代码: 问题答案: 您可以通过CSS属性禁用此行为:

  • 是否有工具来确定PDF是横向的还是纵向的? 旋转:270 “旋转”到底是什么意思?

  • 我正在关注w3c学校关于制作幻灯片网页的教程。 对我来说,唯一不同的要求是,我有相同垂直分辨率的横向和纵向图像(1280x720和420x720)。 当我加载肖像图像时,它们的比例会大得多,因为图像仅受最大宽度的限制。实际上,我希望边界是垂直最大高度,所以当我循环通过它们时,高度是恒定的。 问题是,当我在上指定“最大高度”并删除“最大宽度”时。幻灯片容器,然后将图像左对齐放置在页面上。所以看起来我