如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

huangapple go评论65阅读模式
英文:

How to use PDF4NET to convert PDFPathVisualObject to System.Windows.Shapes.Path for wpf

问题

我正在尝试使用PDF4NET从PDF文件中提取路径元素并在WPF中显示它们。

我参考了PDF4NET的示例,并通过以下代码获取了PDFPathVisualObject。

PDFFixedDocument document = new PDFFixedDocument("path.pdf");

PDFContentExtractor ce = new PDFContentExtractor(document.Pages[0]);
PDFVisualObjectCollection voc = ce.ExtractVisualObjects(false);

PDFPathVisualObject pvo = voc[0] as PDFPathVisualObject;

然而,在将PDFPathVisualObject转换为System.Windows.Shapes.Path时,PathItems中显示的路径信息似乎与实际路径信息不一致,如下图所示(我随机找到了一个包含路径信息的PDF)。

如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

我想知道如何将PDFPathVisualObject转换为System.Windows.Shapes.Path。

英文:

I am trying to extract path elements from PDF files using PDF4NET and display them in WPF

I referenced the example of PDF4NET and obtained the PDFPathVisualObject through the following code.

            PDFFixedDocument document = new PDFFixedDocument("path.pdf");

            PDFContentExtractor ce = new PDFContentExtractor(document.Pages[0]);
            PDFVisualObjectCollection voc = ce.ExtractVisualObjects(false);

            PDFPathVisualObject pvo = voc[0] as PDFPathVisualObject

However, I encountered a problem when converting the PDFPathVisualObject to System.Windows.Shapes.Path. The path information displayed in the PathItems in PDFPathVisualObject seems to be inconsistent with the actual path information, As shown in the following figure (I randomly found a PDF with path information)

如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

I would like to know how to convert PDFPathVisualObject to System. Windows. Shapes. Path

答案1

得分: 2

以下是翻译好的内容:

第1张截图(PDFXplorer应用程序)中的值是标准PDF坐标系统中的原始路径点。

第2张截图中的点是显示坐标系统中的路径点,相对于可见页面区域的左上角。原始路径点通过在绘制路径时处于活动状态的当前变换矩阵进行变换,然后从标准PDF坐标系统转换为显示坐标系统,考虑页面mediabox/cropbox和页面旋转。

您可以直接使用第2张截图中的路径点来创建您的WPF路径,因为它们使用相同的坐标系统。

下面的代码提供了一个起点,它展示了如何将PDFPathVisualObject转换为XAML路径:

private void ConvertPDFPathsToXAML()
{
    PDFFixedDocument document = new PDFFixedDocument("paths.pdf");
    PDFContentExtractor ce = new PDFContentExtractor(document.Pages[0]);
    PDFVisualObjectCollection voc = ce.ExtractVisualObjects(false, false);

    // ...(此处省略了代码的其余部分)
}

private string PdfPathToXamlPathGeometry(PDFPathVisualObject path, bool isFilled, PDFFillMode fillMode)
{
    // ...(此处省略了代码的其余部分)
}

这个PDF文件:
如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

被转换为以下XAML:

<Canvas xmlns="http://schemas.microsoft.com/xps/2005/06" Width="612" Height="792" Background="White">
    <Canvas.Clip>
        <RectangleGeometry Rect="0,0,612,792"/>
    </Canvas.Clip>
    <Path Data="M 0 792 L 612 0 " Stroke="#FF0080" StrokeThickness="16"/>
    <Path Data="M 0 396 L 612 396 " Stroke="#000080" StrokeThickness="16"/>
</Canvas>

它看起来像这样:
如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

注:我为开发PDF4NET的公司工作。

英文:

The values from the 1st screenshot (PDFXplorer application) are raw path points in standard PDF coordinate system.

The points in 2nd screenshot are the path points in display coordinate system relative to top left corner of the visible page area. The raw path points are transformed through the current transformation matrix that is active when the path is painted and then converted from standard PDF coordinate system to display coordinate system considering the page mediabox/cropbox and page rotation.

You can use directly the path points in the 2nd screenshot to create your WPF paths as they use the same coordinate system.

The code below provides a start, it shows how to convert the PDFPathVisualObject to XAML paths:

private void ConvertPDFPathsToXAML()
{
    PDFFixedDocument document = new PDFFixedDocument(&quot;paths.pdf&quot;);
    PDFContentExtractor ce = new PDFContentExtractor(document.Pages[0]);
    PDFVisualObjectCollection voc = ce.ExtractVisualObjects(false, false);

    MemoryStream xamlStream = new MemoryStream();
    XmlTextWriter xamlWriter = new XmlTextWriter(xamlStream, Encoding.UTF8);
    xamlWriter.WriteStartElement(&quot;Canvas&quot;);
    xamlWriter.WriteAttributeString(&quot;xmlns&quot;, &quot;http://schemas.microsoft.com/xps/2005/06&quot;);
    xamlWriter.WriteAttributeString(&quot;Width&quot;, string.Format(CultureInfo.InvariantCulture, &quot;{0:0.####}&quot;, document.Pages[0].Width));
    xamlWriter.WriteAttributeString(&quot;Height&quot;, string.Format(CultureInfo.InvariantCulture, &quot;{0:0.####}&quot;, document.Pages[0].Height));
    xamlWriter.WriteAttributeString(&quot;Background&quot;, &quot;White&quot;);

    xamlWriter.WriteStartElement(&quot;Canvas.Clip&quot;);
    xamlWriter.WriteStartElement(&quot;RectangleGeometry&quot;);
    xamlWriter.WriteAttributeString(&quot;Rect&quot;, string.Format(CultureInfo.InvariantCulture, &quot;0,0,{0:0.#####},{1:0.#####}&quot;, document.Pages[0].Width, document.Pages[0].Height));
    xamlWriter.WriteEndElement();
    xamlWriter.WriteEndElement();

    for (int i = 0; i &lt; voc.Count; i++) 
    { 
        if (voc[i].Type == PDFVisualObjectType.Path)
        {
            PDFPathVisualObject path = (PDFPathVisualObject)voc[i];

            string pathGeometry = PdfPathToXamlPathGeometry(path, path.Brush != null, path.FillMode);

            xamlWriter.WriteStartElement(&quot;Path&quot;);
            xamlWriter.WriteAttributeString(&quot;Data&quot;, pathGeometry);
            if (path.Pen != null) 
            {
                PDFRgbColor rgb = path.Pen.Color.ToRgbColor();
                xamlWriter.WriteAttributeString(&quot;Stroke&quot;, string.Format(&quot;#{0:X02}{1:X02}{2:X02}&quot;, rgb.R, rgb.G, rgb.B));
                xamlWriter.WriteAttributeString(&quot;StrokeThickness&quot;, string.Format(&quot;{0:0.####}&quot;, path.Pen.Width));
            }
            if (path.Brush != null)
            {
                PDFRgbColor rgb = path.Brush.Color.ToRgbColor();
                xamlWriter.WriteAttributeString(&quot;Fill&quot;, string.Format(&quot;#{0:X02}{1:X02}{2:X02}&quot;, rgb.R, rgb.G, rgb.B));
            }
            xamlWriter.WriteEndElement();
        }
    }
    xamlWriter.WriteEndElement();
    xamlWriter.Flush();
    xamlStream.Position = 0;

    Canvas canvas = (Canvas)XamlReader.Load(xamlStream);
    mainGrid.Children.Add(canvas);
}

private string PdfPathToXamlPathGeometry(PDFPathVisualObject path, bool isFilled, PDFFillMode fillMode)
{
    double crtX = 0, crtY = 0;
    double x1, y1, x2, y2, x3, y3;
    StringBuilder pathGeometry = new StringBuilder();

    if (isFilled)
    {
        pathGeometry.Append(fillMode == PDFFillMode.EvenOdd ? &quot;F0 &quot; : &quot;F1 &quot;);
    }

    for (int i = 0; i &lt; path.PathItems.Count; i++)
    {
        switch (path.PathItems[i].Type)
        {
            case PDFPathItemType.MoveTo: // m
                x1 = path.PathItems[i].Points[0].X;
                y1 = path.PathItems[i].Points[0].Y;
                pathGeometry.AppendFormat(CultureInfo.InvariantCulture, &quot;M {0:0.######} {1:0.######} &quot;, x1, y1);
                crtX = x1;
                crtY = y1;
                break;
            case PDFPathItemType.LineTo: // l
                x1 = path.PathItems[i].Points[0].X;
                y1 = path.PathItems[i].Points[0].Y;
                pathGeometry.AppendFormat(CultureInfo.InvariantCulture, &quot;L {0:0.######} {1:0.######} &quot;, x1, y1);
                crtX = x1;
                crtY = y1;
                break;
            case PDFPathItemType.CCurveTo: // c
                x1 = path.PathItems[i].Points[0].X;
                y1 = path.PathItems[i].Points[0].Y;
                x2 = path.PathItems[i].Points[1].X;
                y2 = path.PathItems[i].Points[1].Y;
                x3 = path.PathItems[i].Points[2].X;
                y3 = path.PathItems[i].Points[2].Y;
                pathGeometry.AppendFormat(CultureInfo.InvariantCulture,
                    &quot;C {0:0.######} {1:0.######} {2:0.######} {3:0.######} {4:0.######} {5:0.######} &quot;, x1, y1, x2, y2, x3, y3);
                crtX = x3;
                crtY = y3;
                break;
            case PDFPathItemType.VCurveTo: // v
                x1 = path.PathItems[i].Points[0].X;
                y1 = path.PathItems[i].Points[0].Y;
                x2 = path.PathItems[i].Points[1].X;
                y2 = path.PathItems[i].Points[1].Y;
                pathGeometry.AppendFormat(CultureInfo.InvariantCulture,
                    &quot;C {0:0.######} {1:0.######} {2:0.######} {3:0.######} {4:0.######} {5:0.######} &quot;, crtX, crtY, x1, y1, x2, y2);
                crtX = x2;
                crtY = y2;
                break;
            case PDFPathItemType.YCurveTo: // y
                x1 = path.PathItems[i].Points[0].X;
                y1 = path.PathItems[i].Points[0].Y;
                x2 = path.PathItems[i].Points[1].X;
                y2 = path.PathItems[i].Points[1].Y;
                pathGeometry.AppendFormat(CultureInfo.InvariantCulture,
                    &quot;C {0:0.######} {1:0.######} {2:0.######} {3:0.######} {4:0.######} {5:0.######} &quot;, x1, y1, x2, y2, x2, y2);
                crtX = x2;
                crtY = y2;
                break;
            case PDFPathItemType.CloseSubpath: // h
                pathGeometry.Append(&quot;z &quot;);
                break;
        }
    }

    return pathGeometry.ToString();
}

This PDF file:
如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

is converted to this XAML:

&lt;Canvas xmlns=&quot;http://schemas.microsoft.com/xps/2005/06&quot; Width=&quot;612&quot; Height=&quot;792&quot; Background=&quot;White&quot;&gt;
    &lt;Canvas.Clip&gt;
        &lt;RectangleGeometry Rect=&quot;0,0,612,792&quot;/&gt;
    &lt;/Canvas.Clip&gt;
    &lt;Path Data=&quot;M 0 792 L 612 0 &quot; Stroke=&quot;#FF0080&quot; StrokeThickness=&quot;16&quot;/&gt;
    &lt;Path Data=&quot;M 0 396 L 612 396 &quot; Stroke=&quot;#000080&quot; StrokeThickness=&quot;16&quot;/&gt;
&lt;/Canvas&gt;

and it looks like this:
如何使用PDF4NET将PDFPathVisualObject转换为WPF的System.Windows.Shapes.Path。

Note: I work for the company that develops PDF4NET.

huangapple
  • 本文由 发表于 2023年7月4日 21:37:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76613214.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定