PDF 图像差异比较
从 9.0.0 版本开始,福昕 PDF SDK Web 版提供了 API 来支持通过叠加 PDF 页面来对比 PDF。该功能对两个文档进行逐像素对比,找出其中的不同之处,并生成一个输出图像。开发人员可以利用 SDK 提供的这些 API 在自己的应用中实现覆盖比较的功能。
功能概述
TIP
本节将提供一个完整的示例来展示如何通过叠加 PDF 页面来比较 PDF,包含以下步骤:
- 打开文档
- 创建文档
- 获取 PDF 页面
- 比较页面
- 生成结果页面
- 导出结果文档
初始化 PDFViewer
javascript
const libPath = window.top.location.origin + '/lib';
const pdfViewer = new PDFViewCtrl.PDFViewer({
libPath: libPath,
jr: {
licenseSN: licenseSN,
licenseKey: licenseKey
}
});
pdfViewer.init(document.body);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
加载待比较的文档
javascript
async function loadFiles() {
const sourcePDFDoc = await pdfViewer.loadPDFDocByHttpRangeRequest({
range: {
url: '/assets/test-doc1.pdf'
}
});
const targetPDFDoc = await pdfViewer.loadPDFDocByHttpRangeRequest({
range: {
url: '/assets/test-doc2.pdf'
}
});
return {sourcePDFDoc, targetPDFDoc};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
文档加载方式
SDK 提供了两种加载文档的方法:
loadPDFDocByHttpRangeRequest
: 从远程异步按需加载 PDF 文档loadPDFDocByFile
: 加载内存中的文件流,或通过<input type="file">
选择本地文件
在实际项目中,您也可以通过 PDFViewer.getCurrentPDFDoc
获取当前打开的文档来进行操作。
创建空白文档
javascript
function createBlankDoc() {
return pdfViewer.createNewDoc();
}
1
2
3
2
3
获取待比较页面的 bitmap
javascript
async function getPageBitmaps(loadedFiles) {
const {sourcePDFDoc, targetPDFDoc} = loadedFiles;
const sourcePage = await sourcePDFDoc.getPageByIndex(0);
const sourceBitmap = await sourcePage.render(1);
const targetPage = await targetPDFDoc.getPageByIndex(0);
const targetBitmap = await targetPage.render(1);
return {sourceBitmap, targetBitmap};
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
渲染选项
如果需要自定义渲染参数(如缩放和旋转),可以在 render
方法中传入参数 (scale, rotate)。详细信息请参考 API Reference 中的 PDFPage.render
接口说明。
开始比较文档
javascript
function comparePageBitmap(sourceBitmap, targetBitmap) {
const DiffColor = PDFViewCtrl.overlayComparison.DiffColor;
const service = pdfViewer.getOverlayComparisonService();
const resultCanvas = service.compareImageData({
sourceBitmap,
targetBitmap,
combinePixelsOptions: {
showDiffColor: true,
sourceDiffColor: DiffColor.RED,
targetDiffColor: DiffColor.BLUE,
sourceOpacity: 0xFF,
targetOpacity: 0xFF
},
transformation: {
translateX: 0,
translateY: 0,
rotate: 2 / 180 * Math.PI
}
});
return new Promise(resolve => {
resultCanvas.toBlob(blob => {
const fr = new FileReader();
fr.onloadend = () => {
resolve({
buffer: fr.result,
width: resultCanvas.width,
height: resultCanvas.height
});
};
fr.readAsArrayBuffer(blob);
});
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
比较参数说明
showDiffColor
: 设置为true
时才会标记文档差异sourceDiffColor
和targetDiffColor
: 必须使用DiffColor
枚举中的预定义颜色sourceOpacity
和targetOpacity
: 取值范围为0~0xFF
将比较结果插入到 PDF 页面中
javascript
async function insertResultIntoNewDoc(newDoc, resultImageData) {
const page = await newDoc.getPageByIndex(0);
// resultImageData is the return object of the comparePageBitmap function mentioned in the above example.
// Convert the unit of width and height from pixel to point.
const newPageWidth = resultImageData.width / 4 * 3;
const newPageHeight = resultImageData.height / 4 * 3;
// Reset the size of PDF page to make it the same size as the comparison image.
await page.setPageSize(newPageWidth, newPageHeight);
// Last, insert it into the PDF page as a PDF image object.
await page.addImage(resultImageData.buffer, {
left: 0,
right: newPageWidth,
bottom: 0,
top: newPageHeight
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
将比较结果添加到新文档
javascript
async function addComparisonResultToNewDoc(resultBitmap) {
const newDoc = await createBlankDoc();
const page = await newDoc.addPage(resultBitmap.width, resultBitmap.height);
const image = await page.addImage(resultBitmap.buffer);
const matrix = PDFViewCtrl.PDF.PDFMatrix.create();
await page.addImageObject(image, matrix);
return newDoc;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
导出结果文档
javascript
async function exportDoc(doc) {
const file = await doc.getFile();
const url = URL.createObjectURL(file);
const a = document.createElement('a');
a.href = url;
a.download = 'comparison-result.pdf';
a.click();
URL.revokeObjectURL(url);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
完整示例
TIP
以下是将所有步骤组合在一起的完整示例代码:
javascript
(async function() {
const loadedFiles = await loadFiles();
const {sourceBitmap, targetBitmap} = await getPageBitmaps(loadedFiles);
const resultBitmap = await comparePageBitmap(sourceBitmap, targetBitmap);
const resultDoc = await addComparisonResultToNewDoc(resultBitmap);
await exportDoc(resultDoc);
})();
1
2
3
4
5
6
7
2
3
4
5
6
7
API 说明
PDFViewer.getOverlayComparisonService()
返回一个 OverlayComparisonService
实例,用于比较两个图片。
OverlayComparisonService.compareImageData(options)
比较两个图片并返回一个包含比较结果的 Canvas 对象。
参数说明:
typescript
interface CompareImageDataOptions {
// 源图片的 ImageData 对象
sourceBitmap: ImageData;
// 目标图片的 ImageData 对象
targetBitmap: ImageData;
// 图片合成选项
combinePixelsOptions: {
// 是否显示差异颜色,默认为 false
showDiffColor?: boolean;
// 源图片差异部分的颜色
sourceDiffColor?: DiffColor;
// 目标图片差异部分的颜色
targetDiffColor?: DiffColor;
// 源图片的透明度,取值范围 0~0xFF
sourceOpacity?: number;
// 目标图片的透明度,取值范围 0~0xFF
targetOpacity?: number;
};
// 图片变换选项
transformation?: {
// X轴平移距离
translateX?: number;
// Y轴平移距离
translateY?: number;
// 旋转角度(弧度)
rotate?: number;
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
DiffColor 枚举值
可用的差异颜色选项:
DiffColor.RED
DiffColor.GREEN
DiffColor.BLUE
DiffColor.YELLOW
DiffColor.MAGENTA
DiffColor.CYAN
相关 API 参考
PDFViewer.loadPDFDocByHttpRangeRequest
PDFViewer.loadPDFDocByFile
PDFViewer.createNewDoc
PDFPage.render
json
{
"iframeOptions": {
"style": "height: 800px"
}
}
1
2
3
4
5
2
3
4
5
TIP
为了尽量减少不相干代码的干扰,保证代码更加直观,上面的示例使用了 ESNext 语法编写,请使用现代浏览器打开 developer guide 文档和运行示例。如果需要兼容旧版本浏览器,请在您的项目中使用 JavaScript 转译器,例如 babel。