Skip to content

feat: support ocr for images using llm#374

Open
lukasdotcom wants to merge 3 commits into
mainfrom
ocr
Open

feat: support ocr for images using llm#374
lukasdotcom wants to merge 3 commits into
mainfrom
ocr

Conversation

@lukasdotcom

Copy link
Copy Markdown
Member

No description provided.

Comment thread lib/AppInfo/Application.php Outdated
Comment on lines +145 to +155
$fileType = $file->getMimeType();
if (!str_starts_with($fileType, 'image/')) {
throw new UserFacingProcessingException('Only supports image file types' . $fileType, userFacingMessage: $this->l->t('Only supports image file types'));
}
if ($this->openAiAPIService->isUsingOpenAi()) {
$validFileTypes = [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice if we can also support pdfs through pdf -> jpg conversion. The rest of the path would remain the same.
a small snippet that uses imagick to do this (which preview generator of NC also uses with the imagick php extension):
(ai generated)

private function pdfToJpegFiles(string $pdfPath, int $dpi = 200, int $maxPages = 500): array {
    if (!extension_loaded('imagick')) {
        throw new \RuntimeException('Imagick extension not available');
    }
    if (empty(\Imagick::queryFormats('PDF'))) {
        throw new \RuntimeException('Imagick has no PDF support (Ghostscript missing or blocked by policy.xml)');
    }

    $probe = new \Imagick();
    $probe->pingImage($pdfPath);
    $pageCount = min($probe->getNumberImages(), $maxPages);
    $probe->clear();

    $paths = [];
    for ($i = 0; $i < $pageCount; $i++) {
        $im = new \Imagick();
        $im->setResolution($dpi, $dpi); // before readImage
        $im->readImage($pdfPath . '[' . $i . ']');
        $im->setImageBackgroundColor('white');
        $im = $im->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN); // JPEG has no alpha
        $im->setImageFormat('jpeg');
        $im->setImageCompressionQuality(85);

        $tmpPath = $this->tempManager->getTemporaryFile('.jpg');
        $im->writeImage($tmpPath);
        $im->clear();

        $paths[] = $tmpPath;
    }
    return $paths;
}

for the 500 MB php worker memory limit, we can impose a max limit of 500 pages of pdf in the task type as it is now and convert them to jpgs like above storing them in the disk.
after this the chat completion requests could run with a batch size of 50 converting 50 images to base64 base64_encode(file_get_contents($path), run the OCR and collect the texts.
wdyt?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some code Imagick isn't preinstalled in julius's docker so you'll need to install it manually /usr/local/bin/install-php-extensions imagick (run that in the docker container)
I kept the batch size a lot smaller than this with 5 as that was actually faster than a larger batch size. Honestly it might be worth it to not batch at all as the accuracy goes up with smaller batches at only a very small cost in time (revert the newest commit). Most of the tokens are used by the image anyway.

Batch Size Time (From one attempt)
1 2:29
2 2:02
5 1:54
50 2:02

wdyt?

Signed-off-by: Lukas Schaefer <lukas@lschaefer.xyz>
@lukasdotcom lukasdotcom force-pushed the ocr branch 2 times, most recently from eeddbd5 to ab774bc Compare July 6, 2026 21:57
Signed-off-by: Lukas Schaefer <lukas@lschaefer.xyz>
Signed-off-by: Lukas Schaefer <lukas@lschaefer.xyz>
@julien-nc

Copy link
Copy Markdown
Member

Damn I didn't see this PR and did it again (without PDF support). Can you check the enh/noid/ocr-provider branch and replicate the streaming support? (the provider implements ISynchronousOptionsAwareProvider and reports the output)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants