javascript 如何从地理空间PDF获取坐标/范围?

p1iqtdky  于 2023-11-15  发布在  Java
关注(0)|答案(2)|浏览(208)

我有一个由QGIS导出的地理空间PDF,里面有一个光栅,我需要读取这个光栅来创建一个XYZ tiles structure,为此需要获取文件的坐标/范围,但我不能从PDF甚至光栅文件中提取这些信息。我已经尝试将PDF转换为文本并读取它,我还尝试从PDF文件中提取光栅来读取图像,但是所有的替代方案都不起作用。我在任何地方都没有找到关于在哪里以及如何从文件中获取这些信息的信息。

我尝试的:
**使用PDF:**我尝试使用PDFJS读取PDF元数据。

PDFJS.getDocument(url).then(function (pdfDoc_) {
      pdfDoc = pdfDoc_;   
      pdfDoc.getMetadata().then(function(stuff) {
          console.log(stuff); // Metadata object here
      }).catch(function(err) {
         console.log('Error getting meta data');
         console.log(err);
      });

     // Render the first page or whatever here
     // More code . . . 
}).catch(function(err) {
     console.log('Error getting PDF from ' + url);
     console.log(err);
});

字符串

我还试着浏览了一些读取元数据的网站,例如Website 1Website 2

var PDF_URL  = '/path/to/example.pdf';

PDFJS.getDocument(PDF_URL).then(function (PDFDocumentInstance) {
    
    var totalPages = PDFDocumentInstance.numPages;
    var pageNumber = 1;

    // Extract the text
    getPageText(pageNumber , PDFDocumentInstance).then(function(textPage){
        // Show the text of the page in the console
        console.log(textPage);
    });

}, function (reason) {
    // PDF loading error
    console.error(reason);
});

/**
 * Retrieves the text of a specif page within a PDF Document obtained through pdf.js 
 * 
 * @param {Integer} pageNum Specifies the number of the page 
 * @param {PDFDocument} PDFDocumentInstance The PDF document obtained 
 **/
function getPageText(pageNum, PDFDocumentInstance) {
    // Return a Promise that is solved once the text of the page is retrieven
    return new Promise(function (resolve, reject) {
        PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {
            // The main trick to obtain the text of the PDF page, use the getTextContent method
            pdfPage.getTextContent().then(function (textContent) {
                var textItems = textContent.items;
                var finalString = "";

                // Concatenate the string of the item to the final string
                for (var i = 0; i < textItems.length; i++) {
                    var item = textItems[i];

                    finalString += item.str + " ";
                }

                // Solve promise with the text retrieven from the page
                resolve(finalString);
            });
        });
    });
}


很遗憾,我没有得到任何信息。我通过其他一些网站做了同样的事情,Website 1Website 2Website 3,但结果仍然是空的。

**图像:**我尝试使用在codePen上找到的JS代码从PDF中提取光栅,然后我尝试使用Windows读取图像元数据,但后来我意识到该代码生成了SVG格式的图像,并且元数据丢失了,所以我使用一些具有功能的网站从PDF文件中提取图像,Website 1Website 2。然后我再次尝试使用Windows查看图像的元数据,但没有成功,所以我使用一些网站查看提取图像的元数据,Website 1Website 2,但我也没有任何我需要的信息(坐标/扩展名)。

我回去研究,看看我是否可以找到一个代码在另一种语言,甚至在QGIS。在搜索时,我发现了一个文档的GDAL关于阅读PDF通过一些工具,如PDFIUM,所以我试图下载GDAL通过OSGeo4W和执行代码在python中看到这些信息:

from osgeo import ogr  
from osgeo import gdal

dso = ogr.Open('export.pdf')
print(dso)

dsg = gdal.Open('export.pdf')
print(dsg)

driverGeoPDFogr = ogr.GetDriverByName('PDF')
dso2 = driverGeoPDFogr.Open('export.pdf')
print(dso2)


我尝试运行OSGEO 4 W的shell,但是我在python环境中遇到了一些问题,更具体地说,是导入模块时的一个错误。

