Merge branch 'sphinx-md'

This commit is contained in:
James R. Barlow
2025-04-21 00:53:16 -07:00
40 changed files with 5972 additions and 6221 deletions
+460
View File
@@ -0,0 +1,460 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Advanced features
## Control of unpaper
OCRmyPDF uses `unpaper` to provide the implementation of the
`--clean` and `--clean-final` arguments.
[unpaper](https://github.com/Flameeyes/unpaper/blob/main/doc/basic-concepts.md)
provides a variety of image processing filters to improve images.
By default, OCRmyPDF uses only `unpaper` arguments that were found to
be safe to use on almost all files without having to inspect every page
of the file afterwards. This is particularly true when only `--clean`
is used, since that instructs OCRmyPDF to only clean the image before
OCR and not the final image.
However, if you wish to use the more aggressive options in `unpaper`,
you may use `--unpaper-args '...'` to override the OCRmyPDF's defaults
and forward other arguments to unpaper. This option will forward
arguments to `unpaper` without any knowledge of what that program
considers to be valid arguments. The string of arguments must be quoted
as shown in the examples below. No filename arguments may be included.
OCRmyPDF will assume it can append input and output filename of
intermediate images to the `--unpaper-args` string.
In this example, we tell `unpaper` to expect two pages of text on a
sheet (image), such as occurs when two facing pages of a book are
scanned. `unpaper` uses this information to deskew each independently
and clean up the margins of both.
```bash
ocrmypdf --clean --clean-final --unpaper-args '--layout double' input.pdf output.pdf
ocrmypdf --clean --clean-final --unpaper-args '--layout double --no-noisefilter' input.pdf output.pdf
```
:::{warning}
Some `unpaper` features will reposition text within the image.
`--clean-final` is recommended to avoid this issue.
:::
:::{warning}
Some `unpaper` features cause multiple input or output files to be
consumed or produced. OCRmyPDF requires `unpaper` to consume one
file and produce one file; errors will result if this assumption is not
met.
:::
:::{note}
`unpaper` uses uncompressed PBM/PGM/PPM files for its intermediate
files. For large images or documents, it can take a lot of temporary
disk space.
:::
## Control of OCR options
OCRmyPDF provides many features to control the behavior of the OCR
engine, Tesseract.
### When OCR is skipped
If a page in a PDF seems to have text, by default OCRmyPDF will exit
without modifying the PDF. This is to ensure that PDFs that were
previously OCRed or were "born digital" rather than scanned are not
processed.
If `--skip-text` is issued, then no image processing or OCR will be
performed on pages that already have text. The page will be copied to
the output. This may be useful for documents that contain both "born
digital" and scanned content, or to use OCRmyPDF to normalize and
convert to PDF/A regardless of their contents.
If `--redo-ocr` is issued, then a detailed text analysis is performed.
Text is categorized as either visible or invisible. Invisible text (OCR)
is stripped out. Then an image of each page is created with visible text
masked out. The page image is sent for OCR, and any additional text is
inserted as OCR. If a file contains a mix of text and bitmap images that
contain text, OCRmyPDF will locate the additional text in images without
disrupting the existing text. Some PDF OCR solutions render text as
technically printable or visible in some way, perhaps by drawing it and
then painting over it. OCRmyPDF cannot distinguish this type of OCR
text from real text, so it will not be "redone".
If `--force-ocr` is issued, then all pages will be rasterized to
images, discarding any hidden OCR text, rasterizing any printable
text, and flattening form fields or interactive objects into their visual
representation. This is useful for redoing OCR, for fixing OCR text
with a damaged character map (text is selectable but not searchable),
and destroying redacted information.
### Time and image size limits
By default, OCRmyPDF permits tesseract to run for three minutes (180
seconds) per page. This is usually more than enough time to find all
text on a reasonably sized page with modern hardware.
If a page is skipped, it will be inserted without OCR. If preprocessing
was requested, the preprocessed image layer will be inserted.
If you want to adjust the amount of time spent on OCR, change
`--tesseract-timeout`. You can also automatically skip images that
exceed a certain number of megapixels with `--skip-big`. (A 300 DPI,
8.5×11" page image is 8.4 megapixels.)
```bash
# Allow 300 seconds for OCR; skip any page larger than 50 megapixels
ocrmypdf --tesseract-timeout 300 --skip-big 50 bigfile.pdf output.pdf
```
### OCR for huge images
Tesseract has internal limits on the size
of images it will process. By default,
`--tesseract-downsample-large-images` is enabled, and OCRmyPDF will
downsample images to fit Tesseract limits. (The limits are usually encountered
only for scanned images of oversized media, such as large maps or blueprints exceeding
110 cm or 43 inches in either dimension, and at high DPI.) This feature can disabled
using `--no-tesseract-downsample-large-images`.
`--tesseract-downsample-above Npixels` adjusts the threshold at which images
will be downsampled. By default, only images that exceed any of Tesseract's
internal limits are downsampled (32767 pixels on either dimension).
You will also need to set `--tesseract-timeout` high enough to allow
for processing.
Only the image sent for OCR is downsampled. The original image is
preserved.
```bash
# Allow 600 seconds for OCR on huge images
ocrmypdf --tesseract-timeout 600 \
--tesseract-downsample-large-images \
bigfile.pdf output.pdf
# Downsample images above 5000 pixels on the longest dimension to
# 5000 pixels
ocrmypdf --tesseract-timeout 120 \
--tesseract-downsample-large-images \
--tesseract-downsample-above 5000 \
bigfile.pdf output_downsampled_ocr.pdf
```
### Overriding default tesseract
OCRmyPDF checks the system `PATH` for the `tesseract` binary.
Some relevant environment variables that influence Tesseract's behavior
include:
```{eval-rst}
.. envvar:: TESSDATA_PREFIX
Overrides the path to Tesseract's data files. This can allow
simultaneous installation of the "best" and "fast" training data
sets. OCRmyPDF does not manage this environment variable.
```
```{eval-rst}
.. envvar:: OMP_THREAD_LIMIT
Controls the number of threads Tesseract will use. OCRmyPDF will
manage this environment variable if it is not already set.
```
For example, if you have a development build of Tesseract don't wish to
use the system installation, you can launch OCRmyPDF as follows:
```bash
env \
PATH=/home/user/src/tesseract/api:$PATH \
TESSDATA_PREFIX=/home/user/src/tesseract \
ocrmypdf input.pdf output.pdf
```
In this example `TESSDATA_PREFIX` is required to redirect Tesseract to
an alternate folder for its "tessdata" files.
### Overriding other support programs
In addition to tesseract, OCRmyPDF uses the following external binaries:
- `gs` (Ghostscript)
- `unpaper`
- `pngquant`
- `jbig2`
In each case OCRmyPDF will search the `PATH` environment variable to
locate the binaries. By modifying the `PATH` environment variable, you
can override the binaries that OCRmyPDF uses.
### Changing Tesseract configuration variables
You can override Tesseract's default [control
parameters](https://tesseract-ocr.github.io/tessdoc/tess3/ControlParams.html)
with a configuration file.
As an example, this configuration will disable Tesseract's dictionary
for current language. Normally the dictionary is helpful for
interpolating words that are unclear, but it may interfere with OCR if
the document does not contain many words (for example, a list of part
numbers).
Create a file named "no-dict.cfg" with these contents:
```
load_system_dawg 0
language_model_penalty_non_dict_word 0
language_model_penalty_non_freq_dict_word 0
```
then run ocrmypdf as follows (along with any other desired arguments):
```bash
ocrmypdf --tesseract-config no-dict.cfg input.pdf output.pdf
```
:::{warning}
Some combinations of control parameters will break Tesseract or break
assumptions that OCRmyPDF makes about Tesseract's output.
:::
### Changing page segmentation mode
The directive `--tesseract-pagesegmode Nmode` forwards the desired page segmentation
mode to Tesseract OCR. The default is 3.
Page segmentation can improve OCR results when you know that a PDF ought to be
analyzed a particular way, such as PDFs whose pages contain only a single line of
text. For the vast majority of users, changing the page segmentation mode will only
make things worse.
As of June 2024, the Tesseract page segmentation modes are:
| ID | Description |
| --- | --------------------------------------------------------------------------------------------- |
| 0 | Orientation and script detection (OSD) only. |
| 1 | Automatic page segmentation with OSD. |
| 2 | Automatic page segmentation, but no OSD, or OCR. (not implemented) |
| 3 | Fully automatic page segmentation, but no OSD. (Default) |
| 4 | Assume a single column of text of variable sizes. |
| 5 | Assume a single uniform block of vertically aligned text. |
| 6 | Assume a single uniform block of text. |
| 7 | Treat the image as a single text line. |
| 8 | Treat the image as a single word. |
| 9 | Treat the image as a single word in a circle. |
| 10 | Treat the image as a single character. |
| 11 | Sparse text. Find as much text as possible in no particular order. |
| 12 | Sparse text with OSD. |
| 13 | Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific. |
Modes 0, 1, 2, and 12 (all of those that enable orientation and script detection)
are not compatible with OCRmyPDF, which performs OSD in a separate step from OCR.
Their use may interfere with `--rotate-pages` and other features.
It is currently not possible to use advanced Tesseract OCR features, such as creating
OCR information, when using Tesseract through OCRmyPDF.
## Changing the PDF renderer
rasterizing
: Converting a PDF to an image for display.
rendering
: Creating a new PDF from other data (such as an existing PDF).
OCRmyPDF has these PDF renderers: `sandwich` and `hocr`. The
renderer may be selected using `--pdf-renderer`. The default is
`auto` which lets OCRmyPDF select the renderer to use. Currently,
`auto` always selects `hocr`.
### The `hocr` renderer
:::{versionchanged} 16.0.0
:::
In both renderers, a text-only layer is rendered and sandwiched (overlaid)
on to either the original PDF page, or newly rasterized version of the
original PDF page (when `--force-ocr` is used). In this way, loss
of PDF information is generally avoided. (You may need to disable PDF/A
conversion and optimization to eliminate all lossy transformations.)
The current approach used by the new hOCR renderer is a re-implementation
of Tesseract's PDF renderer, using the same Glyphless font and general
ideas, but fixing many technical issues that impeded it. The new hocr
provides better text placement accuracy, avoids issues with word
segmentation, and provides better positioning of skewed text.
Using the experimental API, it is also possible to edit the OCR output
from Tesseract, using any tool that is capable of editing hOCR files.
Older versions of this renderer did not support non-Latin languages, but
it is now universal.
### The `sandwich` renderer
The `sandwich` renderer uses Tesseract's text-only PDF feature,
which produces a PDF page that lays out the OCR in invisible text.
Currently some problematic PDF viewers like Mozilla PDF.js and macOS
Preview have problems with segmenting its text output, and
mightrunseveralwordstogether. It also does not implement right to left
fonts (Arabic, Hebrew, Persian). The output of this renderer cannot
be edited. The sandwich renderer is retained for testing.
When image preprocessing features like `--deskew` are used, the
original PDF will be rendered as a full page and the OCR layer will be
placed on top.
## Rendering and rasterizing options
:::{versionadded} 14.3.0
:::
The `--continue-on-soft-render-error` option allows OCRmyPDF to
proceed if a page cannot be rasterized/rendered. This is useful if you are
trying to get the best possible OCR from a PDF that is not well-formed,
and you are willing to accept some pages that may not visually match the
input, and that may not OCR well.
## Color conversion strategy
:::{versionadded} 15.0.0
:::
OCRmyPDF uses Ghostscript to convert PDF to PDF/A. In some cases, this
conversion requires color conversion. The default strategy is to convert
using the `LeaveColorUnchanged` strategy, which preserves the original
color space wherever possible (some rare color spaces might still be
converted).
Usually document scanners produce PDFs in the sRGB color space, and do
not need to be converted, so the default strategy is appropriate.
Suppose that you have a document that was prepared for professional
printing in a Separation or CMYK color space, and text was converted to
curves. In this case, you may want to use a different color conversion
strategy. The `--color-conversion-strategy` option allows you to select a
different strategy, such as `RGB`.
## Return code policy
OCRmyPDF writes all messages to `stderr`. `stdout` is reserved for
piping output files. `stdin` is reserved for piping input files.
The return codes generated by the OCRmyPDF are considered part of the
stable user interface. They may be imported from
`ocrmypdf.exceptions`.
```{eval-rst}
.. list-table:: Return codes
:widths: 5 35 60
:header-rows: 1
* - Code
- Name
- Interpretation
* - 0
- ``ExitCode.ok``
- Everything worked as expected.
* - 1
- ``ExitCode.bad_args``
- Invalid arguments, exited with an error.
* - 2
- ``ExitCode.input_file``
- The input file does not seem to be a valid PDF.
* - 3
- ``ExitCode.missing_dependency``
- An external program required by OCRmyPDF is missing.
* - 4
- ``ExitCode.invalid_output_pdf``
- An output file was created, but it does not seem to be a valid PDF. The file will be available.
* - 5
- ``ExitCode.file_access_error``
- The user running OCRmyPDF does not have sufficient permissions to read the input file and write the output file.
* - 6
- ``ExitCode.already_done_ocr``
- The file already appears to contain text so it may not need OCR. See output message.
* - 7
- ``ExitCode.child_process_error``
- An error occurred in an external program (child process) and OCRmyPDF cannot continue.
* - 8
- ``ExitCode.encrypted_pdf``
- The input PDF is encrypted. OCRmyPDF does not read encrypted PDFs. Use another program such as ``qpdf`` to remove encryption.
* - 9
- ``ExitCode.invalid_config``
- A custom configuration file was forwarded to Tesseract using ``--tesseract-config``, and Tesseract rejected this file.
* - 10
- ``ExitCode.pdfa_conversion_failed``
- A valid PDF was created, PDF/A conversion failed. The file will be available.
* - 15
- ``ExitCode.other_error``
- Some other error occurred.
* - 130
- ``ExitCode.ctrl_c``
- The program was interrupted by pressing Ctrl+C.
```
(tmpdir)=
## Changing temporary storage location
OCRmyPDF generates many temporary files during processing.
To change where temporary files are stored, change the `TMPDIR`
environment variable for ocrmypdf's environment. (Python's
`tempfile.gettempdir()` returns the root directory in which temporary
files will be stored.) For example, one could redirect `TMPDIR` to a
large RAM disk to avoid wear on HDD/SSD and potentially improve
performance.
On Windows, the `TEMP` environment variable is used instead.
## Debugging the intermediate files
OCRmyPDF normally saves its intermediate results to a temporary folder
and deletes this folder when it exits, whether it succeeded or failed.
If the `--keep-temporary-files` (`-k`) argument is issued on the
command line, OCRmyPDF will keep the temporary folder and print the location,
whether it succeeded or failed. An example message is:
```none
Temporary working files retained at:
/tmp/ocrmypdf.io.u20wpz07
```
When OCRmyPDF is launched as a snap, this corresponds to the snap filesystem, for instance:
> /tmp/snap-private-tmp/snap.ocrmypdf/tmp/ocrmypdf.io.u20wpz07
The organization of this folder is an implementation detail and subject
to change between releases. However the general organization is that
working files on a per page basis have the page number as a prefix
(starting with page 1), an infix indicates the processing stage, and a
suffix indicates the file type. Some important files include:
- `_rasterize.png` - what the input page looks like
- `_ocr.png` - the file that is sent to Tesseract for OCR; depending
on arguments this may differ from the presentation image
- `_pp_deskew.png` - the image, after deskewing
- `_pp_clean.png` - the image, after cleaning with unpaper
- `_ocr_hocr.pdf` - the OCR file; appears as a blank page with invisible
text embedded
- `_ocr_hocr.txt` - the OCR text (not necessarily all text on the page,
if the page is mixed format)
- `fix_docinfo.pdf` - a temporary file created to fix the PDF DocumentInfo
data structure
- `graft_layers.pdf` - the rendered PDF with OCR layers grafted on
- `pdfa.pdf` - `graft_layers.pdf` after conversion to PDF/A
- `pdfa.ps` - a PostScript file used by Ghostscript for PDF/A conversion
- `optimize.pdf` - the PDF generated before optimization
- `optimize.out.pdf` - the PDF generated by optimization
- `origin` - the input file
- `origin.pdf` - the input file or the input image converted to PDF
- `images/*` - images extracted during the optimization process; here
the prefix indicates a PDF object ID not a page number
-486
View File
@@ -1,486 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
.. SPDX-License-Identifier: CC-BY-SA-4.0
=================
Advanced features
=================
Control of unpaper
==================
OCRmyPDF uses ``unpaper`` to provide the implementation of the
``--clean`` and ``--clean-final`` arguments.
`unpaper <https://github.com/Flameeyes/unpaper/blob/main/doc/basic-concepts.md>`__
provides a variety of image processing filters to improve images.
By default, OCRmyPDF uses only ``unpaper`` arguments that were found to
be safe to use on almost all files without having to inspect every page
of the file afterwards. This is particularly true when only ``--clean``
is used, since that instructs OCRmyPDF to only clean the image before
OCR and not the final image.
However, if you wish to use the more aggressive options in ``unpaper``,
you may use ``--unpaper-args '...'`` to override the OCRmyPDF's defaults
and forward other arguments to unpaper. This option will forward
arguments to ``unpaper`` without any knowledge of what that program
considers to be valid arguments. The string of arguments must be quoted
as shown in the examples below. No filename arguments may be included.
OCRmyPDF will assume it can append input and output filename of
intermediate images to the ``--unpaper-args`` string.
In this example, we tell ``unpaper`` to expect two pages of text on a
sheet (image), such as occurs when two facing pages of a book are
scanned. ``unpaper`` uses this information to deskew each independently
and clean up the margins of both.
.. code-block:: bash
ocrmypdf --clean --clean-final --unpaper-args '--layout double' input.pdf output.pdf
ocrmypdf --clean --clean-final --unpaper-args '--layout double --no-noisefilter' input.pdf output.pdf
.. warning::
Some ``unpaper`` features will reposition text within the image.
``--clean-final`` is recommended to avoid this issue.
.. warning::
Some ``unpaper`` features cause multiple input or output files to be
consumed or produced. OCRmyPDF requires ``unpaper`` to consume one
file and produce one file; errors will result if this assumption is not
met.
.. note::
``unpaper`` uses uncompressed PBM/PGM/PPM files for its intermediate
files. For large images or documents, it can take a lot of temporary
disk space.
Control of OCR options
======================
OCRmyPDF provides many features to control the behavior of the OCR
engine, Tesseract.
When OCR is skipped
-------------------
If a page in a PDF seems to have text, by default OCRmyPDF will exit
without modifying the PDF. This is to ensure that PDFs that were
previously OCRed or were "born digital" rather than scanned are not
processed.
If ``--skip-text`` is issued, then no image processing or OCR will be
performed on pages that already have text. The page will be copied to
the output. This may be useful for documents that contain both "born
digital" and scanned content, or to use OCRmyPDF to normalize and
convert to PDF/A regardless of their contents.
If ``--redo-ocr`` is issued, then a detailed text analysis is performed.
Text is categorized as either visible or invisible. Invisible text (OCR)
is stripped out. Then an image of each page is created with visible text
masked out. The page image is sent for OCR, and any additional text is
inserted as OCR. If a file contains a mix of text and bitmap images that
contain text, OCRmyPDF will locate the additional text in images without
disrupting the existing text. Some PDF OCR solutions render text as
technically printable or visible in some way, perhaps by drawing it and
then painting over it. OCRmyPDF cannot distinguish this type of OCR
text from real text, so it will not be "redone".
If ``--force-ocr`` is issued, then all pages will be rasterized to
images, discarding any hidden OCR text, rasterizing any printable
text, and flattening form fields or interactive objects into their visual
representation. This is useful for redoing OCR, for fixing OCR text
with a damaged character map (text is selectable but not searchable),
and destroying redacted information.
Time and image size limits
--------------------------
By default, OCRmyPDF permits tesseract to run for three minutes (180
seconds) per page. This is usually more than enough time to find all
text on a reasonably sized page with modern hardware.
If a page is skipped, it will be inserted without OCR. If preprocessing
was requested, the preprocessed image layer will be inserted.
If you want to adjust the amount of time spent on OCR, change
``--tesseract-timeout``. You can also automatically skip images that
exceed a certain number of megapixels with ``--skip-big``. (A 300 DPI,
8.5×11" page image is 8.4 megapixels.)
.. code-block:: bash
# Allow 300 seconds for OCR; skip any page larger than 50 megapixels
ocrmypdf --tesseract-timeout 300 --skip-big 50 bigfile.pdf output.pdf
OCR for huge images
-------------------
Tesseract has internal limits on the size
of images it will process. By default,
``--tesseract-downsample-large-images`` is enabled, and OCRmyPDF will
downsample images to fit Tesseract limits. (The limits are usually encountered
only for scanned images of oversized media, such as large maps or blueprints exceeding
110 cm or 43 inches in either dimension, and at high DPI.) This feature can disabled
using ``--no-tesseract-downsample-large-images``.
``--tesseract-downsample-above Npixels`` adjusts the threshold at which images
will be downsampled. By default, only images that exceed any of Tesseract's
internal limits are downsampled (32767 pixels on either dimension).
You will also need to set ``--tesseract-timeout`` high enough to allow
for processing.
Only the image sent for OCR is downsampled. The original image is
preserved.
.. code-block:: bash
# Allow 600 seconds for OCR on huge images
ocrmypdf --tesseract-timeout 600 \
--tesseract-downsample-large-images \
bigfile.pdf output.pdf
# Downsample images above 5000 pixels on the longest dimension to
# 5000 pixels
ocrmypdf --tesseract-timeout 120 \
--tesseract-downsample-large-images \
--tesseract-downsample-above 5000 \
bigfile.pdf output_downsampled_ocr.pdf
Overriding default tesseract
----------------------------
OCRmyPDF checks the system ``PATH`` for the ``tesseract`` binary.
Some relevant environment variables that influence Tesseract's behavior
include:
.. envvar:: TESSDATA_PREFIX
Overrides the path to Tesseract's data files. This can allow
simultaneous installation of the "best" and "fast" training data
sets. OCRmyPDF does not manage this environment variable.
.. envvar:: OMP_THREAD_LIMIT
Controls the number of threads Tesseract will use. OCRmyPDF will
manage this environment variable if it is not already set.
For example, if you have a development build of Tesseract don't wish to
use the system installation, you can launch OCRmyPDF as follows:
.. code-block:: bash
env \
PATH=/home/user/src/tesseract/api:$PATH \
TESSDATA_PREFIX=/home/user/src/tesseract \
ocrmypdf input.pdf output.pdf
In this example ``TESSDATA_PREFIX`` is required to redirect Tesseract to
an alternate folder for its "tessdata" files.
Overriding other support programs
---------------------------------
In addition to tesseract, OCRmyPDF uses the following external binaries:
- ``gs`` (Ghostscript)
- ``unpaper``
- ``pngquant``
- ``jbig2``
In each case OCRmyPDF will search the ``PATH`` environment variable to
locate the binaries. By modifying the ``PATH`` environment variable, you
can override the binaries that OCRmyPDF uses.
Changing Tesseract configuration variables
------------------------------------------
You can override Tesseract's default `control
parameters <https://tesseract-ocr.github.io/tessdoc/tess3/ControlParams.html>`__
with a configuration file.
As an example, this configuration will disable Tesseract's dictionary
for current language. Normally the dictionary is helpful for
interpolating words that are unclear, but it may interfere with OCR if
the document does not contain many words (for example, a list of part
numbers).
Create a file named "no-dict.cfg" with these contents:
::
load_system_dawg 0
language_model_penalty_non_dict_word 0
language_model_penalty_non_freq_dict_word 0
then run ocrmypdf as follows (along with any other desired arguments):
.. code-block:: bash
ocrmypdf --tesseract-config no-dict.cfg input.pdf output.pdf
.. warning::
Some combinations of control parameters will break Tesseract or break
assumptions that OCRmyPDF makes about Tesseract's output.
Changing page segmentation mode
-------------------------------
The directive ``--tesseract-pagesegmode Nmode`` forwards the desired page segmentation
mode to Tesseract OCR. The default is 3.
Page segmentation can improve OCR results when you know that a PDF ought to be
analyzed a particular way, such as PDFs whose pages contain only a single line of
text. For the vast majority of users, changing the page segmentation mode will only
make things worse.
As of June 2024, the Tesseract page segmentation modes are:
+-----+----------------------------------------------------------------------------------+
| ID | Description |
+=====+==================================================================================+
| 0 | Orientation and script detection (OSD) only. |
+-----+----------------------------------------------------------------------------------+
| 1 | Automatic page segmentation with OSD. |
+-----+----------------------------------------------------------------------------------+
| 2 | Automatic page segmentation, but no OSD, or OCR. (not implemented) |
+-----+----------------------------------------------------------------------------------+
| 3 | Fully automatic page segmentation, but no OSD. (Default) |
+-----+----------------------------------------------------------------------------------+
| 4 | Assume a single column of text of variable sizes. |
+-----+----------------------------------------------------------------------------------+
| 5 | Assume a single uniform block of vertically aligned text. |
+-----+----------------------------------------------------------------------------------+
| 6 | Assume a single uniform block of text. |
+-----+----------------------------------------------------------------------------------+
| 7 | Treat the image as a single text line. |
+-----+----------------------------------------------------------------------------------+
| 8 | Treat the image as a single word. |
+-----+----------------------------------------------------------------------------------+
| 9 | Treat the image as a single word in a circle. |
+-----+----------------------------------------------------------------------------------+
| 10 | Treat the image as a single character. |
+-----+----------------------------------------------------------------------------------+
| 11 | Sparse text. Find as much text as possible in no particular order. |
+-----+----------------------------------------------------------------------------------+
| 12 | Sparse text with OSD. |
+-----+----------------------------------------------------------------------------------+
| 13 | Raw line. Treat the image as a single text line, bypassing hacks that are |
| | Tesseract-specific. |
+-----+----------------------------------------------------------------------------------+
Modes 0, 1, 2, and 12 (all of those that enable orientation and script detection)
are not compatible with OCRmyPDF, which performs OSD in a separate step from OCR.
Their use may interfere with ``--rotate-pages`` and other features.
It is currently not possible to use advanced Tesseract OCR features, such as creating
OCR information, when using Tesseract through OCRmyPDF.
Changing the PDF renderer
=========================
rasterizing
Converting a PDF to an image for display.
rendering
Creating a new PDF from other data (such as an existing PDF).
OCRmyPDF has these PDF renderers: ``sandwich`` and ``hocr``. The
renderer may be selected using ``--pdf-renderer``. The default is
``auto`` which lets OCRmyPDF select the renderer to use. Currently,
``auto`` always selects ``hocr``.
The ``hocr`` renderer
---------------------
.. versionchanged:: 16.0.0
In both renderers, a text-only layer is rendered and sandwiched (overlaid)
on to either the original PDF page, or newly rasterized version of the
original PDF page (when ``--force-ocr`` is used). In this way, loss
of PDF information is generally avoided. (You may need to disable PDF/A
conversion and optimization to eliminate all lossy transformations.)
The current approach used by the new hOCR renderer is a re-implementation
of Tesseract's PDF renderer, using the same Glyphless font and general
ideas, but fixing many technical issues that impeded it. The new hocr
provides better text placement accuracy, avoids issues with word
segmentation, and provides better positioning of skewed text.
Using the experimental API, it is also possible to edit the OCR output
from Tesseract, using any tool that is capable of editing hOCR files.
Older versions of this renderer did not support non-Latin languages, but
it is now universal.
The ``sandwich`` renderer
-------------------------
The ``sandwich`` renderer uses Tesseract's text-only PDF feature,
which produces a PDF page that lays out the OCR in invisible text.
Currently some problematic PDF viewers like Mozilla PDF.js and macOS
Preview have problems with segmenting its text output, and
mightrunseveralwordstogether. It also does not implement right to left
fonts (Arabic, Hebrew, Persian). The output of this renderer cannot
be edited. The sandwich renderer is retained for testing.
When image preprocessing features like ``--deskew`` are used, the
original PDF will be rendered as a full page and the OCR layer will be
placed on top.
Rendering and rasterizing options
=================================
.. versionadded:: 14.3.0
The ``--continue-on-soft-render-error`` option allows OCRmyPDF to
proceed if a page cannot be rasterized/rendered. This is useful if you are
trying to get the best possible OCR from a PDF that is not well-formed,
and you are willing to accept some pages that may not visually match the
input, and that may not OCR well.
Color conversion strategy
=========================
.. versionadded:: 15.0.0
OCRmyPDF uses Ghostscript to convert PDF to PDF/A. In some cases, this
conversion requires color conversion. The default strategy is to convert
using the ``LeaveColorUnchanged`` strategy, which preserves the original
color space wherever possible (some rare color spaces might still be
converted).
Usually document scanners produce PDFs in the sRGB color space, and do
not need to be converted, so the default strategy is appropriate.
Suppose that you have a document that was prepared for professional
printing in a Separation or CMYK color space, and text was converted to
curves. In this case, you may want to use a different color conversion
strategy. The ``--color-conversion-strategy`` option allows you to select a
different strategy, such as ``RGB``.
Return code policy
==================
OCRmyPDF writes all messages to ``stderr``. ``stdout`` is reserved for
piping output files. ``stdin`` is reserved for piping input files.
The return codes generated by the OCRmyPDF are considered part of the
stable user interface. They may be imported from
``ocrmypdf.exceptions``.
.. list-table:: Return codes
:widths: 5 35 60
:header-rows: 1
* - Code
- Name
- Interpretation
* - 0
- ``ExitCode.ok``
- Everything worked as expected.
* - 1
- ``ExitCode.bad_args``
- Invalid arguments, exited with an error.
* - 2
- ``ExitCode.input_file``
- The input file does not seem to be a valid PDF.
* - 3
- ``ExitCode.missing_dependency``
- An external program required by OCRmyPDF is missing.
* - 4
- ``ExitCode.invalid_output_pdf``
- An output file was created, but it does not seem to be a valid PDF. The file will be available.
* - 5
- ``ExitCode.file_access_error``
- The user running OCRmyPDF does not have sufficient permissions to read the input file and write the output file.
* - 6
- ``ExitCode.already_done_ocr``
- The file already appears to contain text so it may not need OCR. See output message.
* - 7
- ``ExitCode.child_process_error``
- An error occurred in an external program (child process) and OCRmyPDF cannot continue.
* - 8
- ``ExitCode.encrypted_pdf``
- The input PDF is encrypted. OCRmyPDF does not read encrypted PDFs. Use another program such as ``qpdf`` to remove encryption.
* - 9
- ``ExitCode.invalid_config``
- A custom configuration file was forwarded to Tesseract using ``--tesseract-config``, and Tesseract rejected this file.
* - 10
- ``ExitCode.pdfa_conversion_failed``
- A valid PDF was created, PDF/A conversion failed. The file will be available.
* - 15
- ``ExitCode.other_error``
- Some other error occurred.
* - 130
- ``ExitCode.ctrl_c``
- The program was interrupted by pressing Ctrl+C.
.. _tmpdir:
Changing temporary storage location
===================================
OCRmyPDF generates many temporary files during processing.
To change where temporary files are stored, change the ``TMPDIR``
environment variable for ocrmypdf's environment. (Python's
``tempfile.gettempdir()`` returns the root directory in which temporary
files will be stored.) For example, one could redirect ``TMPDIR`` to a
large RAM disk to avoid wear on HDD/SSD and potentially improve
performance.
On Windows, the ``TEMP`` environment variable is used instead.
Debugging the intermediate files
================================
OCRmyPDF normally saves its intermediate results to a temporary folder
and deletes this folder when it exits, whether it succeeded or failed.
If the ``--keep-temporary-files`` (``-k``) argument is issued on the
command line, OCRmyPDF will keep the temporary folder and print the location,
whether it succeeded or failed. An example message is:
.. code-block:: none
Temporary working files retained at:
/tmp/ocrmypdf.io.u20wpz07
When OCRmyPDF is launched as a snap, this corresponds to the snap filesystem, for instance:
/tmp/snap-private-tmp/snap.ocrmypdf/tmp/ocrmypdf.io.u20wpz07
The organization of this folder is an implementation detail and subject
to change between releases. However the general organization is that
working files on a per page basis have the page number as a prefix
(starting with page 1), an infix indicates the processing stage, and a
suffix indicates the file type. Some important files include:
- ``_rasterize.png`` - what the input page looks like
- ``_ocr.png`` - the file that is sent to Tesseract for OCR; depending
on arguments this may differ from the presentation image
- ``_pp_deskew.png`` - the image, after deskewing
- ``_pp_clean.png`` - the image, after cleaning with unpaper
- ``_ocr_hocr.pdf`` - the OCR file; appears as a blank page with invisible
text embedded
- ``_ocr_hocr.txt`` - the OCR text (not necessarily all text on the page,
if the page is mixed format)
- ``fix_docinfo.pdf`` - a temporary file created to fix the PDF DocumentInfo
data structure
- ``graft_layers.pdf`` - the rendered PDF with OCR layers grafted on
- ``pdfa.pdf`` - ``graft_layers.pdf`` after conversion to PDF/A
- ``pdfa.ps`` - a PostScript file used by Ghostscript for PDF/A conversion
- ``optimize.pdf`` - the PDF generated before optimization
- ``optimize.out.pdf`` - the PDF generated by optimization
- ``origin`` - the input file
- ``origin.pdf`` - the input file or the input image converted to PDF
- ``images/*`` - images extracted during the optimization process; here
the prefix indicates a PDF object ID not a page number
+47 -56
View File
@@ -1,10 +1,7 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow % SPDX-FileCopyrightText: 2022 James R. Barlow
.. % SPDX-License-Identifier: CC-BY-SA-4.0
.. SPDX-License-Identifier: CC-BY-SA-4.0
====================== # Using the OCRmyPDF API
Using the OCRmyPDF API
======================
OCRmyPDF originated as a command line program and continues to have this OCRmyPDF originated as a command line program and continues to have this
legacy, but parts of it can be imported and used in other Python legacy, but parts of it can be imported and used in other Python
@@ -13,100 +10,95 @@ applications.
Some applications may want to consider running ocrmypdf from a Some applications may want to consider running ocrmypdf from a
subprocess call anyway, as this provides isolation of its activities. subprocess call anyway, as this provides isolation of its activities.
Example ## Example
=======
OCRmyPDF provides one high-level function to run its main engine from an OCRmyPDF provides one high-level function to run its main engine from an
application. The parameters are symmetric to the command line arguments application. The parameters are symmetric to the command line arguments
and largely have the same functions. and largely have the same functions.
.. code-block:: python ```python
import ocrmypdf
import ocrmypdf if __name__ == '__main__': # To ensure correct behavior on Windows and macOS
ocrmypdf.ocr('input.pdf', 'output.pdf', deskew=True)
if __name__ == '__main__': # To ensure correct behavior on Windows and macOS ```
ocrmypdf.ocr('input.pdf', 'output.pdf', deskew=True)
With some exceptions, all of the command line arguments are available With some exceptions, all of the command line arguments are available
and may be passed as equivalent keywords. and may be passed as equivalent keywords.
A few differences are that ``verbose`` and ``quiet`` are not available. A few differences are that `verbose` and `quiet` are not available.
Instead, output should be managed by configuring logging. Instead, output should be managed by configuring logging.
Parent process requirements ### Parent process requirements
---------------------------
The :func:`ocrmypdf.ocr` function runs OCRmyPDF similar to command line The {func}`ocrmypdf.ocr` function runs OCRmyPDF similar to command line
execution. To do this, it will: execution. To do this, it will:
- create worker processes or threads - create worker processes or threads
- manage the signal flags of its worker processes - manage the signal flags of its worker processes
- execute other subprocesses (forking and executing other programs) - execute other subprocesses (forking and executing other programs)
The Python process that calls :func:`ocrmypdf.ocr()` must be sufficiently The Python process that calls {func}`ocrmypdf.ocr()` must be sufficiently
privileged to perform these actions. privileged to perform these actions.
There currently is no option to manage how jobs are scheduled other There currently is no option to manage how jobs are scheduled other
than the argument ``jobs=`` which will limit the number of worker than the argument `jobs=` which will limit the number of worker
processes. processes.
Creating a child process to call :func:`ocrmypdf.ocr()` is suggested. That Creating a child process to call {func}`ocrmypdf.ocr()` is suggested. That
way your application will survive and remain interactive even if way your application will survive and remain interactive even if
OCRmyPDF fails for any reason. For example: OCRmyPDF fails for any reason. For example:
.. code-block:: python ```python
from multiprocessing import Process
from multiprocessing import Process def ocrmypdf_process():
ocrmypdf.ocr('input.pdf', 'output.pdf')
def ocrmypdf_process(): def call_ocrmypdf_from_my_app():
ocrmypdf.ocr('input.pdf', 'output.pdf') p = Process(target=ocrmypdf_process)
p.start()
p.join()
```
def call_ocrmypdf_from_my_app(): Programs that call {func}`ocrmypdf.ocr()` should also install a SIGBUS signal
p = Process(target=ocrmypdf_process)
p.start()
p.join()
Programs that call :func:`ocrmypdf.ocr()` should also install a SIGBUS signal
handler (except on Windows), to raise an exception if access to a memory handler (except on Windows), to raise an exception if access to a memory
mapped file fails. OCRmyPDF may use memory mapping. mapped file fails. OCRmyPDF may use memory mapping.
:func:`ocrmypdf.ocr()` will take a threading lock to prevent multiple runs of itself {func}`ocrmypdf.ocr()` will take a threading lock to prevent multiple runs of itself
in the same Python interpreter process. This is not thread-safe, because of how in the same Python interpreter process. This is not thread-safe, because of how
OCRmyPDF's plugins and Python's library import system work. If you need to parallelize OCRmyPDF's plugins and Python's library import system work. If you need to parallelize
OCRmyPDF, use processes. OCRmyPDF, use processes.
.. warning:: :::{warning}
On Windows and macOS, the script that calls {func}`ocrmypdf.ocr()` must be
protected by an "ifmain" guard (`if __name__ == '__main__'`). If you do
not take at least one of these steps, process semantics will prevent
OCRmyPDF from working correctly.
:::
On Windows and macOS, the script that calls :func:`ocrmypdf.ocr()` must be ### Logging
protected by an "ifmain" guard (``if __name__ == '__main__'``). If you do
not take at least one of these steps, process semantics will prevent
OCRmyPDF from working correctly.
Logging OCRmyPDF will log under loggers named `ocrmypdf`. In addition, it
------- imports `pdfminer` and `PIL`, both of which post log messages under
OCRmyPDF will log under loggers named ``ocrmypdf``. In addition, it
imports ``pdfminer`` and ``PIL``, both of which post log messages under
those logging namespaces. those logging namespaces.
You can configure the logging as desired for your application or call You can configure the logging as desired for your application or call
:func:`ocrmypdf.configure_logging` to configure logging the same way {func}`ocrmypdf.configure_logging` to configure logging the same way
OCRmyPDF itself does. The command line parameters such as ``--quiet`` OCRmyPDF itself does. The command line parameters such as `--quiet`
and ``--verbose`` have no equivalents in the API; you must use the and `--verbose` have no equivalents in the API; you must use the
provided configuration function or do configuration in a way that suits provided configuration function or do configuration in a way that suits
your use case. your use case.
Progress monitoring ### Progress monitoring
-------------------
OCRmyPDF uses the ``rich`` package to implement its progress bars. OCRmyPDF uses the `rich` package to implement its progress bars.
:func:`ocrmypdf.configure_logging` will set up logging output to {func}`ocrmypdf.configure_logging` will set up logging output to
``sys.stderr`` in a way that is compatible with the display of the `sys.stderr` in a way that is compatible with the display of the
progress bar. Use ``ocrmypdf.ocr(...progress_bar=False)`` to disable progress bar. Use `ocrmypdf.ocr(...progress_bar=False)` to disable
the progress bar. the progress bar.
Standard output ### Standard output
---------------
OCRmyPDF is strict about not writing to standard output so that OCRmyPDF is strict about not writing to standard output so that
users can safely use it in a pipeline and produce a valid output users can safely use it in a pipeline and produce a valid output
@@ -116,12 +108,11 @@ behavior and support piping to a file. Another benefit of running
OCRmyPDF in a child process, as recommended above, is that it will OCRmyPDF in a child process, as recommended above, is that it will
not interfere with the parent process's standard output. not interfere with the parent process's standard output.
Exceptions ### Exceptions
----------
OCRmyPDF may throw standard Python exceptions, ``ocrmypdf.exceptions.*`` OCRmyPDF may throw standard Python exceptions, `ocrmypdf.exceptions.*`
exceptions, some exceptions related to multiprocessing, and exceptions, some exceptions related to multiprocessing, and
:exc:`KeyboardInterrupt`. The parent process should provide an exception {exc}`KeyboardInterrupt`. The parent process should provide an exception
handler. OCRmyPDF will clean up its temporary files and worker processes handler. OCRmyPDF will clean up its temporary files and worker processes
automatically when an exception occurs. automatically when an exception occurs.
+24 -20
View File
@@ -1,56 +1,60 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow % SPDX-FileCopyrightText: 2022 James R. Barlow
.. % SPDX-License-Identifier: CC-BY-SA-4.0
.. SPDX-License-Identifier: CC-BY-SA-4.0
============= # API reference
API reference
=============
This page summarizes the rest of the public API. Generally speaking this This page summarizes the rest of the public API. Generally speaking this
should be mainly of interest to plugin developers. should be mainly of interest to plugin developers.
ocrmypdf.api ## ocrmypdf.api
============
```{eval-rst}
.. automodule:: ocrmypdf.api .. automodule:: ocrmypdf.api
:members: :members:
```
ocrmypdf.exceptions ## ocrmypdf.exceptions
===================
```{eval-rst}
.. automodule:: ocrmypdf.exceptions .. automodule:: ocrmypdf.exceptions
:members: :members:
:undoc-members: :undoc-members:
```
ocrmypdf.helpers ## ocrmypdf.helpers
================
```{eval-rst}
.. automodule:: ocrmypdf.helpers .. automodule:: ocrmypdf.helpers
:members: :members:
:noindex: deprecated :noindex: deprecated
.. autodecorator:: deprecated .. autodecorator:: deprecated
```
ocrmypdf.hocrtransform ## ocrmypdf.hocrtransform
======================
```{eval-rst}
.. automodule:: ocrmypdf.hocrtransform .. automodule:: ocrmypdf.hocrtransform
:members: :members:
```
ocrmypdf.pdfa ## ocrmypdf.pdfa
=============
```{eval-rst}
.. automodule:: ocrmypdf.pdfa .. automodule:: ocrmypdf.pdfa
:members: :members:
```
ocrmypdf.quality ## ocrmypdf.quality
================
```{eval-rst}
.. automodule:: ocrmypdf.quality .. automodule:: ocrmypdf.quality
:members: :members:
```
ocrmypdf.subprocess ## ocrmypdf.subprocess
===================
```{eval-rst}
.. automodule:: ocrmypdf.subprocess .. automodule:: ocrmypdf.subprocess
:members: :members:
```
+248
View File
@@ -0,0 +1,248 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
Batch processing
================
This article provides information about running OCRmyPDF on multiple
files or configuring it as a service triggered by file system events.
Batch jobs
----------
Consider using the excellent [GNU
Parallel](https://www.gnu.org/software/parallel/) to apply OCRmyPDF to
multiple files at once.
Both `parallel` and `ocrmypdf` will try to use all available processors.
To maximize parallelism without overloading your system with processes,
consider using `parallel -j 2` to limit parallel to running two jobs at
once.
This command will run `ocrmypdf` on all files named `*.pdf` in the
current directory and write them to the previously created `output/`
folder. It will not search subdirectories.
The `--tag` argument tells parallel to print the filename as a prefix
whenever a message is printed, so that one can trace any errors to the
file that produced them.
:::{code} bash
parallel --tag -j 2 ocrmypdf '{}' 'output/{}' ::: *.pdf
:::
OCRmyPDF automatically repairs PDFs before parsing and gathering
information from them.
Directory trees
---------------
This will walk through a directory tree and run OCR on all files in
place, and printing each filename in between runs:
:::{code} bash
find . -name '*.pdf' -printf '%p\n' -exec ocrmypdf '{}' '{}' \;
:::
This only runs one `ocrmypdf` process at a time. This variation uses
`find` to create a directory list and `parallel` to parallelize runs of
`ocrmypdf`, again updating files in place.
:::{code} bash
find . -name '*.pdf' | parallel --tag -j 2 ocrmypdf '{}' '{}'
:::
In a Windows batch file, use
:::{code} bat
for /r %%f in (*.pdf) do ocrmypdf %%f %%f
:::
With a Docker container, you will need to stream through standard input
and output:
:::{code} bash
find . -name '*.pdf' -print0 | xargs -0 | while read pdf; do
pdfout=$(mktemp)
docker run --rm -i jbarlow83/ocrmypdf - - <$pdf >$pdfout && cp $pdfout $pdf
done
:::
### Sample script
This user contributed script also provides an example of batch
processing.
:::{literalinclude} ../misc/batch.py
---
caption: misc/batch.py
---
:::
### Synology DiskStations
Synology DiskStations (Network Attached Storage devices) can run the
Docker image of OCRmyPDF if the Synology [Docker
package](https://www.synology.com/en-global/dsm/packages/Docker) is
installed. Attached is a script to address particular quirks of using
OCRmyPDF on one of these devices.
At the time this script was written, it only worked for x86-based
Synology products. It is not known if it will work on ARM-based Synology
products. Further adjustments might be needed to deal with the
Synology\'s relatively limited CPU and RAM.
:::{literalinclude} ../misc/synology.py
---
caption: misc/synology.py - Sample script for Synology DiskStations
---
:::
### Huge batch jobs
If you have thousands of files to work with, contact the author.
Consulting work related to OCRmyPDF helps fund this open source project
and all inquiries are appreciated.
Hot (watched) folders
---------------------
### Watched folders with watcher.py
OCRmyPDF has a folder watcher called watcher.py, which is currently
included in source distributions but not part of the main program. It
may be used natively or may run in a Docker container. Native instances
tend to give better performance. watcher.py works on all platforms.
Users may need to customize the script to meet their requirements.
:::{code} bash
pip3 install ocrmypdf[watcher]
env OCR_INPUT_DIRECTORY=/mnt/input-pdfs \
OCR_OUTPUT_DIRECTORY=/mnt/output-pdfs \
OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1 \
python3 watcher.py
:::
:::{list-table} watcher.py environment variables
---
header-rows: 1
---
* - Environment variable
- Description
* - OCR\_INPUT\_DIRECTORY
- Set input directory to monitor (recursive)
* - OCR\_OUTPUT\_DIRECTORY
- Set output directory (should not be under input)
* - OCR\_ARCHIVE\_DIRECTORY
- Set archive directory for processed originals (should not be under input, requires `OCR_ON_SUCCESS_ARCHIVE` to be set)
* - OCR\_ON\_SUCCESS\_DELETE
- This will move the processed original file to `OCR_ARCHIVE_DIRECTORY` if the exit code is 0 (OK). Note that `OCR_ON_SUCCESS_DELETE` takes precedence over this option, i.e. if both options are set, the input file will be deleted.
* - OCR\_OUTPUT\_DIRECTORY\_YEAR\_MONTH
- This will place files in the output in `{output}/{year}/{month}/{filename}`
* - OCR\_DESKEW
- Apply deskew to crooked input PDFs
* - OCR\_JSON\_SETTINGS
- A JSON string specifying any other arguments for `ocrmypdf.ocr`, e.g. `'OCR_JSON_SETTINGS={"rotate_pages": true, "optimize": "3"}'`.
* - OCR\_POLL\_NEW\_FILE\_SECONDS
- Polling interval
* - OCR\_LOGLEVEL
- Level of log messages t
:::
One could configure a networked scanner or scanning computer to drop
files in the watched folder.
### Watched folders with Docker
The watcher service is included in the OCRmyPDF Docker image. To run it:
:::{code} bash
docker run \
--volume <path to files to convert>:/input \
--volume <path to store results>:/output \
--volume <path to store processed originals>:/processed \
--env OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1 \
--env OCR_ON_SUCCESS_ARCHIVE=1 \
--env OCR_DESKEW=1 \
--env PYTHONUNBUFFERED=1 \
--interactive --tty --entrypoint python3 \
jbarlow83/ocrmypdf \
watcher.py
:::
This service will watch for a file that matches `/input/\*.pdf`, convert
it to a OCRed PDF in `/output/`, and move the processed original to
`/processed`. The parameters to this image are:
:::{list-table} Watcher Docker Parameters
:header-rows: 1
* - Parameter
- Description
* - `--volume <path to files to convert>:/input`
- Files placed in this location will be OCRed
* - `--volume <path to store results>:/output`
- This is where OCRed files will be stored
* - `--volume <path to store processed originals>:/processed`
- Archive processed originals here
* - `--env OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1`
- Define environment variable `OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1` to place files in the output in `{output}/{year}/{month}/{filename}`
* - `--env OCR_ON_SUCCESS_ARCHIVE=1`
- Define environment variable `OCR_ON_SUCCESS_ARCHIVE` to move processed originals
* - `--env OCR_DESKEW=1`
- Define environment variable `OCR_DESKEW` to apply deskew to crooked input PDFs
* - `--env PYTHONBUFFERED=1`
- This will force `STDOUT` to be unbuffered and allow you to see messages in docker logs
:::
This service relies on polling to check for changes to the filesystem.
It may not be suitable for some environments, such as filesystems shared
on a slow network.
A configuration manager such as Docker Compose could be used to ensure
that the service is always available.
:::{literalinclude} ../misc/docker-compose.example.yml
---
caption: misc/docker-compose.example.yml
---
:::
### Caveats
- `watchmedo` may not work properly on a networked file system,
depending on the capabilities of the file system client and server.
- This simple recipe does not filter for the type of file system
event, so file copies, deletes and moves, and directory operations,
will all be sent to ocrmypdf, producing errors in several cases.
Disable your watched folder if you are doing anything other than
copying files to it.
- If the source and destination directory are the same, watchmedo may
create an infinite loop.
- On BSD, FreeBSD and older versions of macOS, you may need to
increase the number of file descriptors to monitor more files, using
`ulimit -n 1024` to watch a folder of up to 1024 files.
### Alternatives
- On Linux, [systemd user
services](https://wiki.archlinux.org/index.php/Systemd/User) can be
configured to automatically perform OCR on a collection of files.
- [Watchman](https://facebook.github.io/watchman/) is a more powerful
alternative to `watchmedo`.
macOS Automator
---------------
You can use the Automator app with macOS, to create a Workflow or Quick
Action. Use a *Run Shell Script* action in your workflow. In the context
of Automator, the `PATH` may be set differently your Terminal\'s `PATH`;
you may need to explicitly set the PATH to include `ocrmypdf`. The
following example may serve as a starting point:
![](images/macos-workflow.png)
You may customize the command sent to ocrmypdf.
-228
View File
@@ -1,228 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
================
Batch processing
================
This article provides information about running OCRmyPDF on multiple
files or configuring it as a service triggered by file system events.
Batch jobs
==========
Consider using the excellent `GNU
Parallel <https://www.gnu.org/software/parallel/>`__ to apply OCRmyPDF
to multiple files at once.
Both ``parallel`` and ``ocrmypdf`` will try to use all available
processors. To maximize parallelism without overloading your system with
processes, consider using ``parallel -j 2`` to limit parallel to running
two jobs at once.
This command will run ``ocrmypdf`` on all files named ``*.pdf`` in the
current directory and write them to the previously created ``output/``
folder. It will not search subdirectories.
The ``--tag`` argument tells parallel to print the filename as a prefix
whenever a message is printed, so that one can trace any errors to the
file that produced them.
.. code-block:: bash
parallel --tag -j 2 ocrmypdf '{}' 'output/{}' ::: *.pdf
OCRmyPDF automatically repairs PDFs before parsing and gathering
information from them.
Directory trees
===============
This will walk through a directory tree and run OCR on all files in
place, and printing each filename in between runs:
.. code-block:: bash
find . -name '*.pdf' -printf '%p\n' -exec ocrmypdf '{}' '{}' \;
This only runs one ``ocrmypdf`` process at a time. This variation uses
``find`` to create a directory list and ``parallel`` to parallelize runs
of ``ocrmypdf``, again updating files in place.
.. code-block:: bash
find . -name '*.pdf' | parallel --tag -j 2 ocrmypdf '{}' '{}'
In a Windows batch file, use
.. code-block:: bat
for /r %%f in (*.pdf) do ocrmypdf %%f %%f
With a Docker container, you will need to stream through standard input and output:
.. code-block:: bash
find . -name '*.pdf' -print0 | xargs -0 | while read pdf; do
pdfout=$(mktemp)
docker run --rm -i jbarlow83/ocrmypdf - - <$pdf >$pdfout && cp $pdfout $pdf
done
Sample script
-------------
This user contributed script also provides an example of batch
processing.
.. literalinclude:: ../misc/batch.py
:caption: misc/batch.py
Synology DiskStations
---------------------
Synology DiskStations (Network Attached Storage devices) can run the
Docker image of OCRmyPDF if the Synology `Docker
package <https://www.synology.com/en-global/dsm/packages/Docker>`__ is
installed. Attached is a script to address particular quirks of using
OCRmyPDF on one of these devices.
At the time this script was written, it only worked for x86-based Synology
products. It is not known if it will work on ARM-based Synology products.
Further adjustments might be needed to deal with the Synology's relatively
limited CPU and RAM.
.. literalinclude:: ../misc/synology.py
:caption: misc/synology.py - Sample script for Synology DiskStations
Huge batch jobs
---------------
If you have thousands of files to work with, contact the author.
Consulting work related to OCRmyPDF helps fund this open source project
and all inquiries are appreciated.
Hot (watched) folders
=====================
Watched folders with watcher.py
-------------------------------
OCRmyPDF has a folder watcher called watcher.py, which is currently included in source
distributions but not part of the main program. It may be used natively or may run
in a Docker container. Native instances tend to give better performance. watcher.py
works on all platforms.
Users may need to customize the script to meet their requirements.
.. code-block:: bash
pip3 install ocrmypdf[watcher]
env OCR_INPUT_DIRECTORY=/mnt/input-pdfs \
OCR_OUTPUT_DIRECTORY=/mnt/output-pdfs \
OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1 \
python3 watcher.py
.. csv-table:: watcher.py environment variables
:header: "Environment variable", "Description"
:widths: 50, 50
"OCR_INPUT_DIRECTORY", "Set input directory to monitor (recursive)"
"OCR_OUTPUT_DIRECTORY", "Set output directory (should not be under input)"
"OCR_ARCHIVE_DIRECTORY", "Set archive directory for processed originals (should not be under input, requires ``OCR_ON_SUCCESS_ARCHIVE`` to be set)"
"OCR_ON_SUCCESS_DELETE", "This will delete the input file if the exit code is 0 (OK)"
"OCR_ON_SUCCESS_ARCHIVE", "This will move the processed original file to ``OCR_ARCHIVE_DIRECTORY`` if the exit code is 0 (OK). Note that ``OCR_ON_SUCCESS_DELETE`` takes precedence over this option, i.e. if both options are set, the input file will be deleted."
"OCR_OUTPUT_DIRECTORY_YEAR_MONTH", "This will place files in the output in ``{output}/{year}/{month}/{filename}``"
"OCR_DESKEW", "Apply deskew to crooked input PDFs"
"OCR_JSON_SETTINGS", "A JSON string specifying any other arguments for ``ocrmypdf.ocr``, e.g. ``'OCR_JSON_SETTINGS={""rotate_pages"": true, ""optimize"": ""3""}'``."
"OCR_POLL_NEW_FILE_SECONDS", "Polling interval"
"OCR_LOGLEVEL", "Level of log messages to report"
One could configure a networked scanner or scanning computer to drop files in the
watched folder.
Watched folders with Docker
---------------------------
The watcher service is included in the OCRmyPDF Docker image. To run it:
.. code-block:: bash
docker run \
--volume <path to files to convert>:/input \
--volume <path to store results>:/output \
--volume <path to store processed originals>:/processed \
--env OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1 \
--env OCR_ON_SUCCESS_ARCHIVE=1 \
--env OCR_DESKEW=1 \
--env PYTHONUNBUFFERED=1 \
--interactive --tty --entrypoint python3 \
jbarlow83/ocrmypdf \
watcher.py
This service will watch for a file that matches ``/input/\*.pdf``,
convert it to a OCRed PDF in ``/output/``, and move the processed
original to ``/processed``. The parameters to this image are:
.. csv-table:: watcher.py parameters for Docker
:header: "Parameter", "Description"
:widths: 50, 50
"``--volume <path to files to convert>:/input``", "Files placed in this location will be OCRed"
"``--volume <path to store results>:/output``", "This is where OCRed files will be stored"
"``--volume <path to store processed originals>:/processed``", "Archive processed originals here"
"``--env OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1``", "Define environment variable ``OCR_OUTPUT_DIRECTORY_YEAR_MONTH=1`` to place files in the output in ``{output}/{year}/{month}/{filename}``"
"``--env OCR_ON_SUCCESS_ARCHIVE=1``", "Define environment variable ``OCR_ON_SUCCESS_ARCHIVE`` to move processed originals"
"``--env OCR_DESKEW=1``", "Define environment variable ``OCR_DESKEW`` to apply deskew to crooked input PDFs"
"``--env PYTHONBUFFERED=1``", "This will force ``STDOUT`` to be unbuffered and allow you to see messages in docker logs"
This service relies on polling to check for changes to the filesystem. It
may not be suitable for some environments, such as filesystems shared on a
slow network.
A configuration manager such as Docker Compose could be used to ensure that the
service is always available.
.. literalinclude:: ../misc/docker-compose.example.yml
:language: yaml
:caption: misc/docker-compose.example.yml
Caveats
-------
- ``watchmedo`` may not work properly on a networked file system,
depending on the capabilities of the file system client and server.
- This simple recipe does not filter for the type of file system event,
so file copies, deletes and moves, and directory operations, will all
be sent to ocrmypdf, producing errors in several cases. Disable your
watched folder if you are doing anything other than copying files to
it.
- If the source and destination directory are the same, watchmedo may
create an infinite loop.
- On BSD, FreeBSD and older versions of macOS, you may need to increase
the number of file descriptors to monitor more files, using
``ulimit -n 1024`` to watch a folder of up to 1024 files.
Alternatives
------------
- On Linux, `systemd user services <https://wiki.archlinux.org/index.php/Systemd/User>`__
can be configured to automatically perform OCR on a collection of files.
- `Watchman <https://facebook.github.io/watchman/>`__ is a more
powerful alternative to ``watchmedo``.
macOS Automator
===============
You can use the Automator app with macOS, to create a Workflow or Quick
Action. Use a *Run Shell Script* action in your workflow. In the context
of Automator, the ``PATH`` may be set differently your Terminal's
``PATH``; you may need to explicitly set the PATH to include
``ocrmypdf``. The following example may serve as a starting point:
.. figure:: images/macos-workflow.png
:alt: Example macOS Automator workflow
You may customize the command sent to ocrmypdf.
+84
View File
@@ -0,0 +1,84 @@
% SPDX-FileCopyrightText: 2025 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
(ocr-service)=
# Online deployments
OCRmyPDF is designed to be used as a command line tool, but it can be
used in a web service. This document describes some considerations for
doing so.
A basic web service implementation is provided in the source code
repository, as `misc/webservice.py`. It is only demonstration quality
and is not intended for production use.
OCRmyPDF is not designed for use as a public web service where a
malicious user could upload a chosen PDF. In particular, it is not
necessarily secure against PDF malware or PDFs that cause denial of
service. For further discussino of security, see
[security](security).
OCRmyPDF relies on Ghostscript, and therefore, if deployed online one
should be prepared to comply with Ghostscript\'s Affero GPL license, and
any other licenses.
Setting aside these concerns, a side effect of OCRmyPDF is that it may
incidentally sanitize PDFs containing certain types of malware. It
repairs the PDF with pikepdf/libqpdf, which could correct malformed PDF
structures that are part of an attack. When PDF/A output is selected
(the default), the input PDF is partially reconstructed by Ghostscript.
When `--force-ocr` is used, all pages are rasterized and reconverted to
PDF, which could remove malware in embedded images.
## Limiting CPU usage
OCRmyPDF will attempt to use all available CPUs and storage, so
executing `nice ocrmypdf` or limiting the number of jobs with the
`--jobs` argument may ensure the server remains responsive. Another
option would be to run OCRmyPDF jobs inside a Docker container, a
virtual machine, or a cloud instance, which can impose its own limits on
CPU usage and be terminated \"from orbit\" if it fails to complete.
## Temporary storage requirements
OCRmyPDF will use a large amount of temporary storage for its work,
proportional to the total number of pixels needed to rasterize the PDF.
The raster image of a 8.5×11\" color page at 300 DPI takes 25 MB
uncompressed; OCRmyPDF saves its intermediates as PNG, but that still
means it requires about 9 MB per intermediate based on average
compression ratios. Multiple intermediates per page are also required,
depending on the command line given. A rule of thumb would be to allow
100 MB of temporary storage per page in a file -- meaning that a small
cloud servers or small VM partitions should be provisioned with plenty
of extra space, if say, a 500 page file might be sent.
To change the temporary directory, see [tmpdir](#tmpdir).
On Amazon Web Services or other cloud vendors, consider setting your
temporary directory to [empheral
storage](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html).
## Timeouts
To prevent excessively long OCR jobs consider setting
`--tesseract-timeout` and/or `--skip-big` arguments. `--skip-big` is
particularly helpful if your PDFs include documents such as reports on
standard page sizes with large images attached - often large images are
not worth OCR\'ing anyway.
## Document management systems
If you are looking for a full document management system, consider
[paperless-ngx](https://github.com/paperless-ngx/paperless-ngx), which
is a web application that uses OCRmyPDF to automatically OCR and archive
documents.
## Commercial OCR alternatives
The author also provides professional services that include OCR and
building databases around PDFs, and is happy to provide consultation.
Abbyy Cloud OCR is viable commercial alternative with a web services
API. Amazon Textract, Google Cloud Vision, and Microsoft Azure Computer
Vision provide advanced OCR but have less PDF rendering capability.
-92
View File
@@ -1,92 +0,0 @@
.. SPDX-FileCopyrightText: 2023 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
.. _ocr-service:
==================
Online deployments
==================
OCRmyPDF is designed to be used as a command line tool, but it can be
used in a web service. This document describes some considerations for
doing so.
A basic web service implementation is provided in the source code
repository, as ``misc/webservice.py``. It is only demonstration quality
and is not intended for production use.
OCRmyPDF is not designed for use as a public web service where a
malicious user could upload a chosen PDF. In particular, it is not
necessarily secure against PDF malware or PDFs that cause denial of
service. For further discussino of security, see :ref:`security`.
OCRmyPDF relies on Ghostscript, and therefore, if deployed
online one should be prepared to comply with Ghostscript's Affero GPL
license, and any other licenses.
Setting aside these concerns, a side effect of OCRmyPDF is that it may
incidentally sanitize PDFs containing certain types of malware. It
repairs the PDF with pikepdf/libqpdf, which could correct malformed PDF
structures that are part of an attack. When PDF/A output is selected
(the default), the input PDF is partially reconstructed by Ghostscript.
When ``--force-ocr`` is used, all pages are rasterized and reconverted
to PDF, which could remove malware in embedded images.
Limiting CPU usage
------------------
OCRmyPDF will attempt to use all available CPUs and storage, so
executing ``nice ocrmypdf`` or limiting the number of jobs with the
``--jobs`` argument may ensure the server remains responsive. Another option
would be to run OCRmyPDF jobs inside a Docker container, a virtual machine,
or a cloud instance, which can impose its own limits on CPU usage and be
terminated "from orbit" if it fails to complete.
Temporary storage requirements
------------------------------
OCRmyPDF will use a large amount of temporary storage for its work,
proportional to the total number of pixels needed to rasterize the PDF.
The raster image of a 8.5×11" color page at 300 DPI takes 25 MB
uncompressed; OCRmyPDF saves its intermediates as PNG, but that still
means it requires about 9 MB per intermediate based on average
compression ratios. Multiple intermediates per page are also required,
depending on the command line given. A rule of thumb would be to allow
100 MB of temporary storage per page in a file meaning that a small
cloud servers or small VM partitions should be provisioned with plenty
of extra space, if say, a 500 page file might be sent.
To change the temporary directory, see :ref:`tmpdir`.
On Amazon Web Services or other cloud vendors, consider setting your
temporary directory to `empheral
storage <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html>`__.
Timeouts
--------
To prevent excessively long OCR jobs consider setting
``--tesseract-timeout`` and/or ``--skip-big`` arguments. ``--skip-big``
is particularly helpful if your PDFs include documents such as reports
on standard page sizes with large images attached - often large images
are not worth OCR'ing anyway.
Document management systems
---------------------------
If you are looking for a full document management system, consider
`paperless-ngx <https://github.com/paperless-ngx/paperless-ngx>`__,
which is a web application that uses OCRmyPDF to automatically OCR and
archive documents.
Commercial OCR alternatives
---------------------------
The author also provides professional services that include OCR and
building databases around PDFs, and is happy to provide consultation.
Abbyy Cloud OCR is viable commercial alternative with a web services
API. Amazon Textract, Google Cloud Vision, and Microsoft Azure
Computer Vision provide advanced OCR but have less PDF rendering capability.
+7 -10
View File
@@ -26,9 +26,7 @@
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = '8'
#
# needs_sphinx = '1.0'
import datetime import datetime
@@ -36,6 +34,7 @@ import datetime
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = [ extensions = [
'myst_parser',
'sphinx.ext.autodoc', 'sphinx.ext.autodoc',
'sphinx.ext.intersphinx', 'sphinx.ext.intersphinx',
'sphinx.ext.autosummary', 'sphinx.ext.autosummary',
@@ -44,6 +43,8 @@ extensions = [
'sphinx_issues', 'sphinx_issues',
] ]
myst_enable_extensions = ['colon_fence', 'attrs_block', 'attrs_inline', 'substitution']
# Extension settings # Extension settings
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
napoleon_use_rtype = False napoleon_use_rtype = False
@@ -53,11 +54,7 @@ issues_github_path = "ocrmypdf/OCRmyPDF"
templates_path = ['_templates'] templates_path = ['_templates']
# The suffix(es) of source filenames. # The suffix(es) of source filenames.
source_suffix = {'.rst': 'restructuredtext', '.md': 'markdown'} source_suffix = {'.rst': 'restructuredtext', '.md': 'markdown', '.txt': 'markdown'}
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = 'index'
@@ -67,8 +64,8 @@ project = 'ocrmypdf'
year = str(datetime.date.today().year) year = str(datetime.date.today().year)
copyright = ( copyright = (
f'{year}, James R. Barlow. ', f'{year}, James R. Barlow. '
'Licensed under Creative Commons Attribution-ShareAlike 4.0.', + 'Licensed under Creative Commons Attribution-ShareAlike 4.0'
) )
author = 'James R. Barlow' author = 'James R. Barlow'
+72
View File
@@ -0,0 +1,72 @@
% SPDX-FileCopyrightText: 2025 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Contributing guidelines
Contributions are welcome!
## Big changes
Please open a new issue to discuss or propose a major change. Not only
is it fun to discuss big ideas, but we might save each other\'s time
too. Perhaps some of the work you\'re contemplating is already half-done
in a development branch.
## Code style
We use `ruff` for code formatting.
The settings for these programs are in `pyproject.toml`. Pull requests
should follow the style guide. One difference we use from \"black\"
style is that strings shown to the user are always in double quotes
(`"`) and strings for internal uses are in single quotes (`'`).
## Tests
New features should come with tests that confirm their correctness.
## New dependencies
If you are proposing a change that will require a new dependency, we
prefer dependencies that are already packaged by Debian or Red Hat. This
makes life much easier for our downstream package maintainers. A package
that is only available on PyPI or GitHub, and not more widely packaged,
may not be accepted.
We are unlikely to accept a dependency on CUDA or other GPU-based
libraries, because these are still difficult to package and install on
many systems. We recommend implementing these changes as plugins.
Python dependencies must also be license-compatible. GPLv3 or AGPLv3 are
likely incompatible with the project\'s license, but LGPLv3 is
compatible.
## New non-Python dependencies
OCRmyPDF uses several external programs (Tesseract, Ghostscript and
others) for its functionality. In general we prefer to avoid adding new
external programs, and if we are to add external programs, we prefer
those that are already packaged by Debian or Red Hat.
## Plugins
Some new features may be a good fit for a plugin. Plugins are a way to
add features to OCRmyPDF without adding them to the core program.
Plugins are installed separately from OCRmyPDF. They are written in
Python and can be installed from PyPI. See the [plugin
documentation](https://ocrmypdf.readthedocs.io/en/latest/plugins.html).
We are happy to link users to your plugin from the documentation.
## Style guide: Is it OCRmyPDF or ocrmypdf?
The program/project is OCRmyPDF and the name of the executable or
library is ocrmypdf.
## Copyright and license
For contributions over 10 lines of code, please add your name to list of
copyright holders for that file. The core program is licensed under
MPL-2.0, test files and documentation under CC-BY-SA 4.0, and
miscellaneous files under MIT, with a few minor exceptions. Please
contribute only content that you own or have the right to contribute
under these licenses.
-77
View File
@@ -1,77 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
=======================
Contributing guidelines
=======================
Contributions are welcome!
Big changes
===========
Please open a new issue to discuss or propose a major change. Not only is it fun
to discuss big ideas, but we might save each other's time too. Perhaps some of the
work you're contemplating is already half-done in a development branch.
Code style
==========
We use PEP8, ``black`` for code formatting and ``ruff`` for everything else. The
settings for these programs are in ``pyproject.toml``. Pull
requests should follow the style guide. One difference we use from "black" style
is that strings shown to the user are always in double quotes (``"``) and strings
for internal uses are in single quotes (``'``).
Tests
=====
New features should come with tests that confirm their correctness.
New dependencies
================
If you are proposing a change that will require a new dependency, we
prefer dependencies that are already packaged by Debian or Red Hat. This makes
life much easier for our downstream package maintainers. A package that is only
available on PyPI or GitHub, and not more widely packaged, may not be accepted.
We are unlikely to accept a dependency on CUDA or other GPU-based libraries,
because these are still difficult to package and install on many systems.
We recommend implementing these changes as plugins.
Python dependencies must also be license-compatible. GPLv3 or AGPLv3 are likely
incompatible with the project's license, but LGPLv3 is compatible.
New non-Python dependencies
===========================
OCRmyPDF uses several external programs (Tesseract, Ghostscript and others) for
its functionality. In general we prefer to avoid adding new external programs,
and if we are to add external programs, we prefer those that are already
packaged by Debian or Red Hat.
Plugins
=======
Some new features may be a good fit for a plugin. Plugins are a way to add
features to OCRmyPDF without adding them to the core program. Plugins are
installed separately from OCRmyPDF. They are written in Python and can be
installed from PyPI. See the `plugin documentation <https://ocrmypdf.readthedocs.io/en/latest/plugins.html>`_.
We are happy to link users to your plugin from the documentation.
Style guide: Is it OCRmyPDF or ocrmypdf?
========================================
The program/project is OCRmyPDF and the name of the executable or library is ocrmypdf.
Copyright and license
=====================
For contributions over 10 lines of code, please add your name to list of
copyright holders for that file. The core program is licensed under MPL-2.0,
test files and documentation under CC-BY-SA 4.0, and miscellaneous files under
MIT, with a few minor exceptions. Please contribute only content that you own
or have the right to contribute under these licenses.
+369
View File
@@ -0,0 +1,369 @@
% SPDX-FileCopyrightText: 2025 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Cookbook
## Basic examples
### Help!
ocrmypdf has built-in help.
```bash
ocrmypdf --help
```
### Add an OCR layer and convert to PDF/A
```bash
ocrmypdf input.pdf output.pdf
```
### Add an OCR layer and output a standard PDF
```bash
ocrmypdf --output-type pdf input.pdf output.pdf
```
### Create a PDF/A with all color and grayscale images converted to JPEG
```bash
ocrmypdf --output-type pdfa --pdfa-image-compression jpeg input.pdf output.pdf
```
### Modify a file in place
The file will only be overwritten if OCRmyPDF is successful.
```bash
ocrmypdf myfile.pdf myfile.pdf
```
### Correct page rotation
OCR will attempt to automatic correct the rotation of each page. This
can help fix a scanning job that contains a mix of landscape and
portrait pages.
```bash
ocrmypdf --rotate-pages myfile.pdf myfile.pdf
```
You can increase (decrease) the parameter `--rotate-pages-threshold` to
make page rotation more (less) aggressive. The threshold number is the
ratio of how confidence the OCR engine is that the document image should
be changed, compared to kept the same. The default value is quite
conservative; on some files it may not attempt rotations at all unless
it is very confident that the current rotation is wrong. A lower value
of `2.0` will produce more rotations, and more false positives. Run with
`-v1` to see the confidence level for each page to see if there may be a
better value for your files.
If the page is \"just a little off horizontal\", like a crooked picture,
then you want `--deskew`. `--rotate-pages` is for when the cardinal
angle is wrong.
### OCR languages other than English
OCRmyPDF assumes the document is in English unless told otherwise. OCR
quality may be poor if the wrong language is used.
```bash
ocrmypdf -l fra LeParisien.pdf LeParisien.pdf
ocrmypdf -l eng+fra Bilingual-English-French.pdf Bilingual-English-French.pdf
```
Language packs must be installed for all languages specified. See
`Installing additional language packs <lang-packs>`{.interpreted-text
role="ref"}.
Unfortunately, the Tesseract OCR engine has no ability to detect the
language when it is unknown.
### Produce PDF and text file containing OCR text
This produces a file named \"output.pdf\" and a companion text file
named \"output.txt\".
```bash
ocrmypdf --sidecar output.txt input.pdf output.pdf
```
:::{note}
The sidecar file contains the **OCR text** found by OCRmyPDF. If the
document contains pages that already have text, that text will not
appear in the sidecar. If the option `--pages` is used, only those pages
on which OCR was performed will be included in the sidecar. If certain
pages were skipped because of options like `--skip-big` or
`--tesseract-timeout`, those pages will not be in the sidecar.
If you don\'t want to generate the output PDF, use `--output-type=none`
to avoid generating one. Set the output filename to `-` (i.e. redirect
to stdout).
To extract all text from a PDF, whether generated from OCR or otherwise,
use a program like Poppler\'s `pdftotext` or `pdfgrep`.
:::
### OCR images, not PDFs
#### Option: use Tesseract
If you are starting with images, you can just use Tesseract directly to
convert images to PDFs:
```bash
tesseract my-image.jpg output-prefix pdf
```
```bash
# When there are multiple images
tesseract text-file-containing-list-of-image-filenames.txt output-prefix pdf
```
Tesseract\'s PDF output is quite good -- OCRmyPDF uses it internally, in
some cases. However, OCRmyPDF has many features not available in
Tesseract like image processing, metadata control, and PDF/A generation.
#### Option: use img2pdf
You can also use a program like
[img2pdf](https://gitlab.mister-muffin.de/josch/img2pdf) to convert your
images to PDFs, and then pipe the results to run ocrmypdf. The `-` tells
ocrmypdf to read standard input.
```bash
img2pdf my-images*.jpg | ocrmypdf - myfile.pdf
```
`img2pdf` is recommended because it does an excellent job at generating
PDFs without transcoding images.
#### Option: use OCRmyPDF (single images only)
For convenience, OCRmyPDF can also convert single images to PDFs on its
own. If the resolution (dots per inch, DPI) of an image is not set or is
incorrect, it can be overridden with `--image-dpi`. (As 1 inch is 2.54
cm, 1 dpi = 0.39 dpcm).
```bash
ocrmypdf --image-dpi 300 image.png myfile.pdf
```
If you have multiple images, you must use `img2pdf` to convert the
images to PDF.
#### Not recommended
We caution against using ImageMagick or Ghostscript to convert images to
PDF, since they may transcode images or produce downsampled images,
sometimes without warning.
(image-processing)=
## Image processing
OCRmyPDF perform some image processing on each page of a PDF, if
desired. The same processing is applied to each page. It is suggested
that the user review files after image processing as these commands
might remove desirable content, especially from poor quality scans.
- `--rotate-pages` attempts to determine the correct orientation for
each page and rotates the page if necessary.
- `--remove-background` attempts to detect and remove a noisy
background from grayscale or color images. Monochrome images are
ignored. This should not be used on documents that contain color
photos as it may remove them.
- `--deskew` will correct pages that were scanned at a skewed angle by
rotating them back into place.
- `--clean` uses [unpaper](https://www.flameeyes.eu/projects/unpaper)
to clean up pages before OCR, but does not alter the final output.
This makes it less likely that OCR will try to find text in
background noise.
- `--clean-final` uses unpaper to clean up pages before OCR and
inserts the page into the final output. You will want to review each
page to ensure that unpaper did not remove something important.
:::{note}
In many cases image processing will rasterize PDF pages as images,
potentially losing quality.
:::
:::{warning}
`--clean-final` and `--remove-background` may leave undesirable visual
artifacts in some images where their algorithms have shortcomings. Files
should be visually reviewed after using these options.
:::
### Example: OCR and correct document skew (crooked scan)
Deskew:
```bash
ocrmypdf --deskew input.pdf output.pdf
```
Image processing commands can be combined. The order in which options
are given does not matter. OCRmyPDF always applies the steps of the
image processing pipeline in the same order (rotate, remove background,
deskew, clean).
```bash
ocrmypdf --deskew --clean --rotate-pages input.pdf output.pdf
```
Don\'t actually OCR my PDF
--------------------------
If you set `--tesseract-timeout 0` OCRmyPDF will apply its image
processing without performing OCR (by causing OCR to time out). This
works if all you want to is to apply image processing or PDF/A
conversion.
```bash
ocrmypdf --tesseract-timeout=0 --remove-background input.pdf output.pdf
```
:::{versionchanged} v14.1.0
Prior to this version, `--tesseract-timeout 0` would prevent other uses
of Tesseract, such as deskewing, from working. This is no longer the
case. Use `--tesseract-non-ocr-timeout` to control the timeout for
non-OCR operations, if needed.
:::
### Remove all text or OCR from my PDF
This is getting ridiculous, but OCRmyPDF can complete strip all textual
information from a PDF and reconstruct it as a \"bag of images\" PDF.
```bash
ocrmypdf --tesseract-timeout 0 --force-ocr input.pdf output.pdf
```
Why would you want to do this? Perhaps you have a PDF where OCR fails to
produce useful results, and just want to get rid of all OCR information.
This command also removes OCR generated by third party tools.
### Optimize images without performing OCR
You can also optimize all images without performing any OCR:
```bash
ocrmypdf --tesseract-timeout=0 --optimize 3 --skip-text input.pdf output.pdf
```
### Process only certain pages
You can ask OCRmyPDF to only apply [image processing](#image-processing)
and OCR to certain pages.
```bash
ocrmypdf --pages 2,3,13-17 input.pdf output.pdf
```
Hyphens denote a range of pages and commas separate page numbers. If you
prefer to use spaces, quote all of the page numbers:
`--pages '2, 3, 5, 7'`.
OCRmyPDF will warn if your list of page numbers contains duplicates or
overlapping pages. OCRmyPDF does not currently account for document page
numbers, such as an introduction section of a book that uses Roman
numerals. It simply counts the number of virtual pieces of paper since
the start. If your list of pages is out of numerical order, OCRmyPDF
will sort it for you.
Regardless of the argument to `--pages`, OCRmyPDF will optimize all
pages/images in the file and convert it to PDF/A, unless you disable
those options. Both of these steps are \"whole file\" operations. In
this example, we want to OCR only the title and otherwise change the PDF
as little as possible:
```bash
ocrmypdf --pages 1 --output-type pdf --optimize 0 input.pdf output.pdf
```
## Redo existing OCR
To redo OCR on a file OCRed with other OCR software or a previous
version of OCRmyPDF and/or Tesseract, you may use the `--redo-ocr`
argument. (Normally, OCRmyPDF will exit with an error if asked to modify
a file with OCR.)
This may be helpful for users who want to take advantage of accuracy
improvements in Tesseract for files they previously OCRed with an
earlier version of Tesseract and OCRmyPDF.
```bash
ocrmypdf --redo-ocr input.pdf output.pdf
```
This method will replace OCR without rasterizing, reducing quality or
removing vector content. If a file contains a mix of pure digital text
and OCR, digital text will be ignored and OCR will be replaced. As such
this mode is incompatible with image processing options, since they
alter the appearance of the file.
In some cases, existing OCR cannot be detected or replaced. Files
produced by OCRmyPDF v2.2 or earlier, for example, are internally
represented as having visible text with an opaque image drawn on top.
This situation cannot be detected.
If `--redo-ocr` does not work, you can use `--force-ocr`, which will
force rasterization of all pages, potentially reducing quality or losing
vector content.
Improving OCR quality
---------------------
The [Image processing](#image-processing) features can improve OCR
quality.
Rotating pages and deskewing helps to ensure that the page orientation
is correct before OCR begins. Removing the background and/or cleaning
the page can also improve results. The `--oversample DPI` argument can
be specified to resample images to higher resolution before attempting
OCR; this can improve results as well.
OCR quality will suffer if the resolution of input images is not correct
(since the range of pixel sizes that will be checked for possible fonts
will also be incorrect).
## PDF optimization
By default OCRmyPDF will attempt to perform lossless optimizations on
the images inside PDFs after OCR is complete. Optimization is performed
even if no OCR text is found.
The `--optimize N` (short form `-O`) argument controls optimization,
where `N` ranges from 0 to 3 inclusive, analogous to the optimization
levels in the GCC compiler. `-O1` is the default.
For further details, see the section on [PDF optimization](optimizer).
```bash
ocrmypdf --optimize 3 in.pdf out.pdf # Make it small
```
Some users may consider enabling lossy JBIG2. See:
`jbig2-lossy`{.interpreted-text role="ref"}.
:::{note}
Image processing and PDF/A conversion can also introduce lossy
transformations to your PDF images, even when `--optimize 1` is in use.
:::
Digitally signed PDFs
---------------------
OCRmyPDF cannot preserve digital signatures in PDFs and also add OCR to
them. By default, it will refuse to modify a signed PDF regardless of
other settings. You can override this behavior with
`--invalidate-digital-signatures`; as the name suggests, any digital
signatures will be invalidated.
OCRmyPDF cannot open documents that are encrypted with a digital
certificate.
Versions of OCRmyPDF prior to 14.4.0 would invalidate existing digital
signatures without warning.
-410
View File
@@ -1,410 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
========
Cookbook
========
Basic examples
==============
Help!
-----
ocrmypdf has built-in help.
.. code-block:: bash
ocrmypdf --help
Add an OCR layer and convert to PDF/A
-------------------------------------
.. code-block:: bash
ocrmypdf input.pdf output.pdf
Add an OCR layer and output a standard PDF
------------------------------------------
.. code-block:: bash
ocrmypdf --output-type pdf input.pdf output.pdf
Create a PDF/A with all color and grayscale images converted to JPEG
--------------------------------------------------------------------
.. code-block:: bash
ocrmypdf --output-type pdfa --pdfa-image-compression jpeg input.pdf output.pdf
Modify a file in place
----------------------
The file will only be overwritten if OCRmyPDF is successful.
.. code-block:: bash
ocrmypdf myfile.pdf myfile.pdf
Correct page rotation
---------------------
OCR will attempt to automatic correct the rotation of each page. This
can help fix a scanning job that contains a mix of landscape and
portrait pages.
.. code-block:: bash
ocrmypdf --rotate-pages myfile.pdf myfile.pdf
You can increase (decrease) the parameter ``--rotate-pages-threshold``
to make page rotation more (less) aggressive. The threshold number is the ratio
of how confidence the OCR engine is that the document image should be changed,
compared to kept the same. The default value is quite conservative; on some files
it may not attempt rotations at all unless it is very confident that the current
rotation is wrong. A lower value of ``2.0`` will produce more rotations, and
more false positives. Run with ``-v1`` to see the confidence level for each
page to see if there may be a better value for your files.
If the page is "just a little off horizontal", like a crooked picture,
then you want ``--deskew``. ``--rotate-pages`` is for when the cardinal
angle is wrong.
OCR languages other than English
--------------------------------
OCRmyPDF assumes the document is in English unless told otherwise. OCR
quality may be poor if the wrong language is used.
.. code-block:: bash
ocrmypdf -l fra LeParisien.pdf LeParisien.pdf
ocrmypdf -l eng+fra Bilingual-English-French.pdf Bilingual-English-French.pdf
Language packs must be installed for all languages specified. See
:ref:`Installing additional language packs <lang-packs>`.
Unfortunately, the Tesseract OCR engine has no ability to detect the
language when it is unknown.
Produce PDF and text file containing OCR text
---------------------------------------------
This produces a file named "output.pdf" and a companion text file named
"output.txt".
.. code-block:: bash
ocrmypdf --sidecar output.txt input.pdf output.pdf
.. note::
The sidecar file contains the **OCR text** found by OCRmyPDF. If the document
contains pages that already have text, that text will not appear in the
sidecar. If the option ``--pages`` is used, only those pages on which OCR
was performed will be included in the sidecar. If certain pages were skipped
because of options like ``--skip-big`` or ``--tesseract-timeout``, those pages
will not be in the sidecar.
If you don't want to generate the output PDF, use ``--output-type=none`` to
avoid generating one. Set the output filename to ``-`` (i.e. redirect to stdout).
To extract all text from a PDF, whether generated from OCR or otherwise,
use a program like Poppler's ``pdftotext`` or ``pdfgrep``.
OCR images, not PDFs
--------------------
Option: use Tesseract
~~~~~~~~~~~~~~~~~~~~~
If you are starting with images, you can just use Tesseract directly to
convert images to PDFs:
.. code-block:: bash
tesseract my-image.jpg output-prefix pdf
.. code-block:: bash
# When there are multiple images
tesseract text-file-containing-list-of-image-filenames.txt output-prefix pdf
Tesseract's PDF output is quite good  OCRmyPDF uses it internally, in
some cases. However, OCRmyPDF has many features not available in
Tesseract like image processing, metadata control, and PDF/A generation.
Option: use img2pdf
~~~~~~~~~~~~~~~~~~~
You can also use a program like
`img2pdf <https://gitlab.mister-muffin.de/josch/img2pdf>`__ to convert
your images to PDFs, and then pipe the results to run ocrmypdf. The
``-`` tells ocrmypdf to read standard input.
.. code-block:: bash
img2pdf my-images*.jpg | ocrmypdf - myfile.pdf
``img2pdf`` is recommended because it does an excellent job at
generating PDFs without transcoding images.
Option: use OCRmyPDF (single images only)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For convenience, OCRmyPDF can also convert single images to PDFs on its
own. If the resolution (dots per inch, DPI) of an image is not set or is
incorrect, it can be overridden with ``--image-dpi``. (As 1 inch is 2.54
cm, 1 dpi = 0.39 dpcm).
.. code-block:: bash
ocrmypdf --image-dpi 300 image.png myfile.pdf
If you have multiple images, you must use ``img2pdf`` to convert the
images to PDF.
Not recommended
~~~~~~~~~~~~~~~
We caution against using ImageMagick or Ghostscript to convert images to
PDF, since they may transcode images or produce downsampled images,
sometimes without warning.
Image processing
================
OCRmyPDF perform some image processing on each page of a PDF, if
desired. The same processing is applied to each page. It is suggested
that the user review files after image processing as these commands
might remove desirable content, especially from poor quality scans.
- ``--rotate-pages`` attempts to determine the correct orientation for
each page and rotates the page if necessary.
- ``--remove-background`` attempts to detect and remove a noisy
background from grayscale or color images. Monochrome images are
ignored. This should not be used on documents that contain color
photos as it may remove them.
- ``--deskew`` will correct pages that were scanned at a skewed angle by
rotating them back into place.
- ``--clean`` uses
`unpaper <https://www.flameeyes.eu/projects/unpaper>`__ to clean up
pages before OCR, but does not alter the final output. This makes it
less likely that OCR will try to find text in background noise.
- ``--clean-final`` uses unpaper to clean up pages before OCR and
inserts the page into the final output. You will want to review each
page to ensure that unpaper did not remove something important.
.. note::
In many cases image processing will rasterize PDF pages as images,
potentially losing quality.
.. warning::
``--clean-final`` and ``--remove-background`` may leave undesirable
visual artifacts in some images where their algorithms have
shortcomings. Files should be visually reviewed after using these
options.
Example: OCR and correct document skew (crooked scan)
-----------------------------------------------------
Deskew:
.. code-block:: bash
ocrmypdf --deskew input.pdf output.pdf
Image processing commands can be combined. The order in which options
are given does not matter. OCRmyPDF always applies the steps of the
image processing pipeline in the same order (rotate, remove background,
deskew, clean).
.. code-block:: bash
ocrmypdf --deskew --clean --rotate-pages input.pdf output.pdf
Don't actually OCR my PDF
=========================
If you set ``--tesseract-timeout 0`` OCRmyPDF will apply its image
processing without performing OCR (by causing OCR to time out). This works
if all you want to is to apply image processing or PDF/A conversion.
.. code-block:: bash
ocrmypdf --tesseract-timeout=0 --remove-background input.pdf output.pdf
.. versionchanged:: v14.1.0
Prior to this version, ``--tesseract-timeout 0`` would prevent other
uses of Tesseract, such as deskewing, from working. This is no longer
the case. Use ``--tesseract-non-ocr-timeout`` to control the timeout
for non-OCR operations, if needed.
Remove all text or OCR from my PDF
----------------------------------
This is getting ridiculous, but OCRmyPDF can complete strip all textual
information from a PDF and reconstruct it as a "bag of images" PDF.
.. code-block::
ocrmypdf --tesseract-timeout 0 --force-ocr input.pdf output.pdf
Why would you want to do this? Perhaps you have a PDF where OCR
fails to produce useful results, and just want to get rid of all OCR information.
This command also removes OCR generated by third party tools.
Optimize images without performing OCR
--------------------------------------
You can also optimize all images without performing any OCR:
.. code-block:: bash
ocrmypdf --tesseract-timeout=0 --optimize 3 --skip-text input.pdf output.pdf
Process only certain pages
--------------------------
You can ask OCRmyPDF to only apply `image processing <#image-processing>`__
and OCR to certain pages.
.. code-block:: bash
ocrmypdf --pages 2,3,13-17 input.pdf output.pdf
Hyphens denote a range of pages and commas separate page numbers. If you prefer
to use spaces, quote all of the page numbers: ``--pages '2, 3, 5, 7'``.
OCRmyPDF will warn if your list of page numbers contains duplicates or
overlapping pages. OCRmyPDF does not currently account for document page numbers,
such as an introduction section of a book that uses Roman numerals. It simply
counts the number of virtual pieces of paper since the start. If your list of
pages is out of numerical order, OCRmyPDF will sort it for you.
Regardless of the argument to ``--pages``, OCRmyPDF will optimize all pages/images
in the file and convert it to PDF/A, unless you disable those options. Both of these
steps are "whole file" operations. In this example, we want to OCR only the title
and otherwise change the PDF as little as possible:
.. code-block:: bash
ocrmypdf --pages 1 --output-type pdf --optimize 0 input.pdf output.pdf
Redo existing OCR
=================
To redo OCR on a file OCRed with other OCR software or a previous
version of OCRmyPDF and/or Tesseract, you may use the ``--redo-ocr``
argument. (Normally, OCRmyPDF will exit with an error if asked to modify
a file with OCR.)
This may be helpful for users who want to take advantage of accuracy
improvements in Tesseract for files they previously OCRed with an
earlier version of Tesseract and OCRmyPDF.
.. code-block:: bash
ocrmypdf --redo-ocr input.pdf output.pdf
This method will replace OCR without rasterizing, reducing quality or
removing vector content. If a file contains a mix of pure digital text
and OCR, digital text will be ignored and OCR will be replaced. As such
this mode is incompatible with image processing options, since they
alter the appearance of the file.
In some cases, existing OCR cannot be detected or replaced. Files
produced by OCRmyPDF v2.2 or earlier, for example, are internally
represented as having visible text with an opaque image drawn on top.
This situation cannot be detected.
If ``--redo-ocr`` does not work, you can use ``--force-ocr``, which will
force rasterization of all pages, potentially reducing quality or losing
vector content.
Improving OCR quality
=====================
The `Image processing <#image-processing>`__ features can improve OCR
quality.
Rotating pages and deskewing helps to ensure that the page orientation
is correct before OCR begins. Removing the background and/or cleaning
the page can also improve results. The ``--oversample DPI`` argument can
be specified to resample images to higher resolution before attempting
OCR; this can improve results as well.
OCR quality will suffer if the resolution of input images is not correct
(since the range of pixel sizes that will be checked for possible fonts
will also be incorrect).
PDF optimization
================
By default OCRmyPDF will attempt to perform lossless optimizations on
the images inside PDFs after OCR is complete. Optimization is performed
even if no OCR text is found.
The ``--optimize N`` (short form ``-O``) argument controls optimization,
where ``N`` ranges from 0 to 3 inclusive, analogous to the optimization
levels in the GCC compiler.
.. list-table::
:widths: auto
:header-rows: 1
* - Level
- Comments
* - ``--optimize 0``
- Disables optimization.
* - ``--optimize 1``
- Enables lossless optimizations, such as transcoding images to more
efficient formats. Also compress other uncompressed objects in the
PDF and enables the more efficient "object streams" within the PDF.
(If ``--jbig2-lossy`` is issued, then lossy JBIG2 optimization is used.
The decision to use lossy JBIG2 is separate from standard optimization
settings.)
* - ``--optimize 2``
- All of the above, and enables lossy optimizations and color quantization.
* - ``--optimize 3``
- All of the above, and enables more aggressive optimizations and targets lower image quality.
Optimization is improved when a JBIG2 encoder is available and when
``pngquant`` is installed. If either of these components are missing,
then some types of images cannot be optimized.
The types of optimization available may expand over time. By default,
OCRmyPDF compresses data streams inside PDFs, and will change
inefficient compression modes to more modern versions. A program like
``qpdf`` can be used to change encodings, e.g. to inspect the internals
for a PDF.
.. code-block:: bash
ocrmypdf --optimize 3 in.pdf out.pdf # Make it small
Some users may consider enabling lossy JBIG2. See: :ref:`jbig2-lossy`.
.. note::
Image processing and PDF/A conversion can also introduce lossy transformations
to your PDF images, even when ``--optimize 1`` is in use.
Digitally signed PDFs
=====================
OCRmyPDF cannot preserve digital signatures in PDFs and also add OCR to them.
By default, it will refuse to modify a signed PDF regardless of other settings. You can
override this behavior with ``--invalidate-digital-signatures``; as the name suggests,
any digital signatures will be invalidated.
OCRmyPDF cannot open documents that are encrypted with a digital certificate.
Versions of OCRmyPDF prior to 14.4.0 would invalidate existing digital signatures
without warning.
+30
View File
@@ -0,0 +1,30 @@
% SPDX-FileCopyrightText: 2023 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Design notes
## Why doesn\'t OCRmyPDF use PyTesseract?
PyTesseract is a Python wrapper around the Tesseract OCR engine. When
OCRmyPDF was first written, PyTesseract used ABI bindings to call the
Tesseract library. This was not a good fit for OCRmyPDF because ABI
bindings can be fragile.
PyTesseract has since evolved calling the Tesseract executable,
abandoning the ABI approach and using the CLI instead, just like
OCRmyPDF does. If it were written from scratch today, OCRmyPDF might use
PyTesseract.
PyTesseract has more features don\'t particularly need PDF output, but
less features than OCRmyPDF\'s API for creating PDFs.
## What is `executor()`?
OCRmyPDF uses a custom concurrent executor which can support either
threads or processes with the same interface. This is useful because
OCRmyPDF can use either threads or processes to parallelize work,
whichever is more appropriate for the task at hand.
The interface is currently private and subject to change. In particular,
if experiments with asyncio and anyio are successful, the interface will
change.
-32
View File
@@ -1,32 +0,0 @@
.. SPDX-FileCopyrightText: 2023 James R. Barlow
.. SPDX-License-Identifier: CC-BY-SA-4.0
============
Design notes
============
Why doesn't OCRmyPDF use PyTesseract?
=====================================
PyTesseract is a Python wrapper around the Tesseract OCR engine. When OCRmyPDF was
first written, PyTesseract used ABI bindings to call the Tesseract library. This
was not a good fit for OCRmyPDF because ABI bindings can be fragile.
PyTesseract has since evolved calling the Tesseract executable, abandoning the ABI
approach and using the CLI instead, just like OCRmyPDF does. If it were written from
scratch today, OCRmyPDF might use PyTesseract.
PyTesseract has more features don't particularly need PDF output, but less features
than OCRmyPDF's API for creating PDFs.
What is ``executor()``?
=======================
OCRmyPDF uses a custom concurrent executor which can support either threads or
processes with the same interface. This is useful because OCRmyPDF can use
either threads or processes to parallelize work, whichever is more appropriate
for the task at hand.
The interface is currently private and subject to change. In particular, if
experiments with asyncio and anyio are successful, the interface will change.
+245
View File
@@ -0,0 +1,245 @@
# OCRmyPDF Docker image {#docker}
OCRmyPDF is also available in Docker images that packages recent
versions of all dependencies.
For users who already have Docker installed this may be an easy and
convenient option.
On platforms other than Linux, Docker runs in a virtual machine, and so
may be less performant. You may also want to adjust the Docker virtual
machine\'s memory and CPU allocation. On Linux, the Docker image runs
natively and performance is comparable to a system installation.
{#docker-install}
## Installing the Docker image
If you have [Docker](https://docs.docker.com/) installed on your system,
you can install a Docker image of the latest release.
If you can run this command successfully, your system is ready to
download and execute the image:
:::{code} bash
docker run hello-world
:::
:::{list-table} Docker Images
:header-rows: 1
* - Image
- Architecture
- Description
* - `jbarlow83/ocrmypdf-alpine`
- x86_64 and arm64
- Recommended image, based on Alpine Linux.
* - `jbarlow83/ocrmypdf-ubuntu`
- x86_64 and arm64
- Alternate image, based on Ubuntu. When the Alpine image is considered stable and available for arm64, this image will be deprecated.
* - `jbarlow83/ocrmypdf`
- x86_64 and arm64
- Currently an alias for ocrmypdf-ubuntu. When the Alpine image is considered stable and available for arm64, this name will point to the Alpine image. If you don\'t know about the difference between Alpine and Ubuntu, use this image.
:::
To install:
:::{code} bash
docker pull jbarlow83/ocrmypdf-alpine
:::
The `ocrmypdf` image is also available, but is deprecated and will be
removed in the future.
OCRmyPDF will use all available CPU cores. See the Docker documentation
for [adjusting memory and CPU on other
platforms](https://docs.docker.com/config/containers/resource_constraints/)
if you are using Docker on macOS or Windows, where you may need to
manually assign more resources. On Linux, all resources will be
available automatically.
The underlying operating system and other details in Docker images are
considered implementation details and **subject to change at minor
releases**. If you are modifying the image, you should pin the version
you intend to use.
## Using the Docker image on the command line
**Unlike typical Docker containers**, in this section the OCRmyPDF
Docker container is ephemeral -- it runs for one OCR job and terminates,
just like a command line program. We are using Docker to deliver an
application (as opposed to the more conventional case, where a Docker
container runs as a server). For that reason we usually use the `--rm`
argument to delete the container when it exits.
To start a Docker container (instance of the image):
:::{code} bash
docker run --rm -i jbarlow83/ocrmypdf-alpine (... all other arguments here...) - -
:::
For convenience, create a shell alias to hide the Docker command. It is
easier to send the input file as stdin and read the output from stdout
-- **this avoids the messy permission issues with Docker entirely**.
:::{code} bash
alias docker_ocrmypdf='docker run --rm -i jbarlow83/ocrmypdf-alpine'
docker_ocrmypdf --version # runs docker version
docker_ocrmypdf - - <input.pdf >output.pdf
:::
Or in the wonderful [fish shell](https://fishshell.com/):
:::{code} fish
alias docker_ocrmypdf 'docker run --rm jbarlow83/ocrmypdf-alpine'
funcsave docker_ocrmypdf
:::
Alternately, you could mount the local current working directory as a
Docker volume:
:::{code} bash
alias docker_ocrmypdf='docker run --rm -i --user "$(id -u):$(id -g)" --workdir /data -v "$PWD:/data" jbarlow83/ocrmypdf-alpine'
docker_ocrmypdf /data/input.pdf /data/output.pdf
:::
## Podman
Especially if you use [Podman](https://podman.io/) (or have SELinux
enabled on your system), you may need to add `--userns keep-id` there,
otherwise you may get access errors, because the user is otherwise not
mapped to the same UID as on the host:
:::{code} bash
alias podman_ocrmypdf='podman run --rm -i --user "$(id -u):$(id -g)" --userns keep-id --workdir /data -v "$PWD:/data" ocrmypdf'
podman_ocrmypdf /data/input.pdf /data/output.pdf
:::
If you use SELinux you may additionally need to add the `:Z` [suffix to
the
volume](https://docs.podman.io/en/stable/markdown/podman-run.1.html#volume-v-source-volume-host-dir-container-dir-options)
or disable SELinux for the container using
`--security-opt label=disable`, which is suggested for system files as
they should not be re-labelled. Please refer to the „Note" section at
the end of the linked podman documentation for details.
{#docker-lang-packs}
## Adding languages to the Docker image
By default the Docker image includes English, German, Simplified
Chinese, French, Portuguese and Spanish, the most popular languages for
OCRmyPDF users based on feedback. You may add other languages by
creating a new Dockerfile based on the public one.
:::{code} dockerfile
FROM jbarlow83/ocrmypdf
# Example: add Italian
RUN apt install tesseract-ocr-ita
:::
To install language packs (training data) such as the
[tessdata\_best](https://github.com/tesseract-ocr/tessdata_best) suite
or custom data, you first need to determine the version of Tesseract
data files, which may differ from the Tesseract program version. Use
this command to determine the data file version:
:::{code} bash
docker run -i --rm --entrypoint /bin/ls jbarlow83/ocrmypdf /usr/share/tesseract-ocr
:::
As of 2021, the data file version is probably `4.00`.
You can then add new data with either a Dockerfile:
:::{code} dockerfile
FROM jbarlow83/ocrmypdf:{TAG}
# Example: add a tessdata_best file
COPY chi_tra_vert.traineddata /usr/share/tesseract-ocr/<data version>/tessdata/
:::
When creating your own image, you should always pin a specific version
of the OCRmyPDF Docker image. This ensures that your image will not
break when a new version of OCRmyPDF is released.
Alternately, you can copy training data into a Docker container as
follows:
:::{code} bash
docker cp mycustomtraining.traineddata name_of_container:/usr/share/tesseract-ocr/<tesseract version>/tessdata/
:::
Extending the Docker image
--------------------------
You can extend the Docker image with your own customizations, similar to
the way it is extended to add language packs.
Note that the Docker image is subject to change at any time. For
example, the base image may be updated to a newer version of Ubuntu or
Debian. Such changes will be noted in the release notes but might occur
at minor versions releases, unless the way a \"casual\" user of the
Docker image is affected.
If you extend the Docker image, you should pin a specific version of the
OCRmyPDF Docker image.
Executing the test suite
------------------------
The OCRmyPDF test suite is installed with image. To run it:
:::{code} bash
docker run --rm --entrypoint python jbarlow83/ocrmypdf -m pytest
:::
Accessing the shell
-------------------
To use the shell in the Docker image:
:::{code} bash
docker run -it --entrypoint sh jbarlow83/ocrmypdf
:::
Using the OCRmyPDF web service wrapper
--------------------------------------
The OCRmyPDF Docker image includes an example, barebones HTTP web
service. The webservice may be launched as follows:
:::{code} bash
docker run --entrypoint python -p 5000:5000 jbarlow83/ocrmypdf webservice.py
:::
We omit the `--rm` parameter so that the container will not be
automatically deleted when it exits.
This will configure the machine to listen on port 5000. On Linux
machines this is port 5000 of localhost. On macOS or Windows machines
running Docker, this is port 5000 of the virtual machine that runs your
Docker images. You can find its IP address using the command
`docker-machine ip`.
Unlike command line usage this program will open a socket and wait for
connections.
:::{warning}
The OCRmyPDF web service wrapper is intended for demonstration or
development. It provides no security, no authentication, no protection
against denial of service attacks, and no load balancing. The default
Flask WSGI server is used, which is intended for development only. The
server is single-threaded and so can respond to only one client at a
time. While running OCR, it cannot respond to any other clients.
:::
Clients must keep their open connection while waiting for OCR to
complete. This may entail setting a long timeout; this interface is more
useful for internal HTTP API calls.
Unlike the rest of OCRmyPDF, this web service is licensed under the
Affero GPLv3 (AGPLv3) since Ghostscript is also licensed in this way.
In addition to the above, please read our
`general remarks on using OCRmyPDF as a service <ocr-service>`{.interpreted-text
role="ref"}.
-254
View File
@@ -1,254 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
.. _docker:
=====================
OCRmyPDF Docker image
=====================
OCRmyPDF is also available in Docker images that packages recent
versions of all dependencies.
For users who already have Docker installed this may be an easy and
convenient option.
On platforms other than Linux, Docker runs in a virtual machine, and so may
be less performant. You may also want to adjust the Docker virtual machine's
memory and CPU allocation. On Linux, the Docker image runs natively and
performance is comparable to a system installation.
.. _docker-install:
Installing the Docker image
===========================
If you have `Docker <https://docs.docker.com/>`__ installed on your
system, you can install a Docker image of the latest release.
If you can run this command successfully, your system is ready to download and
execute the image:
.. code-block:: bash
docker run hello-world
.. list-table:: Docker images
:widths: 30 20 50
:header-rows: 1
* - Image
- Architecture
- Description
* - ``jbarlow83/ocrmypdf-alpine``
- x86_64 and arm64
- Recommended image, based on Alpine Linux.
* - ``jbarlow83/ocrmypdf-ubuntu``
- x86_64 and arm64
- Alternate image, based on Ubuntu. When the Alpine image is considered
stable and available for arm64, this image will be deprecated.
* - ``jbarlow83/ocrmypdf``
- x86_64 and arm64
- Currently an alias for ocrmypdf-ubuntu. When the Alpine image is
considered stable and available for arm64, this name point to the
Alpine image. If you don't about the difference between Alpine and
Ubuntu, use this image.
To install:
.. code-block:: bash
docker pull jbarlow83/ocrmypdf-alpine
The ``ocrmypdf`` image is also available, but is deprecated and will be removed
in the future.
OCRmyPDF will use all available CPU cores. See the Docker documentation for
`adjusting memory and CPU on other platforms <https://docs.docker.com/config/containers/resource_constraints/>`__
if you are using Docker on macOS or Windows, where you may need to manually assign
more resources. On Linux, all resources will be available automatically.
The underlying operating system and other details in Docker images are considered
implementation details and **subject to change at minor releases**. If you are
modifying the image, you should pin the version you intend to use.
Using the Docker image on the command line
==========================================
**Unlike typical Docker containers**, in this section the OCRmyPDF Docker
container is ephemeral it runs for one OCR job and terminates, just like a
command line program. We are using Docker to deliver an application (as opposed
to the more conventional case, where a Docker container runs as a server).
For that reason we usually use the ``--rm`` argument to delete the container
when it exits.
To start a Docker container (instance of the image):
.. code-block:: bash
docker run --rm -i jbarlow83/ocrmypdf-alpine (... all other arguments here...) - -
For convenience, create a shell alias to hide the Docker command. It is
easier to send the input file as stdin and read the output from
stdout **this avoids the messy permission issues with Docker entirely**.
.. code-block:: bash
alias docker_ocrmypdf='docker run --rm -i jbarlow83/ocrmypdf-alpine'
docker_ocrmypdf --version # runs docker version
docker_ocrmypdf - - <input.pdf >output.pdf
Or in the wonderful `fish shell <https://fishshell.com/>`__:
.. code-block:: fish
alias docker_ocrmypdf 'docker run --rm jbarlow83/ocrmypdf-alpine'
funcsave docker_ocrmypdf
Alternately, you could mount the local current working directory as a
Docker volume:
.. code-block:: bash
alias docker_ocrmypdf='docker run --rm -i --user "$(id -u):$(id -g)" --workdir /data -v "$PWD:/data" jbarlow83/ocrmypdf-alpine'
docker_ocrmypdf /data/input.pdf /data/output.pdf
Podman
======
Especially if you use `Podman <https://podman.io/>`__ (or have SELinux enabled on your
system), you may need to add ``--userns keep-id`` there, otherwise you may get access
errors, because the user is otherwise not mapped to the same UID as on the host:
.. code-block:: bash
alias podman_ocrmypdf='podman run --rm -i --user "$(id -u):$(id -g)" --userns keep-id --workdir /data -v "$PWD:/data" ocrmypdf'
podman_ocrmypdf /data/input.pdf /data/output.pdf
If you use SELinux you may additionally need to add the ``:Z`` `suffix to the volume
<https://docs.podman.io/en/stable/markdown/podman-run.1.html#volume-v-source-volume-host-dir-container-dir-options>`__
or disable SELinux for the container using ``--security-opt label=disable``, which is
suggested for system files as they should not be re-labelled. Please refer to the „Note”
section at the end of the linked podman documentation for details.
.. _docker-lang-packs:
Adding languages to the Docker image
====================================
By default the Docker image includes English, German, Simplified Chinese,
French, Portuguese and Spanish, the most popular languages for OCRmyPDF
users based on feedback. You may add other languages by creating a new
Dockerfile based on the public one.
.. code-block:: dockerfile
FROM jbarlow83/ocrmypdf
# Example: add Italian
RUN apt install tesseract-ocr-ita
To install language packs (training data) such as the
`tessdata_best <https://github.com/tesseract-ocr/tessdata_best>`_ suite or
custom data, you first need to determine the version of Tesseract data files, which
may differ from the Tesseract program version. Use this command to determine the data
file version:
.. code-block:: bash
docker run -i --rm --entrypoint /bin/ls jbarlow83/ocrmypdf /usr/share/tesseract-ocr
As of 2021, the data file version is probably ``4.00``.
You can then add new data with either a Dockerfile:
.. code-block:: dockerfile
FROM jbarlow83/ocrmypdf:{TAG}
# Example: add a tessdata_best file
COPY chi_tra_vert.traineddata /usr/share/tesseract-ocr/<data version>/tessdata/
When creating your own image, you should always pin a specific version of the
OCRmyPDF Docker image. This ensures that your image will not break when a new
version of OCRmyPDF is released.
Alternately, you can copy training data into a Docker container as follows:
.. code-block:: bash
docker cp mycustomtraining.traineddata name_of_container:/usr/share/tesseract-ocr/<tesseract version>/tessdata/
Extending the Docker image
==========================
You can extend the Docker image with your own customizations, similar to the way
it is extended to add language packs.
Note that the Docker image is subject to change at any time. For example, the base
image may be updated to a newer version of Ubuntu or Debian. Such changes will be
noted in the release notes but might occur at minor versions releases, unless the
way a "casual" user of the Docker image is affected.
If you extend the Docker image, you should pin a specific version of the OCRmyPDF
Docker image.
Executing the test suite
========================
The OCRmyPDF test suite is installed with image. To run it:
.. code-block:: bash
docker run --rm --entrypoint python jbarlow83/ocrmypdf -m pytest
Accessing the shell
===================
To use the shell in the Docker image:
.. code-block:: bash
docker run -it --entrypoint sh jbarlow83/ocrmypdf
Using the OCRmyPDF web service wrapper
======================================
The OCRmyPDF Docker image includes an example, barebones HTTP web
service. The webservice may be launched as follows:
.. code-block:: bash
docker run --entrypoint python -p 5000:5000 jbarlow83/ocrmypdf webservice.py
We omit the ``--rm`` parameter so that the container will not be
automatically deleted when it exits.
This will configure the machine to listen on port 5000. On Linux machines
this is port 5000 of localhost. On macOS or Windows machines running
Docker, this is port 5000 of the virtual machine that runs your Docker
images. You can find its IP address using the command ``docker-machine ip``.
Unlike command line usage this program will open a socket and wait for
connections.
.. warning::
The OCRmyPDF web service wrapper is intended for demonstration or
development. It provides no security, no authentication, no
protection against denial of service attacks, and no load balancing.
The default Flask WSGI server is used, which is intended for
development only. The server is single-threaded and so can respond to
only one client at a time. While running OCR, it cannot respond to
any other clients.
Clients must keep their open connection while waiting for OCR to
complete. This may entail setting a long timeout; this interface is more
useful for internal HTTP API calls.
Unlike the rest of OCRmyPDF, this web service is licensed under the
Affero GPLv3 (AGPLv3) since Ghostscript is also licensed in this way.
In addition to the above, please read our
:ref:`general remarks on using OCRmyPDF as a service <ocr-service>`.
+51
View File
@@ -0,0 +1,51 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Common error messages
## Page already has text
:::{code}
ERROR - 1: page already has text! aborting (use --force-ocr to force OCR)
:::
You ran ocrmypdf on a file that already contains printable text or a
hidden OCR text layer (it can\'t quite tell the difference). You
probably don\'t want to do this, because the file is already searchable.
As the error message suggests, your options are:
- `ocrmypdf --force-ocr` to
`rasterize <raster-vector>`{.interpreted-text role="ref"} all vector
content and run OCR on the images. This is useful if a previous OCR
program failed, or if the document contains a text watermark.
- `ocrmypdf --skip-text` to skip OCR and other processing on any pages
that contain text. Text pages will be copied into the output PDF
without modification.
- `ocrmypdf --redo-ocr` to scan the file for any existing OCR
(non-printing text), remove it, and do OCR again. This is one way to
take advantage of improvements in OCR accuracy. Printable vector
text is excluded from OCR, so this can be used on files that contain
a mix of digital and scanned files.
## Input file \'filename\' is not a valid PDF
OCRmyPDF checks files with pikepdf, a library that in turn uses libqpdf
to fixes errors in PDFs, before it tries to work on them. In most cases
this happens because the PDF is corrupt and truncated (incomplete file
copying) and not much can be done.
You can try rewriting the file with Ghostscript:
:::{code} bash
gs -o output.pdf -dSAFER -sDEVICE=pdfwrite input.pdf
:::
`pdftk` can also rewrite PDFs:
:::{code} bash
pdftk input.pdf cat output output.pdf
:::
Sometimes Acrobat can repair PDFs with its [Preflight
tool](https://helpx.adobe.com/acrobat/using/correcting-problem-areas-preflight-tool.html).
-57
View File
@@ -1,57 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
=====================
Common error messages
=====================
Page already has text
=====================
.. code-block::
ERROR - 1: page already has text! aborting (use --force-ocr to force OCR)
You ran ocrmypdf on a file that already contains printable text or a
hidden OCR text layer (it can't quite tell the difference). You probably
don't want to do this, because the file is already searchable.
As the error message suggests, your options are:
- ``ocrmypdf --force-ocr`` to :ref:`rasterize <raster-vector>` all
vector content and run OCR on the images. This is useful if a
previous OCR program failed, or if the document contains a text
watermark.
- ``ocrmypdf --skip-text`` to skip OCR and other processing on any
pages that contain text. Text pages will be copied into the output
PDF without modification.
- ``ocrmypdf --redo-ocr`` to scan the file for any existing OCR
(non-printing text), remove it, and do OCR again. This is one way
to take advantage of improvements in OCR accuracy. Printable vector
text is excluded from OCR, so this can be used on files that contain
a mix of digital and scanned files.
Input file 'filename' is not a valid PDF
========================================
OCRmyPDF checks files with pikepdf, a library that in turn uses libqpdf to fixes
errors in PDFs, before it tries to work on them. In most cases this happens
because the PDF is corrupt and truncated (incomplete file copying) and not much
can be done.
You can try rewriting the file with Ghostscript:
.. code-block:: bash
gs -o output.pdf -dSAFER -sDEVICE=pdfwrite input.pdf
``pdftk`` can also rewrite PDFs:
.. code-block:: bash
pdftk input.pdf cat output output.pdf
Sometimes Acrobat can repair PDFs with its `Preflight
tool <https://helpx.adobe.com/acrobat/using/correcting-problem-areas-preflight-tool.html>`__.
+57
View File
@@ -0,0 +1,57 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# OCRmyPDF documentation
:::{figure} images/logo.svg
:::
OCRmyPDF adds an optical character recognition (OCR) text layer to scanned PDF
files, allowing them to be searched.
PDF is the best format for storing and exchanging scanned documents.
Unfortunately, PDFs can be difficult to modify. OCRmyPDF makes it easy to apply
image processing and OCR (recognized, searchable text) to existing PDFs.
```{toctree}
:maxdepth: 1
introduction
release_notes
installation
languages
jbig2
```
```{toctree}
:caption: Usage
:maxdepth: 2
cookbook
optimizer
docker
advanced
batch
cloud
performance
pdfsecurity
errors
```
```{toctree}
:caption: Developers
:maxdepth: 2
api
plugins
apiref
design_notes
contributing
maintainers
```
# Indices and tables
- {ref}`genindex`
- {ref}`modindex`
- {ref}`search`
-56
View File
@@ -1,56 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
OCRmyPDF documentation
======================
.. figure:: images/logo.svg
OCRmyPDF adds an optical character recognition (OCR) text layer to scanned PDF
files, allowing them to be searched.
PDF is the best format for storing and exchanging scanned documents.
Unfortunately, PDFs can be difficult to modify. OCRmyPDF makes it easy to apply
image processing and OCR (recognized, searchable text) to existing PDFs.
.. toctree::
:maxdepth: 1
introduction
release_notes
installation
languages
jbig2
.. toctree::
:caption: Usage
:maxdepth: 2
cookbook
optimizer
docker
advanced
batch
cloud
performance
pdfsecurity
errors
.. toctree::
:caption: Developers
:maxdepth: 2
api
plugins
apiref
design_notes
contributing
maintainers
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+730
View File
@@ -0,0 +1,730 @@
---
myst:
substitutions:
deb_11: |-
:::{image} https://repology.org/badge/version-for-repo/debian_11/ocrmypdf.svg
:alt: Debian 11
:::
deb_12: |-
:::{image} https://repology.org/badge/version-for-repo/debian_12/ocrmypdf.svg
:alt: Debian 12
:::
deb_unstable: |-
:::{image} https://repology.org/badge/version-for-repo/debian_unstable/ocrmypdf.svg
:alt: Debian unstable
:::
fedora_38: |-
:::{image} https://repology.org/badge/version-for-repo/fedora_38/ocrmypdf.svg
:alt: Fedora 38
:::
fedora_39: |-
:::{image} https://repology.org/badge/version-for-repo/fedora_39/ocrmypdf.svg
:alt: Fedora 39
:::
fedora_rawhide: |-
:::{image} https://repology.org/badge/version-for-repo/fedora_rawhide/ocrmypdf.svg
:alt: Fedore Rawhide
:::
latest: |-
:::{image} https://img.shields.io/pypi/v/ocrmypdf.svg
:alt: OCRmyPDF latest released version on PyPI
:::
ubu_2004: |-
:::{image} https://repology.org/badge/version-for-repo/ubuntu_20_04/ocrmypdf.svg
:alt: Ubuntu 20.04 LTS
:::
ubu_2204: |-
:::{image} https://repology.org/badge/version-for-repo/ubuntu_22_04/ocrmypdf.svg
:alt: Ubuntu 22.04 LTS
:::
---
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Installing OCRmyPDF
(latest)=
The easiest way to install OCRmyPDF is to follow the steps for your operating
system/platform. This version may be out of date, however.
These platforms have one-liner installs:
:::{list-table}
:header-rows: 0
* - Debian, Ubuntu
- ``apt install ocrmypdf``
* - Windows Subsystem for Linux
- ``apt install ocrmypdf``
* - Fedora
- ``dnf install ocrmypdf tesseract-osd``
* - macOS (Homebrew)
- ``brew install ocrmypdf``
* - macOS (MacPorts)
- ``port install ocrmypdf``
* - LinuxBrew
- ``brew install ocrmypdf``
* - FreeBSD
- ``pkg install textproc/py-ocrmypdf``
* - Snap (snapcraft packaging)
- ``snap install ocrmypdf``
:::
More detailed procedures are outlined below. If you want to do a manual
install, or install a more recent version than your platform provides, read on.
:::{contents} Platform-specific steps
:depth: 2
:local: true
:::
## Installing on Linux
### Debian and Ubuntu 20.04 or newer
:::{list-table}
:header-rows: 1
* - OCRmyPDF versions in Debian & Ubuntu
* - {{ latest }}
* - {{ deb_11 }} {{ deb_12 }} {{ deb_unstable }}
* - {{ ubu_2004 }} {{ ubu_2204 }}
:::
Users of Debian or Ubuntu may simply
```bash
apt install ocrmypdf
```
As indicated in the table above, Debian and Ubuntu releases may lag
behind the latest version. If the version available for your platform is
out of date, you could opt to install the latest version from source.
See [Installing HEAD revision from
sources](#installing-head-revision-from-sources).
For full details on version availability for your platform, check the
[Debian Package Tracker](https://tracker.debian.org/pkg/ocrmypdf) or
[Ubuntu launchpad.net](https://launchpad.net/ocrmypdf).
:::{note}
OCRmyPDF for Debian and Ubuntu currently omit the JBIG2 encoder.
OCRmyPDF works fine without it but will produce larger output files.
If you build jbig2enc from source, ocrmypdf will
automatically detect it (specifically the `jbig2` binary) on the
`PATH`. To add JBIG2 encoding, see {ref}`jbig2`.
:::
### Fedora
:::{list-table}
:header-rows: 1
* - OCRmyPDF version
* - {{latest}}
* - {{fedora_38}} {{fedora_39}} {{fedora_rawhide}}
:::
Users of Fedora may simply
```bash
dnf install ocrmypdf tesseract-osd
```
For full details on version availability, check the [Fedora Package
Tracker](https://packages.fedoraproject.org/pkgs/ocrmypdf/ocrmypdf/).
If the version available for your platform is out of date, you could opt
to install the latest version from source. See [Installing HEAD revision
from sources](#installing-head-revision-from-sources).
:::{note}
OCRmyPDF for Fedora currently omits the JBIG2 encoder due to patent
issues. OCRmyPDF works fine without it but will produce larger output
files. If you build jbig2enc from source, ocrmypdf 7.0.0 and later
will automatically detect it on the `PATH`. To add JBIG2 encoding,
see {ref}`Installing the JBIG2 encoder <jbig2>`.
:::
(ubuntu-lts-latest)=
### RHEL 9
Prepare the environment by getting Python 3.11:
```bash
dnf install python3.11 python3.11-pip
```
Then, follow [Requirements for pip and HEAD install](#requirements-for-pip-and-head-install) to install dependencies:
```bash
dnf install ghostscript tesseract
```
and build ocrmypdf in virtual environment:
```bash
python3.11 -m venv .venv
```
To add JBIG2 encoding, see {ref}`Installing the JBIG2 encoder <jbig2>`.
Note Fedora packages for language data haven't been branched for RHEL/EPEL, but you can get traineddata files directly from [tesseract](https://github.com/tesseract-ocr/tessdata/) and place them in `/usr/share/tesseract/tessdata`.
### Installing the latest version on Ubuntu 22.04 LTS
Ubuntu 22.04 includes ocrmypdf 13.4.0 - you can install that with
`apt install ocrmypdf`. To install a more recent version for the current
user, follow these steps:
```bash
sudo apt-get update
sudo apt-get -y install ocrmypdf python3-pip
pip install --user --upgrade ocrmypdf
```
If you get the message `WARNING: The script ocrmypdf is installed in
'/home/$USER/.local/bin' which is not on PATH.`, you may need to re-login
or open a new shell, or manually adjust your PATH.
To add JBIG2 encoding, see {ref}`jbig2`.
### Ubuntu 20.04 LTS
Ubuntu 20.04 includes ocrmypdf 9.6.0 - you can install that with `apt`. The
most convenient way to install recent OCRmyPDF on older Ubuntu is to use
Homebrew on Linux (Linuxbrew).
```bash
brew install ocrmypdf
```
### Arch Linux (AUR)
:::{image} https://repology.org/badge/version-for-repo/aur/ocrmypdf.svg
:alt: ArchLinux
:target: https://repology.org/metapackage/ocrmypdf
:::
There is an [Arch User Repository (AUR) package for OCRmyPDF](https://aur.archlinux.org/packages/ocrmypdf/).
Installing AUR packages as root is not allowed, so you must first [setup a
non-root user](https://wiki.archlinux.org/index.php/Users_and_groups#User_management) and
[configure sudo](https://wiki.archlinux.org/index.php/Sudo#Configuration).
The standard Docker image, `archlinux/base:latest`, does **not** have a
non-root user configured, so users of that image must follow these guides. If
you are using a VM image, such as [the official Vagrant image](https://app.vagrantup.com/archlinux/boxes/archlinux), this work may already
be completed for you.
Next you should install the [base-devel package group](https://archlinux.org/packages/core/any/base-devel/). This includes the
standard tooling needed to build packages, such as a compiler and binary tools.
```bash
sudo pacman -S --needed base-devel
```
Now you are ready to install the OCRmyPDF package.
```bash
curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/ocrmypdf.tar.gz
tar xvzf ocrmypdf.tar.gz
cd ocrmypdf
makepkg -sri
```
At this point you will have a working install of OCRmyPDF, but the Tesseract
install wont include any OCR language data. You can install [the
tesseract-data package group](https://www.archlinux.org/groups/any/tesseract-data/) to add all supported
languages, or use that package listing to identify the appropriate package for
your desired language.
```bash
sudo pacman -S tesseract-data-eng
```
As an alternative to this manual procedure, consider using an [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers). Such a tool will
automatically fetch, build and install the AUR package, resolve dependencies
(including dependencies on AUR packages), and ease the upgrade procedure.
If you have any difficulties with installation, check the repository package
page.
:::{note}
The OCRmyPDF AUR package currently omits the JBIG2 encoder. OCRmyPDF works
fine without it but will produce larger output files. The encoder is
available from [the jbig2enc-git AUR package](https://aur.archlinux.org/packages/jbig2enc-git/) and may be installed
using the same series of steps as for the installation OCRmyPDF AUR
package. Alternatively, it may be built manually from source following the
instructions in {ref}`Installing the JBIG2 encoder <jbig2>`. If JBIG2 is
installed, OCRmyPDF 7.0.0 and later will automatically detect it.
:::
### Alpine Linux
:::{image} https://repology.org/badge/version-for-repo/alpine_edge/ocrmypdf.svg
:alt: Alpine Linux
:target: https://repology.org/metapackage/ocrmypdf
:::
To install OCRmyPDF for Alpine Linux:
```bash
apk add ocrmypdf
```
### Gentoo Linux
:::{image} https://repology.org/badge/version-for-repo/gentoo_ovl_guru/ocrmypdf.svg
:alt: Gentoo Linux
:target: https://repology.org/metapackage/ocrmypdf
:::
To install OCRmyPDF on Gentoo Linux, use the following commands:
```bash
eselect repository enable guru
emaint sync --repo guru
emerge --ask app-text/OCRmyPDF
```
### Other Linux packages
See the
[Repology](https://repology.org/metapackage/ocrmypdf/versions) page.
In general, first install the OCRmyPDF package for your system, then
optionally use the procedure [Installing with Python
pip](#installing-with-python-pip) to install a more recent version.
## Installing on macOS
### Homebrew
:::{image} https://img.shields.io/homebrew/v/ocrmypdf.svg
:alt: homebrew
:target: https://formulae.brew.sh/formula/ocrmypdf
:::
OCRmyPDF is now a standard [Homebrew](https://brew.sh) formula. To
install on macOS:
```bash
brew install ocrmypdf
```
This will include only the English language pack. If you need other
languages you can optionally install them all:
```bash
brew install tesseract-lang # Optional: Install all language packs
```
### MacPorts
:::{image} https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fports.macports.org%2Fapi%2Fv1%2Fports%2Focrmypdf%2F%3Fformat%3Djson&query=version&label=MacPorts
:alt: Macports Version Information
:target: https://ports.macports.org/port/ocrmypdf
:::
OCRmyPDF is includes in MacPorts:
```bash
sudo port install ocrmypdf
```
Note that while this will install tesseract you will need to install
the appropriate tesseract [language ports](https://ports.macports.org/search/?selected_facets=categories_exact%3Atextproc&installed_file=&q=tesseract&name=on).
### Manual installation on macOS
These instructions probably work on all macOS supported by Homebrew, and are
for installing a more current version of OCRmyPDF than is available from
Homebrew. Note that the Homebrew versions usually track the release versions
fairly closely.
If it's not already present, [install Homebrew](http://brew.sh/).
Update Homebrew:
```bash
brew update
```
Install or upgrade the required Homebrew packages, if any are missing.
To do this, use `brew edit ocrmypdf` to obtain a recent list of Homebrew
dependencies. You could also check the `.workflows/build.yml`.
This will include the English, French, German and Spanish language
packs. If you need other languages you can optionally install them all:
(macos-all-languages)=
> ```bash
> brew install tesseract-lang # Option 2: for all language packs
> ```
Update the homebrew pip:
```bash
pip install --upgrade pip
```
You can then install OCRmyPDF from PyPI for the current user:
```bash
pip install --user ocrmypdf
```
The command line program should now be available:
```bash
ocrmypdf --help
```
## Installing on Windows
### Native Windows
% If you have a Windows that is not the Home edition, you can use Windows Sandbox to test on a blank Windows instance.
% https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/
:::{note}
Administrator privileges will be required for some of these steps.
:::
You must install the following for Windows:
- Python 64-bit
- Tesseract 64-bit
- Ghostscript 64-bit
Using the [winget](https://docs.microsoft.com/en-us/windows/package-manager/winget/)
package manager:
- `winget install -e --id Python.Python.3.11`
- `winget install -e --id UB-Mannheim.TesseractOCR`
You will need to install Ghostscript manually, [since it does not support automated
installs anymore](https://artifex.com/news/ghostscript-10.01.0-disabling-silent-install-option).
- [Ghostscript download page](https://ghostscript.com/releases/gsdnld.html).\`
(Or alternately, using the [Chocolatey](https://chocolatey.org/) package manager, install
the following when running in an Administrator command prompt):
- `choco install python3`
- `choco install --pre tesseract`
- `choco install pngquant` (optional)
Either set of commands will install the required software. At the moment there is no
single command to install Windows.
You may then use `pip` to install ocrmypdf. (This can performed by a user or
Administrator.):
- `python3 -m pip install ocrmypdf`
% The Windows Python versions do not place any python or python3 executable in the path.
% They add the py launcher to the path:
% https://docs.python.org/3/using/windows.html#python-launcher-for-windows
If you installed Python using WinGet, then use the following command instead:
- `py -m pip install ocrmypdf`
and use:
- `py -m ocrmypdf`
To start OCRmyPDF.
If you intend to use more Python software on your Windows machine, consider the use of
[pipx](https://pipx.pypa.io/stable/) or a similar tool to create isolated Python
environments for each Python software that you want to use.
OCRmyPDF will check the Windows Registry and standard locations in your Program Files
for third party software it needs (specifically, Tesseract and Ghostscript). To
override the versions OCRmyPDF selects, you can modify the `PATH` environment
variable. [Follow these directions](https://www.computerhope.com/issues/ch000549.htm#dospath)
to change the PATH.
:::{warning}
As of early 2021, users have reported problems with the Microsoft Store version of
Python and OCRmyPDF. These issues affect many other third party Python packages.
Please download Python from Python.org or a package manager instead of the
Microsoft Store version.
:::
:::{warning}
32-bit Windows is not supported.
:::
### Windows Subsystem for Linux
1. Install Ubuntu 22.04 for Windows Subsystem for Linux, if not already installed.
2. Follow the procedure to install {ref}`OCRmyPDF on Ubuntu 22.04 <ubuntu-lts-latest>`.
3. Open the Windows command prompt and create a symlink:
```powershell
wsl sudo ln -s /home/$USER/.local/bin/ocrmypdf /usr/local/bin/ocrmypdf
```
Then confirm that the expected version from PyPI ({{ latest }}) is installed:
```powershell
wsl ocrmypdf --version
```
You can then run OCRmyPDF in the Windows command prompt or Powershell, prefixing
`wsl`, and call it from Windows programs or batch files.
### Cygwin64
First install the the following prerequisite Cygwin packages using `setup-x86_64.exe`:
```
python310 (or later)
python3?-devel
python3?-pip
python3?-lxml
python3?-imaging
(where 3? means match the version of python3 you installed)
gcc-g++
ghostscript
libexempi3
libexempi-devel
libffi6
libffi-devel
pngquant
qpdf
libqpdf-devel
tesseract-ocr
tesseract-ocr-devel
```
Then open a Cygwin terminal (i.e. `mintty`), run the following commands. Note
that if you are using the version of `pip` that was installed with the Cygwin
Python package, the command name will be `pip3`. If you have since updated
`pip` (with, for instance `pip3 install --upgrade pip`) the the command is
likely just `pip` instead of `pip3`:
```bash
pip3 install wheel
pip3 install ocrmypdf
```
The optional dependency "unpaper" that is currently not available under Cygwin.
Without it, certain options such as `--clean` will produce an error message.
However, the OCR-to-text-layer functionality is available.
### Docker
You can also [Install the Docker image](docker) on Windows. Ensure that
your command prompt can run the docker "hello world" container.
## Installing on FreeBSD
:::{image} https://repology.org/badge/version-for-repo/freebsd/ocrmypdf.svg
:alt: FreeBSD
:target: https://repology.org/project/ocrmypdf/versions
:::
```bash
pkg install textproc/py-ocrmypdf
```
To install a more recent version, you could attempt to first install the system
version with `pkg`, then use `pip install --user ocrmypdf`.
## Installing the Docker image
For some users, installing the Docker image will be easier than
installing all of OCRmyPDF's dependencies.
See [Installing the Docker image](docker) for more information.
(installing-with-python-pip)=
## Installing with Python pip
OCRmyPDF is delivered by PyPI because it is a convenient way to install
the latest version. However, PyPI and `pip` cannot address the fact
that `ocrmypdf` depends on certain non-Python system libraries and
programs being installed.
For best results, first install [your platform's
version](https://repology.org/metapackage/ocrmypdf/versions) of
`ocrmypdf`, using the instructions elsewhere in this document. Then
you can use `pip` to get the latest version if your platform version
is out of date. Chances are that this will satisfy most dependencies.
Use `ocrmypdf --version` to confirm what version was installed.
Then you can install the latest OCRmyPDF from the Python wheels. First
try:
```bash
pip install --user ocrmypdf
```
(If the message appears `Requirement already satisfied: ocrmypdf in...`,
you will need to use `pip install --user --upgrade ocrmypdf`.)
You should then be able to run `ocrmypdf --version` and see that the
latest version was located.
## Installing with pipx
Some users may prefer pipx. As with the method above, you will need to
satisfy all non-Python dependencies. Then if pipx is installed, you
can use
```bash
pipx run ocrmypdf
```
(If not installed, pipx will install first.)
(requirements-for-pip-and-head-install)=
### Requirements for pip and HEAD install
OCRmyPDF currently requires these external programs and libraries to be
installed, and must be satisfied using the operating system package
manager. `pip` cannot provide them.
The following versions are required:
- Python 3.10 or newer
- Ghostscript 9.54 or newer
- Tesseract 4.1.1 or newer
- jbig2enc 0.29 or newer
- pngquant 2.5 or newer
- unpaper 6.1
We recommend 64-bit versions of all software. (32-bit versions are not
supported, although on Linux, they may still work.)
jbig2enc, pngquant, and unpaper are optional. If missing certain
features are disabled. OCRmyPDF will discover them as soon as they are
available.
**jbig2enc**, if present, will be used to optimize the encoding of
monochrome images. This can significantly reduce the file size of the
output file. It is not required.
[jbig2enc](https://github.com/agl/jbig2enc) is not generally
available for Ubuntu or Debian due to lingering concerns about patent
issues, but can easily be built from source. To add JBIG2 encoding, see
{ref}`jbig2`.
**pngquant**, if present, is optionally used to optimize the encoding of
PNG-style images in PDFs (actually, any that are that losslessly
encoded) by lossily quantizing to a smaller color palette. It is only
activated then the `--optimize` argument is `2` or `3`.
**unpaper**, if present, enables the `--clean` and `--clean-final`
command line options.
These are in addition to the Python packaging dependencies, meaning that
unfortunately, the `pip install` command cannot satisfy all of them.
(installing-head-revision-from-sources)=
## Installing HEAD revision from sources
If you have `git` and Python 3.10 or newer installed, you can install
from source. When the `pip` installer runs, it will alert you if
dependencies are missing.
If you prefer to build every from source, you will need to [build
pikepdf from
source](https://pikepdf.readthedocs.io/en/latest/installation.html#building-from-source).
First ensure you can build and install pikepdf.
To install the HEAD revision from sources in the current Python 3
environment:
```bash
pip install git+https://github.com/ocrmypdf/OCRmyPDF.git
```
Or, to install in editable mode
allowing customization of OCRmyPDF, use the `-e` flag:
```bash
pip install -e git+https://github.com/ocrmypdf/OCRmyPDF.git
```
You may find it easiest to install in a virtual environment, rather than
system-wide:
```bash
git clone -b main https://github.com/ocrmypdf/OCRmyPDF.git
python3 -m venv .venv
source .venv/bin/activate
cd OCRmyPDF
pip install .
```
However, `ocrmypdf` will only be accessible on the system PATH when
you activate the virtual environment.
To run the program:
```bash
ocrmypdf --help
```
If not yet installed, the script will notify you about dependencies that
need to be installed. The script requires specific versions of the
dependencies. Older version than the ones mentioned in the release notes
are likely not to be compatible to OCRmyPDF.
### For development
To install all of the development and test requirements:
```bash
git clone -b main https://github.com/ocrmypdf/OCRmyPDF.git
python -m venv .venv
source .venv/bin/activate
cd OCRmyPDF
pip install -e .[test]
```
To add JBIG2 encoding, see {ref}`jbig2`.
## Shell completions
Completions for `bash` and `fish` are available in the project's
`misc/completion` folder. The `bash` completions are likely `zsh`
compatible but this has not been confirmed. Package maintainers, please
install these at the appropriate locations for your system.
To manually install the `bash` completion, copy
`misc/completion/ocrmypdf.bash` to `/etc/bash_completion.d/ocrmypdf`
(rename the file).
To manually install the `fish` completion, copy
`misc/completion/ocrmypdf.fish` to
`~/.config/fish/completions/ocrmypdf.fish`.
## Note on 32-bit support
Many Python libraries no longer provide 32-bit binary wheels for Linux. This
includes many of the libraries that OCRmyPDF depends on, such as
Pillow. The easiest way to express this to end users is to say we don't
support 32-bit Linux.
However, if your Linux distribution still supports 32-bit binaries, you
can still install and use OCRmyPDF. A warning message will appear.
In practice, OCRmyPDF may need more than 32-bit memory space to run when
large documents are processed, so there are practical limitations to what
users can accomplish with it. Still, for the common use case of an 32-bit
ARM NAS or Raspberry Pi processing small documents, it should work.
-740
View File
@@ -1,740 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
===================
Installing OCRmyPDF
===================
.. |latest| image:: https://img.shields.io/pypi/v/ocrmypdf.svg
:alt: OCRmyPDF latest released version on PyPI
|latest|
The easiest way to install OCRmyPDF is to follow the steps for your operating
system/platform. This version may be out of date, however.
These platforms have one-liner installs:
+-------------------------------+-----------------------------------------+
| Debian, Ubuntu | ``apt install ocrmypdf`` |
+-------------------------------+-----------------------------------------+
| Windows Subsystem for Linux | ``apt install ocrmypdf`` |
+-------------------------------+-----------------------------------------+
| Fedora | ``dnf install ocrmypdf tesseract-osd`` |
+-------------------------------+-----------------------------------------+
| macOS (Homebrew) | ``brew install ocrmypdf`` |
+-------------------------------+-----------------------------------------+
| macOS (MacPorts) | ``port install ocrmypdf`` |
+-------------------------------+-----------------------------------------+
| LinuxBrew | ``brew install ocrmypdf`` |
+-------------------------------+-----------------------------------------+
| FreeBSD | ``pkg install textproc/py-ocrmypdf`` |
+-------------------------------+-----------------------------------------+
| Snap (snapcraft packaging) | ``snap install ocrmypdf`` |
+-------------------------------+-----------------------------------------+
More detailed procedures are outlined below. If you want to do a manual
install, or install a more recent version than your platform provides, read on.
.. contents:: Platform-specific steps
:depth: 2
:local:
Installing on Linux
===================
Debian and Ubuntu 20.04 or newer
--------------------------------
.. |deb-11| image:: https://repology.org/badge/version-for-repo/debian_11/ocrmypdf.svg
:alt: Debian 11
.. |deb-12| image:: https://repology.org/badge/version-for-repo/debian_12/ocrmypdf.svg
:alt: Debian 12
.. |deb-unstable| image:: https://repology.org/badge/version-for-repo/debian_unstable/ocrmypdf.svg
:alt: Debian unstable
.. |ubu-2004| image:: https://repology.org/badge/version-for-repo/ubuntu_20_04/ocrmypdf.svg
:alt: Ubuntu 20.04 LTS
.. |ubu-2204| image:: https://repology.org/badge/version-for-repo/ubuntu_22_04/ocrmypdf.svg
:alt: Ubuntu 22.04 LTS
+-----------------------------------------------+
| **OCRmyPDF versions in Debian & Ubuntu** |
+-----------------------------------------------+
| |latest| |
+-----------------------------------------------+
| |deb-11| |deb-12| |deb-unstable| |
+-----------------------------------------------+
| |ubu-2004| |ubu-2204| |
+-----------------------------------------------+
Users of Debian or Ubuntu may simply
.. code-block:: bash
apt install ocrmypdf
As indicated in the table above, Debian and Ubuntu releases may lag
behind the latest version. If the version available for your platform is
out of date, you could opt to install the latest version from source.
See `Installing HEAD revision from
sources <#installing-head-revision-from-sources>`__.
For full details on version availability for your platform, check the
`Debian Package Tracker <https://tracker.debian.org/pkg/ocrmypdf>`__ or
`Ubuntu launchpad.net <https://launchpad.net/ocrmypdf>`__.
.. note::
OCRmyPDF for Debian and Ubuntu currently omit the JBIG2 encoder.
OCRmyPDF works fine without it but will produce larger output files.
If you build jbig2enc from source, ocrmypdf will
automatically detect it (specifically the ``jbig2`` binary) on the
``PATH``. To add JBIG2 encoding, see :ref:`jbig2`.
Fedora
------
.. |fedora-38| image:: https://repology.org/badge/version-for-repo/fedora_38/ocrmypdf.svg
:alt: Fedora 38
.. |fedora-39| image:: https://repology.org/badge/version-for-repo/fedora_39/ocrmypdf.svg
:alt: Fedora 39
.. |fedora-rawhide| image:: https://repology.org/badge/version-for-repo/fedora_rawhide/ocrmypdf.svg
:alt: Fedore Rawhide
+-----------------------------------------------+
| **OCRmyPDF version** |
+-----------------------------------------------+
| |latest| |
+-----------------------------------------------+
| |fedora-38| |fedora-39| |fedora-rawhide| |
+-----------------------------------------------+
Users of Fedora may simply
.. code-block:: bash
dnf install ocrmypdf tesseract-osd
For full details on version availability, check the `Fedora Package
Tracker <https://packages.fedoraproject.org/pkgs/ocrmypdf/ocrmypdf/>`__.
If the version available for your platform is out of date, you could opt
to install the latest version from source. See `Installing HEAD revision
from sources <#installing-head-revision-from-sources>`__.
.. note::
OCRmyPDF for Fedora currently omits the JBIG2 encoder due to patent
issues. OCRmyPDF works fine without it but will produce larger output
files. If you build jbig2enc from source, ocrmypdf 7.0.0 and later
will automatically detect it on the ``PATH``. To add JBIG2 encoding,
see :ref:`Installing the JBIG2 encoder <jbig2>`.
.. _ubuntu-lts-latest:
RHEL 9
------
Prepare the environment by getting Python 3.11:
.. code-block:: bash
dnf install python3.11 python3.11-pip
Then, follow `Requirements for pip and HEAD install <#requirements-for-pip-and-head-install>`__ to install dependencies:
.. code-block:: bash
dnf install ghostscript tesseract
and build ocrmypdf in virtual environment:
.. code-block:: bash
python3.11 -m venv .venv
To add JBIG2 encoding, see :ref:`Installing the JBIG2 encoder <jbig2>`.
Note Fedora packages for language data haven't been branched for RHEL/EPEL, but you can get traineddata files directly from `tesseract
<https://github.com/tesseract-ocr/tessdata/>`__ and place them in ``/usr/share/tesseract/tessdata``.
Installing the latest version on Ubuntu 22.04 LTS
-------------------------------------------------
Ubuntu 22.04 includes ocrmypdf 13.4.0 - you can install that with
``apt install ocrmypdf``. To install a more recent version for the current
user, follow these steps:
.. code-block:: bash
sudo apt-get update
sudo apt-get -y install ocrmypdf python3-pip
pip install --user --upgrade ocrmypdf
If you get the message ``WARNING: The script ocrmypdf is installed in
'/home/$USER/.local/bin' which is not on PATH.``, you may need to re-login
or open a new shell, or manually adjust your PATH.
To add JBIG2 encoding, see :ref:`jbig2`.
Ubuntu 20.04 LTS
----------------
Ubuntu 20.04 includes ocrmypdf 9.6.0 - you can install that with ``apt``. The
most convenient way to install recent OCRmyPDF on older Ubuntu is to use
Homebrew on Linux (Linuxbrew).
.. code-block:: bash
brew install ocrmypdf
Arch Linux (AUR)
----------------
.. image:: https://repology.org/badge/version-for-repo/aur/ocrmypdf.svg
:alt: ArchLinux
:target: https://repology.org/metapackage/ocrmypdf
There is an `Arch User Repository (AUR) package for OCRmyPDF
<https://aur.archlinux.org/packages/ocrmypdf/>`__.
Installing AUR packages as root is not allowed, so you must first `setup a
non-root user
<https://wiki.archlinux.org/index.php/Users_and_groups#User_management>`__ and
`configure sudo <https://wiki.archlinux.org/index.php/Sudo#Configuration>`__.
The standard Docker image, ``archlinux/base:latest``, does **not** have a
non-root user configured, so users of that image must follow these guides. If
you are using a VM image, such as `the official Vagrant image
<https://app.vagrantup.com/archlinux/boxes/archlinux>`__, this work may already
be completed for you.
Next you should install the `base-devel package group
<https://archlinux.org/packages/core/any/base-devel/>`__. This includes the
standard tooling needed to build packages, such as a compiler and binary tools.
.. code-block:: bash
sudo pacman -S --needed base-devel
Now you are ready to install the OCRmyPDF package.
.. code-block:: bash
curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/ocrmypdf.tar.gz
tar xvzf ocrmypdf.tar.gz
cd ocrmypdf
makepkg -sri
At this point you will have a working install of OCRmyPDF, but the Tesseract
install wont include any OCR language data. You can install `the
tesseract-data package group
<https://www.archlinux.org/groups/any/tesseract-data/>`__ to add all supported
languages, or use that package listing to identify the appropriate package for
your desired language.
.. code-block:: bash
sudo pacman -S tesseract-data-eng
As an alternative to this manual procedure, consider using an `AUR helper
<https://wiki.archlinux.org/index.php/AUR_helpers>`__. Such a tool will
automatically fetch, build and install the AUR package, resolve dependencies
(including dependencies on AUR packages), and ease the upgrade procedure.
If you have any difficulties with installation, check the repository package
page.
.. note::
The OCRmyPDF AUR package currently omits the JBIG2 encoder. OCRmyPDF works
fine without it but will produce larger output files. The encoder is
available from `the jbig2enc-git AUR package
<https://aur.archlinux.org/packages/jbig2enc-git/>`__ and may be installed
using the same series of steps as for the installation OCRmyPDF AUR
package. Alternatively, it may be built manually from source following the
instructions in :ref:`Installing the JBIG2 encoder <jbig2>`. If JBIG2 is
installed, OCRmyPDF 7.0.0 and later will automatically detect it.
Alpine Linux
------------
.. image:: https://repology.org/badge/version-for-repo/alpine_edge/ocrmypdf.svg
:alt: Alpine Linux
:target: https://repology.org/metapackage/ocrmypdf
To install OCRmyPDF for Alpine Linux:
.. code-block:: bash
apk add ocrmypdf
Gentoo Linux
------------
.. image:: https://repology.org/badge/version-for-repo/gentoo_ovl_guru/ocrmypdf.svg
:alt: Gentoo Linux
:target: https://repology.org/metapackage/ocrmypdf
To install OCRmyPDF on Gentoo Linux, use the following commands:
.. code-block:: bash
eselect repository enable guru
emaint sync --repo guru
emerge --ask app-text/OCRmyPDF
Other Linux packages
--------------------
See the
`Repology <https://repology.org/metapackage/ocrmypdf/versions>`__ page.
In general, first install the OCRmyPDF package for your system, then
optionally use the procedure `Installing with Python
pip <#installing-with-python-pip>`__ to install a more recent version.
Installing on macOS
===================
Homebrew
--------
.. image:: https://img.shields.io/homebrew/v/ocrmypdf.svg
:alt: homebrew
:target: https://formulae.brew.sh/formula/ocrmypdf
OCRmyPDF is now a standard `Homebrew <https://brew.sh>`__ formula. To
install on macOS:
.. code-block:: bash
brew install ocrmypdf
This will include only the English language pack. If you need other
languages you can optionally install them all:
.. code-block:: bash
brew install tesseract-lang # Optional: Install all language packs
MacPorts
--------
.. image:: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fports.macports.org%2Fapi%2Fv1%2Fports%2Focrmypdf%2F%3Fformat%3Djson&query=version&label=MacPorts
:alt: Macports Version Information
:target: https://ports.macports.org/port/ocrmypdf
OCRmyPDF is includes in MacPorts:
.. code-block:: bash
sudo port install ocrmypdf
Note that while this will install tesseract you will need to install
the appropriate tesseract `language ports <https://ports.macports.org/search/?selected_facets=categories_exact%3Atextproc&installed_file=&q=tesseract&name=on>`__.
Manual installation on macOS
----------------------------
These instructions probably work on all macOS supported by Homebrew, and are
for installing a more current version of OCRmyPDF than is available from
Homebrew. Note that the Homebrew versions usually track the release versions
fairly closely.
If it's not already present, `install Homebrew <http://brew.sh/>`__.
Update Homebrew:
.. code-block:: bash
brew update
Install or upgrade the required Homebrew packages, if any are missing.
To do this, use ``brew edit ocrmypdf`` to obtain a recent list of Homebrew
dependencies. You could also check the ``.workflows/build.yml``.
This will include the English, French, German and Spanish language
packs. If you need other languages you can optionally install them all:
.. _macos-all-languages:
.. code-block:: bash
brew install tesseract-lang # Option 2: for all language packs
Update the homebrew pip:
.. code-block:: bash
pip install --upgrade pip
You can then install OCRmyPDF from PyPI for the current user:
.. code-block:: bash
pip install --user ocrmypdf
The command line program should now be available:
.. code-block:: bash
ocrmypdf --help
Installing on Windows
=====================
Native Windows
--------------
..
If you have a Windows that is not the Home edition, you can use Windows Sandbox to test on a blank Windows instance.
https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/
.. note::
Administrator privileges will be required for some of these steps.
You must install the following for Windows:
* Python 64-bit
* Tesseract 64-bit
* Ghostscript 64-bit
Using the `winget <https://docs.microsoft.com/en-us/windows/package-manager/winget/>`_
package manager:
* ``winget install -e --id Python.Python.3.11``
* ``winget install -e --id UB-Mannheim.TesseractOCR``
You will need to install Ghostscript manually, `since it does not support automated
installs anymore <https://artifex.com/news/ghostscript-10.01.0-disabling-silent-install-option>`_.
* `Ghostscript download page <https://ghostscript.com/releases/gsdnld.html>`_.`
(Or alternately, using the `Chocolatey <https://chocolatey.org/>`_ package manager, install
the following when running in an Administrator command prompt):
* ``choco install python3``
* ``choco install --pre tesseract``
* ``choco install pngquant`` (optional)
Either set of commands will install the required software. At the moment there is no
single command to install Windows.
You may then use ``pip`` to install ocrmypdf. (This can performed by a user or
Administrator.):
* ``python3 -m pip install ocrmypdf``
..
The Windows Python versions do not place any python or python3 executable in the path.
They add the py launcher to the path:
https://docs.python.org/3/using/windows.html#python-launcher-for-windows
If you installed Python using WinGet, then use the following command instead:
* ``py -m pip install ocrmypdf``
and use:
* ``py -m ocrmypdf``
To start OCRmyPDF.
If you intend to use more Python software on your Windows machine, consider the use of
`pipx <https://pipx.pypa.io/stable/>`_ or a similar tool to create isolated Python
environments for each Python software that you want to use.
OCRmyPDF will check the Windows Registry and standard locations in your Program Files
for third party software it needs (specifically, Tesseract and Ghostscript). To
override the versions OCRmyPDF selects, you can modify the ``PATH`` environment
variable. `Follow these directions <https://www.computerhope.com/issues/ch000549.htm#dospath>`_
to change the PATH.
.. warning::
As of early 2021, users have reported problems with the Microsoft Store version of
Python and OCRmyPDF. These issues affect many other third party Python packages.
Please download Python from Python.org or a package manager instead of the
Microsoft Store version.
.. warning::
32-bit Windows is not supported.
Windows Subsystem for Linux
---------------------------
#. Install Ubuntu 22.04 for Windows Subsystem for Linux, if not already installed.
#. Follow the procedure to install :ref:`OCRmyPDF on Ubuntu 22.04 <ubuntu-lts-latest>`.
#. Open the Windows command prompt and create a symlink:
.. code-block:: powershell
wsl sudo ln -s /home/$USER/.local/bin/ocrmypdf /usr/local/bin/ocrmypdf
Then confirm that the expected version from PyPI (|latest|) is installed:
.. code-block:: powershell
wsl ocrmypdf --version
You can then run OCRmyPDF in the Windows command prompt or Powershell, prefixing
``wsl``, and call it from Windows programs or batch files.
Cygwin64
--------
First install the the following prerequisite Cygwin packages using ``setup-x86_64.exe``::
python310 (or later)
python3?-devel
python3?-pip
python3?-lxml
python3?-imaging
(where 3? means match the version of python3 you installed)
gcc-g++
ghostscript
libexempi3
libexempi-devel
libffi6
libffi-devel
pngquant
qpdf
libqpdf-devel
tesseract-ocr
tesseract-ocr-devel
Then open a Cygwin terminal (i.e. ``mintty``), run the following commands. Note
that if you are using the version of ``pip`` that was installed with the Cygwin
Python package, the command name will be ``pip3``. If you have since updated
``pip`` (with, for instance ``pip3 install --upgrade pip``) the the command is
likely just ``pip`` instead of ``pip3``:
.. code-block:: bash
pip3 install wheel
pip3 install ocrmypdf
The optional dependency "unpaper" that is currently not available under Cygwin.
Without it, certain options such as ``--clean`` will produce an error message.
However, the OCR-to-text-layer functionality is available.
Docker
------
You can also :ref:`Install the Docker <docker>` container on Windows. Ensure that
your command prompt can run the docker "hello world" container.
Installing on FreeBSD
=====================
.. image:: https://repology.org/badge/version-for-repo/freebsd/ocrmypdf.svg
:alt: FreeBSD
:target: https://repology.org/project/ocrmypdf/versions
.. code-block:: bash
pkg install textproc/py-ocrmypdf
To install a more recent version, you could attempt to first install the system
version with ``pkg``, then use ``pip install --user ocrmypdf``.
Installing the Docker image
===========================
For some users, installing the Docker image will be easier than
installing all of OCRmyPDF's dependencies.
See :ref:`docker` for more information.
Installing with Python pip
==========================
OCRmyPDF is delivered by PyPI because it is a convenient way to install
the latest version. However, PyPI and ``pip`` cannot address the fact
that ``ocrmypdf`` depends on certain non-Python system libraries and
programs being installed.
For best results, first install `your platform's
version <https://repology.org/metapackage/ocrmypdf/versions>`__ of
``ocrmypdf``, using the instructions elsewhere in this document. Then
you can use ``pip`` to get the latest version if your platform version
is out of date. Chances are that this will satisfy most dependencies.
Use ``ocrmypdf --version`` to confirm what version was installed.
Then you can install the latest OCRmyPDF from the Python wheels. First
try:
.. code-block:: bash
pip install --user ocrmypdf
(If the message appears ``Requirement already satisfied: ocrmypdf in...``,
you will need to use ``pip install --user --upgrade ocrmypdf``.)
You should then be able to run ``ocrmypdf --version`` and see that the
latest version was located.
Installing with pipx
====================
Some users may prefer pipx. As with the method above, you will need to
satisfy all non-Python dependencies. Then if pipx is installed, you
can use
.. code-block:: bash
pipx run ocrmypdf
(If not installed, pipx will install first.)
Requirements for pip and HEAD install
-------------------------------------
OCRmyPDF currently requires these external programs and libraries to be
installed, and must be satisfied using the operating system package
manager. ``pip`` cannot provide them.
The following versions are required:
- Python 3.10 or newer
- Ghostscript 9.54 or newer
- Tesseract 4.1.1 or newer
- jbig2enc 0.29 or newer
- pngquant 2.5 or newer
- unpaper 6.1
We recommend 64-bit versions of all software. (32-bit versions are not
supported, although on Linux, they may still work.)
jbig2enc, pngquant, and unpaper are optional. If missing certain
features are disabled. OCRmyPDF will discover them as soon as they are
available.
**jbig2enc**, if present, will be used to optimize the encoding of
monochrome images. This can significantly reduce the file size of the
output file. It is not required.
`jbig2enc <https://github.com/agl/jbig2enc>`__ is not generally
available for Ubuntu or Debian due to lingering concerns about patent
issues, but can easily be built from source. To add JBIG2 encoding, see
:ref:`jbig2`.
**pngquant**, if present, is optionally used to optimize the encoding of
PNG-style images in PDFs (actually, any that are that losslessly
encoded) by lossily quantizing to a smaller color palette. It is only
activated then the ``--optimize`` argument is ``2`` or ``3``.
**unpaper**, if present, enables the ``--clean`` and ``--clean-final``
command line options.
These are in addition to the Python packaging dependencies, meaning that
unfortunately, the ``pip install`` command cannot satisfy all of them.
Installing HEAD revision from sources
=====================================
If you have ``git`` and Python 3.10 or newer installed, you can install
from source. When the ``pip`` installer runs, it will alert you if
dependencies are missing.
If you prefer to build every from source, you will need to `build
pikepdf from
source <https://pikepdf.readthedocs.io/en/latest/installation.html#building-from-source>`__.
First ensure you can build and install pikepdf.
To install the HEAD revision from sources in the current Python 3
environment:
.. code-block:: bash
pip install git+https://github.com/ocrmypdf/OCRmyPDF.git
Or, to install in editable mode
allowing customization of OCRmyPDF, use the ``-e`` flag:
.. code-block:: bash
pip install -e git+https://github.com/ocrmypdf/OCRmyPDF.git
You may find it easiest to install in a virtual environment, rather than
system-wide:
.. code-block:: bash
git clone -b main https://github.com/ocrmypdf/OCRmyPDF.git
python3 -m venv .venv
source .venv/bin/activate
cd OCRmyPDF
pip install .
However, ``ocrmypdf`` will only be accessible on the system PATH when
you activate the virtual environment.
To run the program:
.. code-block:: bash
ocrmypdf --help
If not yet installed, the script will notify you about dependencies that
need to be installed. The script requires specific versions of the
dependencies. Older version than the ones mentioned in the release notes
are likely not to be compatible to OCRmyPDF.
For development
---------------
To install all of the development and test requirements:
.. code-block:: bash
git clone -b main https://github.com/ocrmypdf/OCRmyPDF.git
python -m venv .venv
source .venv/bin/activate
cd OCRmyPDF
pip install -e .[test]
To add JBIG2 encoding, see :ref:`jbig2`.
Shell completions
=================
Completions for ``bash`` and ``fish`` are available in the project's
``misc/completion`` folder. The ``bash`` completions are likely ``zsh``
compatible but this has not been confirmed. Package maintainers, please
install these at the appropriate locations for your system.
To manually install the ``bash`` completion, copy
``misc/completion/ocrmypdf.bash`` to ``/etc/bash_completion.d/ocrmypdf``
(rename the file).
To manually install the ``fish`` completion, copy
``misc/completion/ocrmypdf.fish`` to
``~/.config/fish/completions/ocrmypdf.fish``.
Note on 32-bit support
======================
Many Python libraries no longer provide 32-bit binary wheels for Linux. This
includes many of the libraries that OCRmyPDF depends on, such as
Pillow. The easiest way to express this to end users is to say we don't
support 32-bit Linux.
However, if your Linux distribution still supports 32-bit binaries, you
can still install and use OCRmyPDF. A warning message will appear.
In practice, OCRmyPDF may need more than 32-bit memory space to run when
large documents are processed, so there are practical limitations to what
users can accomplish with it. Still, for the common use case of an 32-bit
ARM NAS or Raspberry Pi processing small documents, it should work.
+62 -74
View File
@@ -1,10 +1,7 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow % SPDX-FileCopyrightText: 2022 James R. Barlow
.. % SPDX-License-Identifier: CC-BY-SA-4.0
.. SPDX-License-Identifier: CC-BY-SA-4.0
============ # Introduction
Introduction
============
OCRmyPDF is a Python application and library that adds text "layers" to images in OCRmyPDF is a Python application and library that adds text "layers" to images in
PDFs, making scanned image PDFs searchable. It uses OCR to guess the text PDFs, making scanned image PDFs searchable. It uses OCR to guess the text
@@ -13,31 +10,30 @@ that enable customization of its processing steps, and it is highly tolerant
of PDFs containing scanned images and "born digital" content that doesn't of PDFs containing scanned images and "born digital" content that doesn't
require text recognition. require text recognition.
About OCR ## About OCR
=========
`Optical character [Optical character
recognition <https://en.wikipedia.org/wiki/Optical_character_recognition>`__ recognition](https://en.wikipedia.org/wiki/Optical_character_recognition)
is a technology that converts images of typed or handwritten text, such as is a technology that converts images of typed or handwritten text, such as
in a scanned document, into computer text that can be selected, searched and copied. in a scanned document, into computer text that can be selected, searched and copied.
OCRmyPDF uses OCRmyPDF uses
`Tesseract <https://github.com/tesseract-ocr/tesseract>`__, a widely [Tesseract](https://github.com/tesseract-ocr/tesseract), a widely
available open source OCR engine, to perform OCR. available open source OCR engine, to perform OCR.
.. _raster-vector: (raster-vector)=
About PDFs ## About PDFs
==========
PDFs are page description files that attempt to preserve a layout PDFs are page description files that attempt to preserve a layout
exactly. They contain `vector exactly. They contain [vector
graphics <http://vector-conversions.com/vectorizing/raster_vs_vector.html>`__ graphics](http://vector-conversions.com/vectorizing/raster_vs_vector.html)
that can contain raster objects, such as scanned images. Because PDFs can that can contain raster objects, such as scanned images. Because PDFs can
contain multiple pages (unlike many image formats) and can contain fonts contain multiple pages (unlike many image formats) and can contain fonts
and text, they are a suitable format for exchanging scanned documents. and text, they are a suitable format for exchanging scanned documents.
|image| :::{image} images/bitmap_vs_svg.svg
:::
A PDF page may contain multiple images, even if it appears to have only A PDF page may contain multiple images, even if it appears to have only
one image. Some scanners or scanning software may segment pages into one image. Some scanners or scanning software may segment pages into
@@ -48,10 +44,9 @@ Rasterizing a PDF is the process of generating corresponding raster images.
OCR engines like Tesseract work with images, not scalable vector graphics OCR engines like Tesseract work with images, not scalable vector graphics
or mixed raster-vector-text graphics such as PDF. or mixed raster-vector-text graphics such as PDF.
About PDF/A ## About PDF/A
===========
`PDF/A <https://en.wikipedia.org/wiki/PDF/A>`__ is an ISO-standardized [PDF/A](https://en.wikipedia.org/wiki/PDF/A) is an ISO-standardized
subset of the full PDF specification that is designed for archiving (the subset of the full PDF specification that is designed for archiving (the
'A' stands for Archive). PDF/A differs from PDF primarily by omitting 'A' stands for Archive). PDF/A differs from PDF primarily by omitting
features that could complicate future file readability, features that could complicate future file readability,
@@ -63,8 +58,8 @@ of embedded content, it is likely more secure.
There are various conformance levels and versions, such as "PDF/A-2b". There are various conformance levels and versions, such as "PDF/A-2b".
In general, the preferred format for scanned documents is PDF/A. Some In general, the preferred format for scanned documents is PDF/A. Some
governments and jurisdictions, US Courts in particular, `mandate the use governments and jurisdictions, US Courts in particular, [mandate the use
of PDF/A <https://pdfblog.com/2012/02/13/what-is-pdfa/>`__ for scanned of PDF/A](https://pdfblog.com/2012/02/13/what-is-pdfa/) for scanned
documents. documents.
Since most individuals scanning documents aim for long-term readability, Since most individuals scanning documents aim for long-term readability,
@@ -78,13 +73,12 @@ files can be digitally signed but may not be encrypted to ensure future
readability. Fortunately, converting from PDF/A to a regular PDF is readability. Fortunately, converting from PDF/A to a regular PDF is
straightforward, and any PDF viewer can handle PDF/A files. straightforward, and any PDF viewer can handle PDF/A files.
What OCRmyPDF does ## What OCRmyPDF does
==================
OCRmyPDF analyzes each page of a PDF to determine the required colorspace OCRmyPDF analyzes each page of a PDF to determine the required colorspace
and resolution (DPI) for capturing all the information on that page without and resolution (DPI) for capturing all the information on that page without
losing content. It uses losing content. It uses
`Ghostscript <http://ghostscript.com/>`__ to rasterize each page and subsequently [Ghostscript](http://ghostscript.com/) to rasterize each page and subsequently
performs OCR on the rasterized image to generate an OCR "layer." This layer performs OCR on the rasterized image to generate an OCR "layer." This layer
is then integrated back into the original PDF. is then integrated back into the original PDF.
@@ -101,10 +95,9 @@ options are utilized, the OCR layer is integrated into the processed image.
By default, OCRmyPDF generates archival PDFs in the PDF/A format, which is By default, OCRmyPDF generates archival PDFs in the PDF/A format, which is
a more rigid subset of PDF features designed for long-term archives. If you a more rigid subset of PDF features designed for long-term archives. If you
prefer regular PDFs, you can disable this feature using the prefer regular PDFs, you can disable this feature using the
``--output-type pdf`` option. `--output-type pdf` option.
Why you shouldn't do this manually ## Why you shouldn't do this manually
==================================
A PDF is similar to an HTML file, in that it contains document structure A PDF is similar to an HTML file, in that it contains document structure
along with images. While some PDFs may solely display a full-page image, along with images. While some PDFs may solely display a full-page image,
@@ -142,55 +135,53 @@ like pikepdf and QPDF, it can auto-repair damaged PDFs. You don't need to
understand the intricacies of these issues; you should be able to use understand the intricacies of these issues; you should be able to use
OCRmyPDF with any PDF file, and expect reasonable results. OCRmyPDF with any PDF file, and expect reasonable results.
Limitations ## Limitations
===========
OCRmyPDF is subject to limitations imposed by the Tesseract OCR engine. OCRmyPDF is subject to limitations imposed by the Tesseract OCR engine.
These limitations are inherent to any software relying on Tesseract: These limitations are inherent to any software relying on Tesseract:
- The OCR accuracy may not match that of commercial OCR solutions. - The OCR accuracy may not match that of commercial OCR solutions.
- It is incapable of recognizing handwriting. - It is incapable of recognizing handwriting.
- It may detect gibberish and report it as OCR output. - It may detect gibberish and report it as OCR output.
- Results may be subpar when a document contains languages not specified - Results may be subpar when a document contains languages not specified
in the ``-l LANG`` argument. in the `-l LANG` argument.
- Tesseract may struggle to analyze the natural reading order of documents. - Tesseract may struggle to analyze the natural reading order of documents.
For instance, it might fail to recognize two columns in a document and For instance, it might fail to recognize two columns in a document and
attempt to join text across columns. attempt to join text across columns.
- Poor quality scans can result in subpar OCR quality. In other words, the - Poor quality scans can result in subpar OCR quality. In other words, the
quality of the OCR output depends on the quality of the input. quality of the OCR output depends on the quality of the input.
- Tesseract does not provide information about the font family to which text - Tesseract does not provide information about the font family to which text
belongs. belongs.
- Tesseract does not divide text into paragraphs or headings. It only provides - Tesseract does not divide text into paragraphs or headings. It only provides
the text and its bounding box. As such, the generated PDF does not the text and its bounding box. As such, the generated PDF does not
contain any information about the document's structure. contain any information about the document's structure.
Ghostscript also imposes some limitations: Ghostscript also imposes some limitations:
- PDFs containing JPEG 2000-encoded content may be converted to JPEG - PDFs containing JPEG 2000-encoded content may be converted to JPEG
encoding, which may introduce compression artifacts, if Ghostscript encoding, which may introduce compression artifacts, if Ghostscript
PDF/A is enabled. PDF/A is enabled.
- Ghostscript may transcode grayscale and color images, potentially - Ghostscript may transcode grayscale and color images, potentially
lossily, based on an internal algorithm. This lossily, based on an internal algorithm. This
behavior can be suppressed by setting ``--pdfa-image-compression`` to behavior can be suppressed by setting `--pdfa-image-compression` to
``jpeg`` or ``lossless`` to set all images to one type or the other. `jpeg` or `lossless` to set all images to one type or the other.
Ghostscript lacks an option to maintain the input image's format. Ghostscript lacks an option to maintain the input image's format.
(Modern Ghostscript can copy JPEG images without transcoding them.) (Modern Ghostscript can copy JPEG images without transcoding them.)
- Ghostscript's PDF/A conversion removes any XMP metadata that is not - Ghostscript's PDF/A conversion removes any XMP metadata that is not
one of the standard XMP metadata namespaces for PDFs. In particular, one of the standard XMP metadata namespaces for PDFs. In particular,
PRISM Metadata is removed. PRISM Metadata is removed.
- Ghostscript's PDF/A conversion may remove or deactivate - Ghostscript's PDF/A conversion may remove or deactivate
hyperlinks and other active content. hyperlinks and other active content.
You can use ``--output-type pdf`` to disable PDF/A conversion and produce You can use `--output-type pdf` to disable PDF/A conversion and produce
a standard, non-archival PDF. a standard, non-archival PDF.
Regarding OCRmyPDF itself: Regarding OCRmyPDF itself:
- PDFs using transparency are not currently represented in the test - PDFs using transparency are not currently represented in the test
suite suite
Similar programs ## Similar programs
================
To the author's knowledge, OCRmyPDF is the most feature-rich and To the author's knowledge, OCRmyPDF is the most feature-rich and
thoroughly tested command line OCR PDF conversion tool. If it does not thoroughly tested command line OCR PDF conversion tool. If it does not
@@ -199,8 +190,7 @@ meet your needs, contributions and suggestions are welcome.
Ghostscript recently added three "pdfocr" output devices. They work by Ghostscript recently added three "pdfocr" output devices. They work by
rasterizing all content and converting all pages to a single colour space. rasterizing all content and converting all pages to a single colour space.
Web front-ends ## Web front-ends
==============
The Docker image of OCRmyPDF provides a web service front-end The Docker image of OCRmyPDF provides a web service front-end
that allows files to submitted over HTTP, and the results can be downloaded. that allows files to submitted over HTTP, and the results can be downloaded.
@@ -210,16 +200,14 @@ public internet and does not provide any security measures.
In addition, the following third-party integrations are available: In addition, the following third-party integrations are available:
- `Paperless-ngx <https://docs.paperless-ngx.com/>`__ is a free software - [Paperless-ngx](https://docs.paperless-ngx.com/) is a free software
document management system that uses OCRmyPDF to perform OCR on document management system that uses OCRmyPDF to perform OCR on
uploaded documents. uploaded documents.
- `Nextcloud OCR <https://github.com/janis91/ocr>`__ is a free software - [Nextcloud OCR](https://github.com/janis91/ocr) is a free software
plugin for the Nextcloud private cloud software. plugin for the Nextcloud private cloud software.
OCRmyPDF is not designed to be secure against malware-bearing PDFs (see OCRmyPDF is not designed to be secure against malware-bearing PDFs (see
`Using OCRmyPDF online <ocr-service>`__). Users should ensure they [Using OCRmyPDF online](ocr-service)). Users should ensure they
comply with OCRmyPDF's licenses and the licenses of all dependencies. In comply with OCRmyPDF's licenses and the licenses of all dependencies. In
particular, OCRmyPDF requires Ghostscript, which is licensed under particular, OCRmyPDF requires Ghostscript, which is licensed under
AGPLv3. AGPLv3.
.. |image| image:: images/bitmap_vs_svg.svg
+74
View File
@@ -0,0 +1,74 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
{#jbig2}
# Installing the JBIG2 encoder
Most Linux distributions do not include a JBIG2 encoder since JBIG2
encoding was patented for a long time. All known JBIG2 US patents have
expired as of 2017, but it is possible that unknown patents exist.
JBIG2 encoding is recommended for OCRmyPDF and is used to losslessly
create smaller PDFs. If JBIG2 encoding is not available, lower quality
CCITT encoding will be used for monochrome images.
JBIG2 decoding is not patented and is performed automatically by most
PDF viewers. It is widely supported and has been part of the PDF
specification since 2001.
JBIG encoding is automatically provided by these OCRmyPDF packages: -
Docker image (both Ubuntu and Alpine) - Snap package - ArchLinux AUR
package - Alpine Linux package - Homebrew on macOS
For all other platforms, you would need to build the JBIG2 encoder from
source:
:::{code} bash
git clone https://github.com/agl/jbig2enc
cd jbig2enc
./autogen.sh
./configure && make
[sudo] make install
:::
Dependencies include libtoolize and libleptonica, which on Ubuntu
systems are packaged as libtool and libleptonica-dev. On Fedora (35)
they are packaged as libtool and leptonica-devel. For this to work,
please make sure to install `autotools`, `automake`, `libtool` and
`leptonica` first if not already installed.
:::{code} bash
[sudo] apt install autotools-dev automake libtool libleptonica-dev
:::
{#jbig2-lossy}
## Lossy mode JBIG2
OCRmyPDF provides lossy mode JBIG2 as an advanced and potentially
dangerous feature. Users should [review the technical concerns with
JBIG2 in lossy mode](https://en.wikipedia.org/wiki/JBIG2#Disadvantages)
and decide if this feature is acceptable for their use case. In general,
this mode should not be used for archival purposes, should not be used
when the original document is not available or will be destroyed, and
should not be used when numbers present in the document are important,
because there is a risk of 6/8 and 8/6 substitution errors.
JBIG2 lossy mode does achieve higher compression ratios than any other
monochrome (bitonal) compression technology; for large text documents
the savings are considerable. JBIG2 lossless still gives great
compression ratios and is a major improvement over the older CCITT G4
standard.
To turn on JBIG2 lossy mode, add the argument `--jbig2-lossy`.
`--optimize {1,2,3}` are necessary for the argument to take effect also
required. Also, a JBIG2 encoder must be installed as described in the
previous section.
You can adjust the threshold for JBIG2 compression with the
`--jbig2-threshold`. The default is 0.85, meaning that if two symbols
are 85% similar, they will be compressed together.
*Due to an oversight, ocrmypdf v7.0 and v7.1 used lossy mode by
default.*
-81
View File
@@ -1,81 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
.. _jbig2:
============================
Installing the JBIG2 encoder
============================
Most Linux distributions do not include a JBIG2 encoder since JBIG2
encoding was patented for a long time. All known JBIG2 US patents have
expired as of 2017, but it is possible that unknown patents exist.
JBIG2 encoding is recommended for OCRmyPDF and is used to losslessly
create smaller PDFs. If JBIG2 encoding is not available, lower quality
CCITT encoding will be used for monochrome images.
JBIG2 decoding is not patented and is performed automatically by most
PDF viewers. It is widely supported and has been part of the PDF
specification since 2001.
JBIG encoding is automatically provided by these OCRmyPDF packages:
- Docker image (both Ubuntu and Alpine)
- Snap package
- ArchLinux AUR package
- Alpine Linux package
- Homebrew on macOS
For all other platforms, you would need to build the JBIG2 encoder from source:
.. code-block:: bash
git clone https://github.com/agl/jbig2enc
cd jbig2enc
./autogen.sh
./configure && make
[sudo] make install
Dependencies include libtoolize and libleptonica, which on Ubuntu systems
are packaged as libtool and libleptonica-dev. On Fedora (35) they are packaged
as libtool and leptonica-devel. For this to work, please make sure to install
``autotools``, ``automake``, ``libtool`` and ``leptonica`` first if not already
installed.
.. code-block:: bash
[sudo] apt install autotools-dev automake libtool libleptonica-dev
.. _jbig2-lossy:
Lossy mode JBIG2
================
OCRmyPDF provides lossy mode JBIG2 as an advanced and potentially dangerous
feature. Users should
`review the technical concerns with JBIG2 in lossy
mode <https://en.wikipedia.org/wiki/JBIG2#Disadvantages>`__
and decide if this feature is acceptable for their use case. In general,
this mode should not be used for archival purposes, should not be used when
the original document is not available or will be destroyed, and should
not be used when numbers present in the document are important, because
there is a risk of 6/8 and 8/6 substitution errors.
JBIG2 lossy mode does achieve higher compression ratios than any other
monochrome (bitonal) compression technology; for large text documents
the savings are considerable. JBIG2 lossless still gives great
compression ratios and is a major improvement over the older CCITT G4
standard.
To turn on JBIG2 lossy mode, add the argument ``--jbig2-lossy``.
``--optimize {1,2,3}`` are necessary for the argument to take effect
also required. Also, a JBIG2 encoder must be installed as described in
the previous section.
You can adjust the threshold for JBIG2 compression with the
``--jbig2-threshold``. The default is 0.85, meaning that if two symbols
are 85% similar, they will be compressed together.
*Due to an oversight, ocrmypdf v7.0 and v7.1 used lossy mode by
default.*
+129
View File
@@ -0,0 +1,129 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
(lang-packs)=
# Installing additional language packs
OCRmyPDF uses Tesseract for OCR, and relies on its language packs for all languages.
On most platforms, English is installed with Tesseract by default, but not always.
Tesseract supports [most
languages](https://github.com/tesseract-ocr/tesseract/blob/main/doc/tesseract.1.asc#languages).
Languages are identified by standardized three-letter codes (called ISO 639-2 Alpha-3).
Tesseract's documentation also lists the three-letter code for your language.
Some are anglicized, e.g. Spanish is `spa` rather than `esp`, while others
are not, e.g. German is `deu` and French is `fra`.
Language packs (strictly speaking, Tesseract "traineddata" files) generally correspond
to the language in question, but different language packs are used in certain
situations. For German, the "Fraktur" language pack can assist with reading older
materials in the Fraktur typeface family (`deu_frak`). Some communities have changed
their script from Cyrillic to Latin; the Cyrillic version of Uzbek is available
as `uzb_cyrl` and the Latin version is `uzb`.
After you have installed a language pack, you can use it with `ocrmypdf -l <language>`,
for example `ocrmypdf -l spa`. For multilingual documents, you can specify
all languages to be expected, e.g. `ocrmypdf -l eng+fra` for English and French.
English is assumed by default unless other language(s) are specified.
For Linux users, you can often find packages that provide language
packs.
## Platform install steps
### Debian and Ubuntu (apt)
```bash
# Display a list of all Tesseract language packs
apt-cache search tesseract-ocr
# Install Chinese Simplified language pack
apt-get install tesseract-ocr-chi-sim
```
You can then pass the `-l LANG` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either `-l eng+fra` (English and French) or
`-l eng -l fra`.
### Fedora
```bash
# Display a list of all Tesseract language packs
dnf search tesseract
# Install Chinese Simplified language pack
dnf install tesseract-langpack-chi_sim
```
You can then pass the `-l LANG` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either `-l eng+fra` (English and French) or
`-l eng -l fra`.
### Arch Linux
```bash
# Display a list of all Tesseract language packs
pacman -Ss tesseract-data
# Install German language pack
pacman -S tesseract-data-deu
```
You can then pass the `-l LANG` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either `-l eng+fra` (English and French) or
`-l eng -l fra`.
### Gentoo
On Gentoo the package `app-text/tessdata_fast`, which `app-text/tesseract` depends on, handles Tesseract languages.
It accepts USE flags to select what languages should be installed, these can be set in `/etc/portage/package.use`.
Alternatively one can globally set the [L10N use extension](https://wiki.gentoo.org/wiki/Localization/Guide#L10N) in `/etc/portage/make.conf`.
This enables these languages for all packages (e.g. including aspell).
```bash
# Display a list of all Tesseract language packs
equery uses app-text/tessdata_fast
# Add English and German language support for Tesseract only
echo 'app-text/tessdata_fast l10n_de l10n_en' >> /etc/portage/package.use
# Add global English and German language support (the `l10n_` from equery has to be omitted)
echo L10N="de en" >> /etc/portage/make.conf
# update system to reflect changed USE flags
emerge --update --deep --newuse @world
```
You can then pass the `-l LANG` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either `-l eng+fra` (English and French) or
`-l eng -l fra`.
### macOS
You can install additional language packs by
{ref}`installing Tesseract using Homebrew with all language packs <macos-all-languages>`.
### Docker
Users of the OCRmyPDF Docker image should install language packs into a
derived Docker image as
{ref}`described in that section <docker-lang-packs>`.
### Windows
The Tesseract installer provided by Chocolatey currently includes only English language.
To install other languages, download the respective language pack (`.traineddata` file)
from <https://github.com/tesseract-ocr/tessdata/> and place it in
`C:\\Program Files\\Tesseract-OCR\\tessdata` (or wherever Tesseract OCR is installed).
## Custom language packs
If you have fine-tuned or trained Tesseract and generated custom trained data, you can
copy your `customlang.traineddata` file into your Tesseract "tessdata" folder, and
then use the `-l customlang` argument to tell OCRmyPDF to pass that language on to
Tesseract.
-141
View File
@@ -1,141 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
.. _lang-packs:
====================================
Installing additional language packs
====================================
OCRmyPDF uses Tesseract for OCR, and relies on its language packs for all languages.
On most platforms, English is installed with Tesseract by default, but not always.
Tesseract supports `most
languages <https://github.com/tesseract-ocr/tesseract/blob/main/doc/tesseract.1.asc#languages>`__.
Languages are identified by standardized three-letter codes (called ISO 639-2 Alpha-3).
Tesseract's documentation also lists the three-letter code for your language.
Some are anglicized, e.g. Spanish is ``spa`` rather than ``esp``, while others
are not, e.g. German is ``deu`` and French is ``fra``.
Language packs (strictly speaking, Tesseract "traineddata" files) generally correspond
to the language in question, but different language packs are used in certain
situations. For German, the "Fraktur" language pack can assist with reading older
materials in the Fraktur typeface family (``deu_frak``). Some communities have changed
their script from Cyrillic to Latin; the Cyrillic version of Uzbek is available
as ``uzb_cyrl`` and the Latin version is ``uzb``.
After you have installed a language pack, you can use it with ``ocrmypdf -l <language>``,
for example ``ocrmypdf -l spa``. For multilingual documents, you can specify
all languages to be expected, e.g. ``ocrmypdf -l eng+fra`` for English and French.
English is assumed by default unless other language(s) are specified.
For Linux users, you can often find packages that provide language
packs.
Platform install steps
======================
Debian and Ubuntu (apt)
-----------------------
.. code-block:: bash
# Display a list of all Tesseract language packs
apt-cache search tesseract-ocr
# Install Chinese Simplified language pack
apt-get install tesseract-ocr-chi-sim
You can then pass the ``-l LANG`` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either ``-l eng+fra`` (English and French) or
``-l eng -l fra``.
Fedora
------
.. code-block:: bash
# Display a list of all Tesseract language packs
dnf search tesseract
# Install Chinese Simplified language pack
dnf install tesseract-langpack-chi_sim
You can then pass the ``-l LANG`` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either ``-l eng+fra`` (English and French) or
``-l eng -l fra``.
Arch Linux
----------
.. code-block:: bash
# Display a list of all Tesseract language packs
pacman -Ss tesseract-data
# Install German language pack
pacman -S tesseract-data-deu
You can then pass the ``-l LANG`` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either ``-l eng+fra`` (English and French) or
``-l eng -l fra``.
Gentoo
------
On Gentoo the package ``app-text/tessdata_fast``, which ``app-text/tesseract`` depends on, handles Tesseract languages.
It accepts USE flags to select what languages should be installed, these can be set in ``/etc/portage/package.use``.
Alternatively one can globally set the `L10N use extension <https://wiki.gentoo.org/wiki/Localization/Guide#L10N>`__ in ``/etc/portage/make.conf``.
This enables these languages for all packages (e.g. including aspell).
.. code-block:: bash
# Display a list of all Tesseract language packs
equery uses app-text/tessdata_fast
# Add English and German language support for Tesseract only
echo 'app-text/tessdata_fast l10n_de l10n_en' >> /etc/portage/package.use
# Add global English and German language support (the `l10n_` from equery has to be omitted)
echo L10N="de en" >> /etc/portage/make.conf
# update system to reflect changed USE flags
emerge --update --deep --newuse @world
You can then pass the ``-l LANG`` argument to OCRmyPDF to give a hint as
to what languages it should search for. Multiple languages can be
requested using either ``-l eng+fra`` (English and French) or
``-l eng -l fra``.
macOS
-----
You can install additional language packs by
:ref:`installing Tesseract using Homebrew with all language packs <macos-all-languages>`.
Docker
------
Users of the OCRmyPDF Docker image should install language packs into a
derived Docker image as
:ref:`described in that section <docker-lang-packs>`.
Windows
-------
The Tesseract installer provided by Chocolatey currently includes only English language.
To install other languages, download the respective language pack (``.traineddata`` file)
from https://github.com/tesseract-ocr/tessdata/ and place it in
``C:\\Program Files\\Tesseract-OCR\\tessdata`` (or wherever Tesseract OCR is installed).
Custom language packs
=====================
If you have fine-tuned or trained Tesseract and generated custom trained data, you can
copy your ``customlang.traineddata`` file into your Tesseract "tessdata" folder, and
then use the ``-l customlang`` argument to tell OCRmyPDF to pass that language on to
Tesseract.
+71
View File
@@ -0,0 +1,71 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Maintainer notes
This is for those who package OCRmyPDF for downstream use. (Thank you
for your hard work.)
## Known ports/packagers
OCRmyPDF has been ported to many platforms already. If you are
interesting in porting to a new platform, check with
[Repology](https://repology.org/projects/?search=ocrmypdf) to see the
status of that platform.
### Make sure you can package pikepdf
pikepdf, created by the same author, is a mixed Python and C++14 package
with much stiffer build requirements. If you want to use OCRmyPDF on
some novel platform or distribution, first make sure you can package
pikepdf.
### Non-Python dependencies
Note that we have non-Python dependencies. In particular, OCRmyPDF
requires Ghostscript and Tesseract OCR to be installed and needs to be
able to locate their binaries on the system PATH. On Windows, OCRmyPDF
will also check the registry for their locations.
Tesseract OCR relies on SIMD for performance and only has proper support
for this on ARM and x86\_64. Performance may be poor on other processor
architectures.
### Versioning scheme
OCRmyPDF uses hatch-vcs for versioning, which derives the version from
Git as a single source of truth. This may be unsuitable for some
distributions, e.g. to indicate that your distribution modifies OCRmyPDF
in some way.
You can patch the `__version__` variable in `src/ocrmypdf/_version.py`
if necessary, or set the environment variable
`SETUPTOOLS_SCM_PRETEND_VERSION` to the required version, if you need to
override versioning for some reason.
### jbig2enc
OCRmyPDF will use jbig2enc, a JBIG2 encoder, if one can be found. Some
distributions have shied away from packaging JBIG2 because it contains
patented algorithms, but all patents have expired since 2017. If
possible, consider packaging it too to improve OCRmyPDF\'s compression.
### Command line completions
Please ensure that command line completions are installed, as described
in the installation documentation.
### 32-bit Linux support
If you maintain a Linux distribution that supports 32-bit x86 or ARM,
OCRmyPDF should continue to work as long as all of its dependencies
continue to be available in 32-bit form. Please note we do not test on
32-bit platforms.
### HEIF/HEIC
OCRmyPDF defaults to installing the pi-heif PyPI package, which supports
converting HEIF (High Efficiency Image File Format) images to PDF from
the command line. If your distribution does not have this library
available, you can exclude it and OCRmyPDF will gracefully degrade
automatically, losing only support for this feature.
-77
View File
@@ -1,77 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
================
Maintainer notes
================
This is for those who package OCRmyPDF for downstream use. (Thank you
for your hard work.)
Known ports/packagers
=====================
OCRmyPDF has been ported to many platforms already. If you are interesting in
porting to a new platform, check with
`Repology <https://repology.org/projects/?search=ocrmypdf>`__ to see the status
of that platform.
Make sure you can package pikepdf
---------------------------------
pikepdf, created by the same author, is a mixed Python and C++14 package with
much stiffer build requirements. If you want to use OCRmyPDF on some novel platform
or distribution, first make sure you can package pikepdf.
Non-Python dependencies
-----------------------
Note that we have non-Python dependencies. In particular, OCRmyPDF requires
Ghostscript and Tesseract OCR to be installed and needs to be able to locate their
binaries on the system PATH. On Windows, OCRmyPDF will also check the registry
for their locations.
Tesseract OCR relies on SIMD for performance and only has proper support for this
on ARM and x86_64. Performance may be poor on other processor architectures.
Versioning scheme
-----------------
OCRmyPDF uses hatch-vcs for versioning, which derives the version from
Git as a single source of truth. This may be unsuitable for some distributions, e.g.
to indicate that your distribution modifies OCRmyPDF in some way.
You can patch the ``__version__`` variable in ``src/ocrmypdf/_version.py`` if
necessary, or set the environment variable ``SETUPTOOLS_SCM_PRETEND_VERSION``
to the required version, if you need to override versioning for some reason.
jbig2enc
--------
OCRmyPDF will use jbig2enc, a JBIG2 encoder, if one can be found. Some distributions
have shied away from packaging JBIG2 because it contains patented algorithms, but
all patents have expired since 2017. If possible, consider packaging it too to
improve OCRmyPDF's compression.
Command line completions
------------------------
Please ensure that command line completions are installed, as described in the
installation documentation.
32-bit Linux support
--------------------
If you maintain a Linux distribution that supports 32-bit x86 or ARM, OCRmyPDF
should continue to work as long as all of its dependencies continue to be
available in 32-bit form. Please note we do not test on 32-bit platforms.
HEIF/HEIC
---------
OCRmyPDF defaults to installing the pi-heif PyPI package, which supports converting
HEIF (High Efficiency Image File Format) images to PDF from the command line.
If your distribution does not have this library available, you can exclude it and
OCRmyPDF will gracefully degrade automatically, losing only support for this
feature.
+111
View File
@@ -0,0 +1,111 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# PDF optimization
OCRmyPDF includes an image-oriented PDF optimizer. By default, the
optimizer runs with safe settings with the goal of improving compression
at no loss of quality. At higher optimization levels, lossy
optimizations may be applied and tuned. Optimization occurs after OCR,
and only if OCR succeeded. It does not perform other possible
optimizations such as deduplicating resources, consolidating fonts,
simplifying vector drawings, or anything of that nature.
:::{list-table} OCRmyPDF optimization settings
---
widths: 33 6 60
header-rows: 1
---
* - Optimization level
- Shorthand
- Description
* - ``--optimize 0``
- ``-O0``
- Disable most optimizations.
* - ``--optimize 1`` (default)
- ``-O1``
- Enables lossless optimizations, such as transcoding images to more
efficient formats. Also compress other uncompressed objects in the
PDF and enables the more efficient "object streams" within the PDF.
(If ``--jbig2-lossy`` is issued, then lossy JBIG2 optimization is used.
The decision to use lossy JBIG2 is separate from standard optimization
settings.)
* - ``--optimize 2``
- ``-O2``
- All of the above, and enables lossy optimizations and color quantization.
* - ``--optimize 3``
- ``-O3``
- All of the above, and enables more aggressive optimizations and targets lower
image quality.
:::
The exact type of optimizations performed will vary over time, and
depend on what third party tools are installed.
Despite optimizations, OCRmyPDF might still increase the overall file
size, since it must embed information about the recognized text, and
depending on the settings chosen, may not be able to represent the
output file as compactly as the input file.
## Optimizations that always occurs
OCRmyPDF will automatically replace obsolete or inferior compression
schemes such as RLE or LZW with superior schemes such as Deflate, and
convert monochrome images to CCITT G4. Since this is lossless, it always
occurs and there is no way to disable it. Other non-image compressed
objects are compressed as well.
## Fast web view
OCRmyPDF automatically optimizes PDFs for \"fast web view\" in Adobe
Acrobat\'s parlance, or equivalently, linearizes PDFs so that the
resources they reference are presented in the order a viewer needs them
for sequential display. This reduces the latency of viewing a PDF both
online and from local storage, in exchange for a slight increase in file
size.
To disable this optimization and all others, use
`ocrmypdf --optimize 0 ...` or the shorthand `-O0`.
Adobe Acrobat might not report the file as being \"fast web view\".
## Lossless optimizations
At optimization level `-O1` (the default), OCRmyPDF will also attempt
lossless image optimization.
If a JBIG2 encoder is available, then monochrome images will be
converted to JBIG2, with the potential for huge savings on large black
and white images, since JBIG2 is far more efficient than any other
monochrome (bi-level) compression. (All known US patents related to
JBIG2 have probably expired, but it remains the responsibility of the
user to supply a JBIG2 encoder such as
[jbig2enc](https://github.com/agl/jbig2enc). OCRmyPDF does not implement
JBIG2 encoding on its own.)
OCRmyPDF currently does not attempt to recompress losslessly compressed
objects more aggressively.
## Lossy optimizations
At optimization level `-O1`, `-O2` and `-O3`, OCRmyPDF will some attempt
loss image optimization.
If Ghostscript is used to create a PDF/A (the default), Ghostscript will
optimize some images by converting them to JPEG, which are lossy. If
`--output-type pdf` is used, there are no lossy optimizations. Ghostscript's
JPEG conversion is quite safe.
If `pngquant` is installed, OCRmyPDF will use it to perform quantize
paletted images to reduce their size.
The quality of JPEGs may be lowered, on the assumption that a lower
quality image may be suitable for storage after OCR.
It is not possible to optimize all image types. Uncommon image types may
be skipped by the optimizer.
OCRmyPDF provides `lossy mode JBIG2 <jbig2-lossy>`{.interpreted-text
role="ref"} as an advanced feature that additional requires the argument
`--jbig2-lossy`.
-100
View File
@@ -1,100 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
================
PDF optimization
================
OCRmyPDF includes an image-oriented PDF optimizer. By default, the optimizer
runs with safe settings with the goal of improving compression at no loss of
quality. At higher optimization levels, lossy optimizations may be applied and
tuned. Optimization occurs after OCR, and only if OCR succeeded. It does not
perform other possible optimizations such as deduplicating resources,
consolidating fonts, simplifying vector drawings, or anything of that nature.
.. list-table:: Title
:widths: 33 6 60
:header-rows: 1
* - Optimization level
- Shorthand
- Description
* - ``--optimize 0``
- ``-O0``
- Disable most optimizations.
* - ``--optimize 1`` (default)
- ``-O1``
- Safe and lossless optimizations.
* - ``--optimize 2``
- ``-O2``
- Safe and lossy optimizations.
* - ``--optimize 3``
- ``-O3``
- Aggressive lossy optimizations.
The exact type of optimizations performed will vary over time, and depend on
the availability of third-party tools.
Despite optimizations, OCRmyPDF might still increase the overall file size,
since it must embed information about the recognized text, and depending on the
settings chosen, may not be able to represent the output file as compactly as
the input file.
Optimizations that always occurs
================================
OCRmyPDF will automatically replace obsolete or inferior compression schemes
such as RLE or LZW with superior schemes such as Deflate, and convert
monochrome images to CCITT G4. Since this is lossless, it always occurs and there
is no way to disable it. Other non-image compressed objects are compressed as
well.
Fast web view
=============
OCRmyPDF automatically optimizes PDFs for "fast web view" in Adobe Acrobat's
parlance, or equivalently, linearizes PDFs so that the resources they reference
are presented in the order a viewer needs them for sequential display. This
reduces the latency of viewing a PDF both online and from local storage, in
exchange for a slight increase in file size.
To disable this optimization and all others, use ``ocrmypdf --optimize 0 ...``
or the shorthand ``-O0``.
Adobe Acrobat might not report the file as being "fast web view".
Lossless optimizations
======================
At optimization level ``-O1`` (the default), OCRmyPDF will also attempt lossless
image optimization.
If a JBIG2 encoder is available, then monochrome images will be converted to
JBIG2, with the potential for huge savings on large black and white images,
since JBIG2 is far more efficient than any other monochrome (bi-level)
compression. (All known US patents related to JBIG2 have probably expired, but
it remains the responsibility of the user to supply a JBIG2 encoder such as
`jbig2enc <https://github.com/agl/jbig2enc>`__. OCRmyPDF does not implement
JBIG2 encoding on its own.)
OCRmyPDF currently does not attempt to recompress losslessly compressed objects
more aggressively.
Lossy optimizations
===================
At optimization level ``-O2`` and ``-O3``, OCRmyPDF will some attempt lossy
image optimization.
If ``pngquant`` is installed, OCRmyPDF will use it to perform quantize paletted
images to reduce their size.
The quality of JPEGs may be lowered, on the assumption that a lower quality
image may be suitable for storage after OCR.
It is not possible to optimize all image types. Uncommon image types may be
skipped by the optimizer.
OCRmyPDF provides :ref:`lossy mode JBIG2 <jbig2-lossy>` as an advanced feature
that additional requires the argument ``--jbig2-lossy``.
+47 -59
View File
@@ -1,15 +1,9 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow (security)=
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
.. _security: # PDF security issues
=================== > OCRmyPDF should only be used on PDFs you trust. It is not designed to
PDF security issues > protect you against malware.
===================
OCRmyPDF should only be used on PDFs you trust. It is not designed to
protect you against malware.
Recognizing that many users have an interest in handling PDFs and Recognizing that many users have an interest in handling PDFs and
applying OCR to PDFs they did not generate themselves, this article applying OCR to PDFs they did not generate themselves, this article
@@ -18,89 +12,84 @@ themselves.
The disclaimer applies: this software has no warranties of any kind. The disclaimer applies: this software has no warranties of any kind.
PDFs may contain malware ## PDFs may contain malware
========================
PDF is a rich, complex file format. The official PDF 1.7 specification, PDF is a rich, complex file format. The official PDF 1.7 specification,
ISO 32000:2008, is hundreds of pages long and references several annexes ISO 32000:2008, is hundreds of pages long and references several annexes
each of which are similar in length. PDFs can contain video, audio, XML, each of which are similar in length. PDFs can contain video, audio, XML,
JavaScript and other programming, and forms. In some cases, they can JavaScript and other programming, and forms. In some cases, they can
open internet connections to pre-selected URLs. All of these are possible open internet connections to pre-selected URLs. All of these are
attack vectors. possible attack vectors.
In short, PDFs `may contain In short, PDFs [may contain
viruses <https://security.stackexchange.com/questions/64052/can-a-pdf-file-contain-a-virus>`__. viruses](https://security.stackexchange.com/questions/64052/can-a-pdf-file-contain-a-virus).
If you do not trust a PDF or its source, do not open it or use OCRmyPDF If you do not trust a PDF or its source, do not open it or use OCRmyPDF
on it. Consider using a Docker container or virtual machine to isolate on it. Consider using a Docker container or virtual machine to isolate
an untrusted PDF from your system. an untrusted PDF from your system.
How OCRmyPDF processes PDFs ## How OCRmyPDF processes PDFs
===========================
OCRmyPDF must open and interpret your PDF in order to insert an OCR OCRmyPDF must open and interpret your PDF in order to insert an OCR
layer. First, it runs all PDFs through layer. First, it runs all PDFs through
`pikepdf <https://github.com/pikepdf/pikepdf>`__, a library based on [pikepdf](https://github.com/pikepdf/pikepdf), a library based on
`QPDF <https://github.com/qpdf/qpdf>`__, a program that repairs PDFs [QPDF](https://github.com/qpdf/qpdf), a program that repairs PDFs with
with syntax errors. This is done because, in the author's experience, a syntax errors. This is done because, in the author\'s experience, a
significant number of PDFs in the wild, especially those created by significant number of PDFs in the wild, especially those created by
scanners, are not well-formed files. QPDF makes it more likely that scanners, are not well-formed files. QPDF makes it more likely that
OCRmyPDF will succeed, but offers no security guarantees. QPDF is also OCRmyPDF will succeed, but offers no security guarantees. QPDF is also
used to split the PDF into single page PDFs. used to split the PDF into single page PDFs.
Finally, OCRmyPDF rasterizes each page of the PDF using Finally, OCRmyPDF rasterizes each page of the PDF using
`Ghostscript <http://ghostscript.com/>`__ in ``-dSAFER`` mode. [Ghostscript](http://ghostscript.com/) in `-dSAFER` mode.
Depending on the options specified, OCRmyPDF may graft the OCR layer Depending on the options specified, OCRmyPDF may graft the OCR layer
into the existing PDF or it may essentially reconstruct ("re-fry") a into the existing PDF or it may essentially reconstruct (\"re-fry\") a
visually identical PDF that may be quite different at the binary level. visually identical PDF that may be quite different at the binary level.
That said, OCRmyPDF is not a tool designed for sanitizing PDFs. That said, OCRmyPDF is not a tool designed for sanitizing PDFs.
Password protected PDFs ## Password protected PDFs
=======================
Password protected PDFs usually have two passwords, and owner and user Password protected PDFs usually have two passwords, and owner and user
password. When the user password is set to empty, PDF readers will open password. When the user password is set to empty, PDF readers will open
the file automatically and mark it as "(SECURED)". Password security can the file automatically and mark it as \"(SECURED)\". Password security
also request certain restrictions on the PDF, but anyone can remove these can also request certain restrictions on the PDF, but anyone can remove
restrictions if they have either the owner *or* user password. Passwords these restrictions if they have either the owner *or* user password.
mainly present a barrier for casual users. Passwords mainly present a barrier for casual users.
OCRmyPDF cannot remove passwords from PDFs. If you want to remove a OCRmyPDF cannot remove passwords from PDFs. If you want to remove a
password from a PDF, you must use other software, such as ``qpdf``. password from a PDF, you must use other software, such as `qpdf`.
If the owner and user password are set, a If the owner and user password are set, a password is required for
password is required for ``qpdf``. If only the owner password is set, then the `qpdf`. If only the owner password is set, then the password can be
password can be stripped, even if one does not have the owner password. To stripped, even if one does not have the owner password. To remove the
remove the password from a using QPDF, use: password from a using QPDF, use:
.. code-block:: bash :::{code} bash
qpdf --decrypt --password='abc123' input.pdf no_password.pdf
qpdf --decrypt --password='abc123' input.pdf no_password.pdf :::
Then you can run OCRmyPDF on the file. Then you can run OCRmyPDF on the file.
In its default mode, OCRmyPDF generates PDF/A. Passwords may not be set on PDF/A In its default mode, OCRmyPDF generates PDF/A. Passwords may not be set
documents. If you want to set a password on the output PDF, you must on PDF/A documents. If you want to set a password on the output PDF, you
specify ``--output-type pdf``. must specify `--output-type pdf`.
Signature images ## Signature images
================
Many programs exist which are capable of inserting an image of someone's Many programs exist which are capable of inserting an image of
signature. On its own, this offers no security guarantees. It is trivial someone\'s signature. On its own, this offers no security guarantees. It
to remove the signature image and apply it to other files. This practice is trivial to remove the signature image and apply it to other files.
offers no real security. This practice offers no real security.
Digital signatures ## Digital signatures
==================
Important documents can be digitally signed and certified to attest to Important documents can be digitally signed and certified to attest to
their authorship, approval or execution of a legal agreement. OCRmyPDF their authorship, approval or execution of a legal agreement. OCRmyPDF
will detect signed PDFs and will not modify them, unless the will detect signed PDFs and will not modify them, unless the
``--invalidate-digital-signatures`` option is used, which will `--invalidate-digital-signatures` option is used, which will invalidate
invalidate any signatures. (The signature may still be present in the PDF any signatures. (The signature may still be present in the PDF if
if opened, but PDF readers will not validate it.) opened, but PDF readers will not validate it.)
A digital signature adds a cryptographic hash of the document to the A digital signature adds a cryptographic hash of the document to the
document, so tamper protection is provided. That also precludes OCRmyPDF document, so tamper protection is provided. That also precludes OCRmyPDF
@@ -108,20 +97,19 @@ from modifying the document and preserving the signature.
Digital signatures are not the same as a signature image. A digital Digital signatures are not the same as a signature image. A digital
signature is a cryptographic hash of the document that is encrypted with signature is a cryptographic hash of the document that is encrypted with
the author's private key. The signature is decrypted with the author's the author\'s private key. The signature is decrypted with the author\'s
public key. The public key is usually distributed by a certificate public key. The public key is usually distributed by a certificate
authority. The signature is then verified by the PDF reader. If the authority. The signature is then verified by the PDF reader. If the
document is modified, the signature will be invalidated. document is modified, the signature will be invalidated.
Certificate-encrypted PDFs ## Certificate-encrypted PDFs
==========================
PDFs can be encrypted with a certificate. This is a more secure form of PDFs can be encrypted with a certificate. This is a more secure form of
encryption than a password. The certificate is usually issued by a encryption than a password. The certificate is usually issued by a
certificate authority. A certificate is used to encrypt the document using certificate authority. A certificate is used to encrypt the document
the public key for the benefit of a specific recipient who possesses using the public key for the benefit of a specific recipient who
the private key. possesses the private key.
OCRmyPDF cannot open certificate-encrypted PDFs. If you have the OCRmyPDF cannot open certificate-encrypted PDFs. If you have the
certificate, you can use other PDF software, such as Acrobat, to certificate, you can use other PDF software, such as Acrobat, to decrypt
decrypt the PDF. the PDF.
+24
View File
@@ -0,0 +1,24 @@
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
# Performance
Some users have noticed that current versions of OCRmyPDF do not run as
quickly as some older versions (specifically 6.x and older). This is
because OCRmyPDF added image optimization as a postprocessing step, and
it is enabled by default.
## Speed
If running OCRmyPDF quickly is your main goal, you can use settings such
as:
- `--optimize 0` to disable file size optimization
- `--output-type pdf` to disable PDF/A generation
- `--fast-web-view 999999` to disable fast web view optimization
- `--skip-big` to skip large images, if some pages have large images
You can also avoid:
- `--force-ocr`
- Image preprocessing
-26
View File
@@ -1,26 +0,0 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow
..
.. SPDX-License-Identifier: CC-BY-SA-4.0
===========
Performance
===========
Some users have noticed that current versions of OCRmyPDF do not run as quickly
as some older versions (specifically 6.x and older). This is because OCRmyPDF
added image optimization as a postprocessing step, and it is enabled by default.
Speed
=====
If running OCRmyPDF quickly is your main goal, you can use settings such as:
* ``--optimize 0`` to disable file size optimization
* ``--output-type pdf`` to disable PDF/A generation
* ``--fast-web-view 999999`` to disable fast web view optimization
* ``--skip-big`` to skip large images, if some pages have large images
You can also avoid:
* ``--force-ocr``
* Image preprocessing
+104 -86
View File
@@ -1,15 +1,12 @@
.. SPDX-FileCopyrightText: 2022 James R. Barlow % SPDX-FileCopyrightText: 2022 James R. Barlow
.. % SPDX-License-Identifier: CC-BY-SA-4.0
.. SPDX-License-Identifier: CC-BY-SA-4.0
======= # Plugins
Plugins
=======
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL > The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and > NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in > "OPTIONAL" in this document are to be interpreted as described in
RFC 2119. > RFC 2119.
You can use plugins to customize the behavior of OCRmyPDF at certain points of You can use plugins to customize the behavior of OCRmyPDF at certain points of
interest. interest.
@@ -24,75 +21,71 @@ Currently, it is possible to:
- replace Ghostscript with another PDF to image converter (rasterizer) or - replace Ghostscript with another PDF to image converter (rasterizer) or
PDF/A generator PDF/A generator
OCRmyPDF plugins are based on the Python ``pluggy`` package and conform to its OCRmyPDF plugins are based on the Python `pluggy` package and conform to its
conventions. Note that: plugins installed with as setuptools entrypoints are conventions. Note that: plugins installed with as setuptools entrypoints are
not checked currently, because OCRmyPDF assumes you may not want to enable not checked currently, because OCRmyPDF assumes you may not want to enable
plugins for all files. plugins for all files.
See [OCRmyPDF-EasyOCR](https://github.com/ocrmypdf/OCRmyPDF-EasyOCR) for an See \[OCRmyPDF-EasyOCR\](<https://github.com/ocrmypdf/OCRmyPDF-EasyOCR>) for an
example of a straightforward, fully working plugin. example of a straightforward, fully working plugin.
Script plugins ## Script plugins
==============
Script plugins may be called from the command line, by specifying the name of a file. Script plugins may be called from the command line, by specifying the name of a file.
Script plugins may be convenient for informal or "one-off" plugins, when a certain Script plugins may be convenient for informal or "one-off" plugins, when a certain
batch of files needs a special processing step for example. batch of files needs a special processing step for example.
.. code-block:: bash ```bash
ocrmypdf --plugin ocrmypdf_example_plugin.py input.pdf output.pdf
```
ocrmypdf --plugin ocrmypdf_example_plugin.py input.pdf output.pdf Multiple plugins may be installed by issuing the `--plugin` argument multiple times.
Multiple plugins may be installed by issuing the ``--plugin`` argument multiple times. ## Packaged plugins
Packaged plugins
================
Installed plugins may be installed into the same virtual environment as OCRmyPDF Installed plugins may be installed into the same virtual environment as OCRmyPDF
is installed into. They may be invoked using Python standard module naming. is installed into. They may be invoked using Python standard module naming.
If you are intending to distribute a plugin, please package it. If you are intending to distribute a plugin, please package it.
.. code-block:: bash ```bash
ocrmypdf --plugin ocrmypdf_fancypants.pockets.contents input.pdf output.pdf
ocrmypdf --plugin ocrmypdf_fancypants.pockets.contents input.pdf output.pdf ```
OCRmyPDF does not automatically import plugins, because the assumption is that OCRmyPDF does not automatically import plugins, because the assumption is that
plugins affect different files differently and you may not want them activated plugins affect different files differently and you may not want them activated
all the time. The command line or ``ocrmypdf.ocr(plugin='...')`` must call all the time. The command line or `ocrmypdf.ocr(plugin='...')` must call
for them. for them.
Third parties that wish to distribute packages for ocrmypdf should package them Third parties that wish to distribute packages for ocrmypdf should package them
as packaged plugins, and these modules should begin with the name ``ocrmypdf_`` as packaged plugins, and these modules should begin with the name `ocrmypdf_`
similar to ``pytest`` packages such as ``pytest-cov`` (the package) and similar to `pytest` packages such as `pytest-cov` (the package) and
``pytest_cov`` (the module). `pytest_cov` (the module).
.. note:: :::{note}
We recommend plugin authors name their plugins with the prefix
`ocrmypdf-` (for the package name on PyPI) and `ocrmypdf_` (for the
module), just like pytest plugins. At the same time, please make it clear
that your package is not official.
:::
We recommend plugin authors name their plugins with the prefix ## Plugins
``ocrmypdf-`` (for the package name on PyPI) and ``ocrmypdf_`` (for the
module), just like pytest plugins. At the same time, please make it clear
that your package is not official.
Plugins
=======
You can also create a plugin that OCRmyPDF will always automatically load if both are You can also create a plugin that OCRmyPDF will always automatically load if both are
installed in the same virtual environment, using a project entrypoint. installed in the same virtual environment, using a project entrypoint.
OCRmyPDF uses the entrypoint namespace "ocrmypdf". OCRmyPDF uses the entrypoint namespace "ocrmypdf".
For example, ``pyproject.toml`` would need to contain the following, for a plugin named For example, `pyproject.toml` would need to contain the following, for a plugin named
``ocrmypdf-exampleplugin``: `ocrmypdf-exampleplugin`:
.. code-block:: toml ```toml
[project]
name = "ocrmypdf-exampleplugin"
[project] [project.entry-points."ocrmypdf"]
name = "ocrmypdf-exampleplugin" exampleplugin = "exampleplugin.pluginmodule"
```
[project.entry-points."ocrmypdf"] ## Plugin requirements
exampleplugin = "exampleplugin.pluginmodule"
Plugin requirements
===================
OCRmyPDF generally uses multiple worker processes. When a new worker is started, OCRmyPDF generally uses multiple worker processes. When a new worker is started,
Python will import all plugins again, including all plugins that were imported earlier. Python will import all plugins again, including all plugins that were imported earlier.
@@ -103,14 +96,14 @@ to obtain a reference to shared state prepared by another hook implementation.
Plugins must expect that other instances of the plugin will be running Plugins must expect that other instances of the plugin will be running
simultaneously. simultaneously.
The ``context`` object that is passed to many hooks can be used to share information The `context` object that is passed to many hooks can be used to share information
about a file being worked on. Plugins must write private, plugin-specific data to about a file being worked on. Plugins must write private, plugin-specific data to
a subfolder named ``{options.work_folder}/ocrmypdf-plugin-name``. Plugins MAY a subfolder named `{options.work_folder}/ocrmypdf-plugin-name`. Plugins MAY
read and write files in ``options.work_folder``, but should be aware that their read and write files in `options.work_folder`, but should be aware that their
semantics are subject to change. semantics are subject to change.
OCRmyPDF will delete ``options.work_folder`` when it has finished OCRing OCRmyPDF will delete `options.work_folder` when it has finished OCRing
a file, unless invoked with ``--keep-temporary-files``. a file, unless invoked with `--keep-temporary-files`.
The documentation for some plugin hooks contain a detailed description of the The documentation for some plugin hooks contain a detailed description of the
execution context in which they will be called. execution context in which they will be called.
@@ -119,114 +112,139 @@ Plugins should be prepared to work whether executed in worker threads or worker
processes. Generally, OCRmyPDF uses processes, but has a semi-hidden threaded processes. Generally, OCRmyPDF uses processes, but has a semi-hidden threaded
argument that simplifies debugging. argument that simplifies debugging.
## Plugin hooks
Plugin hooks
============
A plugin may provide the following hooks. Hooks must be decorated with A plugin may provide the following hooks. Hooks must be decorated with
``ocrmypdf.hookimpl``, for example: `ocrmypdf.hookimpl`, for example:
.. code-block:: python ```python
from ocrmpydf import hookimpl
from ocrmpydf import hookimpl @hookimpl
def add_options(parser):
@hookimpl pass
def add_options(parser): ```
pass
The following is a complete list of hooks that are available, and when The following is a complete list of hooks that are available, and when
they are called. they are called.
.. _firstresult: (firstresult)=
**Note on firstresult hooks** **Note on firstresult hooks**
If multiple plugins install implementations for this hook, they will be called in If multiple plugins install implementations for this hook, they will be called in
the reverse of the order in which they are installed (i.e., last plugin wins). the reverse of the order in which they are installed (i.e., last plugin wins).
When each hook implementation is called in order, the first implementation that When each hook implementation is called in order, the first implementation that
returns a value other than ``None`` will "win" and prevent execution of all other returns a value other than `None` will "win" and prevent execution of all other
hooks. As such, you cannot "chain" a series of plugin filters together in this hooks. As such, you cannot "chain" a series of plugin filters together in this
way. Instead, a single hook implementation should be responsible for any such way. Instead, a single hook implementation should be responsible for any such
chaining operations. chaining operations.
Examples ## Examples
========
* OCRmyPDF's test suite contains several plugins that are used to simulate certain - OCRmyPDF's test suite contains several plugins that are used to simulate certain
test conditions. test conditions.
* `ocrmypdf-papermerge <https://github.com/papermerge/OCRmyPDF_papermerge>`_ is - [ocrmypdf-papermerge](https://github.com/papermerge/OCRmyPDF_papermerge) is
a production plugin that integrates OCRmyPDF and the Papermerge document a production plugin that integrates OCRmyPDF and the Papermerge document
management system. management system.
### Suppressing or overriding other plugins
Suppressing or overriding other plugins ```{eval-rst}
---------------------------------------
.. autofunction:: ocrmypdf.pluginspec.initialize .. autofunction:: ocrmypdf.pluginspec.initialize
```
Custom command line arguments ### Custom command line arguments
-----------------------------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.add_options .. autofunction:: ocrmypdf.pluginspec.add_options
```
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.check_options .. autofunction:: ocrmypdf.pluginspec.check_options
```
Execution and progress reporting ### Execution and progress reporting
--------------------------------
```{eval-rst}
.. autoclass:: ocrmypdf.pluginspec.ProgressBar .. autoclass:: ocrmypdf.pluginspec.ProgressBar
:members: :members:
:special-members: __init__, __enter__, __exit__ :special-members: __init__, __enter__, __exit__
```
```{eval-rst}
.. autoclass:: ocrmypdf.pluginspec.Executor .. autoclass:: ocrmypdf.pluginspec.Executor
:members: :members:
:special-members: __call__ :special-members: __call__
```
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.get_logging_console .. autofunction:: ocrmypdf.pluginspec.get_logging_console
```
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.get_executor .. autofunction:: ocrmypdf.pluginspec.get_executor
```
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.get_progressbar_class .. autofunction:: ocrmypdf.pluginspec.get_progressbar_class
```
Applying special behavior before processing ### Applying special behavior before processing
-------------------------------------------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.validate .. autofunction:: ocrmypdf.pluginspec.validate
```
PDF page to image ### PDF page to image
-----------------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.rasterize_pdf_page .. autofunction:: ocrmypdf.pluginspec.rasterize_pdf_page
```
Modifying intermediate images ### Modifying intermediate images
-----------------------------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.filter_ocr_image .. autofunction:: ocrmypdf.pluginspec.filter_ocr_image
```
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.filter_page_image .. autofunction:: ocrmypdf.pluginspec.filter_page_image
```
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.filter_pdf_page .. autofunction:: ocrmypdf.pluginspec.filter_pdf_page
```
OCR engine ### OCR engine
----------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.get_ocr_engine .. autofunction:: ocrmypdf.pluginspec.get_ocr_engine
```
```{eval-rst}
.. autoclass:: ocrmypdf.pluginspec.OcrEngine .. autoclass:: ocrmypdf.pluginspec.OcrEngine
:members: :members:
.. automethod:: __str__ .. automethod:: __str__
```
```{eval-rst}
.. autoclass:: ocrmypdf.pluginspec.OrientationConfidence .. autoclass:: ocrmypdf.pluginspec.OrientationConfidence
```
PDF/A production ### PDF/A production
----------------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.generate_pdfa .. autofunction:: ocrmypdf.pluginspec.generate_pdfa
```
PDF optimization ### PDF optimization
----------------
```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.optimize_pdf .. autofunction:: ocrmypdf.pluginspec.optimize_pdf
```
.. autofunction:: ocrmypdf.pluginspec.is_optimization_enabled ```{eval-rst}
.. autofunction:: ocrmypdf.pluginspec.is_optimization_enabled
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -48,7 +48,12 @@ Tracker = "https://github.com/ocrmypdf/OCRmyPDF/issues"
Changelog = "https://github.com/ocrmypdf/OCRmyPDF/docs/release_notes.rst" Changelog = "https://github.com/ocrmypdf/OCRmyPDF/docs/release_notes.rst"
[project.optional-dependencies] [project.optional-dependencies]
docs = ["sphinx", "sphinx-issues", "sphinx-rtd-theme"] docs = [
"myst-parser>=4.0.1",
"sphinx",
"sphinx-issues",
"sphinx-rtd-theme",
]
extended_test = ["PyMuPDF>=1.19.1"] extended_test = ["PyMuPDF>=1.19.1"]
test = [ test = [
"coverage[toml]>=6.2", "coverage[toml]>=6.2",
Generated
+80 -15
View File
@@ -1,4 +1,5 @@
version = 1 version = 1
revision = 1
requires-python = ">=3.10" requires-python = ">=3.10"
resolution-markers = [ resolution-markers = [
"python_full_version < '3.11'", "python_full_version < '3.11'",
@@ -234,7 +235,7 @@ name = "click"
version = "8.1.7" version = "8.1.7"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "colorama", marker = "platform_system == 'Windows'" }, { name = "colorama", marker = "sys_platform == 'win32'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 }
wheels = [ wheels = [
@@ -537,7 +538,7 @@ name = "ipykernel"
version = "6.29.5" version = "6.29.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "appnope", marker = "platform_system == 'Darwin'" }, { name = "appnope", marker = "sys_platform == 'darwin'" },
{ name = "comm" }, { name = "comm" },
{ name = "debugpy" }, { name = "debugpy" },
{ name = "ipython" }, { name = "ipython" },
@@ -823,6 +824,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899 }, { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899 },
] ]
[[package]]
name = "mdit-py-plugins"
version = "0.4.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown-it-py" },
]
sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316 },
]
[[package]] [[package]]
name = "mdurl" name = "mdurl"
version = "0.1.2" version = "0.1.2"
@@ -875,6 +888,23 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
] ]
[[package]]
name = "myst-parser"
version = "4.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "docutils" },
{ name = "jinja2" },
{ name = "markdown-it-py" },
{ name = "mdit-py-plugins" },
{ name = "pyyaml" },
{ name = "sphinx" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579 },
]
[[package]] [[package]]
name = "narwhals" name = "narwhals"
version = "1.15.2" version = "1.15.2"
@@ -957,7 +987,6 @@ wheels = [
[[package]] [[package]]
name = "ocrmypdf" name = "ocrmypdf"
version = "16.7.1.dev17+gbfbe571f.d20250104"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "deprecation" }, { name = "deprecation" },
@@ -973,6 +1002,7 @@ dependencies = [
[package.optional-dependencies] [package.optional-dependencies]
docs = [ docs = [
{ name = "myst-parser" },
{ name = "sphinx" }, { name = "sphinx" },
{ name = "sphinx-issues" }, { name = "sphinx-issues" },
{ name = "sphinx-rtd-theme" }, { name = "sphinx-rtd-theme" },
@@ -997,7 +1027,6 @@ watcher = [
{ name = "watchdog" }, { name = "watchdog" },
] ]
webservice = [ webservice = [
{ name = "port-for" },
{ name = "streamlit" }, { name = "streamlit" },
] ]
@@ -1016,13 +1045,13 @@ requires-dist = [
{ name = "deprecation", specifier = ">=2.1.0" }, { name = "deprecation", specifier = ">=2.1.0" },
{ name = "hypothesis", marker = "extra == 'test'", specifier = ">=6.36.0" }, { name = "hypothesis", marker = "extra == 'test'", specifier = ">=6.36.0" },
{ name = "img2pdf", specifier = ">=0.5" }, { name = "img2pdf", specifier = ">=0.5" },
{ name = "myst-parser", marker = "extra == 'docs'", specifier = ">=4.0.1" },
{ name = "packaging", specifier = ">=20" }, { name = "packaging", specifier = ">=20" },
{ name = "pdfminer-six", specifier = ">=20220319" }, { name = "pdfminer-six", specifier = ">=20220319" },
{ name = "pi-heif" }, { name = "pi-heif" },
{ name = "pikepdf", specifier = ">=8.10.1" }, { name = "pikepdf", specifier = ">=8.10.1" },
{ name = "pillow", specifier = ">=10.0.1" }, { name = "pillow", specifier = ">=10.0.1" },
{ name = "pluggy", specifier = ">=1" }, { name = "pluggy", specifier = ">=1" },
{ name = "port-for", marker = "extra == 'webservice'", specifier = ">=0.7.4" },
{ name = "pymupdf", marker = "extra == 'extended-test'", specifier = ">=1.19.1" }, { name = "pymupdf", marker = "extra == 'extended-test'", specifier = ">=1.19.1" },
{ name = "pytest", marker = "extra == 'test'", specifier = ">=6.2.5" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=6.2.5" },
{ name = "pytest-cov", marker = "extra == 'test'", specifier = ">=3.0.0" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=3.0.0" },
@@ -1040,6 +1069,7 @@ requires-dist = [
{ name = "types-pillow", marker = "extra == 'test'" }, { name = "types-pillow", marker = "extra == 'test'" },
{ name = "watchdog", marker = "extra == 'watcher'", specifier = ">=1.0.2" }, { name = "watchdog", marker = "extra == 'watcher'", specifier = ">=1.0.2" },
] ]
provides-extras = ["docs", "extended-test", "test", "watcher", "webservice"]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
@@ -1316,15 +1346,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
] ]
[[package]]
name = "port-for"
version = "0.7.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f6/84/ad5114c85217426d7a5170a74a6f9d6b724df117c2f3b75e41fc9d6c6811/port_for-0.7.4.tar.gz", hash = "sha256:fc7713e7b22f89442f335ce12536653656e8f35146739eccaeff43d28436028d", size = 25077 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9c/a2/579dcefbb0285b31f8d65b537f8a9932ed51319e0a3694e01b5bbc271f92/port_for-0.7.4-py3-none-any.whl", hash = "sha256:08404aa072651a53dcefe8d7a598ee8a1dca320d9ac44ac464da16ccf2a02c4a", size = 21369 },
]
[[package]] [[package]]
name = "prompt-toolkit" name = "prompt-toolkit"
version = "3.0.48" version = "3.0.48"
@@ -1576,6 +1597,50 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 }, { url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 },
] ]
[[package]]
name = "pyyaml"
version = "6.0.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199 },
{ url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758 },
{ url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463 },
{ url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280 },
{ url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239 },
{ url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802 },
{ url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527 },
{ url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052 },
{ url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774 },
{ url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 },
{ url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 },
{ url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 },
{ url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 },
{ url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 },
{ url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 },
{ url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 },
{ url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 },
{ url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 },
{ url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 },
{ url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 },
{ url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 },
{ url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 },
{ url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 },
{ url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 },
{ url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 },
{ url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 },
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 },
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
]
[[package]] [[package]]
name = "pyzmq" name = "pyzmq"
version = "26.2.0" version = "26.2.0"
@@ -1991,7 +2056,7 @@ dependencies = [
{ name = "toml" }, { name = "toml" },
{ name = "tornado" }, { name = "tornado" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
{ name = "watchdog", marker = "platform_system != 'Darwin'" }, { name = "watchdog", marker = "sys_platform != 'darwin'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/78/33/14b5ac0369ecf0af675911e5e84b934e6fcc2cec850857d2390eb373b0a6/streamlit-1.41.1.tar.gz", hash = "sha256:6626d32b098ba1458b71eebdd634c62af2dd876380e59c4b6a1e828a39d62d69", size = 8712473 } sdist = { url = "https://files.pythonhosted.org/packages/78/33/14b5ac0369ecf0af675911e5e84b934e6fcc2cec850857d2390eb373b0a6/streamlit-1.41.1.tar.gz", hash = "sha256:6626d32b098ba1458b71eebdd634c62af2dd876380e59c4b6a1e828a39d62d69", size = 8712473 }
wheels = [ wheels = [