mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
This commit is contained in:
parent
564adb9a57
commit
815fe8d3ba
BIN
packages/app-cli/tests/ocr_samples/multi_page__embedded_text.pdf
Normal file
BIN
packages/app-cli/tests/ocr_samples/multi_page__embedded_text.pdf
Normal file
Binary file not shown.
Binary file not shown.
@ -82,15 +82,20 @@ describe('OcrService', () => {
|
||||
// `jest.retryTimes(2)`
|
||||
}, 60000 * 5);
|
||||
|
||||
it('should process PDF resources', async () => {
|
||||
const { resource } = await createNoteAndResource({ path: `${ocrSampleDir}/dummy.pdf` });
|
||||
test.each([
|
||||
// Use embedded text (skip OCR)
|
||||
['dummy.pdf', 'Dummy PDF file'],
|
||||
['multi_page__embedded_text.pdf', 'This is a test.\nTesting...\nThis PDF has 3 pages.\nThis is page 3.'],
|
||||
['multi_page__no_embedded_text.pdf', 'This is a multi-page PDF\nwith no embedded text.\nPage 2: more text.\nThe third page.'],
|
||||
])('should process PDF resources', async (samplePath: string, expectedText: string) => {
|
||||
const { resource } = await createNoteAndResource({ path: `${ocrSampleDir}/${samplePath}` });
|
||||
|
||||
const service = newOcrService();
|
||||
|
||||
await service.processResources();
|
||||
|
||||
const processedResource: ResourceEntity = await Resource.load(resource.id);
|
||||
expect(processedResource.ocr_text).toBe('Dummy PDF file');
|
||||
expect(processedResource.ocr_text).toBe(expectedText);
|
||||
expect(processedResource.ocr_status).toBe(ResourceOcrStatus.Done);
|
||||
expect(processedResource.ocr_error).toBe('');
|
||||
|
||||
|
@ -62,6 +62,17 @@ export default class OcrService {
|
||||
const resourceFilePath = Resource.fullPath(resource);
|
||||
|
||||
if (resource.mime === 'application/pdf') {
|
||||
// OCR can be slow for large PDFs.
|
||||
// Skip it if the PDF already includes text.
|
||||
const pageTexts = await shim.pdfExtractEmbeddedText(resourceFilePath);
|
||||
const pagesWithText = pageTexts.filter(text => !!text.trim().length);
|
||||
|
||||
if (pagesWithText.length > 0) {
|
||||
return {
|
||||
text: pageTexts.join('\n'),
|
||||
};
|
||||
}
|
||||
|
||||
const imageFilePaths = await shim.pdfToImages(resourceFilePath, await this.pdfExtractDir());
|
||||
const results: RecognizeResult[] = [];
|
||||
|
||||
|
@ -9,6 +9,7 @@ import * as fs from 'fs-extra';
|
||||
import * as pdfJsNamespace from 'pdfjs-dist';
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { ResourceEntity } from './services/database/types';
|
||||
import { TextItem } from 'pdfjs-dist/types/src/display/api';
|
||||
|
||||
const { FileApiDriverLocal } = require('./file-api-driver-local');
|
||||
const mimeUtils = require('./mime-utils.js').mime;
|
||||
@ -734,6 +735,26 @@ function shimInit(options: ShimInitOptions = null) {
|
||||
}
|
||||
};
|
||||
|
||||
shim.pdfExtractEmbeddedText = async (pdfPath: string): Promise<string[]> => {
|
||||
const loadingTask = pdfJs.getDocument(pdfPath);
|
||||
const doc = await loadingTask.promise;
|
||||
|
||||
const textByPage = [];
|
||||
|
||||
for (let pageNum = 1; pageNum <= doc.numPages; pageNum++) {
|
||||
const page = await doc.getPage(pageNum);
|
||||
const textContent = await page.getTextContent();
|
||||
|
||||
const strings = textContent.items.map(item => {
|
||||
const text = (item as TextItem).str ?? '';
|
||||
return text;
|
||||
}).join('\n');
|
||||
textByPage.push(strings);
|
||||
}
|
||||
|
||||
return textByPage;
|
||||
};
|
||||
|
||||
shim.pdfToImages = async (pdfPath: string, outputDirectoryPath: string): Promise<string[]> => {
|
||||
// We handle both the Electron app and testing framework. Potentially
|
||||
// the same code could be use to support the CLI app.
|
||||
|
@ -277,6 +277,11 @@ const shim = {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// Does not do OCR -- just extracts existing text from a PDF.
|
||||
pdfExtractEmbeddedText: async (_pdfPath: string): Promise<string[]> => {
|
||||
throw new Error('Not implemented: textFromPdf');
|
||||
},
|
||||
|
||||
pdfToImages: async (_pdfPath: string, _outputDirectoryPath: string): Promise<string[]> => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user