Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a302fdb88 | ||
|
|
1d9cc239ee | ||
|
|
d240fc1ea6 | ||
|
|
e7d21dd826 | ||
|
|
e774b4650b | ||
|
|
8f8e6dcdd4 | ||
|
|
5252b88f0f | ||
|
|
ea69883386 | ||
|
|
eb343b1e37 | ||
|
|
9f02de55be | ||
|
|
7394a4cf49 | ||
|
|
ed9fb110b1 | ||
|
|
4650074428 | ||
|
|
70aa644c10 | ||
|
|
2ccb3edc58 | ||
|
|
1f40a70554 | ||
|
|
e14ffbf03f | ||
|
|
25a1dde57c | ||
|
|
1d10eac764 | ||
|
|
3f868118cd | ||
|
|
c7cf041e4a | ||
|
|
38ab03655b |
@@ -4,6 +4,7 @@ FROM ubuntu:18.04
|
|||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
ocrmypdf \
|
ocrmypdf \
|
||||||
|
unpaper \
|
||||||
tesseract-ocr-eng \
|
tesseract-ocr-eng \
|
||||||
tesseract-ocr-fra \
|
tesseract-ocr-fra \
|
||||||
tesseract-ocr-deu \
|
tesseract-ocr-deu \
|
||||||
|
|||||||
@@ -2,11 +2,4 @@ Please include the command line and a test file with your issue report.
|
|||||||
|
|
||||||
If possible, please use a test file that we can include in future test cases (no personal information, no copyrighted material).
|
If possible, please use a test file that we can include in future test cases (no personal information, no copyrighted material).
|
||||||
|
|
||||||
If you wish to encrypt a test file so that only the maintainer of OCRmyPDF can view it, you may use:
|
If you wish to encrypt a test file for the OCRmyPDF maintainer only, see the [Wiki](https://github.com/jbarlow83/OCRmyPDF/wiki).
|
||||||
|
|
||||||
```bash
|
|
||||||
|
|
||||||
gpg --recv-keys 4434eb74c4a35f7f --keyserver pgp.mit.edu
|
|
||||||
gpg --output test.pdf.gpg --encrypt --receipient 4434eb74c4a35f7f test.pdf
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|||||||
+4
-1
@@ -2,12 +2,14 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.sublime-*
|
*.sublime-*
|
||||||
venv*/
|
venv*/
|
||||||
|
.venv/
|
||||||
pyvenv.cfg
|
pyvenv.cfg
|
||||||
tasks.py
|
tasks.py
|
||||||
.bash_history
|
.bash_history
|
||||||
.ruffus_history.sqlite
|
.ruffus_history.sqlite
|
||||||
.idea/
|
.idea/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
.pylintrc
|
||||||
|
|
||||||
# Package building
|
# Package building
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
@@ -41,4 +43,5 @@ tmp/
|
|||||||
pdfbox-app*.jar
|
pdfbox-app*.jar
|
||||||
.vscode/
|
.vscode/
|
||||||
IDEAS
|
IDEAS
|
||||||
_Dockerfile.local
|
_Dockerfile.local
|
||||||
|
/scratch.py
|
||||||
|
|||||||
+31
-36
@@ -1,32 +1,51 @@
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
language: python
|
language: python
|
||||||
cache:
|
cache:
|
||||||
ccache: true
|
|
||||||
pip: true
|
pip: true
|
||||||
directories:
|
directories:
|
||||||
- $HOME/Library/Caches/Homebrew
|
- $HOME/Library/Caches/Homebrew
|
||||||
|
|
||||||
env:
|
addons:
|
||||||
global:
|
apt:
|
||||||
- secure: "hsf6MT+n2x3OiDM2fQyJZdV0/PWYmv81LdVqC6cfnHBE/8N3DloJRqQ7WfO14TxhiK9PEC7MpyCj0lSabUHEO7gSH6Vks6I1asoSkt8S9/bSMlhT4hei+pwVpeGEiU5xHVATNjY+D919VC3IFvc3XmjT74h/2SLhaZ+jhEmDggM=" # HOMEBREW_OCRMYPDF_TOKEN
|
update: true
|
||||||
|
sources:
|
||||||
|
- sourceline: 'ppa:alex-p/tesseract-ocr'
|
||||||
|
- sourceline: 'ppa:heyarje/libav-11'
|
||||||
|
- sourceline: 'ppa:vshn/ghostscript'
|
||||||
|
packages:
|
||||||
|
- ghostscript
|
||||||
|
- libavcodec56
|
||||||
|
- libavformat56
|
||||||
|
- libavutil54
|
||||||
|
- libffi-dev
|
||||||
|
- poppler-utils
|
||||||
|
- qpdf
|
||||||
|
- tesseract-ocr
|
||||||
|
- tesseract-ocr-deu
|
||||||
|
- tesseract-ocr-eng
|
||||||
|
- tesseract-ocr-fra
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: required
|
sudo: required
|
||||||
language: python
|
language: python
|
||||||
python: 3.5
|
python: "3.5"
|
||||||
env: EXTRAS=
|
env: EXTRAS=
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: required
|
sudo: required
|
||||||
language: python
|
language: python
|
||||||
python: 3.6
|
python: "3.6"
|
||||||
env: EXTRAS=
|
env: EXTRAS=
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: required
|
sudo: required
|
||||||
language: python
|
language: python
|
||||||
python: 3.6
|
python: "3.6"
|
||||||
env: EXTRAS=[fitz]
|
env: EXTRAS=[fitz]
|
||||||
|
- os: linux
|
||||||
|
sudo: required
|
||||||
|
language: python
|
||||||
|
python: "3.7-dev"
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode8
|
osx_image: xcode8
|
||||||
language: generic
|
language: generic
|
||||||
@@ -41,7 +60,10 @@ before_cache:
|
|||||||
|
|
||||||
before_install: |
|
before_install: |
|
||||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||||
bash .travis/linux_before_install.sh
|
pip install --upgrade pip
|
||||||
|
mkdir -p packages
|
||||||
|
wget -q 'https://www.dropbox.com/s/vaq0kbwi6e6au80/unpaper_6.1-1.deb?raw=1' -O packages/unpaper_6.1-1.deb
|
||||||
|
sudo dpkg -i packages/unpaper_6.1-1.deb
|
||||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
brew update && brew bundle --file=.travis/Brewfile
|
brew update && brew bundle --file=.travis/Brewfile
|
||||||
pip3 install --upgrade pip
|
pip3 install --upgrade pip
|
||||||
@@ -49,6 +71,7 @@ before_install: |
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
- pip3 install pycparser # py3.7 workaround for https://github.com/eliben/pycparser/issues/251
|
||||||
- pip3 install ".$EXTRAS"
|
- pip3 install ".$EXTRAS"
|
||||||
- pip3 install -r test_requirements.txt
|
- pip3 install -r test_requirements.txt
|
||||||
|
|
||||||
@@ -73,31 +96,3 @@ deploy:
|
|||||||
tags: true
|
tags: true
|
||||||
condition: $TRAVIS_PYTHON_VERSION == "3.6" && $TRAVIS_OS_NAME == "linux" && $EXTRAS == ""
|
condition: $TRAVIS_PYTHON_VERSION == "3.6" && $TRAVIS_OS_NAME == "linux" && $EXTRAS == ""
|
||||||
skip_upload_docs: true
|
skip_upload_docs: true
|
||||||
|
|
||||||
# test pypi
|
|
||||||
- provider: pypi
|
|
||||||
server: https://testpypi.pypi.org/legacy/
|
|
||||||
user: ocrmypdf-travis
|
|
||||||
password:
|
|
||||||
secure: "DTFOmmNL6olA0+yXvp4u9jXZlZeqrJsJ0526jzqf4a3gZ6jnGTq5UI6WzRsslSyoMMfXKtHQebqHM6ogSgCZinyZ3ufHJo8fn9brxbEc2gsiWkbj5o3bGwdWMT1vNNE7XW0VCpw87rZ1EEwjl4FJHFudMlPR1yfU5+uq0k0PACo="
|
|
||||||
distributions: "sdist"
|
|
||||||
on:
|
|
||||||
branch: develop
|
|
||||||
tags: false
|
|
||||||
condition: $TRAVIS_OS_NAME == "osx"
|
|
||||||
skip_upload_docs: true
|
|
||||||
|
|
||||||
# null deploy for osx
|
|
||||||
# we really just want to run after_deploy *after* pypi upload is done, but
|
|
||||||
# after_deploy on runs if a given box deployed
|
|
||||||
- provider: script
|
|
||||||
script: /usr/bin/true
|
|
||||||
on:
|
|
||||||
branch: master
|
|
||||||
tags: true
|
|
||||||
condition: $TRAVIS_OS_NAME == "osx"
|
|
||||||
|
|
||||||
after_deploy: |
|
|
||||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
|
||||||
bash .travis/osx_brew.sh
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# © 2017-18 James R. Barlow: github.com/jbarlow83
|
|
||||||
|
|
||||||
from string import Template
|
|
||||||
from subprocess import run, PIPE
|
|
||||||
import re
|
|
||||||
|
|
||||||
recipe_template = Template("""
|
|
||||||
class Ocrmypdf < Formula
|
|
||||||
include Language::Python::Virtualenv
|
|
||||||
|
|
||||||
desc "Adds an OCR text layer to scanned PDF files"
|
|
||||||
homepage "https://github.com/jbarlow83/OCRmyPDF"
|
|
||||||
${ocrmypdf_url}
|
|
||||||
${ocrmypdf_sha256}
|
|
||||||
|
|
||||||
depends_on "pkg-config" => :build
|
|
||||||
depends_on "mupdf-tools" => :build # statically links libmupdf.a
|
|
||||||
depends_on "freetype"
|
|
||||||
depends_on "ghostscript"
|
|
||||||
depends_on "jpeg"
|
|
||||||
depends_on "libpng"
|
|
||||||
depends_on "python"
|
|
||||||
depends_on "qpdf"
|
|
||||||
depends_on "tesseract"
|
|
||||||
depends_on "unpaper"
|
|
||||||
|
|
||||||
${resources}
|
|
||||||
def install
|
|
||||||
venv = virtualenv_create(libexec, "python3")
|
|
||||||
|
|
||||||
resource("Pillow").stage do
|
|
||||||
inreplace "setup.py" do |s|
|
|
||||||
sdkprefix = MacOS::CLT.installed? ? "" : MacOS.sdk_path
|
|
||||||
s.gsub! "openjpeg.h", "probably_not_a_header_called_this_eh.h"
|
|
||||||
s.gsub! "ZLIB_ROOT = None", "ZLIB_ROOT = ('#{sdkprefix}/usr/lib', '#{sdkprefix}/usr/include')"
|
|
||||||
s.gsub! "JPEG_ROOT = None", "JPEG_ROOT = ('#{Formula["jpeg"].opt_prefix}/lib', '#{Formula["jpeg"].opt_prefix}/include')"
|
|
||||||
s.gsub! "FREETYPE_ROOT = None", "FREETYPE_ROOT = ('#{Formula["freetype"].opt_prefix}/lib', '#{Formula["freetype"].opt_prefix}/include')"
|
|
||||||
end
|
|
||||||
|
|
||||||
# avoid triggering "helpful" distutils code that doesn't recognize Xcode 7 .tbd stubs
|
|
||||||
ENV.append "CFLAGS", "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers" unless MacOS::CLT.installed?
|
|
||||||
venv.pip_install Pathname.pwd
|
|
||||||
end
|
|
||||||
|
|
||||||
res = resources.map(&:name).to_set - ["Pillow"]
|
|
||||||
|
|
||||||
res.each do |r|
|
|
||||||
venv.pip_install resource(r)
|
|
||||||
end
|
|
||||||
|
|
||||||
venv.pip_install_and_link buildpath
|
|
||||||
end
|
|
||||||
|
|
||||||
test do
|
|
||||||
# Since we use Python 3, we require a UTF-8 locale
|
|
||||||
ENV["LC_ALL"] = "en_US.UTF-8"
|
|
||||||
|
|
||||||
system "#{bin}/ocrmypdf", "-f", "-q", "--deskew",
|
|
||||||
test_fixtures("test.pdf"), "ocr.pdf"
|
|
||||||
assert_predicate testpath/"ocr.pdf", :exist?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
""")
|
|
||||||
|
|
||||||
def main():
|
|
||||||
p = run(['poet', '--single', 'ocrmypdf'],
|
|
||||||
encoding='utf-8', stdout=PIPE, check=True)
|
|
||||||
|
|
||||||
ocrmypdf_lines = p.stdout.splitlines()
|
|
||||||
ocrmypdf_url = ocrmypdf_lines[1].strip()
|
|
||||||
ocrmypdf_sha256 = ocrmypdf_lines[2].strip()
|
|
||||||
|
|
||||||
ocrmypdf_version = re.search(
|
|
||||||
r'ocrmypdf-(.+)\.tar.*', ocrmypdf_url).group(1)
|
|
||||||
print(f"Autobrewing {ocrmypdf_version}")
|
|
||||||
|
|
||||||
p = run(['poet', '--resources', 'ocrmypdf'],
|
|
||||||
encoding='utf-8', stdout=PIPE, check=True)
|
|
||||||
|
|
||||||
poet_resources = p.stdout
|
|
||||||
|
|
||||||
# Remove the duplicate "ocrmypdf" resource block
|
|
||||||
all_resources = poet_resources.split('resource')
|
|
||||||
kept_resources = [block for block in all_resources if 'ocrmypdf' not in block]
|
|
||||||
resources = 'resource'.join(kept_resources)
|
|
||||||
|
|
||||||
with open('ocrmypdf.rb', 'w') as out:
|
|
||||||
out.write(recipe_template.substitute(**locals()))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# © 2017 James R. Barlow: github.com/jbarlow83
|
|
||||||
set -euo pipefail
|
|
||||||
set -x
|
|
||||||
|
|
||||||
sudo add-apt-repository ppa:vshn/ghostscript -y
|
|
||||||
sudo add-apt-repository ppa:heyarje/libav-11 -y
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -y \
|
|
||||||
ghostscript \
|
|
||||||
poppler-utils \
|
|
||||||
libavformat56 \
|
|
||||||
libavcodec56 \
|
|
||||||
libavutil54 \
|
|
||||||
libffi-dev
|
|
||||||
|
|
||||||
sudo add-apt-repository ppa:alex-p/tesseract-ocr -y
|
|
||||||
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get autoremove -y
|
|
||||||
sudo apt-get install -y --no-install-recommends \
|
|
||||||
tesseract-ocr \
|
|
||||||
tesseract-ocr-eng \
|
|
||||||
tesseract-ocr-fra \
|
|
||||||
tesseract-ocr-deu
|
|
||||||
|
|
||||||
pip install --upgrade pip
|
|
||||||
mkdir -p packages
|
|
||||||
wget -q 'https://www.dropbox.com/s/vaq0kbwi6e6au80/unpaper_6.1-1.deb?raw=1' -O packages/unpaper_6.1-1.deb
|
|
||||||
sudo dpkg -i packages/unpaper_6.1-1.deb
|
|
||||||
|
|
||||||
if [ ! -f /usr/local/bin/qpdf ]; then
|
|
||||||
export QPDF_RELEASE='https://github.com/qpdf/qpdf/releases/download/release-qpdf-8.0.2/qpdf-8.0.2.tar.gz'
|
|
||||||
mkdir qpdf
|
|
||||||
wget -q $QPDF_RELEASE -O - | tar xz -C qpdf --strip-components=1
|
|
||||||
cd qpdf/
|
|
||||||
export PATH="/usr/local/opt/ccache/libexec:$PATH"
|
|
||||||
./configure --prefix=/usr
|
|
||||||
make -j 2
|
|
||||||
sudo make install
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# © 2017 James R. Barlow: github.com/jbarlow83
|
|
||||||
set -uo pipefail
|
|
||||||
set -x
|
|
||||||
|
|
||||||
pip3 install homebrew-pypi-poet
|
|
||||||
python3 .travis/autobrew.py
|
|
||||||
cat ocrmypdf.rb
|
|
||||||
|
|
||||||
# brew audit crashes Travis
|
|
||||||
#brew audit ocrmypdf.rb
|
|
||||||
|
|
||||||
# Important: disable debug output so token is hidden
|
|
||||||
set +x
|
|
||||||
git clone https://$HOMEBREW_OCRMYPDF_TOKEN@github.com/jbarlow83/homebrew-ocrmypdf.git
|
|
||||||
set -x
|
|
||||||
|
|
||||||
pushd homebrew-ocrmypdf
|
|
||||||
cp ../ocrmypdf.rb Formula/ocrmypdf.rb
|
|
||||||
git add Formula/ocrmypdf.rb
|
|
||||||
git commit -m "homebrew-ocrmypdf: automatic release $TRAVIS_BUILD_NUMBER $TRAVIS_TAG"
|
|
||||||
git push origin master
|
|
||||||
popd
|
|
||||||
+7
-9
@@ -4,10 +4,10 @@ OCRmyPDF
|
|||||||
.. image:: https://travis-ci.org/jbarlow83/OCRmyPDF.svg?branch=master
|
.. image:: https://travis-ci.org/jbarlow83/OCRmyPDF.svg?branch=master
|
||||||
:target: https://travis-ci.org/jbarlow83/OCRmyPDF
|
:target: https://travis-ci.org/jbarlow83/OCRmyPDF
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/ocrmypdf.svg
|
.. image:: https://img.shields.io/pypi/v/ocrmypdf.svg
|
||||||
:target: https://pypi.org/project/ocrmypdf/
|
:target: https://pypi.org/project/ocrmypdf/
|
||||||
|
|
||||||
.. image:: https://img.shields.io/homebrew/v/ocrmypdf.svg
|
.. image:: https://img.shields.io/homebrew/v/ocrmypdf.svg
|
||||||
:alt: homebrew
|
:alt: homebrew
|
||||||
:target: http://brewformulas.org/Ocrmypdf
|
:target: http://brewformulas.org/Ocrmypdf
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ Motivation
|
|||||||
I searched the web for a free command line tool to OCR PDF files on
|
I searched the web for a free command line tool to OCR PDF files on
|
||||||
Linux/UNIX: I found many, but none of them were really satisfying.
|
Linux/UNIX: I found many, but none of them were really satisfying.
|
||||||
|
|
||||||
- Either they produced PDF files with misplaced text under the image (making copy/paste impossible)
|
- Either they produced PDF files with misplaced text under the image (making copy/paste impossible)
|
||||||
- Or they did not handle accents and multilingual characters
|
- Or they did not handle accents and multilingual characters
|
||||||
- Or they changed the resolution of the embedded images
|
- Or they changed the resolution of the embedded images
|
||||||
- Or they generated ridiculously large PDF files
|
- Or they generated ridiculously large PDF files
|
||||||
@@ -63,7 +63,7 @@ Linux/UNIX: I found many, but none of them were really satisfying.
|
|||||||
- On top of that none of them produced PDF/A files (format dedicated for long time storage)
|
- On top of that none of them produced PDF/A files (format dedicated for long time storage)
|
||||||
|
|
||||||
...so I decided to develop my own tool (using various existing scripts
|
...so I decided to develop my own tool (using various existing scripts
|
||||||
as an inspiration).
|
as an inspiration).
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
@@ -97,7 +97,7 @@ you can often find packages that provide language packs:
|
|||||||
|
|
||||||
# Debian/Ubuntu users
|
# Debian/Ubuntu users
|
||||||
apt-get install tesseract-ocr-chi-sim # Example: Install Chinese Simplified language back
|
apt-get install tesseract-ocr-chi-sim # Example: Install Chinese Simplified language back
|
||||||
|
|
||||||
You can then pass the ``-l LANG`` argument to OCRmyPDF to give a hint as to what languages it should search for. Multiple
|
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.
|
languages can be requested.
|
||||||
|
|
||||||
@@ -126,9 +126,7 @@ If you detect an issue, please:
|
|||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Runs on CPython 3.6, and requires external program installations of Ghostscript, Tesseract OCR, QPDF, and Leptonica. ocrmypdf is pure Python, but uses CFFI to portably generate library bindings.
|
Runs on CPython 3.5, 3.6 and 3.7. Requires external program installations of Ghostscript, Tesseract OCR, QPDF, and Leptonica. ocrmypdf is pure Python, but uses CFFI to portably generate library bindings.
|
||||||
|
|
||||||
Python 3.5 is also supported.
|
|
||||||
|
|
||||||
Press & Media
|
Press & Media
|
||||||
-------------
|
-------------
|
||||||
@@ -142,7 +140,7 @@ Press & Media
|
|||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
The OCRmyPDF software is licensed under the GNU GPLv3. Certain files are covered by other licenses, as noted in their source files.
|
The OCRmyPDF software is licensed under the GNU GPLv3. Certain files are covered by other licenses, as noted in their source files.
|
||||||
|
|
||||||
The license for each test file varies, and is noted in tests/resources/README.rst. The documentation is licensed under Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA 4.0).
|
The license for each test file varies, and is noted in tests/resources/README.rst. The documentation is licensed under Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA 4.0).
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -65,8 +65,8 @@ By default OCRmyPDF assumes the document is English.
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
ocrmypdf -l fre LeParisien.pdf LeParisien.pdf
|
ocrmypdf -l fra LeParisien.pdf LeParisien.pdf
|
||||||
ocrmypdf -l eng+fre Bilingual-English-French.pdf Bilingual-English-French.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>`.
|
Language packs must be installed for all languages specified. See :ref:`Installing additional language packs <lang-packs>`.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
The easiest way to install OCRmyPDF to follow the steps for your operating system/platform.
|
The easiest way to install OCRmyPDF to follow the steps for your operating system/platform.
|
||||||
|
|
||||||
If you want to use the latest version of OCRmyPDF, your best bet is to install the most recent version your platform provides, and then upgrade that version by installing the Python binary wheels.
|
If you want to use the latest version of OCRmyPDF, your best bet is to install the most recent version your platform provides, and then upgrade that version by installing the Python binary wheels.
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ To see what versions are available, check the `Debian Package Tracker <https://t
|
|||||||
Installing on macOS with Homebrew
|
Installing on macOS with Homebrew
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
.. image:: https://img.shields.io/homebrew/v/ocrmypdf.svg
|
.. image:: https://img.shields.io/homebrew/v/ocrmypdf.svg
|
||||||
:alt: homebrew
|
:alt: homebrew
|
||||||
:target: http://brewformulas.org/Ocrmypdf
|
:target: http://brewformulas.org/Ocrmypdf
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ Follow the Docker installation instructions for your platform. If you can run t
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
docker run hello-world
|
docker run hello-world
|
||||||
|
|
||||||
OCRmyPDF will use all available CPU cores. By default, the VirtualBox machine instance on Windows and macOS has only a single CPU core enabled. Use the VirtualBox Manager to determine the name of your Docker engine host, and then follow these optional steps to enable multiple CPUs:
|
OCRmyPDF will use all available CPU cores. By default, the VirtualBox machine instance on Windows and macOS has only a single CPU core enabled. Use the VirtualBox Manager to determine the name of your Docker engine host, and then follow these optional steps to enable multiple CPUs:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@@ -103,14 +103,14 @@ You can then run ocrmypdf using the command:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
docker run --rm ocrmypdf --help
|
docker run --rm ocrmypdf --help
|
||||||
|
|
||||||
To execute the OCRmyPDF on a local file, you must `provide a writable volume to the Docker image <https://docs.docker.com/userguide/dockervolumes/>`_, and both the input and output file must be inside the writable volume. This example command uses the current working directory as the writable volume:
|
To execute the OCRmyPDF on a local file, you must `provide a writable volume to the Docker image <https://docs.docker.com/userguide/dockervolumes/>`_, and both the input and output file must be inside the writable volume. This example command uses the current working directory as the writable volume:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
docker run --rm -v "$(pwd):/home/docker" <other docker arguments> ocrmypdf <your arguments to ocrmypdf>
|
docker run --rm -v "$(pwd):/home/docker" <other docker arguments> ocrmypdf <your arguments to ocrmypdf>
|
||||||
|
|
||||||
In this worked example, the current working directory contains an input file called ``test.pdf`` and the output will go to ``output.pdf``:
|
In this worked example, the current working directory contains an input file called ``test.pdf`` and the output will go to ``output.pdf``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@@ -167,11 +167,11 @@ Install or upgrade the required Homebrew packages, if any are missing:
|
|||||||
brew install python3
|
brew install python3
|
||||||
brew install libxml2 libffi leptonica
|
brew install libxml2 libffi leptonica
|
||||||
brew install unpaper # optional
|
brew install unpaper # optional
|
||||||
|
|
||||||
Python 3.5 and 3.6 are supported.
|
Python 3.5, 3.6 and 3.7 are supported.
|
||||||
|
|
||||||
Install the required Tesseract OCR engine with the language packs you plan to use:
|
Install the required Tesseract OCR engine with the language packs you plan to use:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
brew install tesseract # Option 1: for English, French, German, Spanish
|
brew install tesseract # Option 1: for English, French, German, Spanish
|
||||||
@@ -398,7 +398,7 @@ The following dependencies are recommended:
|
|||||||
- unpaper 6.1
|
- unpaper 6.1
|
||||||
- PyMuPDF 1.12.5 or newer
|
- PyMuPDF 1.12.5 or newer
|
||||||
|
|
||||||
These are in addition to the Python packaging dependencies, meaning that unfortunately, the ``pip install`` command cannot satisfy all of them.
|
These are in addition to the Python packaging dependencies, meaning that unfortunately, the ``pip install`` command cannot satisfy all of them.
|
||||||
|
|
||||||
Python 3.6 and Tesseract 4.0.0-beta.1 are recommended for best OCR results and best performance.
|
Python 3.6 and Tesseract 4.0.0-beta.1 are recommended for best OCR results and best performance.
|
||||||
|
|
||||||
|
|||||||
+37
-23
@@ -6,9 +6,23 @@ OCRmyPDF uses `semantic versioning <http://semver.org/>`_ for its command line i
|
|||||||
The OCRmyPDF package itself does not contain a public API, although it is fairly stable and breaking changes are usually timed with a major release. A future release will clearly define the stable public API.
|
The OCRmyPDF package itself does not contain a public API, although it is fairly stable and breaking changes are usually timed with a major release. A future release will clearly define the stable public API.
|
||||||
|
|
||||||
.. Issue regex
|
.. Issue regex
|
||||||
find: [^`]\#([0-9]{1,3})[^0-9]
|
find: [^`]\#([0-9]{1,3})[^0-9]
|
||||||
replace: `#$1 <https://github.com/jbarlow83/OCRmyPDF/issues/$1>`_
|
replace: `#$1 <https://github.com/jbarlow83/OCRmyPDF/issues/$1>`_
|
||||||
|
|
||||||
|
|
||||||
|
v6.2.2
|
||||||
|
------
|
||||||
|
|
||||||
|
- Backport compatibility fixes for Python 3.7 and ruffus 2.7.0 from v7.0.0
|
||||||
|
- Backport fix to ignore masks when deciding what colors are on a page
|
||||||
|
- Backport some minor improvements from v7.0.0: better argument validation and warnings about the Tesseract 4.0.0 ``--user-words`` regression
|
||||||
|
|
||||||
|
v6.2.1
|
||||||
|
------
|
||||||
|
|
||||||
|
- Fix recent versions of Tesseract (after 4.0.0-beta1) not being detected as supporting the ``sandwich`` renderer (`#271 <https://github.com/ppjbarlow83/OCRmyPDF/issues/271>`_).
|
||||||
|
|
||||||
|
|
||||||
v6.2.0
|
v6.2.0
|
||||||
------
|
------
|
||||||
|
|
||||||
@@ -34,7 +48,7 @@ v6.1.5
|
|||||||
v6.1.4
|
v6.1.4
|
||||||
------
|
------
|
||||||
|
|
||||||
- Fix issue `#248 <https://github.com/jbarlow83/OCRmyPDF/issues/248>`_ ``--clean`` argument may remove OCR from left column of text on certain documents. We now set ``--layout none`` to suppress this.
|
- Fix issue `#248 <https://github.com/jbarlow83/OCRmyPDF/issues/248>`_ ``--clean`` argument may remove OCR from left column of text on certain documents. We now set ``--layout none`` to suppress this.
|
||||||
|
|
||||||
- The test cache was updated to reflect the change above.
|
- The test cache was updated to reflect the change above.
|
||||||
|
|
||||||
@@ -165,7 +179,7 @@ v5.5
|
|||||||
- Add new argument ``--max-image-mpixels``. Pillow 5.0 now raises an exception when images may be decompression bombs. This argument can be used to override the limit Pillow sets.
|
- Add new argument ``--max-image-mpixels``. Pillow 5.0 now raises an exception when images may be decompression bombs. This argument can be used to override the limit Pillow sets.
|
||||||
- Fix output page cropped when using the sandwich renderer and OCR is skipped on a rotated and image-processed page
|
- Fix output page cropped when using the sandwich renderer and OCR is skipped on a rotated and image-processed page
|
||||||
- A warning is now issued when old versions of Ghostscript are used in cases known to cause issues with non-Latin characters
|
- A warning is now issued when old versions of Ghostscript are used in cases known to cause issues with non-Latin characters
|
||||||
- Fix a few parameter validation checks for ``-output-type pdfa-1`` and ``pdfa-2``
|
- Fix a few parameter validation checks for ``-output-type pdfa-1`` and ``pdfa-2``
|
||||||
|
|
||||||
|
|
||||||
v5.4.4
|
v5.4.4
|
||||||
@@ -175,7 +189,7 @@ v5.4.4
|
|||||||
- Fix issue `#200 <https://github.com/jbarlow83/OCRmyPDF/issues/200>`_: an uncommon syntax for formatting decimal numbers in a PDF would cause qpdf to issue a warning, which ocrmypdf treated as an error. Now this the warning is relayed.
|
- Fix issue `#200 <https://github.com/jbarlow83/OCRmyPDF/issues/200>`_: an uncommon syntax for formatting decimal numbers in a PDF would cause qpdf to issue a warning, which ocrmypdf treated as an error. Now this the warning is relayed.
|
||||||
- Fix an issue where intermediate PDFs would be created at version 1.3 instead of the version of the original file. It's possible but unlikely this had side effects.
|
- Fix an issue where intermediate PDFs would be created at version 1.3 instead of the version of the original file. It's possible but unlikely this had side effects.
|
||||||
- A warning is now issued when older versions of qpdf are used since issues like `#200 <https://github.com/jbarlow83/OCRmyPDF/issues/200>`_ cause qpdf to infinite-loop
|
- A warning is now issued when older versions of qpdf are used since issues like `#200 <https://github.com/jbarlow83/OCRmyPDF/issues/200>`_ cause qpdf to infinite-loop
|
||||||
- Address issue `#140 <https://github.com/jbarlow83/OCRmyPDF/issues/140>`_: if Tesseract outputs invalid UTF-8, escape it and print its message instead of aborting with a Unicode error
|
- Address issue `#140 <https://github.com/jbarlow83/OCRmyPDF/issues/140>`_: if Tesseract outputs invalid UTF-8, escape it and print its message instead of aborting with a Unicode error
|
||||||
- Adding previously unlisted setup requirement, pytest-runner
|
- Adding previously unlisted setup requirement, pytest-runner
|
||||||
- Update documentation: fix an error in the example script for Synology with Docker images, improved security guidance, advised ``pip install --user``
|
- Update documentation: fix an error in the example script for Synology with Docker images, improved security guidance, advised ``pip install --user``
|
||||||
|
|
||||||
@@ -344,7 +358,7 @@ v4.4.1
|
|||||||
|
|
||||||
- To prevent a `TIFF output error <https://github.com/python-pillow/Pillow/issues/2206>`_ caused by img2pdf >= 0.2.1 and Pillow <= 3.4.2, dependencies have been tightened
|
- To prevent a `TIFF output error <https://github.com/python-pillow/Pillow/issues/2206>`_ caused by img2pdf >= 0.2.1 and Pillow <= 3.4.2, dependencies have been tightened
|
||||||
- The Tesseract 4.00 simultaneous process limit was increased from 1 to 2, since it was observed that 1 lowers performance
|
- The Tesseract 4.00 simultaneous process limit was increased from 1 to 2, since it was observed that 1 lowers performance
|
||||||
- Documentation improvements to describe the ``--tesseract-config`` feature
|
- Documentation improvements to describe the ``--tesseract-config`` feature
|
||||||
- Added test cases and fixed error handling for ``--tesseract-config``
|
- Added test cases and fixed error handling for ``--tesseract-config``
|
||||||
- Tweaks to setup.py to deal with issues in the v4.4 release
|
- Tweaks to setup.py to deal with issues in the v4.4 release
|
||||||
|
|
||||||
@@ -407,7 +421,7 @@ v4.3
|
|||||||
|
|
||||||
- New feature ``--remove-background`` to detect and erase the background of color and grayscale images
|
- New feature ``--remove-background`` to detect and erase the background of color and grayscale images
|
||||||
- Better documentation
|
- Better documentation
|
||||||
- Fixed an issue with PDFs that draw images when the raster stack depth is zero
|
- Fixed an issue with PDFs that draw images when the raster stack depth is zero
|
||||||
- ocrmypdf can now redirect its output to stdout for use in a shell pipeline
|
- ocrmypdf can now redirect its output to stdout for use in a shell pipeline
|
||||||
|
|
||||||
+ This does not improve performance since temporary files are still used for buffering
|
+ This does not improve performance since temporary files are still used for buffering
|
||||||
@@ -475,7 +489,7 @@ v4.2
|
|||||||
+ fixes issue `#82 <https://github.com/jbarlow83/OCRmyPDF/issues/82>`_
|
+ fixes issue `#82 <https://github.com/jbarlow83/OCRmyPDF/issues/82>`_
|
||||||
|
|
||||||
- Fixes an issue where, with certain settings, monochrome images in PDFs would be converted to 8-bit grayscale, increasing file size (`#79 <https://github.com/jbarlow83/OCRmyPDF/issues/79>`_)
|
- Fixes an issue where, with certain settings, monochrome images in PDFs would be converted to 8-bit grayscale, increasing file size (`#79 <https://github.com/jbarlow83/OCRmyPDF/issues/79>`_)
|
||||||
- Support for Ubuntu 12.04 LTS "precise" has been dropped in favor of (roughly) Ubuntu 14.04 LTS "trusty"
|
- Support for Ubuntu 12.04 LTS "precise" has been dropped in favor of (roughly) Ubuntu 14.04 LTS "trusty"
|
||||||
|
|
||||||
+ Some Ubuntu "PPAs" (backports) are needed to make it work
|
+ Some Ubuntu "PPAs" (backports) are needed to make it work
|
||||||
|
|
||||||
@@ -590,7 +604,7 @@ New features
|
|||||||
|
|
||||||
- Automatic page rotation (``-r``) is now available. It uses ignores any prior rotation information
|
- Automatic page rotation (``-r``) is now available. It uses ignores any prior rotation information
|
||||||
on PDFs and sets rotation based on the dominant orientation of detectable text. This feature is
|
on PDFs and sets rotation based on the dominant orientation of detectable text. This feature is
|
||||||
fairly reliable but some false positives occur especially if there is not much text to work with. (`#4 <https://github.com/jbarlow83/OCRmyPDF/issues/4>`_)
|
fairly reliable but some false positives occur especially if there is not much text to work with. (`#4 <https://github.com/jbarlow83/OCRmyPDF/issues/4>`_)
|
||||||
- Deskewing is now performed using Leptonica instead of unpaper. Leptonica is faster and more reliable
|
- Deskewing is now performed using Leptonica instead of unpaper. Leptonica is faster and more reliable
|
||||||
at image deskewing than unpaper.
|
at image deskewing than unpaper.
|
||||||
|
|
||||||
@@ -633,7 +647,7 @@ v3.2
|
|||||||
New features
|
New features
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
- Lossless reconstruction: when possible, OCRmyPDF will inject text layers without
|
- Lossless reconstruction: when possible, OCRmyPDF will inject text layers without
|
||||||
otherwise manipulating the content and layout of a PDF page. For example, a PDF containing a mix
|
otherwise manipulating the content and layout of a PDF page. For example, a PDF containing a mix
|
||||||
of vector and raster content would see the vector content preserved. Images may still be transcoded
|
of vector and raster content would see the vector content preserved. Images may still be transcoded
|
||||||
during PDF/A conversion. (``--deskew`` and ``--clean-final`` disable this mode, necessarily.)
|
during PDF/A conversion. (``--deskew`` and ``--clean-final`` disable this mode, necessarily.)
|
||||||
@@ -668,10 +682,10 @@ Changes
|
|||||||
needed to implement support
|
needed to implement support
|
||||||
- Improved some error messages related to missing input files
|
- Improved some error messages related to missing input files
|
||||||
- Fixed issue `#20 <https://github.com/jbarlow83/OCRmyPDF/issues/20>`_ - uppercase .PDF extension not accepted
|
- Fixed issue `#20 <https://github.com/jbarlow83/OCRmyPDF/issues/20>`_ - uppercase .PDF extension not accepted
|
||||||
- Fixed an issue where OCRmyPDF failed to text that certain pages contained previously OCR'ed text,
|
- Fixed an issue where OCRmyPDF failed to text that certain pages contained previously OCR'ed text,
|
||||||
such as OCR text produced by Tesseract 3.04
|
such as OCR text produced by Tesseract 3.04
|
||||||
- Inserts /Creator tag into PDFs so that errors can be traced back to this project
|
- Inserts /Creator tag into PDFs so that errors can be traced back to this project
|
||||||
- Added new option ``--pdf-renderer=auto``, to let OCRmyPDF pick the best PDF renderer.
|
- Added new option ``--pdf-renderer=auto``, to let OCRmyPDF pick the best PDF renderer.
|
||||||
Currently it always chooses the 'hocrtransform' renderer but that behavior may change.
|
Currently it always chooses the 'hocrtransform' renderer but that behavior may change.
|
||||||
- Set up Travis CI automatic integration testing
|
- Set up Travis CI automatic integration testing
|
||||||
|
|
||||||
@@ -681,19 +695,19 @@ v3.0
|
|||||||
New features
|
New features
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
- Easier installation with a Docker container or Python's ``pip`` package manager
|
- Easier installation with a Docker container or Python's ``pip`` package manager
|
||||||
- Eliminated many external dependencies, so it's easier to setup
|
- Eliminated many external dependencies, so it's easier to setup
|
||||||
- Now installs ``ocrmypdf`` to ``/usr/local/bin`` or equivalent for system-wide
|
- Now installs ``ocrmypdf`` to ``/usr/local/bin`` or equivalent for system-wide
|
||||||
access and easier typing
|
access and easier typing
|
||||||
- Improved command line syntax and usage help (``--help``)
|
- Improved command line syntax and usage help (``--help``)
|
||||||
- Tesseract 3.03+ PDF page rendering can be used instead for better positioning
|
- Tesseract 3.03+ PDF page rendering can be used instead for better positioning
|
||||||
of recognized text (``--pdf-renderer tesseract``)
|
of recognized text (``--pdf-renderer tesseract``)
|
||||||
- PDF metadata (title, author, keywords) are now transferred to the
|
- PDF metadata (title, author, keywords) are now transferred to the
|
||||||
output PDF
|
output PDF
|
||||||
- PDF metadata can also be set from the command line (``--title``, etc.)
|
- PDF metadata can also be set from the command line (``--title``, etc.)
|
||||||
- Automatic repairs malformed input PDFs if possible
|
- Automatic repairs malformed input PDFs if possible
|
||||||
- Added test cases to confirm everything is working
|
- Added test cases to confirm everything is working
|
||||||
- Added option to skip extremely large pages that take too long to OCR and are
|
- Added option to skip extremely large pages that take too long to OCR and are
|
||||||
often not OCRable (e.g. large scanned maps or diagrams); other pages are still
|
often not OCRable (e.g. large scanned maps or diagrams); other pages are still
|
||||||
processed (``--skip-big``)
|
processed (``--skip-big``)
|
||||||
- Added option to kill Tesseract OCR process if it seems to be taking too long on
|
- Added option to kill Tesseract OCR process if it seems to be taking too long on
|
||||||
@@ -712,9 +726,9 @@ Changes
|
|||||||
available CPUs, increasing performance
|
available CPUs, increasing performance
|
||||||
- The ``-o DPI`` argument has been phased out, in favor of ``--oversample DPI``, in
|
- The ``-o DPI`` argument has been phased out, in favor of ``--oversample DPI``, in
|
||||||
case we need ``-o OUTPUTFILE`` in the future
|
case we need ``-o OUTPUTFILE`` in the future
|
||||||
- Removed several dependencies, so it's easier to install. We no
|
- Removed several dependencies, so it's easier to install. We no
|
||||||
longer use:
|
longer use:
|
||||||
|
|
||||||
- GNU parallel_
|
- GNU parallel_
|
||||||
- ImageMagick_
|
- ImageMagick_
|
||||||
- Python 2.7
|
- Python 2.7
|
||||||
@@ -730,7 +744,7 @@ Changes
|
|||||||
- qpdf_ 5.0.0+
|
- qpdf_ 5.0.0+
|
||||||
- Unpaper_ 6.1 (optional)
|
- Unpaper_ 6.1 (optional)
|
||||||
- some automatically managed Python packages
|
- some automatically managed Python packages
|
||||||
|
|
||||||
.. _ruffus: http://www.ruffus.org.uk/index.html
|
.. _ruffus: http://www.ruffus.org.uk/index.html
|
||||||
.. _parallel: https://www.gnu.org/software/parallel/
|
.. _parallel: https://www.gnu.org/software/parallel/
|
||||||
.. _ImageMagick: http://www.imagemagick.org/script/index.php
|
.. _ImageMagick: http://www.imagemagick.org/script/index.php
|
||||||
@@ -776,7 +790,7 @@ Release candidates
|
|||||||
- fixed some installer issues and errors in installation instructions
|
- fixed some installer issues and errors in installation instructions
|
||||||
- improve performance: run Ghostscript with multithreaded rendering
|
- improve performance: run Ghostscript with multithreaded rendering
|
||||||
- improve performance: use multiple cores by default
|
- improve performance: use multiple cores by default
|
||||||
- bug fix: checking for wrong exception on process timeout
|
- bug fix: checking for wrong exception on process timeout
|
||||||
|
|
||||||
- rc3: skipping version number intentionally to avoid confusion with Tesseract
|
- rc3: skipping version number intentionally to avoid confusion with Tesseract
|
||||||
- rc2: first release for public testing to test-PyPI, Github
|
- rc2: first release for public testing to test-PyPI, Github
|
||||||
@@ -799,11 +813,11 @@ where ``settings.txt`` contains *one argument per line*, for example:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
-l
|
-l
|
||||||
deu
|
deu
|
||||||
--author
|
--author
|
||||||
A. Merkel
|
A. Merkel
|
||||||
--pdf-renderer
|
--pdf-renderer
|
||||||
tesseract
|
tesseract
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -1,10 +1,11 @@
|
|||||||
# requirements.txt can be used to replicate the developer's build environment
|
# requirements.txt can be used to replicate the developer's build environment
|
||||||
# setup.py lists a separate set of requirements that are looser to simplify
|
# setup.py lists a separate set of requirements that are looser to simplify
|
||||||
# installation
|
# installation
|
||||||
ruffus == 2.6.3
|
ruffus == 2.7.0
|
||||||
Pillow == 5.1.0
|
Pillow == 5.2.0
|
||||||
reportlab == 3.4.0
|
reportlab == 3.4.0
|
||||||
PyPDF2 == 1.26.0
|
PyPDF2 == 1.26.0
|
||||||
img2pdf == 0.2.4
|
img2pdf == 0.2.4
|
||||||
cffi == 1.11.5
|
cffi == 1.11.5
|
||||||
PyMuPDF == 1.12.5
|
PyMuPDF == 1.12.5
|
||||||
|
defusedxml == 0.5.0
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ setup(
|
|||||||
classifiers=[
|
classifiers=[
|
||||||
"Programming Language :: Python :: 3.5",
|
"Programming Language :: Python :: 3.5",
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.6",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
"Development Status :: 5 - Production/Stable",
|
"Development Status :: 5 - Production/Stable",
|
||||||
"Environment :: Console",
|
"Environment :: Console",
|
||||||
"Intended Audience :: End Users/Desktop",
|
"Intended Audience :: End Users/Desktop",
|
||||||
@@ -243,12 +244,12 @@ setup(
|
|||||||
'cffi >= 1.9.1', # must be a setup and install requirement
|
'cffi >= 1.9.1', # must be a setup and install requirement
|
||||||
'defusedxml >= 0.5.0', # pure Python, so track HEAD closely
|
'defusedxml >= 0.5.0', # pure Python, so track HEAD closely
|
||||||
'img2pdf >= 0.2.4', # pure Python, so track HEAD closely
|
'img2pdf >= 0.2.4', # pure Python, so track HEAD closely
|
||||||
'Pillow >= 4.0.0, != 5.1.0 ; sys_platform == "darwin"',
|
'Pillow >= 4.0.0, != 5.1.0 ; sys_platform == "darwin"',
|
||||||
# Pillow < 4 has BytesIO/TIFF bug w/img2pdf 0.2.3
|
# Pillow < 4 has BytesIO/TIFF bug w/img2pdf 0.2.3
|
||||||
# block 5.1.0, broken wheels
|
# block 5.1.0, broken wheels
|
||||||
'PyPDF2 >= 1.26', # pure Python, so track HEAD closely
|
'PyPDF2 >= 1.26', # pure Python, so track HEAD closely
|
||||||
'reportlab >= 3.3.0', # oldest released version with sane image handling
|
'reportlab >= 3.3.0', # oldest released version with sane image handling
|
||||||
'ruffus == 2.6.3', # pinned - ocrmypdf implements a 2.6.3 workaround
|
'ruffus >= 2.7.0',
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
'fitz': ['PyMuPDF >= 1.12.5'] # for table of contents bug
|
'fitz': ['PyMuPDF >= 1.12.5'] # for table of contents bug
|
||||||
|
|||||||
+56
-39
@@ -70,7 +70,7 @@ def complain(message):
|
|||||||
if 'IDE_PROJECT_ROOTS' in os.environ:
|
if 'IDE_PROJECT_ROOTS' in os.environ:
|
||||||
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
|
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
|
||||||
|
|
||||||
# --------
|
# --------
|
||||||
# Critical environment tests
|
# Critical environment tests
|
||||||
|
|
||||||
verify_python3_env()
|
verify_python3_env()
|
||||||
@@ -85,6 +85,20 @@ if tesseract.version() < MINIMUM_TESS_VERSION:
|
|||||||
# -------------
|
# -------------
|
||||||
# Parser
|
# Parser
|
||||||
|
|
||||||
|
def numeric(basetype, min_=None, max_=None):
|
||||||
|
"Validator for numeric params"
|
||||||
|
min_ = basetype(min_) if min_ is not None else None
|
||||||
|
max_ = basetype(max_) if max_ is not None else None
|
||||||
|
def _numeric(string):
|
||||||
|
value = basetype(string)
|
||||||
|
if (min_ is not None and value < min_
|
||||||
|
or max_ is not None and value > max_):
|
||||||
|
msg = "%r not in valid range %r" % (string, (min_, max_))
|
||||||
|
raise argparse.ArgumentTypeError(msg)
|
||||||
|
return value
|
||||||
|
return _numeric
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog=PROGRAM_NAME,
|
prog=PROGRAM_NAME,
|
||||||
fromfile_prefix_chars='@',
|
fromfile_prefix_chars='@',
|
||||||
@@ -156,7 +170,7 @@ parser.add_argument(
|
|||||||
'--image-dpi', metavar='DPI', type=int,
|
'--image-dpi', metavar='DPI', type=int,
|
||||||
help="For input image instead of PDF, use this DPI instead of file's.")
|
help="For input image instead of PDF, use this DPI instead of file's.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--output-type', choices=['pdfa', 'pdf', 'pdfa-1', 'pdfa-2', 'pdfa-3'],
|
'--output-type', choices=['pdfa', 'pdf', 'pdfa-1', 'pdfa-2', 'pdfa-3'],
|
||||||
default='pdfa',
|
default='pdfa',
|
||||||
help="Choose output type. 'pdfa' creates a PDF/A-2b compliant file for "
|
help="Choose output type. 'pdfa' creates a PDF/A-2b compliant file for "
|
||||||
"long term archiving (default, recommended) but may not suitable "
|
"long term archiving (default, recommended) but may not suitable "
|
||||||
@@ -233,7 +247,7 @@ preprocessing.add_argument(
|
|||||||
help="Clean page as above, and incorporate the cleaned image in the final "
|
help="Clean page as above, and incorporate the cleaned image in the final "
|
||||||
"PDF. Might remove desired content.")
|
"PDF. Might remove desired content.")
|
||||||
preprocessing.add_argument(
|
preprocessing.add_argument(
|
||||||
'--oversample', metavar='DPI', type=int, default=0,
|
'--oversample', metavar='DPI', type=numeric(int, 0, 5000), default=0,
|
||||||
help="Oversample images to at least the specified DPI, to improve OCR "
|
help="Oversample images to at least the specified DPI, to improve OCR "
|
||||||
"results slightly")
|
"results slightly")
|
||||||
|
|
||||||
@@ -255,7 +269,7 @@ ocrsettings.add_argument(
|
|||||||
# "pages")
|
# "pages")
|
||||||
|
|
||||||
ocrsettings.add_argument(
|
ocrsettings.add_argument(
|
||||||
'--skip-big', type=float, metavar='MPixels',
|
'--skip-big', type=numeric(float, 0, 5000), metavar='MPixels',
|
||||||
help="Skip OCR on pages larger than the specified amount of megapixels, "
|
help="Skip OCR on pages larger than the specified amount of megapixels, "
|
||||||
"but include skipped pages in final output")
|
"but include skipped pages in final output")
|
||||||
|
|
||||||
@@ -263,7 +277,7 @@ advanced = parser.add_argument_group(
|
|||||||
"Advanced",
|
"Advanced",
|
||||||
"Advanced options to control Tesseract's OCR behavior")
|
"Advanced options to control Tesseract's OCR behavior")
|
||||||
advanced.add_argument(
|
advanced.add_argument(
|
||||||
'--max-image-mpixels', action='store', type=float, metavar='MPixels',
|
'--max-image-mpixels', action='store', type=numeric(float, 0), metavar='MPixels',
|
||||||
help="Set maximum number of pixels to unpack before treating an image as a "
|
help="Set maximum number of pixels to unpack before treating an image as a "
|
||||||
"decompression bomb",
|
"decompression bomb",
|
||||||
default=128.0)
|
default=128.0)
|
||||||
@@ -296,11 +310,11 @@ advanced.add_argument(
|
|||||||
" of Ghostscript; deprecated"
|
" of Ghostscript; deprecated"
|
||||||
)
|
)
|
||||||
advanced.add_argument(
|
advanced.add_argument(
|
||||||
'--tesseract-timeout', default=180.0, type=float, metavar='SECONDS',
|
'--tesseract-timeout', default=180.0, type=numeric(float, 0), metavar='SECONDS',
|
||||||
help='Give up on OCR after the timeout, but copy the preprocessed page '
|
help='Give up on OCR after the timeout, but copy the preprocessed page '
|
||||||
'into the final output')
|
'into the final output')
|
||||||
advanced.add_argument(
|
advanced.add_argument(
|
||||||
'--rotate-pages-threshold', default=14.0, type=float, metavar='CONFIDENCE',
|
'--rotate-pages-threshold', default=14.0, type=numeric(float, max_=1000), metavar='CONFIDENCE',
|
||||||
help="Only rotate pages when confidence is above this value (arbitrary "
|
help="Only rotate pages when confidence is above this value (arbitrary "
|
||||||
"units reported by tesseract)")
|
"units reported by tesseract)")
|
||||||
advanced.add_argument(
|
advanced.add_argument(
|
||||||
@@ -491,6 +505,10 @@ def check_options_advanced(options, log):
|
|||||||
"--output-type is not 'pdfa', 'pdfa-1', or 'pdfa-2'"
|
"--output-type is not 'pdfa', 'pdfa-1', or 'pdfa-2'"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if tesseract.v4() and (options.user_words or options.user_patterns):
|
||||||
|
log.warning(
|
||||||
|
'Tesseract 4.x ignores --user-words, so this has no effect')
|
||||||
|
|
||||||
|
|
||||||
def check_options_metadata(options, log):
|
def check_options_metadata(options, log):
|
||||||
import unicodedata
|
import unicodedata
|
||||||
@@ -574,7 +592,7 @@ def do_ruffus_exception(ruffus_five_tuple, options, log):
|
|||||||
if exc_name == 'builtins.SystemExit':
|
if exc_name == 'builtins.SystemExit':
|
||||||
match = re.search(r"\.(.+?)\)", exc_value)
|
match = re.search(r"\.(.+?)\)", exc_value)
|
||||||
exit_code_name = match.groups()[0]
|
exit_code_name = match.groups()[0]
|
||||||
exit_code = getattr(ExitCode, exit_code_name, 'other_error')
|
exit_code = getattr(ExitCode, exit_code_name, 'other_error')
|
||||||
elif exc_name == 'ruffus.ruffus_exceptions.MissingInputFileError':
|
elif exc_name == 'ruffus.ruffus_exceptions.MissingInputFileError':
|
||||||
log.error(cleanup_ruffus_error_message(exc_value))
|
log.error(cleanup_ruffus_error_message(exc_value))
|
||||||
exit_code = ExitCode.input_file
|
exit_code = ExitCode.input_file
|
||||||
@@ -598,7 +616,7 @@ def do_ruffus_exception(ruffus_five_tuple, options, log):
|
|||||||
(exc_name == 'ocrmypdf.exceptions.EncryptedPdfError'):
|
(exc_name == 'ocrmypdf.exceptions.EncryptedPdfError'):
|
||||||
log.error(textwrap.dedent("""\
|
log.error(textwrap.dedent("""\
|
||||||
Input PDF is encrypted. The encryption must be removed to
|
Input PDF is encrypted. The encryption must be removed to
|
||||||
perform OCR.
|
perform OCR.
|
||||||
|
|
||||||
For information about this PDF's security use
|
For information about this PDF's security use
|
||||||
qpdf --show-encryption infilename
|
qpdf --show-encryption infilename
|
||||||
@@ -607,7 +625,7 @@ def do_ruffus_exception(ruffus_five_tuple, options, log):
|
|||||||
qpdf --decrypt [--password=[password]] infilename
|
qpdf --decrypt [--password=[password]] infilename
|
||||||
|
|
||||||
"""))
|
"""))
|
||||||
exit_code = ExitCode.encrypted_pdf
|
exit_code = ExitCode.encrypted_pdf
|
||||||
elif exc_name == 'ocrmypdf.exceptions.PdfMergeFailedError':
|
elif exc_name == 'ocrmypdf.exceptions.PdfMergeFailedError':
|
||||||
log.error(textwrap.dedent("""\
|
log.error(textwrap.dedent("""\
|
||||||
Failed to merge PDF image layer with OCR layer
|
Failed to merge PDF image layer with OCR layer
|
||||||
@@ -638,33 +656,31 @@ def do_ruffus_exception(ruffus_five_tuple, options, log):
|
|||||||
return ExitCode.other_error
|
return ExitCode.other_error
|
||||||
|
|
||||||
|
|
||||||
def traverse_ruffus_exception(e_args, options, log):
|
def traverse_ruffus_exception(exceptions, options, log):
|
||||||
"""Walk through a RethrownJobError and find the first exception.
|
"""Traverse a RethrownJobError and output the exceptions
|
||||||
|
|
||||||
Ruffus flattens exception to 5 element tuples. Because of a bug
|
Ruffus presents exceptions as 5 element tuples. The RethrownJobException
|
||||||
in <= 2.6.3 it may present either the single:
|
has a list of exceptions like
|
||||||
(task, job, exc, value, stack)
|
e.job_exceptions = [(5-tuple), (5-tuple), ...]
|
||||||
or something like:
|
|
||||||
[[(task, job, exc, value, stack)]]
|
ruffus < 2.7.0 had a bug with exception marshalling that would give
|
||||||
|
different output whether the main or child process raised the exception.
|
||||||
Generally cross-process exception marshalling doesn't work well
|
We no longer support this.
|
||||||
and ruffus doesn't support because BaseException has its own
|
|
||||||
implementation of __reduce__ that attempts to reconstruct the
|
Attempting to log the exception itself will re-marshall it to the logger
|
||||||
exception based on e.__init__(e.args).
|
which is normally running in another process. It's better to avoid re-
|
||||||
|
marshalling.
|
||||||
Attempting to log the exception directly marshalls it to the logger
|
|
||||||
which is probably in another process, so it's better to log only
|
|
||||||
data from the exception at this point.
|
|
||||||
|
|
||||||
The exit code will be based on this, even if multiple exceptions occurred
|
The exit code will be based on this, even if multiple exceptions occurred
|
||||||
at the same time."""
|
at the same time."""
|
||||||
|
|
||||||
if isinstance(e_args, Sequence) and isinstance(e_args[0], str) and \
|
exit_codes = []
|
||||||
len(e_args) == 5:
|
for exc in exceptions:
|
||||||
return do_ruffus_exception(e_args, options, log)
|
exit_code = do_ruffus_exception(exc, options, log)
|
||||||
elif is_iterable_notstr(e_args):
|
exit_codes.append(exit_code)
|
||||||
for exc in e_args:
|
|
||||||
return traverse_ruffus_exception(exc, options, log)
|
return exit_codes[0] # Multiple codes are rare so take the first one
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_closed_streams(options):
|
def check_closed_streams(options):
|
||||||
@@ -749,7 +765,7 @@ def check_environ(options, _log):
|
|||||||
for k in old_envvars:
|
for k in old_envvars:
|
||||||
if k in os.environ:
|
if k in os.environ:
|
||||||
_log.warning(textwrap.dedent("""\
|
_log.warning(textwrap.dedent("""\
|
||||||
OCRmyPDF no longer uses the environment variable {}.
|
OCRmyPDF no longer uses the environment variable {}.
|
||||||
Change PATH to select alternate programs.""".format(k)))
|
Change PATH to select alternate programs.""".format(k)))
|
||||||
|
|
||||||
|
|
||||||
@@ -792,14 +808,14 @@ def report_output_file_size(options, _log, input_file, output_file):
|
|||||||
ratio = output_size / input_size
|
ratio = output_size / input_size
|
||||||
if ratio < 1.35 or input_size < 25000:
|
if ratio < 1.35 or input_size < 25000:
|
||||||
return # Seems fine
|
return # Seems fine
|
||||||
|
|
||||||
reasons = []
|
reasons = []
|
||||||
if not fitz:
|
if not fitz:
|
||||||
reasons.append("The optional dependency PyMuPDF is not installed.")
|
reasons.append("The optional dependency PyMuPDF is not installed.")
|
||||||
image_preproc = {
|
image_preproc = {
|
||||||
'deskew',
|
'deskew',
|
||||||
'clean_final',
|
'clean_final',
|
||||||
'remove_background',
|
'remove_background',
|
||||||
'oversample',
|
'oversample',
|
||||||
'force_ocr'
|
'force_ocr'
|
||||||
}
|
}
|
||||||
@@ -886,7 +902,8 @@ def run_pipeline():
|
|||||||
except ruffus_exceptions.RethrownJobError as e:
|
except ruffus_exceptions.RethrownJobError as e:
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
_log.debug(str(e)) # stringify exception so logger doesn't have to
|
_log.debug(str(e)) # stringify exception so logger doesn't have to
|
||||||
exitcode = traverse_ruffus_exception(e.args, options, _log)
|
exceptions = e.job_exceptions
|
||||||
|
exitcode = traverse_ruffus_exception(exceptions, options, _log)
|
||||||
if exitcode is None:
|
if exitcode is None:
|
||||||
_log.error("Unexpected ruffus exception: " + str(e))
|
_log.error("Unexpected ruffus exception: " + str(e))
|
||||||
_log.error(repr(e))
|
_log.error(repr(e))
|
||||||
@@ -919,7 +936,7 @@ def run_pipeline():
|
|||||||
_log.warning('Output file: The generated PDF is INVALID')
|
_log.warning('Output file: The generated PDF is INVALID')
|
||||||
return ExitCode.invalid_output_pdf
|
return ExitCode.invalid_output_pdf
|
||||||
|
|
||||||
report_output_file_size(options, _log, start_input_file,
|
report_output_file_size(options, _log, start_input_file,
|
||||||
options.output_file)
|
options.output_file)
|
||||||
|
|
||||||
pdfinfo = context.get_pdfinfo()
|
pdfinfo = context.get_pdfinfo()
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ import codecs
|
|||||||
|
|
||||||
def verify_python3_env():
|
def verify_python3_env():
|
||||||
"""Ensures that the environment is good for unicode on Python 3."""
|
"""Ensures that the environment is good for unicode on Python 3."""
|
||||||
|
|
||||||
|
# PEP 538 changes in Python 3.7 should make this wrangling unnecessary
|
||||||
|
if sys.version_info[0:3] >= (3, 7, 0):
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import locale
|
import locale
|
||||||
fs_enc = codecs.lookup(locale.getpreferredencoding()).name
|
fs_enc = codecs.lookup(locale.getpreferredencoding()).name
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from ..exceptions import MissingDependencyError
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_version(program, *,
|
def get_version(program, *,
|
||||||
version_arg='--version', regex=r'(\d+(\.\d+)*)'):
|
version_arg='--version', regex=r'(\d+(\.\d+)*)'):
|
||||||
"Get the version of the specified program"
|
"Get the version of the specified program"
|
||||||
args_prog = [
|
args_prog = [
|
||||||
@@ -37,6 +37,10 @@ def get_version(program, *,
|
|||||||
args_prog, close_fds=True, universal_newlines=True,
|
args_prog, close_fds=True, universal_newlines=True,
|
||||||
stdout=PIPE, stderr=STDOUT, check=True)
|
stdout=PIPE, stderr=STDOUT, check=True)
|
||||||
output = proc.stdout
|
output = proc.stdout
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
raise MissingDependencyError(
|
||||||
|
"Could not find program '{}' on the PATH".format(
|
||||||
|
program)) from e
|
||||||
except CalledProcessError as e:
|
except CalledProcessError as e:
|
||||||
if e.returncode < 0:
|
if e.returncode < 0:
|
||||||
raise MissingDependencyError(
|
raise MissingDependencyError(
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ def has_textonly_pdf():
|
|||||||
"""
|
"""
|
||||||
args_tess = [
|
args_tess = [
|
||||||
'tesseract',
|
'tesseract',
|
||||||
'--print-parameters'
|
'--print-parameters',
|
||||||
|
'pdf'
|
||||||
]
|
]
|
||||||
params = ''
|
params = ''
|
||||||
try:
|
try:
|
||||||
@@ -159,7 +160,7 @@ def get_orientation(input_file, language: list, engine_mode, timeout: float,
|
|||||||
assert 'Rotate' not in osd
|
assert 'Rotate' not in osd
|
||||||
angle = -angle % 360
|
angle = -angle % 360
|
||||||
else:
|
else:
|
||||||
# Tesseract == 3.04.01, hopefully also Tesseract > 3.04.01
|
# Tesseract >= 3.04.01
|
||||||
# reports "Orientation in degrees" as a clockwise angle
|
# reports "Orientation in degrees" as a clockwise angle
|
||||||
assert 'Rotate' in osd
|
assert 'Rotate' in osd
|
||||||
|
|
||||||
|
|||||||
+17
-11
@@ -496,17 +496,23 @@ def rasterize_with_ghostscript(
|
|||||||
options = context.get_options()
|
options = context.get_options()
|
||||||
pageinfo = get_pageinfo(input_file, context)
|
pageinfo = get_pageinfo(input_file, context)
|
||||||
|
|
||||||
device = 'png16m' # 24-bit
|
colorspaces = ['pngmono', 'pnggray', 'png256', 'png16m']
|
||||||
if pageinfo.images:
|
device_idx = 0
|
||||||
if all(image.comp == 1 for image in pageinfo.images):
|
def at_least(cs):
|
||||||
if all(image.bpc == 1 for image in pageinfo.images):
|
return max(device_idx, colorspaces.index(cs))
|
||||||
device = 'pngmono'
|
|
||||||
elif all(image.bpc > 1 and image.color == Colorspace.index
|
for image in pageinfo.images:
|
||||||
for image in pageinfo.images):
|
if image.type_ != 'image':
|
||||||
device = 'png256'
|
continue # ignore masks
|
||||||
elif all(image.bpc > 1 and image.color == Colorspace.gray
|
if image.bpc > 1:
|
||||||
for image in pageinfo.images):
|
if image.color == Colorspace.index:
|
||||||
device = 'pnggray'
|
device_idx = at_least('png256')
|
||||||
|
elif image.color == Colorspace.gray:
|
||||||
|
device_idx = at_least('pnggray')
|
||||||
|
else:
|
||||||
|
device_idx = at_least('png16m')
|
||||||
|
|
||||||
|
device = colorspaces[device_idx]
|
||||||
|
|
||||||
log.debug("Rasterize {0} with {1}".format(
|
log.debug("Rasterize {0} with {1}".format(
|
||||||
os.path.basename(input_file), device))
|
os.path.basename(input_file), device))
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ pytest >= 3.2
|
|||||||
pytest-helpers-namespace
|
pytest-helpers-namespace
|
||||||
pytest-xdist
|
pytest-xdist
|
||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-timeout
|
pytest-timeout == 1.2.1
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ def main():
|
|||||||
source = os.environ['_OCRMYPDF_TEST_INFILE'] # required
|
source = os.environ['_OCRMYPDF_TEST_INFILE'] # required
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
cache_disabled = os.environ.get('_OCRMYPDF_CACHE_DISABLED', False)
|
||||||
|
|
||||||
if args.imagename == 'stdin':
|
if args.imagename == 'stdin':
|
||||||
real_tesseract()
|
real_tesseract()
|
||||||
|
|
||||||
@@ -128,7 +130,7 @@ def main():
|
|||||||
print("Tesseract cache folder {} - ".format(cache_folder), end='',
|
print("Tesseract cache folder {} - ".format(cache_folder), end='',
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
|
|
||||||
if (cache_folder / 'stderr.bin').exists():
|
if (cache_folder / 'stderr.bin').exists() and not cache_disabled:
|
||||||
# Cache hit
|
# Cache hit
|
||||||
print("HIT", file=sys.stderr)
|
print("HIT", file=sys.stderr)
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -300,7 +300,8 @@ def test_autorotate_threshold(
|
|||||||
@pytest.mark.parametrize('renderer',RENDERERS)
|
@pytest.mark.parametrize('renderer',RENDERERS)
|
||||||
def test_ocr_timeout(renderer, resources, outpdf):
|
def test_ocr_timeout(renderer, resources, outpdf):
|
||||||
out = check_ocrmypdf(resources / 'skew.pdf', outpdf,
|
out = check_ocrmypdf(resources / 'skew.pdf', outpdf,
|
||||||
'--tesseract-timeout', '1.0')
|
'--tesseract-timeout', '0.01',
|
||||||
|
'--pdf-renderer', renderer)
|
||||||
pdfinfo = PdfInfo(out)
|
pdfinfo = PdfInfo(out)
|
||||||
assert not pdfinfo[0].has_text
|
assert not pdfinfo[0].has_text
|
||||||
|
|
||||||
@@ -472,7 +473,7 @@ def test_tesseract_image_too_big(renderer, spoof_tesseract_big_image_error,
|
|||||||
resources, outpdf):
|
resources, outpdf):
|
||||||
check_ocrmypdf(
|
check_ocrmypdf(
|
||||||
resources / 'hugemono.pdf', outpdf, '-r',
|
resources / 'hugemono.pdf', outpdf, '-r',
|
||||||
'--pdf-renderer', renderer,
|
'--pdf-renderer', renderer,
|
||||||
'--max-image-mpixels', '0',
|
'--max-image-mpixels', '0',
|
||||||
env=spoof_tesseract_big_image_error)
|
env=spoof_tesseract_big_image_error)
|
||||||
|
|
||||||
@@ -966,6 +967,7 @@ def test_pdfa_n(spoof_tesseract_cache, pdfa_level, resources, outpdf):
|
|||||||
assert pdfa_info['conformance'] == 'PDF/A-{}B'.format(pdfa_level)
|
assert pdfa_info['conformance'] == 'PDF/A-{}B'.format(pdfa_level)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.version_info >= (3, 7, 0), reason='fixed')
|
||||||
def test_bad_locale():
|
def test_bad_locale():
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['LC_ALL'] = 'C'
|
env['LC_ALL'] = 'C'
|
||||||
@@ -993,7 +995,7 @@ def test_bad_utf8(spoof_tess_bad_utf8, renderer, resources, no_outpdf):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
@pytest.mark.skipif(
|
||||||
not tesseract.has_textonly_pdf(),
|
not tesseract.has_textonly_pdf(),
|
||||||
reason="issue only affects sandwich")
|
reason="issue only affects sandwich")
|
||||||
def test_rotate_deskew_timeout(resources, outdir):
|
def test_rotate_deskew_timeout(resources, outdir):
|
||||||
check_ocrmypdf(
|
check_ocrmypdf(
|
||||||
@@ -1043,10 +1045,10 @@ def test_text_curves(spoof_tesseract_noop, resources, outpdf):
|
|||||||
check_ocrmypdf(
|
check_ocrmypdf(
|
||||||
resources / 'vector.pdf', outpdf, '--force-ocr',
|
resources / 'vector.pdf', outpdf, '--force-ocr',
|
||||||
env=spoof_tesseract_noop)
|
env=spoof_tesseract_noop)
|
||||||
|
|
||||||
info = PdfInfo(outpdf)
|
info = PdfInfo(outpdf)
|
||||||
assert len(info.pages[0].images) != 0, "force did not rasterize"
|
assert len(info.pages[0].images) != 0, "force did not rasterize"
|
||||||
|
|
||||||
|
|
||||||
def test_dev_null(spoof_tesseract_noop, resources):
|
def test_dev_null(spoof_tesseract_noop, resources):
|
||||||
p, out, err = run_ocrmypdf(
|
p, out, err = run_ocrmypdf(
|
||||||
|
|||||||
Reference in New Issue
Block a user