错误:

ImportError:python39.dll的模块使用与此版本的Python冲突。
但是运行这段代码对于我想做的事情的进展并不重要,所以我决定现在把它放在一边。
然后,我试图从QGIS和GDAL存储库中查找地理空间PDF导入/导出代码,但我没有成功找到这些代码。
我需要知道是否有一种方法来捕捉坐标/范围的地理空间PDF使用JavaScript。

mccptt67

mccptt671#

我找到了一种用PDF.js来做这件事的方法。
正如@K_J所指出的,PDF中有与地理空间特征相关的字典项。
Adobe添加了 Geospatial Features 规范,并定义了一个可以包含在PDF中的“地理空间测量字典”。如果包含,则必须包含GPTS键,该键定义了地理空间的纬度和经度^1范围:

GPTS(数组)(必需;扩展级别3)* 成对取数的数组,将地理空间中的点定义为纬度和经度。

还有WKT键,K_J指出:

WKT(ASCII字符串)(可选; ExtensionLevel 3)* 描述地理坐标系的众所周知的文本字符串。

这是“Adobe方式”;还有OGC方式^2
地理空间PDF的地理配准元数据通常以两种方式之一进行编码:OGC最佳实践;以及Adobe建议的ISO 32000地理空间扩展。
虽然我找不到OGC的定义。
但是你的PDF似乎使用的是Adobe的方式。那么,如何使用PDF.js获取字典键及其值呢?
从PDF.js文档中,我发现了一个对这个项目^3的引用,这是一个非常简单的“PDF对象浏览器”。我将其分叉,并使其非交互式,以便它遍历整个树,并在找到GPTS键时记录一个路径。
下面是我的browser.js版本的一个片段:

...
const MAX_DEPTH = 10;
...
function walk(node, callDepth, nodePath) {
    // Not sure about this, but I think I'm directing the walker to completely resolve referenced nodes
    while (isRef(node.obj)) {
        var fetched = xref.fetch(node.obj);
        node = new Node(fetched, node.name, node.depth, node.obj);
    }

    nodePath += ' '.repeat(node.depth) + ' - ' + toText(node) + '\n';

    if (node.name === 'GPTS') {
        console.log(nodePath);
        printCoords(node);
        return;
    }

    if (callDepth > MAX_DEPTH) {
        return;
    }

    for (const childNode of node.children) {
        walk(childNode, callDepth + 1, nodePath);
    }
}

function printCoords(gPTSNode) {
    for (const childNode of gPTSNode.children) {
        var path = ' '.repeat(childNode.depth) + ' - ' + toText(childNode);
        console.log(path);
    }
}

字符串
当我从该项目启动index.html并打开示例PDF时,我在控制台中看到以下内容:

- Trailer (dict)
 - Root (dict) [id: 2, gen: 0]
  - Pages (dict) [id: 1, gen: 0]
   - Kids (array)
    - 0 (dict) [id: 8, gen: 0]
     - VP (array)
      - 0 (dict) [id: 5, gen: 0]
       - Measure (dict) [id: 6, gen: 0]
        - GPTS (array)
          - 0 = 6965524.305664567
          - 1 = 582854.0718590557
          - 2 = 6965524.305664567
          - 3 = 585458.7618590547
          - 4 = 6963682.605664568
          - 5 = 582854.0718590557
          - 6 = 6963682.605664568
          - 7 = 585458.7618590547


GPTS数组的子数组是一组坐标,它们应该位于您的世界坐标系中。
你可以尝试使用MAX_DEPTH var,看看有多少(间接?)引用到这个字典。深度阈值越高,你会发现隐藏在树中的引用越多。
这是我第一次研究树和对象,我很高兴地看到路径与对象查看器1:1相关:
x1c 0d1x的数据

brccelvz

brccelvz2#

也许我误解了这个问题,但是你可以使用gdal2tiles.py从栅格创建zxy切片结构,你只需要为https://gdal.org/programs/gdal2tiles.html安装gdal

相关问题