Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72337094ca | ||
|
|
f472587d22 | ||
|
|
f34b3015b2 | ||
|
|
089ece2715 | ||
|
|
6438465e3f | ||
|
|
7d330afd81 | ||
|
|
68fbd9fcc9 | ||
|
|
c771938907 | ||
|
|
c2a947acf4 | ||
|
|
8c0009c5c8 | ||
|
|
cfc5cdf47d | ||
|
|
05152a8af9 | ||
|
|
0880b16491 | ||
|
|
06308a22ce | ||
|
|
80bd7de580 | ||
|
|
8b90c45437 | ||
|
|
72b920eb16 | ||
|
|
b4a51907d6 | ||
|
|
1ca1221432 | ||
|
|
40b72b0fa8 | ||
|
|
0e55b4ad52 | ||
|
|
7b4f5a8fc4 | ||
|
|
9261a38493 | ||
|
|
cc8ff318ed | ||
|
|
ad15e845f9 |
@@ -1,5 +0,0 @@
|
||||
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 you wish to encrypt a test file for the OCRmyPDF maintainer only, see the [Wiki](https://github.com/jbarlow83/OCRmyPDF/wiki).
|
||||
@@ -0,0 +1,33 @@
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the issue is.
|
||||
|
||||
**To Reproduce**
|
||||
What command line were you trying to run?
|
||||
|
||||
```bash
|
||||
ocrmypdf ...arguments... input.pdf output.pdf
|
||||
```
|
||||
|
||||
**Example file**
|
||||
Please include an example *input* PDF (or image). The input file is more helpful.
|
||||
|
||||
Please check any or all that apply about the test file:
|
||||
|
||||
- [ ] This is the input file
|
||||
- [ ] The file contains no personal or confidential information
|
||||
- [ ] I am the copyright holder for this file
|
||||
- [ ] I permit this file to be included in the OCRmyPDF test suite under the CC-BY-SA 4.0 license
|
||||
- [ ] I am not the copyright holder, but this file is available under a free software license
|
||||
|
||||
Files that are not free for inclusion in this project are quite welcome, but we like to collect free files for our test suite when possible. Please do *not* submit files with confidential information. At your option you may encrypt files for OCRmyPDF's author only.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen. Include screenshots if applicable.
|
||||
|
||||
**System:**
|
||||
|
||||
- OS: [e.g. Linux, macOS]
|
||||
- OCRmyPDF Version: [e.g. v7.4.0]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -39,3 +39,5 @@ log/
|
||||
tests/output/
|
||||
tests/resources/private/
|
||||
tmp/
|
||||
/debug_tests.py
|
||||
*.traineddata
|
||||
|
||||
+38
-10
@@ -9,7 +9,7 @@ matrix:
|
||||
dist: trusty
|
||||
sudo: required
|
||||
language: python
|
||||
python: "3.5"
|
||||
python: "3.6"
|
||||
env:
|
||||
- DIST=trusty
|
||||
addons: &trusty_apt
|
||||
@@ -33,14 +33,6 @@ matrix:
|
||||
- tesseract-ocr-deu
|
||||
- tesseract-ocr-eng
|
||||
- tesseract-ocr-fra
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
language: python
|
||||
python: "3.6"
|
||||
env:
|
||||
- DIST=trusty
|
||||
addons: *trusty_apt
|
||||
- os: linux
|
||||
dist: xenial
|
||||
sudo: required
|
||||
@@ -68,6 +60,39 @@ matrix:
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
language: generic
|
||||
addons:
|
||||
homebrew:
|
||||
update: true
|
||||
packages:
|
||||
- exempi
|
||||
- ghostscript
|
||||
- jbig2enc
|
||||
- leptonica
|
||||
- openjpeg
|
||||
- pngquant
|
||||
- python
|
||||
- qpdf
|
||||
- tesseract
|
||||
- unpaper
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
language: generic
|
||||
env:
|
||||
- ADD_PDFMINER=1
|
||||
addons:
|
||||
homebrew:
|
||||
update: true
|
||||
packages:
|
||||
- exempi
|
||||
- ghostscript
|
||||
- jbig2enc
|
||||
- leptonica
|
||||
- openjpeg
|
||||
- pngquant
|
||||
- python
|
||||
- qpdf
|
||||
- tesseract
|
||||
- unpaper
|
||||
|
||||
before_cache:
|
||||
- rm -f $HOME/.cache/pip/log/debug.log
|
||||
@@ -83,7 +108,6 @@ before_install: |
|
||||
sudo dpkg -i packages/unpaper_6.1-1.deb
|
||||
fi
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update --quiet && brew bundle --file=.travis/Brewfile --quiet
|
||||
pip3 install --upgrade pip
|
||||
pip3 install wheel
|
||||
fi
|
||||
@@ -93,6 +117,10 @@ install:
|
||||
- pip3 install pycparser # py3.7 workaround for https://github.com/eliben/pycparser/issues/251
|
||||
- pip3 install -r requirements/main.txt
|
||||
- pip3 install --no-deps .
|
||||
- |
|
||||
if [[ "$ADD_PDFMINER" == "1" ]]; then
|
||||
pip3 install --no-deps .[pdfminer]
|
||||
fi
|
||||
- pip3 install -r requirements/test.txt
|
||||
|
||||
script:
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
brew 'python'
|
||||
|
||||
brew 'exempi'
|
||||
brew 'ghostscript'
|
||||
brew 'jbig2enc'
|
||||
brew 'leptonica'
|
||||
brew 'openjpeg'
|
||||
brew 'pngquant'
|
||||
brew 'qpdf'
|
||||
brew 'tesseract'
|
||||
brew 'unpaper'
|
||||
@@ -25,20 +25,22 @@ ocrmypdf # it's a scriptable command line program
|
||||
output_searchable.pdf # produces validated PDF output
|
||||
```
|
||||
|
||||
[See the release notes for details on the latest changes](https://ocrmypdf.readthedocs.io/en/latest/release_notes.html).
|
||||
|
||||
Main features
|
||||
-------------
|
||||
|
||||
- Generates a searchable [PDF/A](https://en.wikipedia.org/?title=PDF/A) file from a regular PDF
|
||||
- Places OCR text accurately below the image to ease copy / paste
|
||||
- Keeps the exact resolution of the original embedded images
|
||||
- When possible, inserts OCR information as a "lossless" operation without disrupting any other content
|
||||
- Optimizes PDF images, often producing files smaller than the input file
|
||||
- If requested deskews and/or cleans the image before performing OCR
|
||||
- Validates input and output files
|
||||
- Distributes work across all available CPU cores
|
||||
- Uses [Tesseract OCR](https://github.com/tesseract-ocr/tesseract) engine
|
||||
- Supports more than [100 languages](https://github.com/tesseract-ocr/tessdata) recognized by Tesseract
|
||||
- Battle-tested on thousands of PDFs, a test suite and continuous integration
|
||||
- Generates a searchable [PDF/A](https://en.wikipedia.org/?title=PDF/A) file from a regular PDF
|
||||
- Places OCR text accurately below the image to ease copy / paste
|
||||
- Keeps the exact resolution of the original embedded images
|
||||
- When possible, inserts OCR information as a "lossless" operation without disrupting any other content
|
||||
- Optimizes PDF images, often producing files smaller than the input file
|
||||
- If requested deskews and/or cleans the image before performing OCR
|
||||
- Validates input and output files
|
||||
- Distributes work across all available CPU cores
|
||||
- Uses [Tesseract OCR](https://github.com/tesseract-ocr/tesseract) engine
|
||||
- Supports more than [100 languages](https://github.com/tesseract-ocr/tessdata) recognized by Tesseract
|
||||
- Battle-tested on thousands of PDFs, a test suite and continuous integration
|
||||
|
||||
For details: please consult the [documentation](https://ocrmypdf.readthedocs.io/en/latest/).
|
||||
|
||||
@@ -47,13 +49,13 @@ Motivation
|
||||
|
||||
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.
|
||||
|
||||
- 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 changed the resolution of the embedded images
|
||||
- Or they generated ridiculously large PDF files
|
||||
- Or they crashed when trying to OCR
|
||||
- Or they did not produce valid PDF files
|
||||
- On top of that none of them produced PDF/A files (format dedicated for long time storage)
|
||||
- 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 changed the resolution of the embedded images
|
||||
- Or they generated ridiculously large PDF files
|
||||
- Or they crashed when trying to OCR
|
||||
- Or they did not produce valid PDF files
|
||||
- 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.
|
||||
|
||||
@@ -110,11 +112,11 @@ Our [documentation is served on Read the Docs](https://ocrmypdf.readthedocs.io/e
|
||||
|
||||
If you detect an issue, please:
|
||||
|
||||
- Check whether your issue is already known
|
||||
- If no problem report exists on github, please create one here: <https://github.com/jbarlow83/OCRmyPDF/issues>
|
||||
- Describe your problem thoroughly
|
||||
- Append the console output of the script when running the debug mode (`-v 1` option)
|
||||
- If possible provide your input PDF file as well as the content of the temporary folder (using a file sharing service like Dropbox)
|
||||
- Check whether your issue is already known
|
||||
- If no problem report exists on github, please create one here: <https://github.com/jbarlow83/OCRmyPDF/issues>
|
||||
- Describe your problem thoroughly
|
||||
- Append the console output of the script when running the debug mode (`-v 1` option)
|
||||
- If possible provide your input PDF file as well as the content of the temporary folder (using a file sharing service like Dropbox)
|
||||
|
||||
Requirements
|
||||
------------
|
||||
@@ -124,8 +126,10 @@ Runs on CPython 3.5, 3.6 and 3.7. Requires external program installations of Gho
|
||||
Press & Media
|
||||
-------------
|
||||
|
||||
- [c't 1-2014, page 59](http://heise.de/-2279695): Detailed presentation of OCRmyPDF v1.0 in the leading German IT magazine c't
|
||||
- [heise Open Source, 09/2014: Texterkennung mit OCRmyPDF](http://heise.de/-2356670)
|
||||
- [Going paperless with OCRmyPDF](https://medium.com/@ikirichenko/going-paperless-with-ocrmypdf-e2f36143f46a)
|
||||
- [Converting a scanned document into a compressed searchable PDF with redactions](https://medium.com/@treyharris/converting-a-scanned-document-into-a-compressed-searchable-pdf-with-redactions-63f61c34fe4c)
|
||||
- [c't 1-2014, page 59](http://heise.de/-2279695): Detailed presentation of OCRmyPDF v1.0 in the leading German IT magazine c't
|
||||
- [heise Open Source, 09/2014: Texterkennung mit OCRmyPDF](http://heise.de/-2356670)
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Vendored
+6
@@ -95,6 +95,12 @@ Files: tests/resources/vector.pdf
|
||||
Copyright: (C) 2018 Catscratch
|
||||
License: Expat
|
||||
|
||||
Files: test/resources/enron*.pdf
|
||||
Copyright: EnronData.org
|
||||
License: CC-BY-3.0
|
||||
See: https://enrondata.readthedocs.io/en/latest/data/edo-enron-email-pst-dataset/
|
||||
Comment: Unprocessed.
|
||||
|
||||
Files: src/ocrmypdf/data/sRGB.icc
|
||||
Copyright: Kai-Uwe Behrmann <www.behrmann.name>
|
||||
Marti Maria <www.littlecms.com>
|
||||
|
||||
+6
-8
@@ -47,16 +47,16 @@ Some relevant environment variables that influence Tesseract's behavior include:
|
||||
|
||||
Controls the number of threads Tesseract will use. OCRmyPDF will manage this environment if it is not already set. (Currently, it will set it to 1 because this gives the best results in testing.)
|
||||
|
||||
For example, if you are testing tesseract 4.00 and don't wish to use an existing tesseract 3.04 installation, you can launch OCRmyPDF as follows:
|
||||
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/tesseract4/api:$PATH \
|
||||
TESSDATA_PREFIX=/home/user/src/tesseract4 \
|
||||
ocrmypdf --tesseract-oem 2 input.pdf output.pdf
|
||||
PATH=/home/user/src/tesseract/api:$PATH \
|
||||
TESSDATA_PREFIX=/home/user/src/tesseract \
|
||||
ocrmypdf input.pdf output.pdf
|
||||
|
||||
In this example ``TESSDATA_PREFIX`` directs Tesseract 4.0 to use LSTM training data. ``--tesseract-oem 1`` requests tesseract 4.0's new LSTM engine. (Tesseract 4.0 only.)
|
||||
In this example ``TESSDATA_PREFIX`` is required to redirect Tesseract to an alternate folder for its "tessdata" files.
|
||||
|
||||
|
||||
Overriding other support programs
|
||||
@@ -107,7 +107,7 @@ 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`` selects ``sandwich`` for Tesseract 3.05.01 or newer, or ``hocr`` for older versions of Tesseract.
|
||||
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 ``sandwich``.
|
||||
|
||||
The ``sandwich`` renderer
|
||||
"""""""""""""""""""""""""
|
||||
@@ -118,8 +118,6 @@ Currently this is the best renderer for most uses, however it is implemented in
|
||||
|
||||
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.
|
||||
|
||||
If a PDF created with this renderer using Tesseract versions older than 3.05.00 is then passed through Ghostscript's pdfwrite feature, the OCR text *may* be corrupted. The ``--output-type=pdfa`` argument will produce a warning in this situation. For this reason, OCRmyPDF automatically selects the ``hocr`` for older Tesseract versions.
|
||||
|
||||
The ``hocr`` renderer
|
||||
"""""""""""""""""""""
|
||||
|
||||
|
||||
+6
-1
@@ -74,7 +74,12 @@ if on_rtd:
|
||||
def __getattr__(cls, name):
|
||||
return MagicMock()
|
||||
|
||||
MOCK_MODULES = ['pikepdf', 'ocrmypdf.leptonica']
|
||||
MOCK_MODULES = [
|
||||
'pikepdf',
|
||||
'pikepdf.models',
|
||||
'pikepdf.models.metadata',
|
||||
'ocrmypdf.leptonica'
|
||||
]
|
||||
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ This produces a file named "output.pdf" and a companion text file named "output.
|
||||
OCR images, not PDFs
|
||||
--------------------
|
||||
|
||||
If you are starting with images, you can just use Tesseract 3.04 or later directly to convert images to PDFs:
|
||||
If you are starting with images, you can just use Tesseract directly to convert images to PDFs:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
||||
@@ -377,6 +377,9 @@ Assuming you have a Docker engine running, you can download one of the three ava
|
||||
* - ocrmypdf-polyglot
|
||||
- ``docker pull jbarlow83/ocrmypdf-polyglot``
|
||||
- As above, with all available language packs.
|
||||
* - ocrmypdf-webservice
|
||||
- ``docker pull jbarlow83/ocrmypdf-polyglot``
|
||||
- All language packs, and a simple HTTP wrapper allowing OCRmyPDF to be used as a web service. Note that this component is licensed under AGPLv3.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -490,21 +493,17 @@ 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.
|
||||
|
||||
- Python 3.5 or newer
|
||||
- Python 3.6 or newer
|
||||
- Ghostscript 9.15 or newer
|
||||
- libexempi3 2.2.0 or newer
|
||||
- qpdf 8.1.0 or newer
|
||||
- Tesseract 3.04 or newer
|
||||
|
||||
Using Python 3.5 in production is discouraged. Python 3.6 and 3.7 give much better performance.
|
||||
- Tesseract 4.0.0-alpha or newer
|
||||
|
||||
As of ocrmypdf 7.2.1, the following versions are recommended:
|
||||
|
||||
- Python 3.7
|
||||
- Ghostscript 9.23 or newer
|
||||
- libexempi3 2.4.5 or newer
|
||||
- qpdf 8.2.1
|
||||
- Tesseract 4.0.0-rc1
|
||||
- Tesseract 4.0.0 or newer
|
||||
- jbig2enc 0.29 or newer
|
||||
- pngquant 2.5 or newer
|
||||
- unpaper 6.1
|
||||
@@ -523,7 +522,7 @@ These are in addition to the Python packaging dependencies, meaning that unfortu
|
||||
Installing HEAD revision from sources
|
||||
-------------------------------------
|
||||
|
||||
If you have ``git`` and Python 3.5 or newer installed, you can install from source. When the ``pip`` installer runs, it will alert you if dependencies are missing.
|
||||
If you have ``git`` and Python 3.6 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.
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ Ghostscript also imposes some limitations:
|
||||
* PDFs containing JBIG2-encoded content will be converted to CCITT Group4 encoding, which has lower compression ratios, if Ghostscript PDF/A is enabled.
|
||||
* PDFs containing JPEG 2000-encoded content will be converted to JPEG encoding, which may introduce compression artifacts, if Ghostscript PDF/A is enabled.
|
||||
* Ghostscript may transcode grayscale and color images, either lossy to lossless or lossless to lossy, based on an internal algorithm. This behavior can be suppressed by setting ``--pdfa-image-compression`` to ``jpeg`` or ``lossless`` to set all images to one type or the other. Ghostscript has no option to maintain the input image's format. (Ghostscript 9.25+ can copy JPEG images without transcoding them; earlier versions will transcode.)
|
||||
* Ghostscript's PDF/A conversion removes any XMP metadata that is not one of the standard XMP metadata namespaces for PDFs. In particular, PRISM Metdata is removed.
|
||||
|
||||
Regarding OCRmyPDF itself:
|
||||
|
||||
@@ -109,7 +110,10 @@ To the author's knowledge, OCRmyPDF is the most feature-rich and thoroughly test
|
||||
Web front-ends
|
||||
--------------
|
||||
|
||||
* `Nextcloud OCR <https://github.com/janis91/ocr>`_ is a free software plugin for the Nextcloud private cloud software
|
||||
* `OCRmyPDF-web <https://github.com/sseemayer/OCRmyPDF-web>`_, a micro web-frontend for OCRmyPDF (third-party, not actively maintained)
|
||||
The Docker image ocrmypdf-webservice provides a web service front-end that allows files to submitted over HTTP and the results "downloaded". This is an HTTP server intended to simplify web services deployments; it is not intended to be deployed on the public internet and no real security measures to speak of.
|
||||
|
||||
Bear in mind that OCRmyPDF is not designed to be secure against malware-bearing PDFs (see `Using OCRmyPDF online`_).
|
||||
In addition, the following integrations are available:
|
||||
|
||||
* `Nextcloud OCR <https://github.com/janis91/ocr>`_ is a free software plugin for the Nextcloud private cloud software
|
||||
|
||||
Bear in mind that OCRmyPDF is not designed to be secure against malware-bearing PDFs (see `Using OCRmyPDF online`_). Users should ensure they comply with OCRmyPDF's licenses and the licenses of all dependencies. In particular, OCRmyPDF requires Ghostscript, which is licensed under AGPLv3.
|
||||
|
||||
@@ -13,6 +13,36 @@ Note that it is licensed under GPLv3, so scripts that ``import ocrmypdf`` and ar
|
||||
find: [^`]\#([0-9]{1,3})[^0-9]
|
||||
replace: `#$1 <https://github.com/jbarlow83/OCRmyPDF/issues/$1>`_
|
||||
|
||||
|
||||
v8.0.0
|
||||
------
|
||||
|
||||
No major features. The intent of this release is to sever support for older versions of certain dependencies.
|
||||
|
||||
**Breaking changes**
|
||||
|
||||
- Dropped support for Tesseract 3.x. Tesseract 4.0 or newer is now required.
|
||||
|
||||
- Dropped support for Python 3.5.
|
||||
|
||||
- Some ``ocrmypdf.pdfa`` APIs that were deprecated in v7.x were removed. This functionality has been moved to pikepdf.
|
||||
|
||||
**Other changes**
|
||||
|
||||
- Fixed an unhandled exception when attempting to mask barcodes. `#322 <https://github.com/jbarlow83/OCRmyPDF/issues/322>`_
|
||||
|
||||
- It is now possible to use ocrmypdf without pdfminer.six, to support distributions that do not have it or cannot currently use it (e.g. Homebrew). Downstream maintainers should include pdfminer.six if possible.
|
||||
|
||||
- A warning is now issue when PDF/A conversion removes some XMP metadata from the input PDF. (Only a "whitelist" of certain XMP metadata types are allowed in PDF/A.)
|
||||
|
||||
- Fixed several issues that caused PDF/As to be produced with nonconforming XMP metadata (would fail validation with veraPDF).
|
||||
|
||||
- Fixed some instances where invalid DocumentInfo from a PDF cause XMP metadata creation to fail.
|
||||
|
||||
- Fixed a few documentation problems.
|
||||
|
||||
- pikepdf 1.0.2 is now required.
|
||||
|
||||
v7.4.0
|
||||
------
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
complete -c ocrmypdf -l version
|
||||
complete -c ocrmypdf -l help
|
||||
|
||||
complete -c ocrmypdf -l sidecar -r -d "write OCR to text file"
|
||||
complete -c ocrmypdf -s q -l quiet
|
||||
|
||||
complete -c ocrmypdf -s r -l rotate-pages -d "rotate pages to correct orientation"
|
||||
complete -c ocrmypdf -s d -l deskew -d "fix small horizontal alignment skew"
|
||||
complete -c ocrmypdf -s c -l clean -d "clean document images before OCR"
|
||||
complete -c ocrmypdf -s i -l clean-final -d "clean document images and keep result"
|
||||
complete -c ocrmypdf -l remove-vectors -d "don't send vector objects to OCR"
|
||||
complete -c ocrmypdf -l mask-barcodes -d "mask barcodes from OCR"
|
||||
complete -c ocrmypdf -l threshold -d "threshold images before OCR"
|
||||
|
||||
complete -c ocrmypdf -s f -l force-ocr -d "OCR documents that already have printable text"
|
||||
complete -c ocrmypdf -s s -l skip-ocr -d "skip OCR on pages that text, otherwise try OCR"
|
||||
complete -c ocrmypdf -l redo-ocr -d "redo OCR on any pages that seem to have OCR already"
|
||||
|
||||
complete -c ocrmypdf -s k -l keep-temporary-files -d "keep temporary files (debug)"
|
||||
|
||||
complete -c ocrmypdf -x -s l -l language -d 'language'
|
||||
complete -c ocrmypdf -x -s l -l language -a '(tesseract --list-langs)'
|
||||
|
||||
complete -c ocrmypdf -x -l image-dpi -d "assume this DPI if input image DPI is unknown"
|
||||
|
||||
function __fish_ocrmypdf_output_type
|
||||
echo -e "pdfa\t"(_ "output a PDF/A (default)")
|
||||
echo -e "pdf\t"(_ "output a standard PDF")
|
||||
echo -e "pdfa-1\t"(_ "output a PDF/A-1b")
|
||||
echo -e "pdfa-2\t"(_ "output a PDF/A-2b")
|
||||
echo -e "pdfa-3\t"(_ "output a PDF/A-3b")
|
||||
end
|
||||
complete -c ocrmypdf -x -l output-type -a '(__fish_ocrmypdf_output_type)' -d "select PDF output options"
|
||||
|
||||
function __fish_ocrmypdf_pdf_renderer
|
||||
echo -e "auto\t"(_ "auto select PDF renderer")
|
||||
echo -e "hocr\t"(_ "use hocr renderer")
|
||||
echo -e "sandwich\t"(_ "use sandwich renderer")
|
||||
end
|
||||
complete -c ocrmypdf -x -l pdf-render -a '(__fish_ocrmypdf_pdf_renderer)' -d "select PDF renderer options"
|
||||
|
||||
function __fish_ocrmypdf_optimize
|
||||
echo -e "0\t"(_ "do not optimize")
|
||||
echo -e "1\t"(_ "do safe, lossless optimizations (default)")
|
||||
echo -e "2\t"(_ "do some lossy optimizations")
|
||||
echo -e "3\t"(_ "do aggressive lossy optimizations (including lossy JBIG2)")
|
||||
end
|
||||
complete -c ocrmypdf -x -s O -l optimize -a '(__fish_ocrmypdf_optimize)' -d "select optimization level"
|
||||
|
||||
complete -c ocrmypdf -x -s j -l jobs -d "how many worker processes to use"
|
||||
complete -c ocrmypdf -x -s v -a '(seq 1 9)'
|
||||
complete -c ocrmypdf -x -l title -d "set metadata"
|
||||
complete -c ocrmypdf -x -l author -d "set metadata"
|
||||
complete -c ocrmypdf -x -l subject -d "set metadata"
|
||||
complete -c ocrmypdf -x -l keywords -d "set metadata"
|
||||
complete -c ocrmypdf -x -l oversample -d "oversample images to this DPI"
|
||||
complete -c ocrmypdf -x -l skip-big -d "skip OCR on pages larger than this many MPixels"
|
||||
|
||||
complete -c ocrmypdf -x -l jpeg-quality -d "JPEG quality [0..100]"
|
||||
complete -c ocrmypdf -x -l png-quality -d "PNG quality [0..100]"
|
||||
complete -c ocrmypdf -x -l jbig2-lossy -d "enable lossy JBIG2 (see docs)"
|
||||
complete -c ocrmypdf -x -l max-image-mpixels -d "image decompression bomb threshold"
|
||||
complete -c ocrmypdf -x -l tesseract-config -d "set custom tesseract config file"
|
||||
complete -c ocrmypdf -x -l tesseract-pagesegmode -d "set tesseract --psm"
|
||||
complete -c ocrmypdf -x -l tesseract-oem -d "set tesseract --oem"
|
||||
complete -c ocrmypdf -x -l tesseract-timeout -d "maximum number of seconds to wait for OCR"
|
||||
complete -c ocrmypdf -x -l rotate-pages-threshold -d "page rotation confidence"
|
||||
complete -c ocrmypdf -x -l pdfa-image-compression -a 'auto jpeg lossless' -d "set PDF/A image compression options"
|
||||
|
||||
complete -c ocrmypdf -x -a "(__fish_complete_suffix .pdf)"
|
||||
@@ -5,7 +5,7 @@ chardet == 3.0.4
|
||||
cffi == 1.11.5
|
||||
img2pdf == 0.3.1
|
||||
pdfminer.six == 20181108
|
||||
pikepdf == 0.9.1
|
||||
pikepdf == 1.0.2
|
||||
Pillow >= 5.0.0, != 5.1.0 ; sys_platform == "darwin"
|
||||
pycparser == 2.19
|
||||
python-xmp-toolkit == 2.0.1
|
||||
|
||||
@@ -14,5 +14,12 @@ testpaths = tests
|
||||
filterwarnings =
|
||||
ignore:.*XMLParser.*:DeprecationWarning
|
||||
|
||||
[isort]
|
||||
multi_line_output=3
|
||||
include_trailing_comma=True
|
||||
force_grid_wrap=0
|
||||
use_parentheses=True
|
||||
line_length=88
|
||||
|
||||
[metadata]
|
||||
license_file = LICENSE
|
||||
|
||||
@@ -20,15 +20,16 @@
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import sys
|
||||
if sys.version_info < (3, 5):
|
||||
print("Python 3.5 or newer is required", file=sys.stderr)
|
||||
if sys.version_info < (3, 6):
|
||||
print("Python 3.6 or newer is required", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
from setuptools import setup, find_packages # nopep8
|
||||
from subprocess import STDOUT, check_output, CalledProcessError # nopep8
|
||||
from collections.abc import Mapping # nopep8
|
||||
import re # nopep8
|
||||
from setuptools import setup, find_packages
|
||||
from subprocess import STDOUT, check_output, CalledProcessError
|
||||
from collections.abc import Mapping
|
||||
import re
|
||||
|
||||
# pylint: disable=w0613
|
||||
|
||||
missing_program = '''
|
||||
The program '{program}' could not be executed or was not found on your
|
||||
@@ -131,12 +132,12 @@ def check_external_program(
|
||||
program,
|
||||
need_version,
|
||||
package,
|
||||
version_check_args=['--version'],
|
||||
version_check_args=None,
|
||||
version_scrape_regex=re.compile(r'(\d+\.\d+(?:\.\d+)?)'),
|
||||
optional=False):
|
||||
|
||||
print('Checking for {program} >= {need_version}...'.format(
|
||||
program=program, need_version=need_version))
|
||||
if not version_check_args:
|
||||
version_check_args = ['--version']
|
||||
print(f'Checking for {program} >= {need_version}...')
|
||||
try:
|
||||
result = check_output(
|
||||
[program] + version_check_args,
|
||||
@@ -145,7 +146,7 @@ def check_external_program(
|
||||
error_missing_program(program, package, optional)
|
||||
if not optional:
|
||||
sys.exit(1)
|
||||
print('Continuing install without {program}'.format(program=program))
|
||||
print(f'Continuing install without {program}')
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -158,8 +159,7 @@ def check_external_program(
|
||||
error_old_version(program, package, optional, need_version,
|
||||
found_version)
|
||||
|
||||
print('Found {program} {found_version}'.format(
|
||||
program=program, found_version=found_version))
|
||||
print(f'Found {program} {found_version}')
|
||||
|
||||
|
||||
command = next((arg for arg in sys.argv[1:] if not arg.startswith('-')), '')
|
||||
@@ -170,7 +170,7 @@ if not forced and command.startswith('install') or \
|
||||
command in ['check', 'test', 'nosetests', 'easy_install']:
|
||||
check_external_program(
|
||||
program='tesseract',
|
||||
need_version='3.04', # using backport for Travis CI
|
||||
need_version='4.0.0', # using backport for Travis CI
|
||||
package={'darwin': 'tesseract', 'linux': 'tesseract-ocr'}
|
||||
)
|
||||
check_external_program(
|
||||
@@ -219,7 +219,6 @@ setup(
|
||||
package_dir={'': 'src'},
|
||||
keywords=['PDF', 'OCR', 'optical character recognition', 'PDF/A', 'scanning'],
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
@@ -236,7 +235,7 @@ setup(
|
||||
"Topic :: Text Processing :: Indexing",
|
||||
"Topic :: Text Processing :: Linguistic",
|
||||
],
|
||||
python_requires=' >= 3.5',
|
||||
python_requires=' >= 3.6',
|
||||
setup_requires=[
|
||||
'cffi >= 1.9.1', # to build the leptonica module
|
||||
'pytest-runner', # to enable python setup.py test
|
||||
@@ -251,8 +250,8 @@ setup(
|
||||
'chardet >= 3.0.4, < 4', # unlisted requirement of pdfminer.six 20181108
|
||||
'cffi >= 1.9.1', # must be a setup and install requirement
|
||||
'img2pdf >= 0.3.0, < 0.4', # pure Python, so track HEAD closely
|
||||
'pdfminer.six == 20181108',
|
||||
'pikepdf >= 0.9.1',
|
||||
'pdfminer.six == 20181108 ; sys_platform != "darwin"',
|
||||
'pikepdf >= 1.0.2, < 2',
|
||||
'Pillow >= 4.0.0, != 5.1.0 ; sys_platform == "darwin"',
|
||||
# Pillow < 4 has BytesIO/TIFF bug w/img2pdf 0.2.3
|
||||
# block 5.1.0, broken wheels
|
||||
@@ -260,7 +259,7 @@ setup(
|
||||
'ruffus >= 2.7.0',
|
||||
],
|
||||
extras_require={
|
||||
'fitz': [], # Backward compatibility
|
||||
'pdfminer': ['pdfminer.six == 20181108'],
|
||||
},
|
||||
tests_require=tests_require,
|
||||
entry_points={
|
||||
|
||||
@@ -25,10 +25,18 @@ __version__ = pkg_resources.get_distribution('ocrmypdf').version
|
||||
VERSION = __version__
|
||||
|
||||
from .exceptions import (
|
||||
ExitCode, BadArgsError, PdfMergeFailedError, MissingDependencyError,
|
||||
UnsupportedImageFormatError, DpiError, OutputFileAccessError,
|
||||
PriorOcrFoundError, InputFileError, SubprocessOutputError,
|
||||
EncryptedPdfError, TesseractConfigError
|
||||
ExitCode,
|
||||
BadArgsError,
|
||||
PdfMergeFailedError,
|
||||
MissingDependencyError,
|
||||
UnsupportedImageFormatError,
|
||||
DpiError,
|
||||
OutputFileAccessError,
|
||||
PriorOcrFoundError,
|
||||
InputFileError,
|
||||
SubprocessOutputError,
|
||||
EncryptedPdfError,
|
||||
TesseractConfigError,
|
||||
)
|
||||
|
||||
from . import helpers
|
||||
|
||||
+398
-287
File diff suppressed because it is too large
Load Diff
@@ -15,10 +15,10 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import shutil
|
||||
import sys
|
||||
from contextlib import suppress
|
||||
from multiprocessing.managers import SyncManager
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
from .pdfinfo import PdfInfo
|
||||
|
||||
@@ -77,8 +77,7 @@ class JobContextManager(SyncManager):
|
||||
|
||||
def cleanup_working_files(work_folder, options):
|
||||
if options.keep_temporary_files:
|
||||
print("Temporary working files saved at:\n{0}".format(work_folder),
|
||||
file=sys.stderr)
|
||||
print(f"Temporary working files saved at:\n{work_folder}", file=sys.stderr)
|
||||
else:
|
||||
with suppress(FileNotFoundError):
|
||||
shutil.rmtree(work_folder)
|
||||
|
||||
+305
-314
File diff suppressed because it is too large
Load Diff
@@ -33,9 +33,9 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import sys
|
||||
import codecs
|
||||
|
||||
|
||||
def verify_python3_env(): # pragma: no cover
|
||||
@@ -47,6 +47,7 @@ def verify_python3_env(): # pragma: no cover
|
||||
|
||||
try:
|
||||
import locale
|
||||
|
||||
fs_enc = codecs.lookup(locale.getpreferredencoding()).name
|
||||
except Exception:
|
||||
fs_enc = 'ascii'
|
||||
@@ -56,8 +57,10 @@ def verify_python3_env(): # pragma: no cover
|
||||
extra = ''
|
||||
if os.name == 'posix':
|
||||
import subprocess
|
||||
rv = subprocess.Popen(['locale', '-a'], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).communicate()[0]
|
||||
|
||||
rv = subprocess.Popen(
|
||||
['locale', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
).communicate()[0]
|
||||
good_locales = set()
|
||||
has_c_utf8 = False
|
||||
|
||||
@@ -108,6 +111,8 @@ def verify_python3_env(): # pragma: no cover
|
||||
'is not supported'
|
||||
) % bad_locale
|
||||
|
||||
raise RuntimeError('ocrmypdf will abort further execution because Python 3 '
|
||||
'was configured to use ASCII as encoding for the '
|
||||
'environment.' + extra)
|
||||
raise RuntimeError(
|
||||
'ocrmypdf will abort further execution because Python 3 '
|
||||
'was configured to use ASCII as encoding for the '
|
||||
'environment.' + extra
|
||||
)
|
||||
|
||||
+33
-38
@@ -15,13 +15,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pathlib import Path
|
||||
from itertools import groupby
|
||||
from pathlib import Path
|
||||
|
||||
import pikepdf
|
||||
|
||||
from .helpers import flatten_groups, page_number
|
||||
from .exec import tesseract
|
||||
from .helpers import flatten_groups, page_number
|
||||
|
||||
|
||||
def _update_page_resources(*, page, font, font_key, procset):
|
||||
@@ -89,8 +89,8 @@ def strip_invisible_text(pdf, page, log):
|
||||
|
||||
|
||||
def _weave_layers_graft(
|
||||
*, pdf_base, page_num, text, font, font_key, procset, rotation,
|
||||
strip_old_text, log):
|
||||
*, pdf_base, page_num, text, font, font_key, procset, rotation, strip_old_text, log
|
||||
):
|
||||
"""Insert the text layer from text page 0 on to pdf_base at page_num"""
|
||||
|
||||
log.debug("Grafting")
|
||||
@@ -108,7 +108,7 @@ def _weave_layers_graft(
|
||||
stream = bytearray(pdf_text_contents)
|
||||
pattern = b'/Im1 Do'
|
||||
idx = stream.find(pattern)
|
||||
stream[idx:(idx + len(pattern))] = b' ' * len(pattern)
|
||||
stream[idx : (idx + len(pattern))] = b' ' * len(pattern)
|
||||
pdf_text_contents = bytes(stream)
|
||||
|
||||
base_page = pdf_base.pages.p(page_num)
|
||||
@@ -117,12 +117,10 @@ def _weave_layers_graft(
|
||||
# content may have a rotation applied. Wrap the text stream with a rotation
|
||||
# so it will be oriented the same way as the rest of the page content.
|
||||
# (Previous versions OCRmyPDF rotated the content layer to match the text.)
|
||||
mediabox = [float(pdf_text.pages[0].MediaBox[v])
|
||||
for v in range(4)]
|
||||
mediabox = [float(pdf_text.pages[0].MediaBox[v]) for v in range(4)]
|
||||
wt, ht = mediabox[2] - mediabox[0], mediabox[3] - mediabox[1]
|
||||
|
||||
mediabox = [float(base_page.MediaBox[v])
|
||||
for v in range(4)]
|
||||
mediabox = [float(base_page.MediaBox[v]) for v in range(4)]
|
||||
wp, hp = mediabox[2] - mediabox[0], mediabox[3] - mediabox[1]
|
||||
|
||||
translate = pikepdf.PdfMatrix().translated(-wt / 2, -ht / 2)
|
||||
@@ -147,11 +145,7 @@ def _weave_layers_graft(
|
||||
# for a size different between initial and text PDF, then untranslate
|
||||
ctm = translate @ rotate @ scale @ untranslate
|
||||
|
||||
pdf_text_contents = (
|
||||
b'q %s cm\n' % ctm.encode() +
|
||||
pdf_text_contents +
|
||||
b'\nQ\n'
|
||||
)
|
||||
pdf_text_contents = b'q %s cm\n' % ctm.encode() + pdf_text_contents + b'\nQ\n'
|
||||
|
||||
new_text_layer = pikepdf.Stream(pdf_base, pdf_text_contents)
|
||||
|
||||
@@ -254,8 +248,7 @@ def _fix_toc(pdf_base, pageref_remap, log):
|
||||
if not isinstance(dest_node, pikepdf.Array):
|
||||
return
|
||||
pageref = dest_node[0]
|
||||
if pageref['/Type'] == '/Page' and \
|
||||
pageref.objgen in pageref_remap:
|
||||
if pageref['/Type'] == '/Page' and pageref.objgen in pageref_remap:
|
||||
new_objgen = pageref_remap[pageref.objgen]
|
||||
dest_node[0] = pdf_base.get_object(new_objgen)
|
||||
|
||||
@@ -278,11 +271,7 @@ def _fix_toc(pdf_base, pageref_remap, log):
|
||||
_traverse_toc(pdf_base, visit_remap_dest, log)
|
||||
|
||||
|
||||
def weave_layers(
|
||||
infiles,
|
||||
output_file,
|
||||
log,
|
||||
context):
|
||||
def weave_layers(infiles, output_file, log, context):
|
||||
"""Apply text layer and/or image layer changes to baseline file
|
||||
|
||||
This is where the magic happens. infiles will be the main PDF to modify,
|
||||
@@ -313,6 +302,7 @@ def weave_layers(
|
||||
return page_number(key)
|
||||
except ValueError:
|
||||
return -1
|
||||
|
||||
flat_inputs = sorted(flatten_groups(infiles), key=input_sorter)
|
||||
groups = groupby(flat_inputs, key=input_sorter)
|
||||
|
||||
@@ -333,7 +323,8 @@ def weave_layers(
|
||||
_traverse_toc(pdf_base, None, log)
|
||||
|
||||
procset = pdf_base.make_indirect(
|
||||
pikepdf.Object.parse(b'[ /PDF /Text /ImageB /ImageC /ImageI ]'))
|
||||
pikepdf.Object.parse(b'[ /PDF /Text /ImageB /ImageC /ImageI ]')
|
||||
)
|
||||
|
||||
# Iterate rest
|
||||
for page_num, layers in groups:
|
||||
@@ -341,12 +332,8 @@ def weave_layers(
|
||||
log.debug(page_num)
|
||||
log.debug(layers)
|
||||
|
||||
text = next(
|
||||
(ii for ii in layers if ii.endswith('.text.pdf')), None
|
||||
)
|
||||
image = next(
|
||||
(ii for ii in layers if ii.endswith('.image-layer.pdf')), None
|
||||
)
|
||||
text = next((ii for ii in layers if ii.endswith('.text.pdf')), None)
|
||||
image = next((ii for ii in layers if ii.endswith('.image-layer.pdf')), None)
|
||||
|
||||
if text and not font:
|
||||
font, font_key = _find_font(text, pdf_base)
|
||||
@@ -378,23 +365,30 @@ def weave_layers(
|
||||
content_rotation = autorotate_correction
|
||||
text_rotation = autorotate_correction
|
||||
text_misaligned = (text_rotation - content_rotation) % 360
|
||||
log.debug('%r', [
|
||||
text_rotation, autorotate_correction, text_misaligned,
|
||||
content_rotation]
|
||||
log.debug(
|
||||
'%r',
|
||||
[text_rotation, autorotate_correction, text_misaligned, content_rotation],
|
||||
)
|
||||
|
||||
if text and font:
|
||||
# Graft the text layer onto this page, whether new or old
|
||||
strip_old = context.get_options().redo_ocr
|
||||
_weave_layers_graft(
|
||||
pdf_base=pdf_base, page_num=page_num, text=text, font=font,
|
||||
font_key=font_key, rotation=text_misaligned, procset=procset,
|
||||
strip_old_text=strip_old, log=log
|
||||
pdf_base=pdf_base,
|
||||
page_num=page_num,
|
||||
text=text,
|
||||
font=font,
|
||||
font_key=font_key,
|
||||
rotation=text_misaligned,
|
||||
procset=procset,
|
||||
strip_old_text=strip_old,
|
||||
log=log,
|
||||
)
|
||||
|
||||
# Correct the rotation if applicable
|
||||
pdf_base.pages[page_num - 1].Rotate = \
|
||||
(content_rotation - autorotate_correction) % 360
|
||||
pdf_base.pages[page_num - 1].Rotate = (
|
||||
content_rotation - autorotate_correction
|
||||
) % 360
|
||||
|
||||
if len(keep_open) > 100:
|
||||
# qpdf limitations require us to keep files open when we intend
|
||||
@@ -404,8 +398,9 @@ def weave_layers(
|
||||
# even if page 1 doesn't use it, so we have a way to get it back.
|
||||
page0 = pdf_base.pages[0]
|
||||
_update_page_resources(
|
||||
page=page0, font=font, font_key=font_key, procset=procset)
|
||||
interim = output_file + '_working{}.pdf'.format(page_num)
|
||||
page=page0, font=font, font_key=font_key, procset=procset
|
||||
)
|
||||
interim = output_file + f'_working{page_num}.pdf'
|
||||
pdf_base.save(interim)
|
||||
del pdf_base
|
||||
keep_open = []
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
from enum import IntEnum
|
||||
from textwrap import dedent
|
||||
|
||||
|
||||
class ExitCode(IntEnum):
|
||||
ok = 0
|
||||
bad_args = 1
|
||||
@@ -52,7 +53,8 @@ class BadArgsError(ExitCodeException):
|
||||
|
||||
class PdfMergeFailedError(ExitCodeException):
|
||||
exit_code = ExitCode.input_file
|
||||
message = dedent('''\
|
||||
message = dedent(
|
||||
'''\
|
||||
Failed to merge PDF image layer with OCR layer
|
||||
|
||||
Usually this happens because the input PDF file is malformed and
|
||||
@@ -60,7 +62,9 @@ class PdfMergeFailedError(ExitCodeException):
|
||||
|
||||
Try using
|
||||
ocrmypdf --pdf-renderer sandwich [..other args..]
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
class MissingDependencyError(ExitCodeException):
|
||||
exit_code = ExitCode.missing_dependency
|
||||
@@ -92,7 +96,8 @@ class SubprocessOutputError(ExitCodeException):
|
||||
|
||||
class EncryptedPdfError(ExitCodeException):
|
||||
exit_code = ExitCode.encrypted_pdf
|
||||
message = dedent('''\
|
||||
message = dedent(
|
||||
'''\
|
||||
Input PDF is encrypted. The encryption must be removed to
|
||||
perform OCR.
|
||||
|
||||
@@ -101,7 +106,8 @@ class EncryptedPdfError(ExitCodeException):
|
||||
|
||||
You can remove the encryption using
|
||||
qpdf --decrypt [--password=[password]] infilename
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
class TesseractConfigError(ExitCodeException):
|
||||
|
||||
@@ -24,36 +24,37 @@ from subprocess import run, STDOUT, PIPE, CalledProcessError
|
||||
from ..exceptions import MissingDependencyError
|
||||
|
||||
|
||||
def get_version(program, *,
|
||||
version_arg='--version', regex=r'(\d+(\.\d+)*)'):
|
||||
def get_version(program, *, version_arg='--version', regex=r'(\d+(\.\d+)*)'):
|
||||
"Get the version of the specified program"
|
||||
args_prog = [
|
||||
program,
|
||||
version_arg
|
||||
]
|
||||
args_prog = [program, version_arg]
|
||||
try:
|
||||
proc = run(
|
||||
args_prog, close_fds=True, universal_newlines=True,
|
||||
stdout=PIPE, stderr=STDOUT, check=True)
|
||||
args_prog,
|
||||
close_fds=True,
|
||||
universal_newlines=True,
|
||||
stdout=PIPE,
|
||||
stderr=STDOUT,
|
||||
check=True,
|
||||
)
|
||||
output = proc.stdout
|
||||
except FileNotFoundError as e:
|
||||
raise MissingDependencyError(
|
||||
"Could not find program '{}' on the PATH".format(
|
||||
program)) from e
|
||||
f"Could not find program '{program}' on the PATH"
|
||||
) from e
|
||||
except CalledProcessError as e:
|
||||
if e.returncode < 0:
|
||||
raise MissingDependencyError(
|
||||
"Ran program '{}' but it exited with an error:\n{}".format(
|
||||
program, e.output)) from e
|
||||
f"Ran program '{program}' but it exited with an error:\n{e.output}"
|
||||
) from e
|
||||
raise MissingDependencyError(
|
||||
"Could not find program '{}' on the PATH".format(
|
||||
program)) from e
|
||||
f"Could not find program '{program}' on the PATH"
|
||||
) from e
|
||||
try:
|
||||
version = re.match(regex, output.strip()).group(1)
|
||||
except AttributeError as e:
|
||||
raise MissingDependencyError(
|
||||
("The program '{}' did not report its version. "
|
||||
"Message was:\n{}").format(program, output)
|
||||
f"The program '{program}' did not report its version. "
|
||||
f"Message was:\n{output}"
|
||||
)
|
||||
|
||||
return version
|
||||
|
||||
@@ -15,15 +15,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from tempfile import NamedTemporaryFile
|
||||
from subprocess import run, PIPE, STDOUT
|
||||
from shutil import copy
|
||||
from functools import lru_cache
|
||||
import re
|
||||
from functools import lru_cache
|
||||
from os import fspath
|
||||
from shutil import copy
|
||||
from subprocess import PIPE, STDOUT, run
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from . import get_version
|
||||
from ..exceptions import SubprocessOutputError
|
||||
from ..helpers import fspath
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
@@ -69,39 +71,46 @@ def extract_text(input_file, pageno=1):
|
||||
"""
|
||||
|
||||
if pageno is not None:
|
||||
pages = [
|
||||
'-dFirstPage=%i' % pageno,
|
||||
'-dLastPage=%i' % pageno
|
||||
]
|
||||
pages = ['-dFirstPage=%i' % pageno, '-dLastPage=%i' % pageno]
|
||||
else:
|
||||
pages = []
|
||||
|
||||
args_gs = [
|
||||
'gs',
|
||||
'-dQUIET',
|
||||
'-dSAFER',
|
||||
'-dBATCH',
|
||||
'-dNOPAUSE',
|
||||
'-sDEVICE=txtwrite',
|
||||
'-dTextFormat=0',
|
||||
] + pages + [
|
||||
'-o', '-',
|
||||
fspath(input_file)
|
||||
]
|
||||
args_gs = (
|
||||
[
|
||||
'gs',
|
||||
'-dQUIET',
|
||||
'-dSAFER',
|
||||
'-dBATCH',
|
||||
'-dNOPAUSE',
|
||||
'-sDEVICE=txtwrite',
|
||||
'-dTextFormat=0',
|
||||
]
|
||||
+ pages
|
||||
+ ['-o', '-', fspath(input_file)]
|
||||
)
|
||||
|
||||
p = run(args_gs, stdout=PIPE, stderr=PIPE)
|
||||
if p.returncode != 0:
|
||||
raise SubprocessOutputError(
|
||||
'Ghostscript text extraction failed\n%s\n%s\n%s' % (
|
||||
input_file, p.stdout.decode(), p.stderr.decode()
|
||||
)
|
||||
'Ghostscript text extraction failed\n%s\n%s\n%s'
|
||||
% (input_file, p.stdout.decode(), p.stderr.decode())
|
||||
)
|
||||
|
||||
return p.stdout
|
||||
|
||||
|
||||
def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
|
||||
pageno=1, page_dpi=None, rotation=None, filter_vector=False):
|
||||
def rasterize_pdf(
|
||||
input_file,
|
||||
output_file,
|
||||
xres,
|
||||
yres,
|
||||
raster_device,
|
||||
log,
|
||||
pageno=1,
|
||||
page_dpi=None,
|
||||
rotation=None,
|
||||
filter_vector=False,
|
||||
):
|
||||
"""Rasterize one page of a PDF at resolution (xres, yres) in canvas units.
|
||||
|
||||
The image is sized to match the integer pixels dimensions implied by
|
||||
@@ -126,26 +135,30 @@ def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
|
||||
page_dpi = res
|
||||
|
||||
with NamedTemporaryFile(delete=True) as tmp:
|
||||
args_gs = [
|
||||
'gs',
|
||||
'-dQUIET',
|
||||
'-dSAFER',
|
||||
'-dBATCH',
|
||||
'-dNOPAUSE',
|
||||
'-sDEVICE=%s' % raster_device,
|
||||
'-dFirstPage=%i' % pageno,
|
||||
'-dLastPage=%i' % pageno,
|
||||
'-r{0}x{1}'.format(str(int_res[0]), str(int_res[1])),
|
||||
] + (['-dFILTERVECTOR'] if filter_vector else []) + [
|
||||
'-o', tmp.name,
|
||||
'-dAutoRotatePages=/None', # Probably has no effect on raster
|
||||
'-f',
|
||||
fspath(input_file)
|
||||
]
|
||||
args_gs = (
|
||||
[
|
||||
'gs',
|
||||
'-dQUIET',
|
||||
'-dSAFER',
|
||||
'-dBATCH',
|
||||
'-dNOPAUSE',
|
||||
f'-sDEVICE={raster_device}',
|
||||
f'-dFirstPage={pageno}',
|
||||
f'-dLastPage={pageno}',
|
||||
f'-r{str(int_res[0])}x{str(int_res[1])}',
|
||||
]
|
||||
+ (['-dFILTERVECTOR'] if filter_vector else [])
|
||||
+ [
|
||||
'-o',
|
||||
tmp.name,
|
||||
'-dAutoRotatePages=/None', # Probably has no effect on raster
|
||||
'-f',
|
||||
fspath(input_file),
|
||||
]
|
||||
)
|
||||
|
||||
log.debug(args_gs)
|
||||
p = run(args_gs, stdout=PIPE, stderr=STDOUT,
|
||||
universal_newlines=True)
|
||||
p = run(args_gs, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
|
||||
if _gs_error_reported(p.stdout):
|
||||
log.error(p.stdout)
|
||||
else:
|
||||
@@ -162,12 +175,14 @@ def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
|
||||
|
||||
tmp.seek(0)
|
||||
with Image.open(tmp) as im:
|
||||
expected_size = round(im.size[0] / int_res[0] * res[0]), \
|
||||
round(im.size[1] / int_res[1] * res[1])
|
||||
expected_size = (
|
||||
round(im.size[0] / int_res[0] * res[0]),
|
||||
round(im.size[1] / int_res[1] * res[1]),
|
||||
)
|
||||
if expected_size != im.size or page_dpi != (xres, yres):
|
||||
log.debug(
|
||||
"Ghostscript: resize output image {} -> {}".format(
|
||||
im.size, expected_size))
|
||||
f"Ghostscript: resize output image {im.size} -> {expected_size}"
|
||||
)
|
||||
im = im.resize(expected_size)
|
||||
|
||||
if rotation is not None:
|
||||
@@ -185,8 +200,15 @@ def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
|
||||
im.save(fspath(output_file), dpi=page_dpi)
|
||||
|
||||
|
||||
def generate_pdfa(pdf_pages, output_file, compression, log,
|
||||
threads=1, pdf_version='1.5', pdfa_part='2'):
|
||||
def generate_pdfa(
|
||||
pdf_pages,
|
||||
output_file,
|
||||
compression,
|
||||
log,
|
||||
threads=1,
|
||||
pdf_version='1.5',
|
||||
pdfa_part='2',
|
||||
):
|
||||
"""Generate a PDF/A.
|
||||
|
||||
The pdf_pages, a list files, will be merged into output_file. One or more
|
||||
@@ -240,26 +262,29 @@ def generate_pdfa(pdf_pages, output_file, compression, log,
|
||||
# nb no need to specify ProcessColorModel when ColorConversionStrategy
|
||||
# is set; see:
|
||||
# https://bugs.ghostscript.com/show_bug.cgi?id=699392
|
||||
args_gs = [
|
||||
"gs",
|
||||
"-dQUIET",
|
||||
"-dBATCH",
|
||||
"-dNOPAUSE",
|
||||
"-dCompatibilityLevel=" + str(pdf_version),
|
||||
"-dNumRenderingThreads=" + str(threads),
|
||||
"-sDEVICE=pdfwrite",
|
||||
"-dAutoRotatePages=/None",
|
||||
"-sColorConversionStrategy=" + strategy
|
||||
] + compression_args + [
|
||||
"-dJPEGQ=95",
|
||||
"-dPDFA=" + pdfa_part,
|
||||
"-dPDFACompatibilityPolicy=1",
|
||||
"-sOutputFile=" + gs_pdf.name,
|
||||
]
|
||||
args_gs = (
|
||||
[
|
||||
"gs",
|
||||
"-dQUIET",
|
||||
"-dBATCH",
|
||||
"-dNOPAUSE",
|
||||
"-dCompatibilityLevel=" + str(pdf_version),
|
||||
"-dNumRenderingThreads=" + str(threads),
|
||||
"-sDEVICE=pdfwrite",
|
||||
"-dAutoRotatePages=/None",
|
||||
"-sColorConversionStrategy=" + strategy,
|
||||
]
|
||||
+ compression_args
|
||||
+ [
|
||||
"-dJPEGQ=95",
|
||||
"-dPDFA=" + pdfa_part,
|
||||
"-dPDFACompatibilityPolicy=1",
|
||||
"-sOutputFile=" + gs_pdf.name,
|
||||
]
|
||||
)
|
||||
args_gs.extend(fspath(s) for s in pdf_pages) # Stringify Path objs
|
||||
log.debug(args_gs)
|
||||
p = run(args_gs, stdout=PIPE, stderr=STDOUT,
|
||||
universal_newlines=True)
|
||||
p = run(args_gs, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
|
||||
|
||||
if _gs_error_reported(p.stdout):
|
||||
log.error(p.stdout)
|
||||
@@ -270,7 +295,7 @@ def generate_pdfa(pdf_pages, output_file, compression, log,
|
||||
log.debug(
|
||||
"Ghostscript had to remove PDF 'overprinting' from the "
|
||||
"input file to complete PDF/A conversion. "
|
||||
)
|
||||
)
|
||||
else:
|
||||
log.debug(p.stdout)
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from subprocess import run, PIPE
|
||||
from functools import lru_cache
|
||||
from subprocess import PIPE, run
|
||||
|
||||
from . import get_version
|
||||
from ..exceptions import MissingDependencyError
|
||||
@@ -42,7 +42,7 @@ def convert_group(*, cwd, infiles, out_prefix):
|
||||
out_prefix,
|
||||
'-s', # symbol mode (lossy)
|
||||
# '-r', # refinement mode (lossless symbol mode, currently disabled in
|
||||
# jbig2)
|
||||
# jbig2)
|
||||
'-p',
|
||||
]
|
||||
args.extend(infiles)
|
||||
@@ -52,11 +52,7 @@ def convert_group(*, cwd, infiles, out_prefix):
|
||||
|
||||
|
||||
def convert_single(*, cwd, infile, outfile):
|
||||
args = [
|
||||
'jbig2',
|
||||
'-p',
|
||||
infile
|
||||
]
|
||||
args = ['jbig2', '-p', infile]
|
||||
with open(outfile, 'wb') as fstdout:
|
||||
proc = run(args, cwd=cwd, stdout=fstdout, stderr=PIPE)
|
||||
proc.check_returncode()
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from subprocess import run
|
||||
from functools import lru_cache
|
||||
from subprocess import run
|
||||
|
||||
from . import get_version
|
||||
from ..exceptions import MissingDependencyError
|
||||
@@ -40,10 +40,12 @@ def quantize(input_file, output_file, quality_min, quality_max):
|
||||
'pngquant',
|
||||
'--force',
|
||||
'--skip-if-larger',
|
||||
'--output', output_file,
|
||||
'--quality', '{}-{}'.format(quality_min, quality_max),
|
||||
'--output',
|
||||
output_file,
|
||||
'--quality',
|
||||
f'{quality_min}-{quality_max}',
|
||||
'--',
|
||||
input_file
|
||||
input_file,
|
||||
]
|
||||
proc = run(args)
|
||||
proc.check_returncode()
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from subprocess import CalledProcessError, STDOUT, PIPE, run
|
||||
from functools import lru_cache
|
||||
from os import fspath
|
||||
from subprocess import PIPE, STDOUT, CalledProcessError, run
|
||||
|
||||
from . import get_version
|
||||
from ..helpers import fspath
|
||||
from . import get_version
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
@@ -28,22 +28,16 @@ def version():
|
||||
|
||||
|
||||
def check(input_file, log=None):
|
||||
args_qpdf = [
|
||||
'qpdf',
|
||||
'--check',
|
||||
fspath(input_file)
|
||||
]
|
||||
args_qpdf = ['qpdf', '--check', fspath(input_file)]
|
||||
|
||||
if log is None:
|
||||
import logging as log
|
||||
|
||||
try:
|
||||
run(args_qpdf, stderr=STDOUT, stdout=PIPE, universal_newlines=True,
|
||||
check=True)
|
||||
run(args_qpdf, stderr=STDOUT, stdout=PIPE, universal_newlines=True, check=True)
|
||||
except CalledProcessError as e:
|
||||
if e.returncode == 2:
|
||||
log.error("%s: not a valid PDF, and could not repair it.",
|
||||
input_file)
|
||||
log.error("%s: not a valid PDF, and could not repair it.", input_file)
|
||||
log.error("Details:")
|
||||
log.error(e.output)
|
||||
elif e.returncode == 3:
|
||||
|
||||
@@ -15,22 +15,28 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
from functools import lru_cache
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from textwrap import dedent
|
||||
from subprocess import CalledProcessError, TimeoutExpired, check_output, STDOUT, run, PIPE
|
||||
from contextlib import suppress
|
||||
from functools import lru_cache
|
||||
from os import fspath
|
||||
from subprocess import (
|
||||
PIPE,
|
||||
STDOUT,
|
||||
CalledProcessError,
|
||||
TimeoutExpired,
|
||||
check_output,
|
||||
run,
|
||||
)
|
||||
from textwrap import dedent
|
||||
|
||||
from ..exceptions import MissingDependencyError, TesseractConfigError
|
||||
from ..helpers import page_number, fspath
|
||||
from . import get_version
|
||||
from ..exceptions import MissingDependencyError, TesseractConfigError
|
||||
from ..helpers import page_number
|
||||
|
||||
OrientationConfidence = namedtuple(
|
||||
'OrientationConfidence',
|
||||
('angle', 'confidence'))
|
||||
OrientationConfidence = namedtuple('OrientationConfidence', ('angle', 'confidence'))
|
||||
|
||||
HOCR_TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
@@ -39,8 +45,8 @@ HOCR_TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name='ocr-system' content='tesseract 3.05.00' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word'/>
|
||||
<meta name='ocr-system' content='tesseract 4.0.0' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word ocrp_wconf'/>
|
||||
</head>
|
||||
<body>
|
||||
<div class='ocr_page' id='page_1' title='image "_blank.png"; bbox 0 0 {0} {1}; ppageno 0'>
|
||||
@@ -64,50 +70,37 @@ def v4():
|
||||
def has_textonly_pdf():
|
||||
"""Does Tesseract have textonly_pdf capability?
|
||||
|
||||
Available in 3.05.01, and v4.00.00alpha since January 2017. Best to
|
||||
Available in v4.00.00alpha since January 2017. Best to
|
||||
parse the parameter list
|
||||
"""
|
||||
args_tess = [
|
||||
'tesseract',
|
||||
'--print-parameters',
|
||||
'pdf'
|
||||
]
|
||||
args_tess = ['tesseract', '--print-parameters', 'pdf']
|
||||
params = ''
|
||||
try:
|
||||
params = check_output(
|
||||
args_tess, universal_newlines=True, stderr=STDOUT)
|
||||
params = check_output(args_tess, universal_newlines=True, stderr=STDOUT)
|
||||
except CalledProcessError as e:
|
||||
print("Could not --print-parameters from tesseract",
|
||||
file=sys.stderr)
|
||||
print("Could not --print-parameters from tesseract", file=sys.stderr)
|
||||
raise MissingDependencyError from e
|
||||
if 'textonly_pdf' in params:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def psm():
|
||||
"If Tesseract 4.0, use argument --psm instead of -psm"
|
||||
return '--psm' if v4() else '-psm'
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def languages():
|
||||
def lang_error(output):
|
||||
msg = dedent("""Tesseract failed to report available languages.
|
||||
msg = dedent(
|
||||
"""Tesseract failed to report available languages.
|
||||
Output from Tesseract:
|
||||
-----------
|
||||
""")
|
||||
"""
|
||||
)
|
||||
msg += output
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
args_tess = [
|
||||
'tesseract',
|
||||
'--list-langs'
|
||||
]
|
||||
args_tess = ['tesseract', '--list-langs']
|
||||
try:
|
||||
proc = run(
|
||||
args_tess, universal_newlines=True, stdout=PIPE, stderr=STDOUT,
|
||||
check=True
|
||||
args_tess, universal_newlines=True, stdout=PIPE, stderr=STDOUT, check=True
|
||||
)
|
||||
output = proc.stdout
|
||||
except CalledProcessError as e:
|
||||
@@ -122,9 +115,7 @@ def languages():
|
||||
|
||||
|
||||
def tess_base_args(langs, engine_mode):
|
||||
args = [
|
||||
'tesseract',
|
||||
]
|
||||
args = ['tesseract']
|
||||
if langs:
|
||||
args.extend(['-l', '+'.join(langs)])
|
||||
if engine_mode is not None and v4():
|
||||
@@ -134,20 +125,22 @@ def tess_base_args(langs, engine_mode):
|
||||
|
||||
def get_orientation(input_file, engine_mode, timeout: float, log):
|
||||
args_tesseract = tess_base_args(['osd'], engine_mode) + [
|
||||
psm(), '0',
|
||||
'--psm',
|
||||
'0',
|
||||
fspath(input_file),
|
||||
'stdout'
|
||||
'stdout',
|
||||
]
|
||||
|
||||
try:
|
||||
stdout = check_output(
|
||||
args_tesseract, stderr=STDOUT, timeout=timeout)
|
||||
stdout = check_output(args_tesseract, stderr=STDOUT, timeout=timeout)
|
||||
except TimeoutExpired:
|
||||
return OrientationConfidence(angle=0, confidence=0.0)
|
||||
except CalledProcessError as e:
|
||||
tesseract_log_output(log, e.output, input_file)
|
||||
if (b'Too few characters. Skipping this page' in e.output or
|
||||
b'Image too large' in e.output):
|
||||
if (
|
||||
b'Too few characters. Skipping this page' in e.output
|
||||
or b'Image too large' in e.output
|
||||
):
|
||||
return OrientationConfidence(0, 0)
|
||||
raise e from e
|
||||
else:
|
||||
@@ -159,32 +152,24 @@ def get_orientation(input_file, engine_mode, timeout: float, log):
|
||||
osd[parts[0].strip()] = parts[1].strip()
|
||||
|
||||
angle = int(osd.get('Orientation in degrees', 0))
|
||||
if 'Orientation' in osd:
|
||||
# Tesseract < 3.04.01
|
||||
# reports "Orientation in degrees" as a counterclockwise angle
|
||||
# We keep it clockwise
|
||||
assert 'Rotate' not in osd
|
||||
angle = -angle % 360
|
||||
else:
|
||||
# Tesseract >= 3.04.01
|
||||
# reports "Orientation in degrees" as a clockwise angle
|
||||
assert 'Rotate' in osd
|
||||
|
||||
oc = OrientationConfidence(
|
||||
angle=angle,
|
||||
confidence=float(osd.get('Orientation confidence', 0)))
|
||||
angle=angle, confidence=float(osd.get('Orientation confidence', 0))
|
||||
)
|
||||
return oc
|
||||
|
||||
|
||||
def tesseract_log_output(log, stdout, input_file):
|
||||
prefix = "{0:4d}: [tesseract] ".format(page_number(input_file))
|
||||
prefix = f"{(page_number(input_file)):4d}: [tesseract] "
|
||||
|
||||
try:
|
||||
text = stdout.decode()
|
||||
except UnicodeDecodeError:
|
||||
log.error(prefix + "command line output was not utf-8. " +
|
||||
"This usually means Tesseract's language packs do not match "
|
||||
"the installed version of Tesseract.")
|
||||
log.error(
|
||||
prefix
|
||||
+ "command line output was not utf-8. "
|
||||
+ "This usually means Tesseract's language packs do not match "
|
||||
"the installed version of Tesseract."
|
||||
)
|
||||
text = stdout.decode('utf-8', 'backslashreplace')
|
||||
|
||||
lines = text.splitlines()
|
||||
@@ -216,7 +201,7 @@ def tesseract_log_output(log, stdout, input_file):
|
||||
|
||||
|
||||
def page_timedout(log, input_file):
|
||||
prefix = "{0:4d}: [tesseract] ".format(page_number(input_file))
|
||||
prefix = f"{(page_number(input_file)):4d}: [tesseract] "
|
||||
log.warning(prefix + " took too long to OCR - skipping")
|
||||
|
||||
|
||||
@@ -234,10 +219,18 @@ def _generate_null_hocr(output_hocr, output_sidecar, image):
|
||||
f.write('[skipped page]')
|
||||
|
||||
|
||||
def generate_hocr(input_file, output_files, language: list, engine_mode,
|
||||
tessconfig: list,
|
||||
timeout: float, pagesegmode: int, user_words, user_patterns,
|
||||
log):
|
||||
def generate_hocr(
|
||||
input_file,
|
||||
output_files,
|
||||
language: list,
|
||||
engine_mode,
|
||||
tessconfig: list,
|
||||
timeout: float,
|
||||
pagesegmode: int,
|
||||
user_words,
|
||||
user_patterns,
|
||||
log,
|
||||
):
|
||||
|
||||
output_hocr = next(o for o in output_files if o.endswith('.hocr'))
|
||||
output_sidecar = next(o for o in output_files if o.endswith('.txt'))
|
||||
@@ -246,7 +239,7 @@ def generate_hocr(input_file, output_files, language: list, engine_mode,
|
||||
args_tesseract = tess_base_args(language, engine_mode)
|
||||
|
||||
if pagesegmode is not None:
|
||||
args_tesseract.extend([psm(), str(pagesegmode)])
|
||||
args_tesseract.extend(['--psm', str(pagesegmode)])
|
||||
|
||||
if user_words:
|
||||
args_tesseract.extend(['--user-words', user_words])
|
||||
@@ -256,20 +249,10 @@ def generate_hocr(input_file, output_files, language: list, engine_mode,
|
||||
|
||||
# Reminder: test suite tesseract spoofers will break after any changes
|
||||
# to the number of order parameters here
|
||||
# Tesseract 3.04 requires the order here to be "hocr txt" and will fail
|
||||
# on "txt hocr"
|
||||
|
||||
args_tesseract.extend([
|
||||
input_file,
|
||||
prefix,
|
||||
'hocr',
|
||||
'txt'
|
||||
] + tessconfig)
|
||||
args_tesseract.extend([input_file, prefix, 'hocr', 'txt'] + tessconfig)
|
||||
try:
|
||||
log.debug(args_tesseract)
|
||||
stdout = check_output(
|
||||
args_tesseract, stderr=STDOUT,
|
||||
timeout=timeout)
|
||||
stdout = check_output(args_tesseract, stderr=STDOUT, timeout=timeout)
|
||||
except TimeoutExpired:
|
||||
# Generate a HOCR file with no recognized text if tesseract times out
|
||||
# Temporary workaround to hocrTransform not being able to function if
|
||||
@@ -307,10 +290,22 @@ def use_skip_page(text_only, skip_pdf, output_pdf, output_text):
|
||||
out.write(b'')
|
||||
|
||||
|
||||
def generate_pdf(*, input_image, skip_pdf=None, output_pdf, output_text,
|
||||
language: list, engine_mode, text_only: bool,
|
||||
tessconfig: list, timeout: float, pagesegmode: int,
|
||||
user_words, user_patterns, log):
|
||||
def generate_pdf(
|
||||
*,
|
||||
input_image,
|
||||
skip_pdf=None,
|
||||
output_pdf,
|
||||
output_text,
|
||||
language: list,
|
||||
engine_mode,
|
||||
text_only: bool,
|
||||
tessconfig: list,
|
||||
timeout: float,
|
||||
pagesegmode: int,
|
||||
user_words,
|
||||
user_patterns,
|
||||
log,
|
||||
):
|
||||
'''Use Tesseract to render a PDF.
|
||||
|
||||
input_image -- image to analyze
|
||||
@@ -328,7 +323,7 @@ def generate_pdf(*, input_image, skip_pdf=None, output_pdf, output_text,
|
||||
args_tesseract = tess_base_args(language, engine_mode)
|
||||
|
||||
if pagesegmode is not None:
|
||||
args_tesseract.extend([psm(), str(pagesegmode)])
|
||||
args_tesseract.extend(['--psm', str(pagesegmode)])
|
||||
|
||||
if text_only and has_textonly_pdf():
|
||||
args_tesseract.extend(['-c', 'textonly_pdf=1'])
|
||||
@@ -344,18 +339,11 @@ def generate_pdf(*, input_image, skip_pdf=None, output_pdf, output_text,
|
||||
# Reminder: test suite tesseract spoofers might break after any changes
|
||||
# to the number of order parameters here
|
||||
|
||||
args_tesseract.extend([
|
||||
input_image,
|
||||
prefix,
|
||||
'pdf',
|
||||
'txt'
|
||||
] + tessconfig)
|
||||
args_tesseract.extend([input_image, prefix, 'pdf', 'txt'] + tessconfig)
|
||||
|
||||
try:
|
||||
log.debug(args_tesseract)
|
||||
stdout = check_output(
|
||||
args_tesseract, stderr=STDOUT,
|
||||
timeout=timeout)
|
||||
stdout = check_output(args_tesseract, stderr=STDOUT, timeout=timeout)
|
||||
if os.path.exists(prefix + '.txt'):
|
||||
shutil.move(prefix + '.txt', output_text)
|
||||
except TimeoutExpired:
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
# unpaper documentation:
|
||||
# https://github.com/Flameeyes/unpaper/blob/master/doc/basic-concepts.md
|
||||
|
||||
from subprocess import CalledProcessError, STDOUT, check_output
|
||||
from tempfile import NamedTemporaryFile
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from ..exceptions import MissingDependencyError
|
||||
from . import get_version
|
||||
from subprocess import STDOUT, CalledProcessError, check_output
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from . import get_version
|
||||
from ..exceptions import MissingDependencyError
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
@@ -40,11 +40,7 @@ def version():
|
||||
|
||||
|
||||
def run(input_file, output_file, dpi, log, mode_args):
|
||||
args_unpaper = [
|
||||
'unpaper',
|
||||
'-v',
|
||||
'--dpi', str(dpi)
|
||||
] + mode_args
|
||||
args_unpaper = ['unpaper', '-v', '--dpi', str(dpi)] + mode_args
|
||||
|
||||
SUFFIXES = {'1': '.pbm', 'L': '.pgm', 'RGB': '.ppm'}
|
||||
|
||||
@@ -68,8 +64,9 @@ def run(input_file, output_file, dpi, log, mode_args):
|
||||
im.close()
|
||||
raise MissingDependencyError() from e
|
||||
|
||||
with NamedTemporaryFile(suffix=suffix) as input_pnm, \
|
||||
NamedTemporaryFile(suffix=suffix, mode="r+b") as output_pnm:
|
||||
with NamedTemporaryFile(suffix=suffix) as input_pnm, NamedTemporaryFile(
|
||||
suffix=suffix, mode="r+b"
|
||||
) as output_pnm:
|
||||
im.save(input_pnm, format='PPM')
|
||||
im.close()
|
||||
|
||||
@@ -78,9 +75,8 @@ def run(input_file, output_file, dpi, log, mode_args):
|
||||
args_unpaper.extend([input_pnm.name, output_pnm.name])
|
||||
try:
|
||||
stdout = check_output(
|
||||
args_unpaper, close_fds=True,
|
||||
universal_newlines=True, stderr=STDOUT,
|
||||
)
|
||||
args_unpaper, close_fds=True, universal_newlines=True, stderr=STDOUT
|
||||
)
|
||||
except CalledProcessError as e:
|
||||
log.debug(e.output)
|
||||
raise e from e
|
||||
@@ -91,12 +87,20 @@ def run(input_file, output_file, dpi, log, mode_args):
|
||||
|
||||
|
||||
def clean(input_file, output_file, dpi, log):
|
||||
run(input_file, output_file, dpi, log, [
|
||||
'--layout', 'none',
|
||||
'--mask-scan-size', '100', # don't blank out narrow columns
|
||||
'--no-border-align', # don't align visible content to borders
|
||||
'--no-mask-center', # don't center visible content within page
|
||||
'--no-grayfilter', # don't remove light gray areas
|
||||
'--no-blackfilter', # don't remove solid black areas
|
||||
'--no-deskew', # don't deskew
|
||||
])
|
||||
run(
|
||||
input_file,
|
||||
output_file,
|
||||
dpi,
|
||||
log,
|
||||
[
|
||||
'--layout',
|
||||
'none',
|
||||
'--mask-scan-size',
|
||||
'100', # don't blank out narrow columns
|
||||
'--no-border-align', # don't align visible content to borders
|
||||
'--no-mask-center', # don't center visible content within page
|
||||
'--no-grayfilter', # don't remove light gray areas
|
||||
'--no-blackfilter', # don't remove solid black areas
|
||||
'--no-deskew', # don't deskew
|
||||
],
|
||||
)
|
||||
|
||||
+30
-66
@@ -15,22 +15,22 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from functools import partial, wraps
|
||||
import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from collections.abc import Iterable
|
||||
from contextlib import suppress
|
||||
from functools import partial, wraps
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import os
|
||||
import multiprocessing
|
||||
import warnings
|
||||
|
||||
|
||||
def re_symlink(input_file, soft_link_name, log=None):
|
||||
"""
|
||||
Helper function: relinks soft symbolic link if necessary
|
||||
"""
|
||||
input_file = fspath(input_file) # For Py3.5
|
||||
soft_link_name = fspath(soft_link_name)
|
||||
input_file = os.fspath(input_file)
|
||||
soft_link_name = os.fspath(soft_link_name)
|
||||
if log is None:
|
||||
prdebug = partial(print, file=sys.stderr)
|
||||
else:
|
||||
@@ -38,32 +38,29 @@ def re_symlink(input_file, soft_link_name, log=None):
|
||||
|
||||
# Guard against soft linking to oneself
|
||||
if input_file == soft_link_name:
|
||||
prdebug("Warning: No symbolic link made. You are using " +
|
||||
"the original data directory as the working directory.")
|
||||
prdebug(
|
||||
"Warning: No symbolic link made. You are using "
|
||||
+ "the original data directory as the working directory."
|
||||
)
|
||||
return
|
||||
|
||||
# Soft link already exists: delete for relink?
|
||||
if os.path.lexists(soft_link_name):
|
||||
# do not delete or overwrite real (non-soft link) file
|
||||
if not os.path.islink(soft_link_name):
|
||||
raise FileExistsError(
|
||||
"%s exists and is not a link" % soft_link_name)
|
||||
raise FileExistsError("%s exists and is not a link" % soft_link_name)
|
||||
try:
|
||||
os.unlink(soft_link_name)
|
||||
except OSError:
|
||||
prdebug("Can't unlink %s" % (soft_link_name))
|
||||
|
||||
if not os.path.exists(input_file):
|
||||
raise FileNotFoundError(
|
||||
"trying to create a broken symlink to %s" % input_file)
|
||||
raise FileNotFoundError("trying to create a broken symlink to %s" % input_file)
|
||||
|
||||
prdebug("os.symlink(%s, %s)" % (input_file, soft_link_name))
|
||||
|
||||
# Create symbolic link using absolute path
|
||||
os.symlink(
|
||||
os.path.abspath(input_file),
|
||||
soft_link_name
|
||||
)
|
||||
os.symlink(os.path.abspath(input_file), soft_link_name)
|
||||
|
||||
|
||||
def is_iterable_notstr(thing):
|
||||
@@ -72,7 +69,7 @@ def is_iterable_notstr(thing):
|
||||
|
||||
def page_number(input_file):
|
||||
"""Get one-based page number implied by filename (000002.pdf -> 2)"""
|
||||
return int(os.path.basename(fspath(input_file))[0:6])
|
||||
return int(os.path.basename(os.fspath(input_file))[0:6])
|
||||
|
||||
|
||||
def available_cpu_count():
|
||||
@@ -83,13 +80,14 @@ def available_cpu_count():
|
||||
|
||||
try:
|
||||
import psutil
|
||||
|
||||
return psutil.cpu_count()
|
||||
except (ImportError, AttributeError):
|
||||
pass
|
||||
|
||||
warnings.warn(
|
||||
"Could not get CPU count. Assuming one (1) CPU."
|
||||
"Use -j N to set manually.")
|
||||
"Could not get CPU count. Assuming one (1) CPU." "Use -j N to set manually."
|
||||
)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -103,20 +101,15 @@ def is_file_writable(test_file):
|
||||
p = Path(test_file)
|
||||
|
||||
if p.is_symlink():
|
||||
# Python 3.5 does not accept parameters for Path.resolve() and behaves
|
||||
# as if strict=True (throws an exception on failure). Python 3.6
|
||||
# defaults to strict=False. This implements strict=False like behavior
|
||||
# for Python 3.5.
|
||||
if sys.version_info[0:2] <= (3, 5):
|
||||
p = Path(os.path.realpath(fspath(p)))
|
||||
else:
|
||||
p = p.resolve(strict=False)
|
||||
p = p.resolve(strict=False)
|
||||
|
||||
# p.is_file() throws an exception in some cases
|
||||
if p.exists() and p.is_file():
|
||||
return os.access(
|
||||
fspath(p), os.W_OK,
|
||||
effective_ids=(os.access in os.supports_effective_ids))
|
||||
os.fspath(p),
|
||||
os.W_OK,
|
||||
effective_ids=(os.access in os.supports_effective_ids),
|
||||
)
|
||||
else:
|
||||
try:
|
||||
fp = p.open('wb')
|
||||
@@ -129,39 +122,6 @@ def is_file_writable(test_file):
|
||||
return True
|
||||
|
||||
|
||||
if sys.version_info[0:2] <= (3, 5):
|
||||
def fspath(path):
|
||||
"""https://www.python.org/dev/peps/pep-0519/#os"""
|
||||
import pathlib
|
||||
if isinstance(path, (str, bytes)):
|
||||
return path
|
||||
|
||||
# Work from the object's type to match method resolution of other magic
|
||||
# methods.
|
||||
path_type = type(path)
|
||||
try:
|
||||
path = path_type.__fspath__(path)
|
||||
except AttributeError:
|
||||
# Added for Python 3.5 support.
|
||||
if isinstance(path, pathlib.Path):
|
||||
return str(path)
|
||||
elif hasattr(path_type, '__fspath__'):
|
||||
raise
|
||||
else:
|
||||
if isinstance(path, (str, bytes)):
|
||||
return path
|
||||
else:
|
||||
raise TypeError("expected __fspath__() to return str or bytes, "
|
||||
"not " + type(path).__name__)
|
||||
|
||||
raise TypeError(
|
||||
"expected str, bytes, pathlib.Path or os.PathLike object, not "
|
||||
+ path_type.__name__)
|
||||
|
||||
else:
|
||||
fspath = os.fspath
|
||||
|
||||
|
||||
def flatten_groups(groups):
|
||||
for obj in groups:
|
||||
if is_iterable_notstr(obj):
|
||||
@@ -172,12 +132,16 @@ def flatten_groups(groups):
|
||||
|
||||
def deprecated(func):
|
||||
"""Warn that function is deprecated"""
|
||||
|
||||
@wraps(func)
|
||||
def new_func(*args, **kwargs):
|
||||
warnings.simplefilter('always', DeprecationWarning) # turn off filter
|
||||
warnings.warn("Call to deprecated function {}.".format(func.__name__),
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2)
|
||||
warnings.warn(
|
||||
"Call to deprecated function {}.".format(func.__name__),
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
warnings.simplefilter('default', DeprecationWarning) # reset filter
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return new_func
|
||||
|
||||
+113
-73
@@ -28,14 +28,14 @@
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from reportlab.pdfgen.canvas import Canvas
|
||||
from reportlab.lib.units import inch
|
||||
from xml.etree import ElementTree
|
||||
from collections import namedtuple
|
||||
from math import atan, sin, cos
|
||||
import re
|
||||
import argparse
|
||||
import re
|
||||
from collections import namedtuple
|
||||
from math import atan, cos, sin
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from reportlab.lib.units import inch
|
||||
from reportlab.pdfgen.canvas import Canvas
|
||||
|
||||
Rect = namedtuple('Rect', ['x1', 'y1', 'x2', 'y2'])
|
||||
|
||||
@@ -44,7 +44,7 @@ class HocrTransformError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class HocrTransform():
|
||||
class HocrTransform:
|
||||
|
||||
"""
|
||||
A class for converting documents from the hOCR format.
|
||||
@@ -53,17 +53,16 @@ class HocrTransform():
|
||||
"""
|
||||
|
||||
box_pattern = re.compile(r'bbox((\s+\d+){4})')
|
||||
baseline_pattern = re.compile(r'''
|
||||
baseline_pattern = re.compile(
|
||||
r'''
|
||||
baseline \s+
|
||||
([\-\+]?\d*\.?\d*) \s+ # +/- decimal float
|
||||
([\-\+]?\d+) # +/- int''', re.VERBOSE)
|
||||
ligatures = str.maketrans({
|
||||
'ff': 'ff',
|
||||
'ffi': 'ffi',
|
||||
'ffl': 'ffl',
|
||||
'fi': 'fi',
|
||||
'fl': 'fl',
|
||||
})
|
||||
([\-\+]?\d+) # +/- int''',
|
||||
re.VERBOSE,
|
||||
)
|
||||
ligatures = str.maketrans(
|
||||
{'ff': 'ff', 'ffi': 'ffi', 'ffl': 'ffl', 'fi': 'fi', 'fl': 'fl'}
|
||||
)
|
||||
|
||||
def __init__(self, hocrFileName, dpi):
|
||||
self.dpi = dpi
|
||||
@@ -78,8 +77,7 @@ class HocrTransform():
|
||||
|
||||
# get dimension in pt (not pixel!!!!) of the OCRed image
|
||||
self.width, self.height = None, None
|
||||
for div in self.hocr.findall(
|
||||
".//%sdiv[@class='ocr_page']" % (self.xmlns)):
|
||||
for div in self.hocr.findall(".//%sdiv[@class='ocr_page']" % (self.xmlns)):
|
||||
coords = self.element_coordinates(div)
|
||||
pt_coords = self.pt_from_pixel(coords)
|
||||
self.width = pt_coords.x2 - pt_coords.x1
|
||||
@@ -144,8 +142,7 @@ class HocrTransform():
|
||||
"""
|
||||
Returns the quantity in PDF units (pt) given quantity in pixels
|
||||
"""
|
||||
return Rect._make(
|
||||
(c / self.dpi * inch) for c in pxl)
|
||||
return Rect._make((c / self.dpi * inch) for c in pxl)
|
||||
|
||||
@classmethod
|
||||
def replace_unsupported_chars(cls, s):
|
||||
@@ -156,8 +153,15 @@ class HocrTransform():
|
||||
"""
|
||||
return s.translate(cls.ligatures)
|
||||
|
||||
def to_pdf(self, outFileName, imageFileName=None, showBoundingboxes=False,
|
||||
fontname="Helvetica", invisibleText=False, interwordSpaces=False):
|
||||
def to_pdf(
|
||||
self,
|
||||
outFileName,
|
||||
imageFileName=None,
|
||||
showBoundingboxes=False,
|
||||
fontname="Helvetica",
|
||||
invisibleText=False,
|
||||
interwordSpaces=False,
|
||||
):
|
||||
"""
|
||||
Creates a PDF file with an image superimposed on top of the text.
|
||||
Text is positioned according to the bounding box of the lines in
|
||||
@@ -168,17 +172,15 @@ class HocrTransform():
|
||||
"""
|
||||
# create the PDF file
|
||||
# page size in points (1/72 in.)
|
||||
pdf = Canvas(
|
||||
outFileName, pagesize=(self.width, self.height), pageCompression=1)
|
||||
pdf = Canvas(outFileName, pagesize=(self.width, self.height), pageCompression=1)
|
||||
|
||||
# draw bounding box for each paragraph
|
||||
# light blue for bounding box of paragraph
|
||||
pdf.setStrokeColorRGB(0, 1, 1)
|
||||
# light blue for bounding box of paragraph
|
||||
pdf.setFillColorRGB(0, 1, 1)
|
||||
pdf.setLineWidth(0) # no line for bounding box
|
||||
for elem in self.hocr.findall(
|
||||
".//%sp[@class='%s']" % (self.xmlns, "ocr_par")):
|
||||
pdf.setLineWidth(0) # no line for bounding box
|
||||
for elem in self.hocr.findall(".//%sp[@class='%s']" % (self.xmlns, "ocr_par")):
|
||||
|
||||
elemtxt = self._get_element_text(elem).rstrip()
|
||||
if len(elemtxt) == 0:
|
||||
@@ -190,38 +192,58 @@ class HocrTransform():
|
||||
# draw the bbox border
|
||||
if showBoundingboxes:
|
||||
pdf.rect(
|
||||
pt.x1, self.height - pt.y2, pt.x2 - pt.x1, pt.y2 - pt.y1,
|
||||
fill=1)
|
||||
pt.x1, self.height - pt.y2, pt.x2 - pt.x1, pt.y2 - pt.y1, fill=1
|
||||
)
|
||||
|
||||
found_lines = False
|
||||
for line in self.hocr.findall(
|
||||
".//%sspan[@class='%s']" % (self.xmlns, "ocr_line")):
|
||||
".//%sspan[@class='%s']" % (self.xmlns, "ocr_line")
|
||||
):
|
||||
found_lines = True
|
||||
self._do_line(pdf, line, "ocrx_word", fontname, invisibleText,
|
||||
interwordSpaces, showBoundingboxes)
|
||||
self._do_line(
|
||||
pdf,
|
||||
line,
|
||||
"ocrx_word",
|
||||
fontname,
|
||||
invisibleText,
|
||||
interwordSpaces,
|
||||
showBoundingboxes,
|
||||
)
|
||||
|
||||
if not found_lines:
|
||||
# Tesseract did not report any lines (just words)
|
||||
root = self.hocr.find(".//%sdiv[@class='%s']" % (self.xmlns, "ocr_page"))
|
||||
self._do_line(pdf, root, "ocrx_word", fontname, invisibleText,
|
||||
interwordSpaces, showBoundingboxes)
|
||||
self._do_line(
|
||||
pdf,
|
||||
root,
|
||||
"ocrx_word",
|
||||
fontname,
|
||||
invisibleText,
|
||||
interwordSpaces,
|
||||
showBoundingboxes,
|
||||
)
|
||||
# put the image on the page, scaled to fill the page
|
||||
if imageFileName is not None:
|
||||
pdf.drawImage(imageFileName, 0, 0,
|
||||
width=self.width, height=self.height)
|
||||
pdf.drawImage(imageFileName, 0, 0, width=self.width, height=self.height)
|
||||
|
||||
# finish up the page and save it
|
||||
pdf.showPage()
|
||||
pdf.save()
|
||||
|
||||
|
||||
@classmethod
|
||||
def polyval(cls, poly, x):
|
||||
return x * poly[0] + poly[1]
|
||||
|
||||
|
||||
def _do_line(self, pdf, line, elemclass, fontname, invisibleText,
|
||||
interwordSpaces, showBoundingboxes):
|
||||
def _do_line(
|
||||
self,
|
||||
pdf,
|
||||
line,
|
||||
elemclass,
|
||||
fontname,
|
||||
invisibleText,
|
||||
interwordSpaces,
|
||||
showBoundingboxes,
|
||||
):
|
||||
pxl_line_coords = self.element_coordinates(line)
|
||||
line_box = self.pt_from_pixel(pxl_line_coords)
|
||||
line_height = line_box.y2 - line_box.y1
|
||||
@@ -254,23 +276,20 @@ class HocrTransform():
|
||||
pdf.setLineWidth(0.5)
|
||||
# negate slope because it is defined as a rise/run in pixel
|
||||
# coordinates and page coordinates have the y axis flipped
|
||||
pdf.line(line_box.x1,
|
||||
baseline_y2,
|
||||
line_box.x2,
|
||||
self.polyval((-slope, baseline_y2),
|
||||
line_box.x2 - line_box.x1))
|
||||
pdf.line(
|
||||
line_box.x1,
|
||||
baseline_y2,
|
||||
line_box.x2,
|
||||
self.polyval((-slope, baseline_y2), line_box.x2 - line_box.x1),
|
||||
)
|
||||
# light green for bounding box of word/line
|
||||
pdf.setDash(6, 3)
|
||||
pdf.setStrokeColorRGB(1, 0, 0)
|
||||
|
||||
text.setTextTransform(
|
||||
cos_a, -sin_a, sin_a, cos_a,
|
||||
line_box.x1, baseline_y2
|
||||
)
|
||||
text.setTextTransform(cos_a, -sin_a, sin_a, cos_a, line_box.x1, baseline_y2)
|
||||
pdf.setFillColorRGB(0, 0, 0) # text in black
|
||||
|
||||
elements = line.findall(
|
||||
".//%sspan[@class='%s']" % (self.xmlns, elemclass))
|
||||
elements = line.findall(".//%sspan[@class='%s']" % (self.xmlns, elemclass))
|
||||
for elem in elements:
|
||||
elemtxt = self._get_element_text(elem).strip()
|
||||
elemtxt = self.replace_unsupported_chars(elemtxt)
|
||||
@@ -287,22 +306,22 @@ class HocrTransform():
|
||||
# though it would look better, because it will interfere with
|
||||
# naive text extraction. \n does not work either.
|
||||
elemtxt += ' '
|
||||
box = Rect._make((
|
||||
box.x1,
|
||||
line_box.y1,
|
||||
box.x2 + pdf.stringWidth(' ', fontname, line_height),
|
||||
line_box.y2))
|
||||
box = Rect._make(
|
||||
(
|
||||
box.x1,
|
||||
line_box.y1,
|
||||
box.x2 + pdf.stringWidth(' ', fontname, line_height),
|
||||
line_box.y2,
|
||||
)
|
||||
)
|
||||
box_width = box.x2 - box.x1
|
||||
font_width = pdf.stringWidth(elemtxt, fontname, fontsize)
|
||||
|
||||
# draw the bbox border
|
||||
if showBoundingboxes:
|
||||
pdf.rect(
|
||||
box.x1,
|
||||
self.height - line_box.y2,
|
||||
box_width,
|
||||
line_height,
|
||||
fill=0)
|
||||
box.x1, self.height - line_box.y2, box_width, line_height, fill=0
|
||||
)
|
||||
|
||||
# Adjust relative position of cursor
|
||||
# This is equivalent to:
|
||||
@@ -331,19 +350,40 @@ class HocrTransform():
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Convert hocr file to PDF')
|
||||
parser.add_argument('-b', '--boundingboxes', action="store_true",
|
||||
default=False, help='Show bounding boxes borders')
|
||||
parser.add_argument('-r', '--resolution', type=int,
|
||||
default=300,
|
||||
help='Resolution of the image that was OCRed')
|
||||
parser.add_argument('-i', '--image', default=None,
|
||||
help='Path to the image to be placed above the text')
|
||||
parser.add_argument('--interword-spaces', action='store_true',
|
||||
default=False, help='Add spaces between words')
|
||||
parser.add_argument('hocrfile', help='Path to the hocr file to be parsed')
|
||||
parser.add_argument(
|
||||
'outputfile', help='Path to the PDF file to be generated')
|
||||
'-b',
|
||||
'--boundingboxes',
|
||||
action="store_true",
|
||||
default=False,
|
||||
help='Show bounding boxes borders',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-r',
|
||||
'--resolution',
|
||||
type=int,
|
||||
default=300,
|
||||
help='Resolution of the image that was OCRed',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-i',
|
||||
'--image',
|
||||
default=None,
|
||||
help='Path to the image to be placed above the text',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--interword-spaces',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Add spaces between words',
|
||||
)
|
||||
parser.add_argument('hocrfile', help='Path to the hocr file to be parsed')
|
||||
parser.add_argument('outputfile', help='Path to the PDF file to be generated')
|
||||
args = parser.parse_args()
|
||||
|
||||
hocr = HocrTransform(args.hocrfile, args.resolution)
|
||||
hocr.to_pdf(args.outputfile, args.image, args.boundingboxes, interwordSpaces=args.interword_spaces)
|
||||
hocr.to_pdf(
|
||||
args.outputfile,
|
||||
args.image,
|
||||
args.boundingboxes,
|
||||
interwordSpaces=args.interword_spaces,
|
||||
)
|
||||
|
||||
+161
-106
@@ -20,20 +20,20 @@
|
||||
#
|
||||
# Python FFI wrapper for Leptonica library
|
||||
|
||||
from collections.abc import Sequence
|
||||
from contextlib import suppress
|
||||
from ctypes.util import find_library
|
||||
from functools import lru_cache
|
||||
from io import BytesIO
|
||||
from tempfile import TemporaryFile
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from collections.abc import Sequence
|
||||
from contextlib import suppress
|
||||
from ctypes.util import find_library
|
||||
from functools import lru_cache
|
||||
from io import BytesIO
|
||||
from os import fspath
|
||||
from tempfile import TemporaryFile
|
||||
|
||||
from .lib._leptonica import ffi
|
||||
from .helpers import fspath
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
@@ -69,14 +69,14 @@ class _LeptonicaErrorTrap:
|
||||
|
||||
def __enter__(self):
|
||||
from io import UnsupportedOperation
|
||||
|
||||
self.tmpfile = TemporaryFile()
|
||||
|
||||
# Save the old stderr, and redirect stderr to temporary file
|
||||
sys.stderr.flush()
|
||||
try:
|
||||
self.copy_of_stderr = os.dup(sys.stderr.fileno())
|
||||
os.dup2(self.tmpfile.fileno(), sys.stderr.fileno(),
|
||||
inheritable=False)
|
||||
os.dup2(self.tmpfile.fileno(), sys.stderr.fileno(), inheritable=False)
|
||||
except UnsupportedOperation:
|
||||
self.copy_of_stderr = None
|
||||
return
|
||||
@@ -185,9 +185,13 @@ class Pix(LeptonicaObject):
|
||||
def __repr__(self):
|
||||
if self._cdata:
|
||||
s = "<leptonica.Pix image size={0}x{1} depth={2}{4} at 0x{3:x}>"
|
||||
return s.format(self._cdata.w, self._cdata.h, self._cdata.d,
|
||||
int(ffi.cast('intptr_t', self._cdata)),
|
||||
'(colormapped)' if self._cdata.colormap else '')
|
||||
return s.format(
|
||||
self._cdata.w,
|
||||
self._cdata.h,
|
||||
self._cdata.d,
|
||||
int(ffi.cast('intptr_t', self._cdata)),
|
||||
'(colormapped)' if self._cdata.colormap else '',
|
||||
)
|
||||
else:
|
||||
return "<leptonica.Pix image NULL>"
|
||||
|
||||
@@ -289,8 +293,7 @@ class Pix(LeptonicaObject):
|
||||
with _LeptonicaErrorTrap():
|
||||
return cls(lept.pixRead(os.fsencode(filename)))
|
||||
|
||||
def write_implied_format(
|
||||
self, path, jpeg_quality=0, jpeg_progressive=0):
|
||||
def write_implied_format(self, path, jpeg_quality=0, jpeg_progressive=0):
|
||||
"""Write pix to the filename, with the extension indicating format.
|
||||
|
||||
jpeg_quality -- quality (iff JPEG; 1 - 100, 0 for default)
|
||||
@@ -299,8 +302,8 @@ class Pix(LeptonicaObject):
|
||||
filename = fspath(path)
|
||||
with _LeptonicaErrorTrap():
|
||||
lept.pixWriteImpliedFormat(
|
||||
os.fsencode(filename),
|
||||
self._cdata, jpeg_quality, jpeg_progressive)
|
||||
os.fsencode(filename), self._cdata, jpeg_quality, jpeg_progressive
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def frompil(self, pillow_image):
|
||||
@@ -401,11 +404,13 @@ class Pix(LeptonicaObject):
|
||||
|
||||
"""
|
||||
with _LeptonicaErrorTrap():
|
||||
return Pix(lept.pixRemoveColormapGeneral(
|
||||
self._cdata, removal_type, lept.L_COPY))
|
||||
return Pix(
|
||||
lept.pixRemoveColormapGeneral(self._cdata, removal_type, lept.L_COPY)
|
||||
)
|
||||
|
||||
def otsu_adaptive_threshold(
|
||||
self, tile_size=(300, 300), kernel_size=(4, 4), scorefract=0.1):
|
||||
self, tile_size=(300, 300), kernel_size=(4, 4), scorefract=0.1
|
||||
):
|
||||
with _LeptonicaErrorTrap():
|
||||
sx, sy = tile_size
|
||||
smoothx, smoothy = kernel_size
|
||||
@@ -413,20 +418,23 @@ class Pix(LeptonicaObject):
|
||||
|
||||
pix = Pix(lept.pixConvertTo8(self._cdata, 0))
|
||||
result = lept.pixOtsuAdaptiveThreshold(
|
||||
pix._cdata,
|
||||
sx, sy,
|
||||
smoothx, smoothy,
|
||||
scorefract,
|
||||
ffi.NULL,
|
||||
p_pix)
|
||||
pix._cdata, sx, sy, smoothx, smoothy, scorefract, ffi.NULL, p_pix
|
||||
)
|
||||
if result == 0:
|
||||
return Pix(p_pix[0])
|
||||
else:
|
||||
return None
|
||||
|
||||
def otsu_threshold_on_background_norm(
|
||||
self, mask=None, tile_size=(10, 15), thresh=100, mincount=50,
|
||||
bgval=255, kernel_size=(2, 2), scorefract=0.1):
|
||||
self,
|
||||
mask=None,
|
||||
tile_size=(10, 15),
|
||||
thresh=100,
|
||||
mincount=50,
|
||||
bgval=255,
|
||||
kernel_size=(2, 2),
|
||||
scorefract=0.1,
|
||||
):
|
||||
with _LeptonicaErrorTrap():
|
||||
sx, sy = tile_size
|
||||
smoothx, smoothy = kernel_size
|
||||
@@ -438,17 +446,27 @@ class Pix(LeptonicaObject):
|
||||
thresh_pix = lept.pixOtsuThreshOnBackgroundNorm(
|
||||
pix._cdata,
|
||||
mask,
|
||||
sx, sy,
|
||||
thresh, mincount, bgval,
|
||||
smoothx, smoothy,
|
||||
sx,
|
||||
sy,
|
||||
thresh,
|
||||
mincount,
|
||||
bgval,
|
||||
smoothx,
|
||||
smoothy,
|
||||
scorefract,
|
||||
ffi.NULL
|
||||
ffi.NULL,
|
||||
)
|
||||
return Pix(thresh_pix)
|
||||
|
||||
def masked_threshold_on_background_norm(
|
||||
self, mask=None, tile_size=(10, 15), thresh=100, mincount=50,
|
||||
kernel_size=(2, 2), scorefract=0.1):
|
||||
self,
|
||||
mask=None,
|
||||
tile_size=(10, 15),
|
||||
thresh=100,
|
||||
mincount=50,
|
||||
kernel_size=(2, 2),
|
||||
scorefract=0.1,
|
||||
):
|
||||
with _LeptonicaErrorTrap():
|
||||
sx, sy = tile_size
|
||||
smoothx, smoothy = kernel_size
|
||||
@@ -460,74 +478,91 @@ class Pix(LeptonicaObject):
|
||||
thresh_pix = lept.pixMaskedThreshOnBackgroundNorm(
|
||||
pix._cdata,
|
||||
mask,
|
||||
sx, sy,
|
||||
thresh, mincount,
|
||||
smoothx, smoothy,
|
||||
sx,
|
||||
sy,
|
||||
thresh,
|
||||
mincount,
|
||||
smoothx,
|
||||
smoothy,
|
||||
scorefract,
|
||||
ffi.NULL
|
||||
ffi.NULL,
|
||||
)
|
||||
return Pix(thresh_pix)
|
||||
|
||||
def crop_to_foreground(
|
||||
self, threshold=128, mindist=70, erasedist=30, pagenum=0,
|
||||
showmorph=0, display=0, pdfdir=ffi.NULL):
|
||||
self,
|
||||
threshold=128,
|
||||
mindist=70,
|
||||
erasedist=30,
|
||||
pagenum=0,
|
||||
showmorph=0,
|
||||
display=0,
|
||||
pdfdir=ffi.NULL,
|
||||
):
|
||||
with _LeptonicaErrorTrap():
|
||||
cropbox = Box(lept.pixFindPageForeground(
|
||||
self._cdata,
|
||||
threshold,
|
||||
mindist,
|
||||
erasedist,
|
||||
pagenum,
|
||||
showmorph,
|
||||
display,
|
||||
pdfdir))
|
||||
cropbox = Box(
|
||||
lept.pixFindPageForeground(
|
||||
self._cdata,
|
||||
threshold,
|
||||
mindist,
|
||||
erasedist,
|
||||
pagenum,
|
||||
showmorph,
|
||||
display,
|
||||
pdfdir,
|
||||
)
|
||||
)
|
||||
|
||||
cropped_pix = lept.pixClipRectangle(
|
||||
self._cdata,
|
||||
cropbox._cdata,
|
||||
ffi.NULL)
|
||||
cropped_pix = lept.pixClipRectangle(self._cdata, cropbox._cdata, ffi.NULL)
|
||||
|
||||
return Pix(cropped_pix)
|
||||
|
||||
def clean_background_to_white(
|
||||
self, mask=None, grayscale=None, gamma=1.0, black=0, white=255):
|
||||
self, mask=None, grayscale=None, gamma=1.0, black=0, white=255
|
||||
):
|
||||
with _LeptonicaErrorTrap():
|
||||
return Pix(lept.pixCleanBackgroundToWhite(
|
||||
self._cdata,
|
||||
mask or ffi.NULL,
|
||||
grayscale or ffi.NULL,
|
||||
gamma,
|
||||
black,
|
||||
white))
|
||||
return Pix(
|
||||
lept.pixCleanBackgroundToWhite(
|
||||
self._cdata,
|
||||
mask or ffi.NULL,
|
||||
grayscale or ffi.NULL,
|
||||
gamma,
|
||||
black,
|
||||
white,
|
||||
)
|
||||
)
|
||||
|
||||
def gamma_trc(self, gamma=1.0, minval=0, maxval=255):
|
||||
with _LeptonicaErrorTrap():
|
||||
return Pix(lept.pixGammaTRC(
|
||||
ffi.NULL,
|
||||
self._cdata,
|
||||
gamma,
|
||||
minval,
|
||||
maxval
|
||||
))
|
||||
return Pix(lept.pixGammaTRC(ffi.NULL, self._cdata, gamma, minval, maxval))
|
||||
|
||||
def background_norm(
|
||||
self, mask=None, grayscale=None, tile_size=(10, 15), fg_threshold=60,
|
||||
min_count=40, bg_val=200, smooth_kernel=(2, 1)):
|
||||
self,
|
||||
mask=None,
|
||||
grayscale=None,
|
||||
tile_size=(10, 15),
|
||||
fg_threshold=60,
|
||||
min_count=40,
|
||||
bg_val=200,
|
||||
smooth_kernel=(2, 1),
|
||||
):
|
||||
# Background norm doesn't work on color mapped Pix, so remove colormap
|
||||
target_pix = self.remove_colormap(lept.REMOVE_CMAP_BASED_ON_SRC)
|
||||
with _LeptonicaErrorTrap():
|
||||
return Pix(lept.pixBackgroundNorm(
|
||||
target_pix._cdata,
|
||||
mask or ffi.NULL,
|
||||
grayscale or ffi.NULL,
|
||||
tile_size[0],
|
||||
tile_size[1],
|
||||
fg_threshold,
|
||||
min_count,
|
||||
bg_val,
|
||||
smooth_kernel[0],
|
||||
smooth_kernel[1]
|
||||
))
|
||||
return Pix(
|
||||
lept.pixBackgroundNorm(
|
||||
target_pix._cdata,
|
||||
mask or ffi.NULL,
|
||||
grayscale or ffi.NULL,
|
||||
tile_size[0],
|
||||
tile_size[1],
|
||||
fg_threshold,
|
||||
min_count,
|
||||
bg_val,
|
||||
smooth_kernel[0],
|
||||
smooth_kernel[1],
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@lru_cache(maxsize=1)
|
||||
@@ -544,8 +579,7 @@ class Pix(LeptonicaObject):
|
||||
raise LeptonicaError("Leptonica version is too old")
|
||||
|
||||
correlation = ffi.new('float *', 0.0)
|
||||
result = lept.pixCorrelationBinary(pix1._cdata, pix2._cdata,
|
||||
correlation)
|
||||
result = lept.pixCorrelationBinary(pix1._cdata, pix2._cdata, correlation)
|
||||
if result != 0:
|
||||
raise LeptonicaError("Correlation failed")
|
||||
return correlation[0]
|
||||
@@ -553,8 +587,7 @@ class Pix(LeptonicaObject):
|
||||
def generate_pdf_ci_data(self, type_, quality):
|
||||
"Convert to PDF data, with transcoding"
|
||||
p_compdata = ffi.new('L_COMP_DATA **')
|
||||
result = lept.pixGenerateCIData(self._cdata, type_, quality, 0,
|
||||
p_compdata)
|
||||
result = lept.pixGenerateCIData(self._cdata, type_, quality, 0, p_compdata)
|
||||
if result != 0:
|
||||
raise LeptonicaError("Generate PDF data failed")
|
||||
return CompressedData(p_compdata[0])
|
||||
@@ -567,17 +600,23 @@ class Pix(LeptonicaObject):
|
||||
with _LeptonicaErrorTrap():
|
||||
pix = Pix(lept.pixConvertTo8(self._cdata, 0))
|
||||
pixa_candidates = PixArray(lept.pixExtractBarcodes(pix._cdata, 0))
|
||||
with suppress(FileNotFoundError):
|
||||
os.unlink('junkpixt.png') # leptonica may produce this
|
||||
sarray = StringArray(lept.pixReadBarcodes(
|
||||
pixa_candidates._cdata,
|
||||
lept.L_BF_ANY,
|
||||
lept.L_USE_WIDTHS,
|
||||
ffi.NULL,
|
||||
0
|
||||
))
|
||||
except (LeptonicaError, ValueError) as e:
|
||||
if not pixa_candidates:
|
||||
return
|
||||
sarray = StringArray(
|
||||
lept.pixReadBarcodes(
|
||||
pixa_candidates._cdata,
|
||||
lept.L_BF_ANY,
|
||||
lept.L_USE_WIDTHS,
|
||||
ffi.NULL,
|
||||
0,
|
||||
)
|
||||
)
|
||||
except (LeptonicaError, ValueError, IndexError):
|
||||
return
|
||||
finally:
|
||||
with suppress(FileNotFoundError):
|
||||
os.unlink('junkpixt.png') # leptonica may produce this
|
||||
os.unlink('junkpixt')
|
||||
|
||||
for n, s in enumerate(sarray):
|
||||
decoded = s.decode()
|
||||
@@ -631,7 +670,8 @@ class CompressedData(LeptonicaObject):
|
||||
|
||||
p_compdata = ffi.new('L_COMP_DATA **')
|
||||
result = lept.l_generateCIDataForPdf(
|
||||
os.fsencode(filename), ffi.NULL, jpeg_quality, p_compdata)
|
||||
os.fsencode(filename), ffi.NULL, jpeg_quality, p_compdata
|
||||
)
|
||||
if result != 0:
|
||||
raise LeptonicaError("CompressedData.open")
|
||||
return CompressedData(p_compdata[0])
|
||||
@@ -685,7 +725,8 @@ class Box(LeptonicaObject):
|
||||
def __repr__(self):
|
||||
if self._cdata:
|
||||
return '<leptonica.Box x={0} y={1} w={2} h={3}>'.format(
|
||||
self.x, self.y, self.w, self.h)
|
||||
self.x, self.y, self.w, self.h
|
||||
)
|
||||
return '<leptonica.Box NULL>'
|
||||
|
||||
@property
|
||||
@@ -804,15 +845,22 @@ def deskew(infile, outfile, dpi):
|
||||
raise LeptonicaIOError("Failed to open destination file: %s" % outfile)
|
||||
|
||||
|
||||
def remove_background(infile, outfile, tile_size=(40, 60), gamma=1.0,
|
||||
black_threshold=70, white_threshold=190):
|
||||
def remove_background(
|
||||
infile,
|
||||
outfile,
|
||||
tile_size=(40, 60),
|
||||
gamma=1.0,
|
||||
black_threshold=70,
|
||||
white_threshold=190,
|
||||
):
|
||||
try:
|
||||
pix = Pix.open(infile)
|
||||
except LeptonicaIOError:
|
||||
raise LeptonicaIOError("Failed to open file: %s" % infile)
|
||||
|
||||
pix = pix.background_norm(tile_size=tile_size).gamma_trc(
|
||||
gamma, black_threshold, white_threshold)
|
||||
gamma, black_threshold, white_threshold
|
||||
)
|
||||
|
||||
try:
|
||||
pix.write_implied_format(outfile)
|
||||
@@ -821,15 +869,22 @@ def remove_background(infile, outfile, tile_size=(40, 60), gamma=1.0,
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Python wrapper to access Leptonica")
|
||||
parser = argparse.ArgumentParser(description="Python wrapper to access Leptonica")
|
||||
|
||||
subparsers = parser.add_subparsers(title='commands',
|
||||
description='supported operations')
|
||||
subparsers = parser.add_subparsers(
|
||||
title='commands', description='supported operations'
|
||||
)
|
||||
|
||||
parser_deskew = subparsers.add_parser('deskew')
|
||||
parser_deskew.add_argument('-r', '--dpi', dest='dpi', action='store',
|
||||
type=int, default=300, help='input resolution')
|
||||
parser_deskew.add_argument(
|
||||
'-r',
|
||||
'--dpi',
|
||||
dest='dpi',
|
||||
action='store',
|
||||
type=int,
|
||||
default=300,
|
||||
help='input resolution',
|
||||
)
|
||||
parser_deskew.add_argument('infile', help='image to deskew')
|
||||
parser_deskew.add_argument('outfile', help='deskewed output image')
|
||||
parser_deskew.set_defaults(func=deskew)
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
from cffi import FFI
|
||||
|
||||
ffibuilder = FFI()
|
||||
ffibuilder.cdef("""
|
||||
ffibuilder.cdef(
|
||||
"""
|
||||
typedef signed char l_int8;
|
||||
typedef unsigned char l_uint8;
|
||||
typedef short l_int16;
|
||||
@@ -202,9 +203,11 @@ enum {
|
||||
SEL_MISS = 2
|
||||
};
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
ffibuilder.cdef("""
|
||||
ffibuilder.cdef(
|
||||
"""
|
||||
PIX * pixRead ( const char *filename );
|
||||
PIX * pixReadMem ( const l_uint8 *data, size_t size );
|
||||
PIX * pixScale ( PIX *pixs, l_float32 scalex, l_float32 scaley );
|
||||
@@ -480,7 +483,8 @@ void selDestroy ( SEL **psel );
|
||||
l_int32
|
||||
setMsgSeverity(l_int32 newsev);
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
ffibuilder.set_source("ocrmypdf.lib._leptonica", None)
|
||||
|
||||
+70
-81
@@ -15,27 +15,28 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with OCRmyPDF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pathlib import Path
|
||||
import concurrent.futures
|
||||
from collections import defaultdict
|
||||
import logging
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from os import fspath
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
|
||||
import pikepdf
|
||||
|
||||
from ._jobcontext import JobContext
|
||||
from . import leptonica
|
||||
from .helpers import re_symlink, fspath
|
||||
from .exec import pngquant, jbig2enc
|
||||
from ._jobcontext import JobContext
|
||||
from .exec import jbig2enc, pngquant
|
||||
from .helpers import re_symlink
|
||||
|
||||
DEFAULT_JPEG_QUALITY = 75
|
||||
DEFAULT_PNG_QUALITY = 70
|
||||
|
||||
|
||||
def img_name(root, xref, ext):
|
||||
return fspath(root / '{:08d}{}'.format(xref, ext))
|
||||
return fspath(root / f'{xref:08d}{ext}')
|
||||
|
||||
|
||||
def png_name(root, xref):
|
||||
@@ -79,11 +80,13 @@ def extract_image_jbig2(*, pike, root, log, image, xref, options):
|
||||
return None
|
||||
pim, filtdp = result
|
||||
|
||||
if pim.bits_per_component == 1 \
|
||||
and filtdp != '/JBIG2Decode' \
|
||||
and jbig2enc.available():
|
||||
if (
|
||||
pim.bits_per_component == 1
|
||||
and filtdp != '/JBIG2Decode'
|
||||
and jbig2enc.available()
|
||||
):
|
||||
try:
|
||||
imgname = Path(root / '{:08d}'.format(xref))
|
||||
imgname = Path(root / f'{xref:08d}')
|
||||
with imgname.open('wb') as f:
|
||||
ext = pim.extract_to(stream=f)
|
||||
imgname.rename(imgname.with_suffix(ext))
|
||||
@@ -99,8 +102,7 @@ def extract_image_generic(*, pike, root, log, image, xref, options):
|
||||
return None
|
||||
pim, filtdp = result
|
||||
|
||||
if filtdp[0] == '/DCTDecode' \
|
||||
and options.optimize >= 2:
|
||||
if filtdp[0] == '/DCTDecode' and options.optimize >= 2:
|
||||
# This is a simple heuristic derived from some training data, that has
|
||||
# about a 70% chance of guessing whether the JPEG is high quality,
|
||||
# and possibly recompressible, or not. The number itself doesn't mean
|
||||
@@ -118,16 +120,18 @@ def extract_image_generic(*, pike, root, log, image, xref, options):
|
||||
# with Image.open(stream) as im:
|
||||
# im.save(jpg_name(root, xref), icc_profile=iccbytes)
|
||||
try:
|
||||
imgname = Path(root / '{:08d}'.format(xref))
|
||||
imgname = Path(root / f'{xref:08d}')
|
||||
with imgname.open('wb') as f:
|
||||
ext = pim.extract_to(stream=f)
|
||||
imgname.rename(imgname.with_suffix(ext))
|
||||
except pikepdf.UnsupportedImageTypeError:
|
||||
return None
|
||||
return xref, ext
|
||||
elif pim.indexed \
|
||||
and pim.colorspace in pim.SIMPLE_COLORSPACES \
|
||||
and options.optimize >= 3:
|
||||
elif (
|
||||
pim.indexed
|
||||
and pim.colorspace in pim.SIMPLE_COLORSPACES
|
||||
and options.optimize >= 3
|
||||
):
|
||||
# Try to improve on indexed images - these are far from low hanging
|
||||
# fruit in most cases
|
||||
pim.as_pil_image().save(png_name(root, xref))
|
||||
@@ -141,11 +145,10 @@ def extract_image_generic(*, pike, root, log, image, xref, options):
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def extract_images(pike, root, log, options, extract_fn):
|
||||
"""Extract image using extract_fn
|
||||
|
||||
extract_fn decides where the image is interesting in this case
|
||||
extract_fn decides whether the image is interesting in this case
|
||||
"""
|
||||
|
||||
include_xrefs = set()
|
||||
@@ -171,8 +174,7 @@ def extract_images(pike, root, log, options, extract_fn):
|
||||
image = pike.get_object((xref, 0))
|
||||
try:
|
||||
result = extract_fn(
|
||||
pike=pike, root=root, log=log, image=image,
|
||||
xref=xref, options=options
|
||||
pike=pike, root=root, log=log, image=image, xref=xref, options=options
|
||||
)
|
||||
except Exception as e:
|
||||
log.debug("Image xref %s", xref)
|
||||
@@ -189,17 +191,13 @@ def extract_images_generic(pike, root, log, options):
|
||||
|
||||
jpegs = []
|
||||
pngs = []
|
||||
for _, xref, ext in extract_images(
|
||||
pike, root, log, options, extract_image_generic):
|
||||
for _, xref, ext in extract_images(pike, root, log, options, extract_image_generic):
|
||||
log.debug('xref = %s ext = %s', xref, ext)
|
||||
if ext == '.png':
|
||||
pngs.append(xref)
|
||||
elif ext == '.jpg':
|
||||
jpegs.append(xref)
|
||||
log.debug(
|
||||
"Optimizable images: "
|
||||
"JPEGs: %s PNGs: %s", len(jpegs), len(pngs)
|
||||
)
|
||||
log.debug("Optimizable images: " "JPEGs: %s PNGs: %s", len(jpegs), len(pngs))
|
||||
return jpegs, pngs
|
||||
|
||||
|
||||
@@ -208,17 +206,16 @@ def extract_images_jbig2(pike, root, log, options):
|
||||
|
||||
jbig2_groups = defaultdict(list)
|
||||
for pageno, xref, ext in extract_images(
|
||||
pike, root, log, options, extract_image_jbig2):
|
||||
pike, root, log, options, extract_image_jbig2
|
||||
):
|
||||
group = pageno // options.jbig2_page_group_size
|
||||
jbig2_groups[group].append((xref, ext))
|
||||
|
||||
# Elide empty groups
|
||||
jbig2_groups = {group: xrefs for group, xrefs in jbig2_groups.items()
|
||||
if len(xrefs) > 0}
|
||||
log.debug(
|
||||
"Optimizable images: "
|
||||
"JBIG2 groups: %s", (len(jbig2_groups),)
|
||||
)
|
||||
jbig2_groups = {
|
||||
group: xrefs for group, xrefs in jbig2_groups.items() if len(xrefs) > 0
|
||||
}
|
||||
log.debug("Optimizable images: " "JBIG2 groups: %s", (len(jbig2_groups),))
|
||||
return jbig2_groups
|
||||
|
||||
|
||||
@@ -227,18 +224,18 @@ def _produce_jbig2_images(jbig2_groups, root, log, options):
|
||||
|
||||
def jbig2_group_futures(executor, root, groups):
|
||||
for group, xref_exts in groups.items():
|
||||
prefix = 'group{:08d}'.format(group)
|
||||
prefix = f'group{group:08d}'
|
||||
future = executor.submit(
|
||||
jbig2enc.convert_group,
|
||||
cwd=fspath(root),
|
||||
infiles=(img_name(root, xref, ext) for xref, ext in xref_exts),
|
||||
out_prefix=prefix
|
||||
out_prefix=prefix,
|
||||
)
|
||||
yield future
|
||||
|
||||
def jbig2_single_futures(executor, root, groups):
|
||||
for group, xref_exts in groups.items():
|
||||
prefix = 'group{:08d}'.format(group)
|
||||
prefix = f'group{group:08d}'
|
||||
# Second loop is to ensure multiple images per page are unpacked
|
||||
for n, xref_ext in enumerate(xref_exts):
|
||||
xref, ext = xref_ext
|
||||
@@ -246,7 +243,7 @@ def _produce_jbig2_images(jbig2_groups, root, log, options):
|
||||
jbig2enc.convert_single,
|
||||
cwd=fspath(root),
|
||||
infile=img_name(root, xref, ext),
|
||||
outfile=root / ('{}.{:04d}'.format(prefix, n))
|
||||
outfile=root / f'{prefix}.{n:04d}',
|
||||
)
|
||||
yield future
|
||||
|
||||
@@ -255,8 +252,7 @@ def _produce_jbig2_images(jbig2_groups, root, log, options):
|
||||
else:
|
||||
jbig2_futures = jbig2_single_futures
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(
|
||||
max_workers=options.jobs) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=options.jobs) as executor:
|
||||
futures = jbig2_futures(executor, root, jbig2_groups)
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
proc = future.result()
|
||||
@@ -280,14 +276,12 @@ def convert_to_jbig2(pike, jbig2_groups, root, log, options):
|
||||
_produce_jbig2_images(jbig2_groups, root, log, options)
|
||||
|
||||
for group, xref_exts in jbig2_groups.items():
|
||||
prefix = 'group{:08d}'.format(group)
|
||||
prefix = f'group{group:08d}'
|
||||
jbig2_symfile = root / (prefix + '.sym')
|
||||
if jbig2_symfile.exists():
|
||||
jbig2_globals_data = jbig2_symfile.read_bytes()
|
||||
jbig2_globals = pikepdf.Stream(pike, jbig2_globals_data)
|
||||
jbig2_globals_dict = pikepdf.Dictionary({
|
||||
'/JBIG2Globals': jbig2_globals
|
||||
})
|
||||
jbig2_globals_dict = pikepdf.Dictionary({'/JBIG2Globals': jbig2_globals})
|
||||
elif options.jbig2_page_group_size == 1:
|
||||
jbig2_globals_dict = None
|
||||
else:
|
||||
@@ -295,13 +289,13 @@ def convert_to_jbig2(pike, jbig2_groups, root, log, options):
|
||||
|
||||
for n, xref_ext in enumerate(xref_exts):
|
||||
xref, _ = xref_ext
|
||||
jbig2_im_file = root / (prefix + '.{:04d}'.format(n))
|
||||
jbig2_im_file = root / (prefix + f'.{n:04d}')
|
||||
jbig2_im_data = jbig2_im_file.read_bytes()
|
||||
im_obj = pike.get_object(xref, 0)
|
||||
im_obj.write(
|
||||
jbig2_im_data,
|
||||
filter=pikepdf.Name('/JBIG2Decode'),
|
||||
decode_parms=jbig2_globals_dict
|
||||
decode_parms=jbig2_globals_dict,
|
||||
)
|
||||
|
||||
|
||||
@@ -315,9 +309,7 @@ def transcode_jpegs(pike, jpegs, root, log, options):
|
||||
# 'close'. Seems to be mostly harmless
|
||||
# https://github.com/python-pillow/Pillow/issues/1144
|
||||
with Image.open(fspath(in_jpg)) as im:
|
||||
im.save(fspath(opt_jpg),
|
||||
optimize=True,
|
||||
quality=options.jpeg_quality)
|
||||
im.save(fspath(opt_jpg), optimize=True, quality=options.jpeg_quality)
|
||||
# pylint: disable=no-member
|
||||
if opt_jpg.stat().st_size > in_jpg.stat().st_size:
|
||||
log.debug("xref %s, jpeg, made larger - skip", xref)
|
||||
@@ -325,24 +317,26 @@ def transcode_jpegs(pike, jpegs, root, log, options):
|
||||
|
||||
compdata = leptonica.CompressedData.open(opt_jpg)
|
||||
im_obj = pike.get_object(xref, 0)
|
||||
im_obj.write(
|
||||
compdata.read(), filter=pikepdf.Name('/DCTDecode')
|
||||
)
|
||||
im_obj.write(compdata.read(), filter=pikepdf.Name('/DCTDecode'))
|
||||
|
||||
|
||||
def transcode_pngs(pike, pngs, root, log, options):
|
||||
if options.optimize >= 2:
|
||||
png_quality = (
|
||||
max(10, options.png_quality - 10),
|
||||
min(100, options.png_quality + 10)
|
||||
min(100, options.png_quality + 10),
|
||||
)
|
||||
with concurrent.futures.ThreadPoolExecutor(
|
||||
max_workers=options.jobs) as executor:
|
||||
max_workers=options.jobs
|
||||
) as executor:
|
||||
for xref in pngs:
|
||||
executor.submit(
|
||||
pngquant.quantize,
|
||||
png_name(root, xref), png_name(root, xref),
|
||||
png_quality[0], png_quality[1])
|
||||
png_name(root, xref),
|
||||
png_name(root, xref),
|
||||
png_quality[0],
|
||||
png_quality[1],
|
||||
)
|
||||
|
||||
for xref in pngs:
|
||||
im_obj = pike.get_object(xref, 0)
|
||||
@@ -352,9 +346,7 @@ def transcode_pngs(pike, pngs, root, log, options):
|
||||
pix = leptonica.Pix.open(png_name(root, xref))
|
||||
if pix.depth == 1:
|
||||
pix = pix.invert() # PDF assumes 1 is black for monochrome
|
||||
compdata = pix.generate_pdf_ci_data(
|
||||
leptonica.lept.L_FLATE_ENCODE, 0
|
||||
)
|
||||
compdata = pix.generate_pdf_ci_data(leptonica.lept.L_FLATE_ENCODE, 0)
|
||||
except leptonica.LeptonicaError as e:
|
||||
log.error(e)
|
||||
continue
|
||||
@@ -362,7 +354,7 @@ def transcode_pngs(pike, pngs, root, log, options):
|
||||
# This is what we should be doing: open the compressed data without
|
||||
# transcoding. However this shifts each pixel row by one for some
|
||||
# reason.
|
||||
#compdata = leptonica.CompressedData.open(png_name(root, xref))
|
||||
# compdata = leptonica.CompressedData.open(png_name(root, xref))
|
||||
if len(compdata) > int(im_obj.stream_dict.Length):
|
||||
continue # If we produced a larger image, don't use
|
||||
|
||||
@@ -378,8 +370,12 @@ def transcode_pngs(pike, pngs, root, log, options):
|
||||
palette_pdf_string = compdata.get_palette_pdf_string()
|
||||
palette_data = pikepdf.Object.parse(palette_pdf_string)
|
||||
palette_stream = pikepdf.Stream(pike, bytes(palette_data))
|
||||
palette = [pikepdf.Name('/Indexed'), pikepdf.Name('/DeviceRGB'),
|
||||
compdata.ncolors - 1, palette_stream]
|
||||
palette = [
|
||||
pikepdf.Name('/Indexed'),
|
||||
pikepdf.Name('/DeviceRGB'),
|
||||
compdata.ncolors - 1,
|
||||
palette_stream,
|
||||
]
|
||||
cs = palette
|
||||
else:
|
||||
if compdata.spp == 1:
|
||||
@@ -390,16 +386,11 @@ def transcode_pngs(pike, pngs, root, log, options):
|
||||
cs = pikepdf.Name('/DeviceCMYK')
|
||||
im_obj.ColorSpace = cs
|
||||
im_obj.write(
|
||||
compdata.read(),
|
||||
filter=pikepdf.Name('/FlateDecode'), decode_parms=predictor
|
||||
compdata.read(), filter=pikepdf.Name('/FlateDecode'), decode_parms=predictor
|
||||
)
|
||||
|
||||
|
||||
def optimize(
|
||||
input_file,
|
||||
output_file,
|
||||
log,
|
||||
context):
|
||||
def optimize(input_file, output_file, log, context):
|
||||
|
||||
options = context.get_options()
|
||||
if options.optimize == 0:
|
||||
@@ -407,14 +398,11 @@ def optimize(
|
||||
return
|
||||
|
||||
if options.jpeg_quality == 0:
|
||||
options.jpeg_quality = \
|
||||
DEFAULT_JPEG_QUALITY if options.optimize < 3 else 40
|
||||
options.jpeg_quality = DEFAULT_JPEG_QUALITY if options.optimize < 3 else 40
|
||||
if options.png_quality == 0:
|
||||
options.png_quality = \
|
||||
DEFAULT_PNG_QUALITY if options.optimize < 3 else 30
|
||||
options.png_quality = DEFAULT_PNG_QUALITY if options.optimize < 3 else 30
|
||||
if options.jbig2_page_group_size == 0:
|
||||
options.jbig2_page_group_size = \
|
||||
10 if options.jbig2_lossy else 1
|
||||
options.jbig2_page_group_size = 10 if options.jbig2_lossy else 1
|
||||
|
||||
pike = pikepdf.Pdf.open(input_file)
|
||||
|
||||
@@ -430,15 +418,17 @@ def optimize(
|
||||
|
||||
target_file = Path(output_file).with_suffix('.opt.pdf')
|
||||
pike.remove_unreferenced_resources()
|
||||
pike.save(target_file, preserve_pdfa=True,
|
||||
object_stream_mode=pikepdf.ObjectStreamMode.generate)
|
||||
pike.save(
|
||||
target_file,
|
||||
preserve_pdfa=True,
|
||||
object_stream_mode=pikepdf.ObjectStreamMode.generate,
|
||||
)
|
||||
|
||||
input_size = Path(input_file).stat().st_size
|
||||
output_size = Path(target_file).stat().st_size
|
||||
ratio = input_size / output_size
|
||||
savings = 1 - output_size / input_size
|
||||
log.info("Optimize ratio: {:.2f} savings: {:.1f}%".format(
|
||||
ratio, 100 * savings))
|
||||
log.info(f"Optimize ratio: {ratio:.2f} savings: {(100 * savings):.1f}%")
|
||||
|
||||
if savings < 0:
|
||||
log.info("Optimize did not improve the file - discarded")
|
||||
@@ -454,8 +444,7 @@ def main(infile, outfile, level, jobs=1):
|
||||
class OptimizeOptions:
|
||||
"""Emulate ocrmypdf's options"""
|
||||
|
||||
def __init__(
|
||||
self, jobs, optimize, jpeg_quality, png_quality, jb2lossy):
|
||||
def __init__(self, jobs, optimize, jpeg_quality, png_quality, jb2lossy):
|
||||
self.jobs = jobs
|
||||
self.optimize = optimize
|
||||
self.jpeg_quality = jpeg_quality
|
||||
@@ -472,7 +461,7 @@ def main(infile, outfile, level, jobs=1):
|
||||
optimize=int(level),
|
||||
jpeg_quality=0, # Use default
|
||||
png_quality=0,
|
||||
jb2lossy=False
|
||||
jb2lossy=False,
|
||||
)
|
||||
ctx.set_options(options)
|
||||
|
||||
|
||||
+25
-93
@@ -31,26 +31,18 @@ Ghostscript's handling of pdfmark.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from binascii import hexlify
|
||||
from pathlib import Path
|
||||
from string import Template
|
||||
|
||||
import pkg_resources
|
||||
import os
|
||||
|
||||
import pikepdf
|
||||
|
||||
from pikepdf.models.metadata import (
|
||||
encode_pdf_date as _encode_date,
|
||||
decode_pdf_date as _decode_date
|
||||
)
|
||||
|
||||
from .helpers import deprecated
|
||||
|
||||
|
||||
ICC_PROFILE_RELPATH = 'data/sRGB.icc'
|
||||
|
||||
SRGB_ICC_PROFILE = pkg_resources.resource_filename(
|
||||
'ocrmypdf', ICC_PROFILE_RELPATH)
|
||||
SRGB_ICC_PROFILE = pkg_resources.resource_filename('ocrmypdf', ICC_PROFILE_RELPATH)
|
||||
|
||||
|
||||
# This is a template written in PostScript which is needed to create PDF/A
|
||||
@@ -91,90 +83,29 @@ def
|
||||
"""
|
||||
|
||||
|
||||
@deprecated
|
||||
def encode_text_string(s: str) -> str:
|
||||
"""
|
||||
Encode text string to hex string for use in a PDF
|
||||
def generate_pdfa_ps(target_filename, icc='sRGB'):
|
||||
"""Create a Postscript pdfmark file for Ghostscript PDF/A conversion
|
||||
|
||||
From PDF 32000-1:2008 a string object may be included in hexademical form
|
||||
if it is enclosed in angle brackets. For general Unicode the string should
|
||||
be UTF-16 (big endian) with byte order marks. Many strings including all
|
||||
ASCII strings could be encoded as PdfDocEncoding literals provided
|
||||
that certain Postscript sequences are escaped. But it's far simpler to
|
||||
encode everything as UTF-16.
|
||||
"""
|
||||
A pdfmark file is a small Postscript program that provides some information
|
||||
Ghostscript needs to perform PDF/A conversion. The only information we put
|
||||
in specifies that we want the file to be a PDF/A, and we want to Ghostscript
|
||||
to convert objects to the sRGB colorspace if it runs into any object that
|
||||
it decides must be converted.
|
||||
|
||||
# Sometimes lazy C programmers leave their NULs at the end of strings they
|
||||
# insert into PDFs
|
||||
# tests/resources/aspect.pdf is one example (created by ImageMagick)
|
||||
s = s.replace('\x00', '')
|
||||
See the Adobe pdfmark Reference for details:
|
||||
https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdfmark_reference.pdf
|
||||
|
||||
if s == '':
|
||||
return ''
|
||||
|
||||
utf16_bytes = s.encode('utf-16be')
|
||||
ascii_hex_bytes = hexlify(b'\xfe\xff' + utf16_bytes)
|
||||
ascii_hex_str = ascii_hex_bytes.decode('ascii').lower()
|
||||
return ascii_hex_str
|
||||
|
||||
|
||||
def _encode_ascii(s: str) -> str:
|
||||
"""
|
||||
Aggressively strip non-ASCII and PDF escape sequences
|
||||
|
||||
Ghostscript 9.24+ lost support for UTF-16BE in pdfmark files for reasons
|
||||
given in GhostPDL commit e997c683. Our temporary workaround is use ASCII
|
||||
and drop all non-ASCII characters. A slightly improved alternative would
|
||||
be to implement PdfDocEncoding in pikepdf and encode to that, or handle
|
||||
metadata there.
|
||||
"""
|
||||
trans = str.maketrans({
|
||||
'(': '',
|
||||
')': '',
|
||||
'\\': '',
|
||||
'\0': ''
|
||||
})
|
||||
return s.translate(trans).encode('ascii', errors='replace').decode()
|
||||
|
||||
|
||||
@deprecated
|
||||
def encode_pdf_date(*args, **kwargs):
|
||||
return _encode_date(*args, **kwargs)
|
||||
|
||||
|
||||
@deprecated
|
||||
def decode_pdf_date(*args, **kwargs):
|
||||
return _decode_date(*args, **kwargs)
|
||||
|
||||
|
||||
def _get_pdfa_def(icc_profile, icc_identifier, pdfmark=None, ascii_docinfo=None):
|
||||
"""
|
||||
Create a Postscript pdfmark file for Ghostscript.
|
||||
|
||||
pdfmark contains the various objects as strings; these must be encoded in
|
||||
ASCII, and dates have a special format.
|
||||
|
||||
:param icc_profile: filename of the ICC profile to include in pdfmark
|
||||
:param icc_identifier: ICC identifier such as 'sRGB'
|
||||
:param pdfmark: a dictionary containing keys to include the pdfmark
|
||||
:param ascii_docinfo: parameter is no longer meaningful
|
||||
:param target_filename: filename to save
|
||||
:param icc: ICC identifier such as 'sRGB'
|
||||
|
||||
:returns: a string containing the entire pdfmark
|
||||
"""
|
||||
|
||||
t = Template(pdfa_def_template)
|
||||
result = t.substitute(icc_profile=icc_profile,
|
||||
icc_identifier=icc_identifier)
|
||||
return result
|
||||
|
||||
|
||||
def generate_pdfa_ps(target_filename, pdfmark=None, icc='sRGB', ascii_docinfo=None):
|
||||
if icc == 'sRGB':
|
||||
icc_profile = SRGB_ICC_PROFILE
|
||||
else:
|
||||
raise NotImplementedError("Only supporting sRGB")
|
||||
|
||||
# pdfmark must contain the full path to the ICC profile, and pdfmark must
|
||||
# pdfmark must contain the full path to the ICC profile, and pdfmark must be
|
||||
# also encoded in ASCII. ocrmypdf can be installed anywhere, including to
|
||||
# paths that have a non-ASCII character in the filename. Ghostscript
|
||||
# accepts hex-encoded strings and converts them to byte strings, so
|
||||
@@ -185,7 +116,8 @@ def generate_pdfa_ps(target_filename, pdfmark=None, icc='sRGB', ascii_docinfo=No
|
||||
hex_icc_profile = hexlify(bytes_icc_profile)
|
||||
icc_profile = '<' + hex_icc_profile.decode('ascii') + '>'
|
||||
|
||||
ps = _get_pdfa_def(icc_profile, icc, pdfmark)
|
||||
t = Template(pdfa_def_template)
|
||||
ps = t.substitute(icc_profile=icc_profile, icc_identifier=icc)
|
||||
|
||||
# We should have encoded everything to pure ASCII by this point, and
|
||||
# to be safe, only allow ASCII in PostScript
|
||||
@@ -195,20 +127,20 @@ def generate_pdfa_ps(target_filename, pdfmark=None, icc='sRGB', ascii_docinfo=No
|
||||
def file_claims_pdfa(filename):
|
||||
"""Determines if the file claims to be PDF/A compliant
|
||||
|
||||
Checking if a file is a truly compliant PDF/A is a massive undertaking
|
||||
that no open source tool does properly. Some commercial tools are
|
||||
generally reliable (Acrobat).
|
||||
|
||||
This checks if the XMP metadata contains a PDF/A marker.
|
||||
This only checks if the XMP metadata contains a PDF/A marker. It does not
|
||||
do full PDF/A validation.
|
||||
"""
|
||||
|
||||
pdf = pikepdf.open(filename)
|
||||
pdfmeta = pdf.open_metadata()
|
||||
if not pdfmeta.pdfa_status:
|
||||
return {'pass': False, 'output': 'pdf',
|
||||
'conformance': 'No PDF/A metadata in XMP'}
|
||||
return {
|
||||
'pass': False,
|
||||
'output': 'pdf',
|
||||
'conformance': 'No PDF/A metadata in XMP',
|
||||
}
|
||||
valid_part_conforms = {'1A', '1B', '2A', '2B', '2U', '3A', '3B', '3U'}
|
||||
conformance = 'PDF/A-{}'.format(pdfmeta.pdfa_status)
|
||||
conformance = f'PDF/A-{pdfmeta.pdfa_status}'
|
||||
pdfa_dict = {}
|
||||
if pdfmeta.pdfa_status in valid_part_conforms:
|
||||
pdfa_dict['pass'] = True
|
||||
|
||||
@@ -20,6 +20,7 @@ from collections import namedtuple
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
from math import hypot, isclose
|
||||
from os import fspath
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
from warnings import warn
|
||||
@@ -29,18 +30,15 @@ from pikepdf import PdfMatrix
|
||||
import pikepdf
|
||||
|
||||
from . import ghosttext
|
||||
from .layout import get_page_analysis, get_text_boxes
|
||||
|
||||
from ..exceptions import EncryptedPdfError
|
||||
from ..helpers import fspath
|
||||
from ..exceptions import EncryptedPdfError, MissingDependencyError
|
||||
|
||||
|
||||
Colorspace = Enum('Colorspace',
|
||||
'gray rgb cmyk lab icc index sep devn pattern jpeg2000')
|
||||
Colorspace = Enum('Colorspace', 'gray rgb cmyk lab icc index sep devn pattern jpeg2000')
|
||||
|
||||
Encoding = Enum('Encoding',
|
||||
'ccitt jpeg jpeg2000 jbig2 asciihex ascii85 lzw flate ' + \
|
||||
'runlength')
|
||||
Encoding = Enum(
|
||||
'Encoding', 'ccitt jpeg jpeg2000 jbig2 asciihex ascii85 lzw flate ' + 'runlength'
|
||||
)
|
||||
|
||||
FRIENDLY_COLORSPACE = {
|
||||
'/DeviceGray': Colorspace.gray,
|
||||
@@ -71,7 +69,7 @@ FRIENDLY_ENCODING = {
|
||||
'/A85': Encoding.ascii85,
|
||||
'/LZW': Encoding.lzw,
|
||||
'/Fl': Encoding.flate,
|
||||
'/RL': Encoding.runlength
|
||||
'/RL': Encoding.runlength,
|
||||
}
|
||||
|
||||
FRIENDLY_COMP = {
|
||||
@@ -79,28 +77,28 @@ FRIENDLY_COMP = {
|
||||
Colorspace.rgb: 3,
|
||||
Colorspace.cmyk: 4,
|
||||
Colorspace.lab: 3,
|
||||
Colorspace.index: 1
|
||||
Colorspace.index: 1,
|
||||
}
|
||||
|
||||
|
||||
UNIT_SQUARE = (1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
|
||||
|
||||
|
||||
def _is_unit_square(shorthand):
|
||||
values = map(float, shorthand)
|
||||
pairwise = zip(values, UNIT_SQUARE)
|
||||
return all([isclose(a, b, rel_tol=1e-3) for a, b in pairwise])
|
||||
|
||||
XobjectSettings = namedtuple('XobjectSettings',
|
||||
['name', 'shorthand', 'stack_depth'])
|
||||
|
||||
InlineSettings = namedtuple('InlineSettings',
|
||||
['iimage', 'shorthand', 'stack_depth'])
|
||||
XobjectSettings = namedtuple('XobjectSettings', ['name', 'shorthand', 'stack_depth'])
|
||||
|
||||
ContentsInfo = namedtuple('ContentsInfo',
|
||||
['xobject_settings', 'inline_images', 'found_vector'])
|
||||
InlineSettings = namedtuple('InlineSettings', ['iimage', 'shorthand', 'stack_depth'])
|
||||
|
||||
TextboxInfo = namedtuple('TextboxInfo',
|
||||
['bbox', 'is_visible', 'is_corrupt'])
|
||||
ContentsInfo = namedtuple(
|
||||
'ContentsInfo', ['xobject_settings', 'inline_images', 'found_vector']
|
||||
)
|
||||
|
||||
TextboxInfo = namedtuple('TextboxInfo', ['bbox', 'is_visible', 'is_corrupt'])
|
||||
|
||||
|
||||
class VectorInfo:
|
||||
@@ -112,9 +110,9 @@ def _normalize_stack(graphobjs):
|
||||
"""Convert runs of qQ's in the stack into single graphobjs"""
|
||||
for operands, operator in graphobjs:
|
||||
operator = str(operator)
|
||||
if re.match(r'Q*q+$', operator): # Zero or more Q, one or more q
|
||||
for char in operator: # Split into individual
|
||||
yield ([], char) # Yield individual
|
||||
if re.match(r'Q*q+$', operator): # Zero or more Q, one or more q
|
||||
for char in operator: # Split into individual
|
||||
yield ([], char) # Yield individual
|
||||
else:
|
||||
yield (operands, operator)
|
||||
|
||||
@@ -155,15 +153,19 @@ def _interpret_contents(contentstream, initial_shorthand=UNIT_SQUARE):
|
||||
image_ops = set('BI ID EI q Q Do cm'.split())
|
||||
operator_whitelist = ' '.join(vector_ops | image_ops)
|
||||
|
||||
for n, graphobj in enumerate(_normalize_stack(
|
||||
pikepdf.parse_content_stream(contentstream, operator_whitelist))):
|
||||
for n, graphobj in enumerate(
|
||||
_normalize_stack(
|
||||
pikepdf.parse_content_stream(contentstream, operator_whitelist)
|
||||
)
|
||||
):
|
||||
operands, operator = graphobj
|
||||
if operator == 'q':
|
||||
stack.append(ctm)
|
||||
if len(stack) > 32: # See docstring
|
||||
if len(stack) > 128:
|
||||
raise RuntimeError(
|
||||
"PDF graphics stack overflowed hard limit, operator %i" % n)
|
||||
"PDF graphics stack overflowed hard limit, operator %i" % n
|
||||
)
|
||||
warn("PDF graphics stack overflowed spec limit")
|
||||
elif operator == 'Q':
|
||||
try:
|
||||
@@ -177,14 +179,14 @@ def _interpret_contents(contentstream, initial_shorthand=UNIT_SQUARE):
|
||||
elif operator == 'Do':
|
||||
image_name = operands[0]
|
||||
settings = XobjectSettings(
|
||||
name=image_name, shorthand=ctm.shorthand,
|
||||
stack_depth=len(stack))
|
||||
name=image_name, shorthand=ctm.shorthand, stack_depth=len(stack)
|
||||
)
|
||||
xobject_settings.append(settings)
|
||||
elif operator == 'INLINE IMAGE': # BI/ID/EI are grouped into this
|
||||
elif operator == 'INLINE IMAGE': # BI/ID/EI are grouped into this
|
||||
iimage = operands[0]
|
||||
inline = InlineSettings(
|
||||
iimage=iimage, shorthand=ctm.shorthand,
|
||||
stack_depth=len(stack))
|
||||
iimage=iimage, shorthand=ctm.shorthand, stack_depth=len(stack)
|
||||
)
|
||||
inline_images.append(inline)
|
||||
elif operator in vector_ops:
|
||||
found_vector = True
|
||||
@@ -192,7 +194,8 @@ def _interpret_contents(contentstream, initial_shorthand=UNIT_SQUARE):
|
||||
return ContentsInfo(
|
||||
xobject_settings=xobject_settings,
|
||||
inline_images=inline_images,
|
||||
found_vector=found_vector)
|
||||
found_vector=found_vector,
|
||||
)
|
||||
|
||||
|
||||
def _get_dpi(ctm_shorthand, image_size):
|
||||
@@ -262,8 +265,7 @@ def _get_dpi(ctm_shorthand, image_size):
|
||||
class ImageInfo:
|
||||
DPI_PREC = Decimal('1.000')
|
||||
|
||||
def __init__(self, *, name='', pdfimage=None, inline=None,
|
||||
shorthand=None):
|
||||
def __init__(self, *, name='', pdfimage=None, inline=None, shorthand=None):
|
||||
|
||||
self._name = str(name)
|
||||
self._shorthand = shorthand
|
||||
@@ -348,19 +350,24 @@ class ImageInfo:
|
||||
return _get_dpi(self._shorthand, (self._width, self._height))[1]
|
||||
|
||||
def __repr__(self):
|
||||
class_locals = {attr: getattr(self, attr, None) for attr in dir(self)
|
||||
if not attr.startswith('_')}
|
||||
class_locals = {
|
||||
attr: getattr(self, attr, None)
|
||||
for attr in dir(self)
|
||||
if not attr.startswith('_')
|
||||
}
|
||||
return (
|
||||
"<ImageInfo '{name}' {type_} {width}x{height} {color} "
|
||||
"{comp} {bpc} {enc} {xres}x{yres}>").format(**class_locals)
|
||||
"{comp} {bpc} {enc} {xres}x{yres}>"
|
||||
).format(**class_locals)
|
||||
|
||||
|
||||
def _find_inline_images(contentsinfo):
|
||||
"Find inline images in the contentstream"
|
||||
|
||||
for n, inline in enumerate(contentsinfo.inline_images):
|
||||
yield ImageInfo(name='inline-%02d' % n, shorthand=inline.shorthand,
|
||||
inline=inline)
|
||||
yield ImageInfo(
|
||||
name='inline-%02d' % n, shorthand=inline.shorthand, inline=inline
|
||||
)
|
||||
|
||||
|
||||
def _image_xobjects(container):
|
||||
@@ -414,8 +421,7 @@ def _find_regular_images(container, contentsinfo):
|
||||
# these from our DPI calculation for the page.
|
||||
continue
|
||||
|
||||
yield ImageInfo(name=draw.name, pdfimage=pdfimage, shorthand=
|
||||
draw.shorthand)
|
||||
yield ImageInfo(name=draw.name, pdfimage=pdfimage, shorthand=draw.shorthand)
|
||||
|
||||
|
||||
def _find_form_xobject_images(pdf, container, contentsinfo):
|
||||
@@ -446,7 +452,8 @@ def _find_form_xobject_images(pdf, container, contentsinfo):
|
||||
# same object are both very rare.
|
||||
ctm_shorthand = settings.shorthand
|
||||
yield from _process_content_streams(
|
||||
pdf=pdf, container=form_xobject, shorthand=ctm_shorthand)
|
||||
pdf=pdf, container=form_xobject, shorthand=ctm_shorthand
|
||||
)
|
||||
|
||||
|
||||
def _process_content_streams(*, pdf, container, shorthand=None):
|
||||
@@ -470,8 +477,7 @@ def _process_content_streams(*, pdf, container, shorthand=None):
|
||||
|
||||
if container.get('/Type') == '/Page' and '/Contents' in container:
|
||||
initial_shorthand = shorthand or UNIT_SQUARE
|
||||
elif container.get('/Type') == '/XObject' and \
|
||||
container['/Subtype'] == '/Form':
|
||||
elif container.get('/Type') == '/XObject' and container['/Subtype'] == '/Form':
|
||||
# Set the CTM to the state it was when the "Do" operator was
|
||||
# encountered that is drawing this instance of the Form XObject
|
||||
ctm = PdfMatrix(shorthand) if shorthand else PdfMatrix.identity()
|
||||
@@ -505,9 +511,9 @@ def _page_has_text(text_blocks, page_width, page_height):
|
||||
margin_ratio = 0.125
|
||||
interior_bbox = (
|
||||
margin_ratio * pw, # left
|
||||
(1 - margin_ratio) * ph, # top
|
||||
(1 - margin_ratio) * pw, # right
|
||||
margin_ratio * ph # bottom (first quadrant: bottom < top)
|
||||
(1 - margin_ratio) * ph, # top
|
||||
(1 - margin_ratio) * pw, # right
|
||||
margin_ratio * ph, # bottom (first quadrant: bottom < top)
|
||||
)
|
||||
|
||||
def rects_intersect(a, b):
|
||||
@@ -526,17 +532,17 @@ def _page_has_text(text_blocks, page_width, page_height):
|
||||
return has_text
|
||||
|
||||
|
||||
def simplify_textboxes(miner):
|
||||
def simplify_textboxes(miner, textbox_getter):
|
||||
"""Extract only limited content from text boxes
|
||||
|
||||
We do this to save memory and ensure that our objects are pickleable.
|
||||
"""
|
||||
for box in get_text_boxes(miner):
|
||||
for box in textbox_getter(miner):
|
||||
first_line = box._objs[0]
|
||||
first_char = first_line._objs[0]
|
||||
|
||||
visible = (first_char.rendermode != 3)
|
||||
corrupt = (first_char.get_text() == '\ufffd')
|
||||
visible = first_char.rendermode != 3
|
||||
corrupt = first_char.get_text() == '\ufffd'
|
||||
yield TextboxInfo(box.bbox, visible, corrupt)
|
||||
|
||||
|
||||
@@ -552,17 +558,24 @@ def _pdf_get_pageinfo(pdf, pageno: int, infile, xmltext):
|
||||
|
||||
if xmltext is not None:
|
||||
bboxes = ghosttext.page_get_textblocks(
|
||||
fspath(infile), pageno, xmltext=xmltext, height=height_pt)
|
||||
fspath(infile), pageno, xmltext=xmltext, height=height_pt
|
||||
)
|
||||
pageinfo['bboxes'] = bboxes
|
||||
else:
|
||||
# pdfminer required for this section
|
||||
try:
|
||||
from .layout import get_page_analysis, get_text_boxes
|
||||
except ImportError:
|
||||
raise MissingDependencyError(
|
||||
"pdfminer is required for this feature. Your distribution "
|
||||
"may not have installed it."
|
||||
)
|
||||
pscript5_mode = str(pdf.docinfo.get('/Creator')).startswith('PScript5')
|
||||
miner = get_page_analysis(infile, pageno, pscript5_mode)
|
||||
pageinfo['textboxes'] = list(simplify_textboxes(miner))
|
||||
pageinfo['textboxes'] = list(simplify_textboxes(miner, get_text_boxes))
|
||||
bboxes = (box.bbox for box in pageinfo['textboxes'])
|
||||
|
||||
pageinfo['has_text'] = _page_has_text(
|
||||
bboxes, width_pt, height_pt
|
||||
)
|
||||
pageinfo['has_text'] = _page_has_text(bboxes, width_pt, height_pt)
|
||||
|
||||
userunit = page.get('/UserUnit', Decimal(1.0))
|
||||
if not isinstance(userunit, Decimal):
|
||||
@@ -577,24 +590,24 @@ def _pdf_get_pageinfo(pdf, pageno: int, infile, xmltext):
|
||||
pageinfo['rotate'] = 0
|
||||
|
||||
userunit_shorthand = (userunit, 0, 0, userunit, 0, 0)
|
||||
contentsinfo = [ci for ci in
|
||||
_process_content_streams(pdf=pdf, container=page,
|
||||
shorthand=userunit_shorthand)]
|
||||
contentsinfo = [
|
||||
ci
|
||||
for ci in _process_content_streams(
|
||||
pdf=pdf, container=page, shorthand=userunit_shorthand
|
||||
)
|
||||
]
|
||||
|
||||
pageinfo['has_vector'] = False
|
||||
if any(isinstance(ci, VectorInfo) for ci in contentsinfo):
|
||||
pageinfo['has_vector'] = True
|
||||
|
||||
pageinfo['images'] = [im for im in contentsinfo
|
||||
if isinstance(im, ImageInfo)]
|
||||
pageinfo['images'] = [im for im in contentsinfo if isinstance(im, ImageInfo)]
|
||||
if pageinfo['images']:
|
||||
xres = Decimal(max(image.xres for image in pageinfo['images']))
|
||||
yres = Decimal(max(image.yres for image in pageinfo['images']))
|
||||
pageinfo['xres'], pageinfo['yres'] = xres, yres
|
||||
pageinfo['width_pixels'] = \
|
||||
int(round(xres * pageinfo['width_inches']))
|
||||
pageinfo['height_pixels'] = \
|
||||
int(round(yres * pageinfo['height_inches']))
|
||||
pageinfo['width_pixels'] = int(round(xres * pageinfo['width_inches']))
|
||||
pageinfo['height_pixels'] = int(round(yres * pageinfo['height_inches']))
|
||||
|
||||
return pageinfo
|
||||
|
||||
@@ -689,13 +702,14 @@ class PageInfo:
|
||||
|
||||
if 'textboxes' not in self._pageinfo:
|
||||
if visible is not None and corrupt is not None:
|
||||
raise NotImplementedError(
|
||||
'Ghostscript textboxes cannot be classified')
|
||||
raise NotImplementedError('Ghostscript textboxes cannot be classified')
|
||||
return self._pageinfo['bboxes']
|
||||
|
||||
return (obj.bbox for obj in self._pageinfo['textboxes']
|
||||
if predicate(obj, visible, corrupt))
|
||||
|
||||
return (
|
||||
obj.bbox
|
||||
for obj in self._pageinfo['textboxes']
|
||||
if predicate(obj, visible, corrupt)
|
||||
)
|
||||
|
||||
@property
|
||||
def xres(self):
|
||||
@@ -718,11 +732,15 @@ class PageInfo:
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
'<PageInfo '
|
||||
'pageno={} {}"x{}" rotation={} res={}x{} has_text={}>').format(
|
||||
self.pageno, self.width_inches, self.height_inches,
|
||||
'<PageInfo ' 'pageno={} {}"x{}" rotation={} res={}x{} has_text={}>'
|
||||
).format(
|
||||
self.pageno,
|
||||
self.width_inches,
|
||||
self.height_inches,
|
||||
self.rotation,
|
||||
self.xres, self.yres, self.has_text
|
||||
self.xres,
|
||||
self.yres,
|
||||
self.has_text,
|
||||
)
|
||||
|
||||
|
||||
@@ -732,7 +750,8 @@ class PdfInfo:
|
||||
def __init__(self, infile, detailed_page_analysis=False, log=None):
|
||||
self._infile = infile
|
||||
self._pages, pdf = _pdf_get_all_pageinfo(
|
||||
infile, detailed_page_analysis, log=log)
|
||||
infile, detailed_page_analysis, log=log
|
||||
)
|
||||
self._needs_rendering = pdf.root.get('/NeedsRendering', False)
|
||||
self._has_acroform = '/AcroForm' in pdf.root
|
||||
|
||||
@@ -770,15 +789,18 @@ class PdfInfo:
|
||||
return len(self._pages)
|
||||
|
||||
def __repr__(self):
|
||||
return "<PdfInfo('...'), page count={}>".format(len(self))
|
||||
return f"<PdfInfo('...'), page count={len(self)}>"
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('infile')
|
||||
args = parser.parse_args()
|
||||
info = _pdf_get_all_pageinfo(args.infile)
|
||||
from pprint import pprint
|
||||
|
||||
pprint(info)
|
||||
|
||||
|
||||
|
||||
@@ -23,13 +23,16 @@ from ..exec import ghostscript
|
||||
# Forgive me for I have sinned
|
||||
# I am using regular expressions to parse XML. However the XML in this case,
|
||||
# generated by Ghostscript, is self-consistent enough to be parseable.
|
||||
regex_remove_char_tags = re.compile(br"""
|
||||
regex_remove_char_tags = re.compile(
|
||||
br"""
|
||||
<char\b
|
||||
(?: [^>] # anything single character but >
|
||||
| \">\" # special case: trap ">"
|
||||
)*
|
||||
/> # terminate with '/>'
|
||||
""", re.VERBOSE)
|
||||
""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
|
||||
def page_get_textblocks(infile, pageno, xmltext, height):
|
||||
@@ -76,15 +79,14 @@ def extract_text_xml(infile, pdf, pageno=None, log=None):
|
||||
existing_text = regex_remove_char_tags.sub(b' ', existing_text)
|
||||
|
||||
try:
|
||||
root = ET.fromstringlist([
|
||||
b'<document>\n', existing_text, b'</document>\n'
|
||||
])
|
||||
root = ET.fromstringlist([b'<document>\n', existing_text, b'</document>\n'])
|
||||
page_xml = root.findall('page')
|
||||
except ET.ParseError as e:
|
||||
log.error(
|
||||
"An error occurred while attempting to retrieve existing text in "
|
||||
"the input file. Will attempt to continue assuming that there is "
|
||||
"no existing text in the file. The error was:")
|
||||
"no existing text in the file. The error was:"
|
||||
)
|
||||
log.error(e)
|
||||
page_xml = [None] * len(pdf.pages)
|
||||
|
||||
|
||||
@@ -25,13 +25,11 @@ import pdfminer.pdfdevice
|
||||
import pdfminer.pdfinterp
|
||||
from pdfminer.converter import PDFLayoutAnalyzer
|
||||
from pdfminer.glyphlist import glyphname2unicode
|
||||
from pdfminer.layout import (LAParams, LTChar, LTContainer, LTLayoutContainer,
|
||||
LTPage, LTTextBox, LTTextLine)
|
||||
from pdfminer.layout import LAParams, LTChar, LTPage, LTTextBox
|
||||
from pdfminer.pdfdocument import PDFTextExtractionNotAllowed
|
||||
from pdfminer.pdffont import (PDFCIDFont, PDFFont, PDFType3Font,
|
||||
PDFUnicodeNotDefined, PDFSimpleFont)
|
||||
from pdfminer.pdffont import PDFFont, PDFSimpleFont, PDFUnicodeNotDefined
|
||||
from pdfminer.pdfpage import PDFPage
|
||||
from pdfminer.utils import bbox2str, fsplit, matrix2str
|
||||
from pdfminer.utils import bbox2str, matrix2str
|
||||
|
||||
from ..exceptions import EncryptedPdfError
|
||||
|
||||
@@ -41,6 +39,7 @@ STRIP_NAME = re.compile(r'[0-9]+')
|
||||
# Unconditional pdfminer patches
|
||||
#
|
||||
|
||||
|
||||
def name2unicode(name):
|
||||
"""Fix pdfminer's name2unicode function
|
||||
|
||||
@@ -62,9 +61,13 @@ def name2unicode(name):
|
||||
if not m:
|
||||
raise KeyError(name)
|
||||
return chr(int(m.group(0)))
|
||||
|
||||
|
||||
pdfminer.encodingdb.name2unicode = name2unicode
|
||||
|
||||
original_PDFFont_init = PDFFont.__init__
|
||||
|
||||
|
||||
def PDFFont__init__(self, descriptor, widths, default_width=None):
|
||||
original_PDFFont_init(self, descriptor, widths, default_width)
|
||||
# PDF spec says descent should be negative
|
||||
@@ -74,9 +77,13 @@ def PDFFont__init__(self, descriptor, widths, default_width=None):
|
||||
# to misposition text.
|
||||
if self.descent > 0:
|
||||
self.descent = -self.descent
|
||||
|
||||
|
||||
PDFFont.__init__ = PDFFont__init__
|
||||
|
||||
original_PDFSimpleFont_init = PDFSimpleFont.__init__
|
||||
|
||||
|
||||
def PDFSimpleFont__init__(self, descriptor, widths, spec):
|
||||
# Font encoding is specified either by a name of
|
||||
# built-in encoding or a dictionary that describes
|
||||
@@ -87,20 +94,25 @@ def PDFSimpleFont__init__(self, descriptor, widths, spec):
|
||||
if not self.unicode_map and 'Encoding' not in spec:
|
||||
self.cid2unicode = {}
|
||||
return
|
||||
|
||||
|
||||
PDFSimpleFont.__init__ = PDFSimpleFont__init__
|
||||
#
|
||||
# pdfminer patches when creator is PScript5.dll
|
||||
#
|
||||
|
||||
|
||||
def PDFType3Font__PScript5_get_height(self):
|
||||
h = self.bbox[3]-self.bbox[1]
|
||||
h = self.bbox[3] - self.bbox[1]
|
||||
if h == 0:
|
||||
h = self.ascent - self.descent
|
||||
return h * copysign(1.0, self.vscale)
|
||||
|
||||
|
||||
def PDFType3Font__PScript5_get_descent(self):
|
||||
return self.descent * copysign(1.0, self.vscale)
|
||||
|
||||
|
||||
def PDFType3Font__PScript5_get_ascent(self):
|
||||
return self.ascent * copysign(1.0, self.vscale)
|
||||
|
||||
@@ -109,14 +121,48 @@ class LTStateAwareChar(LTChar):
|
||||
"""A subclass of LTChar that tracks text render mode at time of drawing"""
|
||||
|
||||
__slots__ = (
|
||||
'rendermode', '_text', 'matrix', 'fontname', 'adv', 'upright', 'size',
|
||||
'width', 'height', 'bbox', 'x0', 'x1', 'y0', 'y1'
|
||||
'rendermode',
|
||||
'_text',
|
||||
'matrix',
|
||||
'fontname',
|
||||
'adv',
|
||||
'upright',
|
||||
'size',
|
||||
'width',
|
||||
'height',
|
||||
'bbox',
|
||||
'x0',
|
||||
'x1',
|
||||
'y0',
|
||||
'y1',
|
||||
)
|
||||
|
||||
def __init__(self, matrix, font, fontsize, scaling, rise, text, textwidth,
|
||||
textdisp, textstate, *args):
|
||||
super().__init__(matrix, font, fontsize, scaling, rise, text, textwidth,
|
||||
textdisp, *args)
|
||||
def __init__(
|
||||
self,
|
||||
matrix,
|
||||
font,
|
||||
fontsize,
|
||||
scaling,
|
||||
rise,
|
||||
text,
|
||||
textwidth,
|
||||
textdisp,
|
||||
ncs,
|
||||
graphicstate,
|
||||
textstate,
|
||||
):
|
||||
super().__init__(
|
||||
matrix,
|
||||
font,
|
||||
fontsize,
|
||||
scaling,
|
||||
rise,
|
||||
text,
|
||||
textwidth,
|
||||
textdisp,
|
||||
ncs,
|
||||
graphicstate,
|
||||
)
|
||||
self.rendermode = textstate.render
|
||||
|
||||
def is_compatible(self, obj):
|
||||
@@ -126,8 +172,7 @@ class LTStateAwareChar(LTChar):
|
||||
- the Unicode mapping is known, and both have the same render mode
|
||||
- the Unicode mapping is unknown but both are part of the same font
|
||||
"""
|
||||
both_unicode_mapped = (isinstance(self._text, str) and
|
||||
isinstance(obj._text, str))
|
||||
both_unicode_mapped = isinstance(self._text, str) and isinstance(obj._text, str)
|
||||
try:
|
||||
if both_unicode_mapped:
|
||||
return self.rendermode == obj.rendermode
|
||||
@@ -143,10 +188,15 @@ class LTStateAwareChar(LTChar):
|
||||
return self._text
|
||||
|
||||
def __repr__(self):
|
||||
return ('<%s %s matrix=%s rendermode=%r font=%r adv=%s text=%r>' %
|
||||
(self.__class__.__name__, bbox2str(self.bbox),
|
||||
matrix2str(self.matrix), self.rendermode, self.fontname, self.adv,
|
||||
self.get_text()))
|
||||
return '<%s %s matrix=%s rendermode=%r font=%r adv=%s text=%r>' % (
|
||||
self.__class__.__name__,
|
||||
bbox2str(self.bbox),
|
||||
matrix2str(self.matrix),
|
||||
self.rendermode,
|
||||
self.fontname,
|
||||
self.adv,
|
||||
self.get_text(),
|
||||
)
|
||||
|
||||
|
||||
class TextPositionTracker(PDFLayoutAnalyzer):
|
||||
@@ -169,11 +219,13 @@ class TextPositionTracker(PDFLayoutAnalyzer):
|
||||
self.pageno += 1
|
||||
self.receive_layout(self.cur_item)
|
||||
|
||||
def render_string(self, textstate, seq, *args):
|
||||
def render_string(self, textstate, seq, ncs, graphicstate):
|
||||
self.textstate = textstate.copy()
|
||||
super().render_string(self.textstate, seq, *args)
|
||||
super().render_string(self.textstate, seq, ncs, graphicstate)
|
||||
|
||||
def render_char(self, matrix, font, fontsize, scaling, rise, cid, *args):
|
||||
def render_char(
|
||||
self, matrix, font, fontsize, scaling, rise, cid, ncs, graphicstate
|
||||
):
|
||||
try:
|
||||
text = font.to_unichr(cid)
|
||||
assert isinstance(text, str), str(type(text))
|
||||
@@ -182,13 +234,23 @@ class TextPositionTracker(PDFLayoutAnalyzer):
|
||||
textwidth = font.char_width(cid)
|
||||
textdisp = font.char_disp(cid)
|
||||
item = LTStateAwareChar(
|
||||
matrix, font, fontsize, scaling, rise, text,
|
||||
textwidth, textdisp, self.textstate, *args)
|
||||
matrix,
|
||||
font,
|
||||
fontsize,
|
||||
scaling,
|
||||
rise,
|
||||
text,
|
||||
textwidth,
|
||||
textdisp,
|
||||
ncs,
|
||||
graphicstate,
|
||||
self.textstate,
|
||||
)
|
||||
self.cur_item.add(item)
|
||||
return item.adv
|
||||
|
||||
def handle_undefined_char(self, font, cid):
|
||||
#log.info('undefined: %r, %r', font, cid)
|
||||
# log.info('undefined: %r, %r', font, cid)
|
||||
return (font.fontname, cid)
|
||||
|
||||
def receive_layout(self, ltpage):
|
||||
@@ -209,7 +271,7 @@ def get_page_analysis(infile, pageno, pscript5_mode):
|
||||
spec=True,
|
||||
get_ascent=PDFType3Font__PScript5_get_ascent,
|
||||
get_descent=PDFType3Font__PScript5_get_descent,
|
||||
get_height=PDFType3Font__PScript5_get_height
|
||||
get_height=PDFType3Font__PScript5_get_height,
|
||||
)
|
||||
patcher.start()
|
||||
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+16
-16
@@ -1,25 +1,25 @@
|
||||
é la Waterman
|
||||
a la Waterman
|
||||
|
||||
h ens linzen
|
||||
4 ons linzen
|
||||
|
||||
3 liter water
|
||||
|
||||
3 mien
|
||||
3 uien
|
||||
|
||||
bloem} hater
|
||||
bloem, boter
|
||||
|
||||
2 kopjes melk
|
||||
|
||||
laurier, kruidnagel, kerrie, gout
|
||||
|
||||
Be linzen wassen en in¢l liter kokend wa-
|
||||
ter 1 dag laten weken. 2 liter water bi'
|
||||
de linzen voegen, gender hat water wagrin
|
||||
ze geweekt zijn af te gieten. De helft Van
|
||||
de mien bakken met laurier en kruiénagal.
|
||||
Alla mien, kerrie en zout bij de linzen
|
||||
voegen. A1135 aan de Rook brengem. Van de
|
||||
bloem mat boter-en melk een papje maken en
|
||||
verder afmaken met de soap. A13 de linzen
|
||||
gaar zijn is de seep klaar.
|
||||
laurier, kruidnagel, kerrie, zout
|
||||
|
||||
De linzgen wassen en in -l liter kokend wa-
|
||||
ter 1 dag laten weken, 2 liter water bij
|
||||
de linzen voegen, zonder het water waarin
|
||||
ze geweekt zijn af te gieten, De helft van
|
||||
de uien bakken met laurier en Kruicdnagel.
|
||||
Alle uien, kerrie en gout bij de linzen
|
||||
voegen, Alles aan de kook brengen,. Van de
|
||||
bloem met boter en melk een papje maken en
|
||||
verder afmaken met de soep, Als de linzen
|
||||
gaar Zijn is de soep klaar.
|
||||
|
||||
Binary file not shown.
+1
-3
@@ -1,3 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Too few characters. Skipping this page
|
||||
OSD: Weak margin (0.00) for 24 blob text block, but using orientation anyway: 0
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
This shnuld be a perfect circle-
|
||||
|
||||
This should be a perfect circle:
|
||||
|
||||
@@ -5,20 +5,27 @@
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name='ocr-system' content='tesseract 3.05.01' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word'/>
|
||||
<meta name='ocr-system' content='tesseract 4.0.0' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word ocrp_wconf'/>
|
||||
</head>
|
||||
<body>
|
||||
<div class='ocr_page' id='page_1' title='image "/var/folders/37/78_114p552q16vv6vmgm5kr00000gn/T/com.github.ocrmypdf.7vjmeixk/000001.ocr.png"; bbox 0 0 1000 800; ppageno 0'>
|
||||
<div class='ocr_page' id='page_1' title='image "/var/folders/37/78_114p552q16vv6vmgm5kr00000gn/T/com.github.ocrmypdf.jz4b2s0s/000001.ocr.png"; bbox 0 0 1000 800; ppageno 0'>
|
||||
<div class='ocr_carea' id='block_1_1' title="bbox 296 96 704 504">
|
||||
<p class='ocr_par' id='par_1_1' lang='eng' title="bbox 296 96 704 504">
|
||||
<span class='ocr_line' id='line_1_1' title="bbox 296 96 704 504; baseline 0 296; x_size 169.33333; x_descenders 42.333332; x_ascenders 42.333336"><span class='ocrx_word' id='word_1_1' title='bbox 296 96 704 504; x_wconf 95'><strong> </strong></span>
|
||||
<span class='ocr_line' id='line_1_1' title="bbox 296 96 704 504; baseline 0 296; x_size 169.33333; x_descenders 42.333332; x_ascenders 42.333336">
|
||||
<span class='ocrx_word' id='word_1_1' title='bbox 296 96 704 504; x_wconf 95'><strong><em> </em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_2' title="bbox 150 592 841 622">
|
||||
<p class='ocr_par' id='par_1_2' lang='eng' title="bbox 150 592 841 622">
|
||||
<span class='ocr_line' id='line_1_2' title="bbox 150 592 841 622; baseline 0 -6; x_size 30; x_descenders 6; x_ascenders 8"><span class='ocrx_word' id='word_1_2' title='bbox 150 592 230 616; x_wconf 85'><strong>This</strong></span> <span class='ocrx_word' id='word_1_3' title='bbox 260 592 384 616; x_wconf 81'>shnuld</span> <span class='ocrx_word' id='word_1_4' title='bbox 413 592 449 616; x_wconf 81'><strong>be</strong></span> <span class='ocrx_word' id='word_1_5' title='bbox 479 600 493 616; x_wconf 85'><em>a</em></span> <span class='ocrx_word' id='word_1_6' title='bbox 523 592 668 622; x_wconf 76'>perfect</span> <span class='ocrx_word' id='word_1_7' title='bbox 698 592 841 616; x_wconf 76'><strong>circle-</strong></span>
|
||||
<span class='ocr_line' id='line_1_2' title="bbox 150 592 841 622; baseline 0 -6; x_size 30; x_descenders 6; x_ascenders 8">
|
||||
<span class='ocrx_word' id='word_1_2' title='bbox 150 592 230 616; x_wconf 96'><strong><em>This</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_3' title='bbox 260 592 384 616; x_wconf 95'><strong><em>should</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_4' title='bbox 413 592 449 616; x_wconf 95'><strong><em>be</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_5' title='bbox 479 600 493 616; x_wconf 95'><strong><em>a</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_6' title='bbox 523 592 668 622; x_wconf 95'><strong><em>perfect</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_7' title='bbox 698 592 841 616; x_wconf 55'><strong><em>circle:</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Too few characters. Skipping this page
|
||||
OSD: Weak margin (0.00) for 24 blob text block, but using orientation anyway: 0
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
This shnuld be a perfect circle-
|
||||
|
||||
This should be a perfect circle:
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
+815
-85
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
+815
-85
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
+815
-85
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
+815
-85
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first‘track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
Page number: 0
|
||||
Orientation in degrees: 0
|
||||
Rotate: 0
|
||||
Orientation confidence: 18.91
|
||||
Orientation confidence: 34.40
|
||||
Script: Latin
|
||||
Script confidence: 0.97
|
||||
Script confidence: 2.90
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
Page number: 0
|
||||
Orientation in degrees: 90
|
||||
Rotate: 270
|
||||
Orientation confidence: 17.21
|
||||
Orientation confidence: 34.53
|
||||
Script: Latin
|
||||
Script confidence: 1.06
|
||||
Script confidence: 3.83
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
Page number: 0
|
||||
Orientation in degrees: 180
|
||||
Rotate: 180
|
||||
Orientation confidence: 14.79
|
||||
Orientation confidence: 31.79
|
||||
Script: Latin
|
||||
Script confidence: 2.87
|
||||
Script confidence: 3.18
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
Page number: 0
|
||||
Orientation in degrees: 270
|
||||
Rotate: 90
|
||||
Orientation confidence: 19.19
|
||||
Orientation confidence: 32.59
|
||||
Script: Latin
|
||||
Script confidence: 0.58
|
||||
Script confidence: 2.85
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+32
-32
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHZ 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
The LinnSequencer
|
||||
32 Track MIDI Sequence Recorder
|
||||
|
||||
The LinnSequencer is a state—of—the-art composition and performance tool for the professional musician. It is
|
||||
The LinnSequencer is a state-of-the-art composition and performance tool for the professional musician. It is
|
||||
|
||||
extremely powerful, yet amazingly simple to learn and use. It’s many remarkable features include:
|
||||
|
||||
0 Operation is similar to multi—track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
¢ Operation is similar to multi-track tape recorder with PLAY, STOP, RECORD, FAST
|
||||
FORWARD, REWIND, and LOCATE controls.
|
||||
|
||||
0 Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
e Each of the 100 sequences contains 32 simultaneous, polyphonic tracks. Each track may
|
||||
be assigned to one of 16 MIDI channels. Simultaneously plays up to 16 polyphonic
|
||||
|
||||
synthesizers !
|
||||
synthesizers!
|
||||
|
||||
0 Ultra—fast 3 1/2 ” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
¢ Ultra-fast 3%” disk drive stores complex songs in seconds and holds over 110,000 notes
|
||||
|
||||
per disk!
|
||||
|
||||
0 One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
0 Exclusive real—time ERASE function makes editing FAST.
|
||||
0 Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
¢ One or all tracks may be TRANSPOSED at the touch of a key.
|
||||
e Exclusive real-time ERASE function makes editing FAST.
|
||||
* Exclusive REPEAT function automatically repeats any held notes at a pre-selected
|
||||
|
||||
rhythmic value.
|
||||
|
||||
0 TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
¢ TIMING CORRECTION works during playback and operates without ‘chopping’ notes.
|
||||
|
||||
0 Optional SMPTE time code synchronization.
|
||||
¢ Optional SMPTE time code synchronization.
|
||||
|
||||
0 Optional remote control.
|
||||
© Optional remote control.
|
||||
|
||||
Recording 3 Sequence
|
||||
Recording a Sequence
|
||||
|
||||
To record a sequence, simply press RECORD and PLAY,
|
||||
then play your MIDI keyboard in time to the Sequencer’s
|
||||
click track. When the sequence loops back around to bar 1,
|
||||
you’ll hear what you played—only all timing errors will be
|
||||
you’ ll hear what you played—only all timing errors will be
|
||||
|
||||
corrected! (Timing correction may be adjusted or defeated).
|
||||
|
||||
Any additional notes played will be added into the track
|
||||
—existing notes are not erased while recording!
|
||||
— existing notes are not erased while recording!
|
||||
|
||||
FAST FORWARD, REWIND, and LOCATE controls
|
||||
may be used at any time to quickly access any location in
|
||||
your sequence for spot—recording. To overdub a new part,
|
||||
select a different track and start recording~while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
your sequence for spot-recording. To overdub a new part,
|
||||
select a different track and start recording—while you
|
||||
record, the first track will play in perfect sync (unless you
|
||||
MUTE it, or SOLO another track). In this way, up to 32
|
||||
tracks may be overdubbed! All MIDI effects are recorded
|
||||
including pitch bend, modulation, velocity, aftertouch,
|
||||
@@ -58,7 +58,7 @@ the note to be erased just before it plays in the sequence—
|
||||
when played back, it will be gone. Notes may also be
|
||||
|
||||
added, erased, or changed using the SINGLE STEP func-
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
tion. To overdub notes at specific points within a sequence,
|
||||
|
||||
Additional Features
|
||||
|
||||
@@ -70,7 +70,7 @@ from one location to another—in the same sequence or a
|
||||
different one. For example, you might insert a copy of the
|
||||
first verse between the second chorus and the bridge.
|
||||
DELETE BARS operates the same way to remove
|
||||
unwanted sections.
|
||||
unwanted sections,
|
||||
|
||||
Creating a Song
|
||||
|
||||
@@ -90,34 +90,34 @@ the LinnSequencer is designed to let you compose, record
|
||||
and edit while devoting your undivided attention to your
|
||||
music. See your Linn dealer today for a demonstration!
|
||||
|
||||
0 Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
* Simple, easy to learn operation—the 32 character LCD display clearly guides you through all operations. If needed, the
|
||||
|
||||
HELP button displays additional explanations.
|
||||
|
||||
0 Non-destructive recording—existing notes are not erased while recording.
|
||||
0 Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
* Non-destructive recording—existing notes are not erased while recording.
|
||||
¢ Two FOOTSWITCH INPUTS may be assigned to remotely control many of the commonly used functions, including
|
||||
|
||||
ERASE, REPEAT, PLAY/STOP, or LOCATE.
|
||||
|
||||
0 Two TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
¢ Iwo TRIGGER OUTPUTS may be programmed to output pulses at any selected note value.
|
||||
|
||||
0 Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
© Will sync to standard LinnDrum or Linn 9000 sync tone.
|
||||
|
||||
' Utilizes ultra high—speed, 8 MHZ 80186 16 bit computer internally for FAST operation.
|
||||
0 TEMPO may be specified in BEATS-PER—MINUTE or FRAMES-PER—BEAT at 24, 25, or 30 frames per second,
|
||||
© Utilizes ultra high-speed, 8 MHz 80186 16 bit computer internally for FAST operation.
|
||||
* TEMPO may be specified in BEATS-PER-MINUTE or FRAMES-PER-BEAT at 24, 25, or 30 frames per second,
|
||||
|
||||
(even drop frame!)
|
||||
|
||||
0 TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
¢ TEMPO may be entered numerically, adjustable in tenths of a Beat-Per-Minute increments, or by tapping quarter notes
|
||||
|
||||
on the TAP TEMPO button.
|
||||
|
||||
0 TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
° Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
¢ TEMPO CHANGES may be programmed into a sequence, with smooth transitions if desired.
|
||||
¢ Any TIME SIGNATURE may be used, and may be changed within a song.
|
||||
|
||||
E1111
|
||||
linn
|
||||
Linn Electronics, Inc.
|
||||
|
||||
18720 Oxnard Street, Tarzana, CA 91356
|
||||
(818) 7088131 T ELEX #298949 LINN UR
|
||||
|
||||
(818) 708-8131 TELEX #298949 LINN UR
|
||||
|
||||
Binary file not shown.
+1
-2
@@ -1,2 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
OSD: Weak margin (6.83) for 47 blob text block, but using orientation anyway: 0
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Multicolor Black
|
||||
Pure Block (K = 100)
|
||||
Pure Black (K = 100}
|
||||
|
||||
Pure Magenta
|
||||
|
||||
Pu re Cya n
|
||||
Pure Cyan
|
||||
|
||||
Pure Yellow
|
||||
|
||||
|
||||
@@ -5,34 +5,47 @@
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name='ocr-system' content='tesseract 3.05.01' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word'/>
|
||||
<meta name='ocr-system' content='tesseract 4.0.0' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word ocrp_wconf'/>
|
||||
</head>
|
||||
<body>
|
||||
<div class='ocr_page' id='page_1' title='image "/var/folders/37/78_114p552q16vv6vmgm5kr00000gn/T/com.github.ocrmypdf.lfruqc8g/000001.ocr.png"; bbox 0 0 900 900; ppageno 0'>
|
||||
<div class='ocr_page' id='page_1' title='image "/var/folders/37/78_114p552q16vv6vmgm5kr00000gn/T/com.github.ocrmypdf.wy7q83pl/000001.ocr.png"; bbox 0 0 900 900; ppageno 0'>
|
||||
<div class='ocr_carea' id='block_1_1' title="bbox 97 87 502 204">
|
||||
<p class='ocr_par' id='par_1_1' lang='eng' title="bbox 97 87 502 204">
|
||||
<span class='ocr_line' id='line_1_1' title="bbox 97 87 399 122; baseline 0 0; x_size 40.714287; x_descenders 5.7142859; x_ascenders 15"><span class='ocrx_word' id='word_1_1' title='bbox 97 87 285 122; x_wconf 75'>Multicolor</span> <span class='ocrx_word' id='word_1_2' title='bbox 302 87 399 122; x_wconf 83'>Black</span>
|
||||
<span class='ocr_line' id='line_1_1' title="bbox 97 87 399 122; baseline 0 0; x_size 40.714287; x_descenders 5.7142859; x_ascenders 15">
|
||||
<span class='ocrx_word' id='word_1_1' title='bbox 97 87 285 122; x_wconf 95'><strong><em>Multicolor</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_2' title='bbox 302 87 399 122; x_wconf 96'><strong><em>Black</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_2' title="bbox 114 160 502 204; baseline 0 -9; x_size 44; x_descenders 9; x_ascenders 15"><span class='ocrx_word' id='word_1_3' title='bbox 114 163 191 195; x_wconf 91'>Pure</span> <span class='ocrx_word' id='word_1_4' title='bbox 210 160 308 195; x_wconf 81'>Block</span> <span class='ocrx_word' id='word_1_5' title='bbox 325 160 363 204; x_wconf 88'>(K</span> <span class='ocrx_word' id='word_1_6' title='bbox 378 174 400 183; x_wconf 96'><strong>=</strong></span> <span class='ocrx_word' id='word_1_7' title='bbox 421 160 502 204; x_wconf 77'>100)</span>
|
||||
<span class='ocr_line' id='line_1_2' title="bbox 114 160 502 204; baseline 0 -9; x_size 44; x_descenders 9; x_ascenders 15">
|
||||
<span class='ocrx_word' id='word_1_3' title='bbox 114 163 191 195; x_wconf 96'><strong><em>Pure</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_4' title='bbox 210 160 308 195; x_wconf 93'><strong><em>Black</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_5' title='bbox 325 160 363 204; x_wconf 93'><strong><em>(K</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_6' title='bbox 378 174 400 183; x_wconf 96'><strong><em>=</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_7' title='bbox 421 160 502 204; x_wconf 70'><strong><em>100}</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_2' title="bbox 121 282 383 326">
|
||||
<p class='ocr_par' id='par_1_2' lang='eng' title="bbox 121 282 383 326">
|
||||
<span class='ocr_line' id='line_1_3' title="bbox 121 282 383 326; baseline 0 -11; x_size 44; x_descenders 11; x_ascenders 13"><span class='ocrx_word' id='word_1_8' title='bbox 121 283 199 315; x_wconf 91'>Pure</span> <span class='ocrx_word' id='word_1_9' title='bbox 216 282 383 326; x_wconf 75'>Magenta</span>
|
||||
<span class='ocr_line' id='line_1_3' title="bbox 121 282 383 326; baseline 0 -11; x_size 44; x_descenders 11; x_ascenders 13">
|
||||
<span class='ocrx_word' id='word_1_8' title='bbox 121 283 199 315; x_wconf 96'><strong><em>Pure</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_9' title='bbox 216 282 383 326; x_wconf 96'><strong><em>Magenta</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_3' title="bbox 140 375 329 418">
|
||||
<p class='ocr_par' id='par_1_3' lang='eng' title="bbox 140 375 329 418">
|
||||
<span class='ocr_line' id='line_1_4' title="bbox 140 375 329 418; baseline 0 -11; x_size 43; x_descenders 11; x_ascenders 12"><span class='ocrx_word' id='word_1_10' title='bbox 140 375 178 407; x_wconf 94'>Pu</span> <span class='ocrx_word' id='word_1_11' title='bbox 184 387 218 407; x_wconf 90'>re</span> <span class='ocrx_word' id='word_1_12' title='bbox 234 375 306 418; x_wconf 85'>Cya</span> <span class='ocrx_word' id='word_1_13' title='bbox 312 387 329 407; x_wconf 94'>n</span>
|
||||
<span class='ocr_line' id='line_1_4' title="bbox 140 375 329 418; baseline 0 -11; x_size 43; x_descenders 11; x_ascenders 12">
|
||||
<span class='ocrx_word' id='word_1_10' title='bbox 140 375 218 407; x_wconf 96'><strong><em>Pure</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_11' title='bbox 234 375 329 418; x_wconf 96'><strong><em>Cyan</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_4' title="bbox 207 570 422 605">
|
||||
<p class='ocr_par' id='par_1_4' lang='eng' title="bbox 207 570 422 605">
|
||||
<span class='ocr_line' id='line_1_5' title="bbox 207 570 422 605; baseline 0 0; x_size 40.365852; x_descenders 5.3658538; x_ascenders 15"><span class='ocrx_word' id='word_1_14' title='bbox 207 573 285 605; x_wconf 91'><strong>Pure</strong></span> <span class='ocrx_word' id='word_1_15' title='bbox 299 570 422 605; x_wconf 88'>Yellow</span>
|
||||
<span class='ocr_line' id='line_1_5' title="bbox 207 570 422 605; baseline 0 0; x_size 40.365852; x_descenders 5.3658538; x_ascenders 15">
|
||||
<span class='ocrx_word' id='word_1_12' title='bbox 207 573 285 605; x_wconf 96'><strong><em>Pure</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_13' title='bbox 299 570 422 605; x_wconf 95'><strong><em>Yellow</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
OSD: Weak margin (6.83) for 47 blob text block, but using orientation anyway: 0
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Multicolor Black
|
||||
Pure Block (K = 100)
|
||||
Pure Black (K = 100}
|
||||
|
||||
Pure Magenta
|
||||
|
||||
Pu re Cya n
|
||||
Pure Cyan
|
||||
|
||||
Pure Yellow
|
||||
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+6
-6
@@ -1,13 +1,13 @@
|
||||
Portez ce vieux whisky au juge
|
||||
blond qui fume sur son île
|
||||
intérieure, à côté de l'alcôve
|
||||
ovoïde, où les bûches se
|
||||
consument dans l'être, ce qui
|
||||
ovoide, où les bûches se
|
||||
consument dans l'âtre, ce qui
|
||||
lui permet de penser à la
|
||||
cænogénèse de l'être dont il
|
||||
est question dans la cause
|
||||
ambiguë entendue à Moÿ, dans
|
||||
un capharnaüm qui, pense—t—il,
|
||||
diminue çà et là la qualité de son
|
||||
oeuvre.
|
||||
|
||||
un capharnaüm qui, pense-t-il,
|
||||
diminue cà et là la qualité de son
|
||||
œuvre.
|
||||
|
||||
BIN
Binary file not shown.
+1
-2
@@ -1,2 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
OSD: Weak margin (4.74) for 181 blob text block, but using orientation anyway: 0
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+3
-3
@@ -4,8 +4,8 @@ Replacement of "creationism" with "intelligent design"
|
||||
|
||||
|
||||
|
||||
+ "Creation" and "creationist"
|
||||
+ "Intelligent design"
|
||||
—@— "Creation" and "creationist"
|
||||
—®@-— "Intelligent design"
|
||||
and "design proponent"
|
||||
|
||||
Word count
|
||||
@@ -17,4 +17,4 @@ Word count
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
+26
-26
@@ -1,62 +1,62 @@
|
||||
415T CONGRESS, } SENATE. { Ex. Doc.
|
||||
4ist ConGREss, } SENATE. { Ex. Doc,
|
||||
3d Session. No. 25.
|
||||
|
||||
MESSAGE
|
||||
|
||||
OF THE
|
||||
|
||||
PRESIDENT OF THE UNITED STATES.
|
||||
PRESIDENT OF THE UNITED STATES,
|
||||
|
||||
commcnme
|
||||
COMMUNICATING
|
||||
|
||||
A copy of regulation for the comqu courta of the Um'tmi States in Japan,
|
||||
decreed and iesued by the minister of the United States in that country.
|
||||
A copy of regulations for the consular courts of the United States in Japan,
|
||||
decreed and issued by the minister of the United States in that country.
|
||||
|
||||
anunr 91, 1571.——Read,refened to me pfimittee on Commerce, and ordered to be
|
||||
pun .
|
||||
JANUARY 27, 1871,—Read, referred to the Committee on Commerce, and ordered to be
|
||||
printed.
|
||||
|
||||
1'» the Senate and House of Reprcommtires :
|
||||
To the Senate and House of Representatives :
|
||||
|
||||
I transmit herewith, for the consideration of Congress, a report from
|
||||
the Secretary of State, and the papers which accompanied it, concern-
|
||||
ing regulations for the consular courts of the United States in J epan.
|
||||
ing regulations for the consular courts of the United States in Japan.
|
||||
|
||||
U. S. GRAN 1‘.
|
||||
U. 8. GRANT.
|
||||
|
||||
WASHINGTON, January 27, 1871.
|
||||
‘WASHINGTON, January 27, 1871.
|
||||
|
||||
DEPARTMENT OF STATE,
|
||||
Waahinyton, Ja/nuary 26, 1870.
|
||||
Washington, January 26, 1870,
|
||||
|
||||
The Secretary of State has the honor 1:0 submit herewith for revision
|
||||
by Congress, in conformity with the provisions of section (5 of the act.
|
||||
approved 22d of June, 1860, a. copy of “regulations for the consular
|
||||
courts of the United States in Japan,” decreed and issued by C. E.
|
||||
The Secretary of State has the honor to submit herewith, for revision
|
||||
by Congress, in conformity with the provisions of section 6 of the act
|
||||
approved 22d of June, 1860, a copy of “regulations for the consular
|
||||
courts of the United States in Japan,” decreed and issued by C. BE.
|
||||
De Long, the minister of the United States in that country, in Septem-
|
||||
ber, 1870; and also the papers mentioned in the subjoiued list, which.
|
||||
ber, 1870; and also the papers mentioned in the subjoined list, which,
|
||||
contain suggestions on the subject thereof.
|
||||
|
||||
A copy of Article XXVI of the consular regulations is also submitted,
|
||||
and the Secretary of State respectfully suggests, fur the consideration
|
||||
of Congress, the propriety of limiting the power of ministers tomake
|
||||
deerees and regulation, in the sense, in which it is limited by paragraph
|
||||
431 of the article before named—that is, “ to acts neeessaryto organize
|
||||
and give efficiency to the courts created by the act.”
|
||||
and the Secretary of State respectfully suggests, for the consideration
|
||||
of Congress, the propriety of limiting the power of ministers to make
|
||||
decrees and regulation, in the sense in which it is limited by paragraph
|
||||
431 of the article before named—that is, “to acts necessary to organize
|
||||
and give efficiency to the courts created by the act.”
|
||||
|
||||
Respectfully submitted.
|
||||
|
||||
HAMILTON FISH.
|
||||
|
||||
The PRESIDENT.
|
||||
The PRESIDENT,
|
||||
|
||||
List of accompanying papers.
|
||||
|
||||
1. Regulations for the consular courts of the United States in Japan.
|
||||
2. Mr. Fish to Mr. De Long, September 10, 1870.
|
||||
1, Regulations for the consular courts of the United States in Japan.
|
||||
2, Mr. Fish to Mr. De Long, September 10, 1870,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,169 +5,471 @@
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name='ocr-system' content='tesseract 3.05.01' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word'/>
|
||||
<meta name='ocr-system' content='tesseract 4.0.0' />
|
||||
<meta name='ocr-capabilities' content='ocr_page ocr_carea ocr_par ocr_line ocrx_word ocrp_wconf'/>
|
||||
</head>
|
||||
<body>
|
||||
<div class='ocr_page' id='page_1' title='image "/var/folders/37/78_114p552q16vv6vmgm5kr00000gn/T/com.github.ocrmypdf.xd964naf/000001.ocr.png"; bbox 0 0 1000 1520; ppageno 0'>
|
||||
<div class='ocr_page' id='page_1' title='image "/var/folders/37/78_114p552q16vv6vmgm5kr00000gn/T/com.github.ocrmypdf.doxmgxvs/000001.ocr.png"; bbox 0 0 1000 1520; ppageno 0'>
|
||||
<div class='ocr_carea' id='block_1_1' title="bbox 122 103 848 146">
|
||||
<p class='ocr_par' id='par_1_1' lang='eng' title="bbox 122 103 848 146">
|
||||
<span class='ocr_line' id='line_1_1' title="bbox 122 103 848 146; baseline 0 -26; x_size 22; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_1' title='bbox 122 104 169 121; x_wconf 71'><strong>415T</strong></span> <span class='ocrx_word' id='word_1_2' title='bbox 177 103 291 125; x_wconf 63'><strong>CONGRESS,</strong></span> <span class='ocrx_word' id='word_1_3' title='bbox 300 105 308 146; x_wconf 60'>}</span> <span class='ocrx_word' id='word_1_4' title='bbox 439 103 543 120; x_wconf 79'><strong>SENATE.</strong></span> <span class='ocrx_word' id='word_1_5' title='bbox 736 105 745 146; x_wconf 66'>{</span> <span class='ocrx_word' id='word_1_6' title='bbox 753 103 788 120; x_wconf 85'><strong>Ex.</strong></span> <span class='ocrx_word' id='word_1_7' title='bbox 798 103 848 121; x_wconf 80'>Doc.</span>
|
||||
<span class='ocr_line' id='line_1_1' title="bbox 122 103 848 146; baseline 0 -26; x_size 22; x_descenders 5; x_ascenders 4">
|
||||
<span class='ocrx_word' id='word_1_1' title='bbox 122 104 169 121; x_wconf 29'><strong><em>4ist</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_2' title='bbox 177 103 291 125; x_wconf 54'><strong><em>ConGREss,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_3' title='bbox 300 105 308 146; x_wconf 46'><strong><em>}</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_4' title='bbox 439 103 543 120; x_wconf 94'><strong><em>SENATE.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_5' title='bbox 736 105 745 146; x_wconf 90'><strong><em>{</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_6' title='bbox 753 103 788 120; x_wconf 94'><strong><em>Ex.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_7' title='bbox 798 103 848 121; x_wconf 95'><strong><em>Doc,</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_2' title="bbox 152 125 838 143; baseline -0.001 0; x_size 21.943821; x_descenders 4.94382; x_ascenders 5"><span class='ocrx_word' id='word_1_8' title='bbox 152 126 176 142; x_wconf 84'><strong>3d</strong></span> <span class='ocrx_word' id='word_1_9' title='bbox 185 126 260 143; x_wconf 64'><strong>Session.</strong></span> <span class='ocrx_word' id='word_1_10' title='bbox 767 125 802 142; x_wconf 71'><strong>No.</strong></span> <span class='ocrx_word' id='word_1_11' title='bbox 810 126 838 142; x_wconf 80'><strong>25.</strong></span>
|
||||
<span class='ocr_line' id='line_1_2' title="bbox 152 125 838 143; baseline -0.001 0; x_size 21.943821; x_descenders 4.94382; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_8' title='bbox 152 126 176 142; x_wconf 93'><strong><em>3d</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_9' title='bbox 185 126 260 143; x_wconf 88'><strong><em>Session.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_10' title='bbox 767 125 802 142; x_wconf 86'><strong><em>No.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_11' title='bbox 810 126 838 142; x_wconf 76'><strong><em>25.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_2' title="bbox 384 245 594 269">
|
||||
<p class='ocr_par' id='par_1_2' lang='eng' title="bbox 384 245 594 269">
|
||||
<span class='ocr_line' id='line_1_3' title="bbox 384 245 594 269; baseline 0 0; x_size 32.666668; x_descenders 8.166667; x_ascenders 8.166667"><span class='ocrx_word' id='word_1_12' title='bbox 384 245 594 269; x_wconf 81'><strong>MESSAGE</strong></span>
|
||||
<span class='ocr_line' id='line_1_3' title="bbox 384 245 594 269; baseline 0 0; x_size 32.666668; x_descenders 8.166667; x_ascenders 8.166667">
|
||||
<span class='ocrx_word' id='word_1_12' title='bbox 384 245 594 269; x_wconf 94'><strong><em>MESSAGE</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_3' title="bbox 459 302 523 313">
|
||||
<p class='ocr_par' id='par_1_3' lang='eng' title="bbox 459 302 523 313">
|
||||
<span class='ocr_line' id='line_1_4' title="bbox 459 302 523 313; baseline 0 0; x_size 20; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_13' title='bbox 459 302 481 313; x_wconf 74'><strong>OF</strong></span> <span class='ocrx_word' id='word_1_14' title='bbox 490 302 523 313; x_wconf 75'><strong>THE</strong></span>
|
||||
<span class='ocr_line' id='line_1_4' title="bbox 459 302 523 313; baseline 0 0; x_size 20; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_13' title='bbox 459 302 481 313; x_wconf 87'><strong><em>OF</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_14' title='bbox 490 302 523 313; x_wconf 96'><strong><em>THE</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_4' title="bbox 148 338 839 375">
|
||||
<p class='ocr_par' id='par_1_4' lang='eng' title="bbox 148 338 839 375">
|
||||
<span class='ocr_line' id='line_1_5' title="bbox 148 338 839 375; baseline 0.003 -3; x_size 43.490196; x_descenders 10.872549; x_ascenders 10.872549"><span class='ocrx_word' id='word_1_15' title='bbox 148 339 358 372; x_wconf 80'><strong>PRESIDENT</strong></span> <span class='ocrx_word' id='word_1_16' title='bbox 379 339 422 371; x_wconf 81'><strong>OF</strong></span> <span class='ocrx_word' id='word_1_17' title='bbox 444 338 518 371; x_wconf 88'><strong>THE</strong></span> <span class='ocrx_word' id='word_1_18' title='bbox 539 338 673 371; x_wconf 86'><strong>UNITED</strong></span> <span class='ocrx_word' id='word_1_19' title='bbox 694 338 839 375; x_wconf 83'>STATES.</span>
|
||||
<span class='ocr_line' id='line_1_5' title="bbox 148 338 839 375; baseline 0.003 -3; x_size 43.490196; x_descenders 10.872549; x_ascenders 10.872549">
|
||||
<span class='ocrx_word' id='word_1_15' title='bbox 148 339 358 372; x_wconf 96'><strong><em>PRESIDENT</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_16' title='bbox 379 339 422 371; x_wconf 95'><strong><em>OF</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_17' title='bbox 444 338 518 371; x_wconf 96'><strong><em>THE</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_18' title='bbox 539 338 673 371; x_wconf 96'><strong><em>UNITED</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_19' title='bbox 694 338 839 375; x_wconf 96'><strong><em>STATES,</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_5' title="bbox 423 406 563 417">
|
||||
<p class='ocr_par' id='par_1_5' lang='eng' title="bbox 423 406 563 417">
|
||||
<span class='ocr_line' id='line_1_6' title="bbox 423 406 563 417; baseline 0 -1; x_size 20; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_20' title='bbox 423 406 563 417; x_wconf 68'><strong>commcnme</strong></span>
|
||||
<span class='ocr_line' id='line_1_6' title="bbox 423 406 563 417; baseline 0 -1; x_size 20; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_20' title='bbox 423 406 563 417; x_wconf 95'><strong><em>COMMUNICATING</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_6' title="bbox 123 447 859 492">
|
||||
<p class='ocr_par' id='par_1_6' lang='eng' title="bbox 123 447 859 492">
|
||||
<span class='ocr_line' id='line_1_7' title="bbox 123 447 859 470; baseline 0.001 -6; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_21' title='bbox 123 447 141 465; x_wconf 79'><strong><em>A</em></strong></span> <span class='ocrx_word' id='word_1_22' title='bbox 147 452 189 469; x_wconf 74'><strong>copy</strong></span> <span class='ocrx_word' id='word_1_23' title='bbox 193 447 215 469; x_wconf 78'><strong>of</strong></span> <span class='ocrx_word' id='word_1_24' title='bbox 220 447 329 469; x_wconf 62'><strong>regulation</strong></span> <span class='ocrx_word' id='word_1_25' title='bbox 335 447 369 468; x_wconf 78'><strong>for</strong></span> <span class='ocrx_word' id='word_1_26' title='bbox 374 447 401 464; x_wconf 75'><strong>the</strong></span> <span class='ocrx_word' id='word_1_27' title='bbox 410 447 492 464; x_wconf 75'><em>comqu</em></span> <span class='ocrx_word' id='word_1_28' title='bbox 497 449 555 464; x_wconf 71'><strong>courta</strong></span> <span class='ocrx_word' id='word_1_29' title='bbox 563 447 585 469; x_wconf 84'><strong>of</strong></span> <span class='ocrx_word' id='word_1_30' title='bbox 590 447 617 464; x_wconf 77'><strong>the</strong></span> <span class='ocrx_word' id='word_1_31' title='bbox 628 447 692 465; x_wconf 68'><strong>Um'tmi</strong></span> <span class='ocrx_word' id='word_1_32' title='bbox 700 447 758 465; x_wconf 71'><strong>States</strong></span> <span class='ocrx_word' id='word_1_33' title='bbox 766 448 785 464; x_wconf 72'><strong>in</strong></span> <span class='ocrx_word' id='word_1_34' title='bbox 793 447 859 470; x_wconf 71'><strong><em>Japan,</em></strong></span>
|
||||
<span class='ocr_line' id='line_1_7' title="bbox 123 447 859 470; baseline 0.001 -6; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_21' title='bbox 123 447 141 465; x_wconf 95'><strong><em>A</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_22' title='bbox 147 452 189 469; x_wconf 95'><strong><em>copy</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_23' title='bbox 193 447 215 469; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_24' title='bbox 220 447 329 469; x_wconf 96'><strong><em>regulations</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_25' title='bbox 335 447 369 468; x_wconf 95'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_26' title='bbox 374 447 401 464; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_27' title='bbox 410 447 492 464; x_wconf 96'><strong><em>consular</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_28' title='bbox 497 449 555 464; x_wconf 79'><strong><em>courts</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_29' title='bbox 563 447 585 469; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_30' title='bbox 590 447 617 464; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_31' title='bbox 628 447 692 465; x_wconf 96'><strong><em>United</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_32' title='bbox 700 447 758 465; x_wconf 93'><strong><em>States</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_33' title='bbox 766 448 785 464; x_wconf 93'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_34' title='bbox 793 447 859 470; x_wconf 96'><strong><em>Japan,</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_8' title="bbox 145 468 832 492; baseline 0 -6; x_size 23; x_descenders 5; x_ascenders 6"><span class='ocrx_word' id='word_1_35' title='bbox 145 470 213 486; x_wconf 73'><strong>decreed</strong></span> <span class='ocrx_word' id='word_1_36' title='bbox 220 470 256 487; x_wconf 74'><strong>and</strong></span> <span class='ocrx_word' id='word_1_37' title='bbox 263 469 321 487; x_wconf 65'><strong>iesued</strong></span> <span class='ocrx_word' id='word_1_38' title='bbox 329 469 351 490; x_wconf 74'><strong>by</strong></span> <span class='ocrx_word' id='word_1_39' title='bbox 359 469 386 486; x_wconf 80'><strong>the</strong></span> <span class='ocrx_word' id='word_1_40' title='bbox 393 468 474 486; x_wconf 73'><strong>minister</strong></span> <span class='ocrx_word' id='word_1_41' title='bbox 480 469 502 491; x_wconf 79'><strong>of</strong></span> <span class='ocrx_word' id='word_1_42' title='bbox 507 470 533 487; x_wconf 77'><strong>the</strong></span> <span class='ocrx_word' id='word_1_43' title='bbox 544 469 608 487; x_wconf 67'><strong>United</strong></span> <span class='ocrx_word' id='word_1_44' title='bbox 616 470 674 487; x_wconf 69'><strong>States</strong></span> <span class='ocrx_word' id='word_1_45' title='bbox 680 470 700 487; x_wconf 76'><strong>in</strong></span> <span class='ocrx_word' id='word_1_46' title='bbox 708 470 746 487; x_wconf 77'><strong>that</strong></span> <span class='ocrx_word' id='word_1_47' title='bbox 753 472 832 492; x_wconf 72'><strong>country.</strong></span>
|
||||
<span class='ocr_line' id='line_1_8' title="bbox 145 468 832 492; baseline 0 -6; x_size 23; x_descenders 5; x_ascenders 6">
|
||||
<span class='ocrx_word' id='word_1_35' title='bbox 145 470 213 486; x_wconf 96'><strong><em>decreed</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_36' title='bbox 220 470 256 487; x_wconf 95'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_37' title='bbox 263 469 321 487; x_wconf 95'><strong><em>issued</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_38' title='bbox 329 469 351 490; x_wconf 96'><strong><em>by</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_39' title='bbox 359 469 386 486; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_40' title='bbox 393 468 474 486; x_wconf 96'><strong><em>minister</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_41' title='bbox 480 469 502 491; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_42' title='bbox 507 470 533 487; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_43' title='bbox 544 469 608 487; x_wconf 96'><strong><em>United</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_44' title='bbox 616 470 674 487; x_wconf 96'><strong><em>States</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_45' title='bbox 680 470 700 487; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_46' title='bbox 708 470 746 487; x_wconf 96'><strong><em>that</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_47' title='bbox 753 472 832 492; x_wconf 83'><strong><em>country.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_7' title="bbox 121 543 860 579">
|
||||
<p class='ocr_par' id='par_1_7' lang='eng' title="bbox 121 543 860 579">
|
||||
<span class='ocr_line' id='line_1_9' title="bbox 121 543 860 575; baseline 0 -17; x_size 19; x_descenders 4; x_ascenders 4"><span class='ocrx_word' id='word_1_48' title='bbox 121 544 200 559; x_wconf 66'><strong>anunr</strong></span> <span class='ocrx_word' id='word_1_49' title='bbox 206 544 229 562; x_wconf 66'><strong>91,</strong></span> <span class='ocrx_word' id='word_1_50' title='bbox 236 543 413 561; x_wconf 75'><strong>1571.——Read,refened</strong></span> <span class='ocrx_word' id='word_1_51' title='bbox 419 545 435 558; x_wconf 72'><strong>to</strong></span> <span class='ocrx_word' id='word_1_52' title='bbox 441 543 469 557; x_wconf 68'><strong>me</strong></span> <span class='ocrx_word' id='word_1_53' title='bbox 478 543 570 575; x_wconf 43'><strong>pfimittee</strong></span> <span class='ocrx_word' id='word_1_54' title='bbox 581 547 601 557; x_wconf 83'><strong>on</strong></span> <span class='ocrx_word' id='word_1_55' title='bbox 612 543 703 562; x_wconf 73'><strong>Commerce,</strong></span> <span class='ocrx_word' id='word_1_56' title='bbox 710 543 741 558; x_wconf 71'><strong>and</strong></span> <span class='ocrx_word' id='word_1_57' title='bbox 748 544 812 558; x_wconf 77'><strong>ordered</strong></span> <span class='ocrx_word' id='word_1_58' title='bbox 817 545 834 558; x_wconf 69'><strong>to</strong></span> <span class='ocrx_word' id='word_1_59' title='bbox 840 544 860 558; x_wconf 81'><strong>be</strong></span>
|
||||
<span class='ocr_line' id='line_1_9' title="bbox 121 543 860 575; baseline 0 -17; x_size 19; x_descenders 4; x_ascenders 4">
|
||||
<span class='ocrx_word' id='word_1_48' title='bbox 121 544 200 559; x_wconf 95'><strong><em>JANUARY</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_49' title='bbox 206 544 229 562; x_wconf 85'><strong><em>27,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_50' title='bbox 236 543 342 561; x_wconf 58'><strong><em>1871,—Read,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_51' title='bbox 346 543 413 558; x_wconf 95'><strong><em>referred</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_52' title='bbox 419 545 435 558; x_wconf 96'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_53' title='bbox 441 543 469 557; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_54' title='bbox 478 543 570 575; x_wconf 66'><strong><em>Committee</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_55' title='bbox 581 547 601 557; x_wconf 96'><strong><em>on</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_56' title='bbox 612 543 703 562; x_wconf 96'><strong><em>Commerce,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_57' title='bbox 710 543 741 558; x_wconf 96'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_58' title='bbox 748 544 812 558; x_wconf 96'><strong><em>ordered</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_59' title='bbox 817 545 834 558; x_wconf 96'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_60' title='bbox 840 544 860 558; x_wconf 96'><strong><em>be</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_10' title="bbox 458 565 524 579; baseline 0 -4; x_size 18.782608; x_descenders 4; x_ascenders 4.782609"><span class='ocrx_word' id='word_1_60' title='bbox 458 565 492 579; x_wconf 73'><strong>pun</strong></span> <span class='ocrx_word' id='word_1_61' title='bbox 521 572 524 575; x_wconf 98'>.</span>
|
||||
<span class='ocr_line' id='line_1_10' title="bbox 458 565 524 579; baseline 0 -4; x_size 18.782608; x_descenders 4; x_ascenders 4.782609">
|
||||
<span class='ocrx_word' id='word_1_61' title='bbox 458 565 524 579; x_wconf 93'><strong><em>printed.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_8' title="bbox 121 631 858 770">
|
||||
<p class='ocr_par' id='par_1_8' lang='eng' title="bbox 123 631 565 653">
|
||||
<span class='ocr_line' id='line_1_11' title="bbox 123 631 565 653; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_62' title='bbox 123 631 149 649; x_wconf 72'><strong>1'»</strong></span> <span class='ocrx_word' id='word_1_63' title='bbox 157 631 185 648; x_wconf 75'><strong>the</strong></span> <span class='ocrx_word' id='word_1_64' title='bbox 193 631 255 648; x_wconf 67'><strong>Senate</strong></span> <span class='ocrx_word' id='word_1_65' title='bbox 263 631 300 649; x_wconf 73'><strong>and</strong></span> <span class='ocrx_word' id='word_1_66' title='bbox 306 631 367 648; x_wconf 66'><strong>House</strong></span> <span class='ocrx_word' id='word_1_67' title='bbox 375 631 397 653; x_wconf 84'><strong>of</strong></span> <span class='ocrx_word' id='word_1_68' title='bbox 404 631 554 652; x_wconf 64'><strong>Reprcommtires</strong></span> <span class='ocrx_word' id='word_1_69' title='bbox 559 638 565 648; x_wconf 91'><strong><em>:</em></strong></span>
|
||||
<span class='ocr_line' id='line_1_11' title="bbox 123 631 565 653; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_62' title='bbox 123 631 149 649; x_wconf 96'><strong><em>To</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_63' title='bbox 157 631 185 648; x_wconf 95'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_64' title='bbox 193 631 255 648; x_wconf 95'><strong><em>Senate</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_65' title='bbox 263 631 300 649; x_wconf 95'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_66' title='bbox 306 631 367 648; x_wconf 95'><strong><em>House</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_67' title='bbox 375 631 397 653; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_68' title='bbox 404 631 554 652; x_wconf 74'><strong><em>Representatives</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_69' title='bbox 559 638 565 648; x_wconf 86'><strong><em>:</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_9' lang='eng' title="bbox 121 658 858 724">
|
||||
<span class='ocr_line' id='line_1_12' title="bbox 145 658 857 681; baseline 0.003 -7; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_70' title='bbox 145 658 155 674; x_wconf 91'>I</span> <span class='ocrx_word' id='word_1_71' title='bbox 162 659 250 675; x_wconf 72'><strong>transmit</strong></span> <span class='ocrx_word' id='word_1_72' title='bbox 261 658 357 681; x_wconf 75'><strong>herewith,</strong></span> <span class='ocrx_word' id='word_1_73' title='bbox 365 658 394 675; x_wconf 80'><strong>for</strong></span> <span class='ocrx_word' id='word_1_74' title='bbox 401 659 434 675; x_wconf 82'><strong>the</strong></span> <span class='ocrx_word' id='word_1_75' title='bbox 441 658 577 675; x_wconf 78'><strong>consideration</strong></span> <span class='ocrx_word' id='word_1_76' title='bbox 586 658 607 675; x_wconf 85'><strong>of</strong></span> <span class='ocrx_word' id='word_1_77' title='bbox 616 658 714 680; x_wconf 77'><strong>Congress,</strong></span> <span class='ocrx_word' id='word_1_78' title='bbox 723 663 734 675; x_wconf 72'><strong>a</strong></span> <span class='ocrx_word' id='word_1_79' title='bbox 742 659 805 679; x_wconf 74'><strong>report</strong></span> <span class='ocrx_word' id='word_1_80' title='bbox 810 658 857 676; x_wconf 81'><strong>from</strong></span>
|
||||
<span class='ocr_line' id='line_1_12' title="bbox 145 658 857 681; baseline 0.003 -7; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_70' title='bbox 145 658 155 674; x_wconf 92'><strong><em>I</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_71' title='bbox 162 659 250 675; x_wconf 92'><strong><em>transmit</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_72' title='bbox 261 658 357 681; x_wconf 94'><strong><em>herewith,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_73' title='bbox 365 658 394 675; x_wconf 96'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_74' title='bbox 401 659 434 675; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_75' title='bbox 441 658 577 675; x_wconf 96'><strong><em>consideration</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_76' title='bbox 586 658 607 675; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_77' title='bbox 616 658 714 680; x_wconf 95'><strong><em>Congress,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_78' title='bbox 723 663 734 675; x_wconf 94'><strong><em>a</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_79' title='bbox 742 659 805 679; x_wconf 96'><strong><em>report</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_80' title='bbox 810 658 857 676; x_wconf 96'><strong><em>from</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_13' title="bbox 121 680 858 703; baseline 0 -6; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_81' title='bbox 121 680 155 697; x_wconf 75'><strong>the</strong></span> <span class='ocrx_word' id='word_1_82' title='bbox 163 680 259 702; x_wconf 68'><strong>Secretary</strong></span> <span class='ocrx_word' id='word_1_83' title='bbox 268 680 288 697; x_wconf 75'><strong>of</strong></span> <span class='ocrx_word' id='word_1_84' title='bbox 299 680 357 703; x_wconf 75'><strong>State,</strong></span> <span class='ocrx_word' id='word_1_85' title='bbox 366 681 403 697; x_wconf 66'><strong>and</strong></span> <span class='ocrx_word' id='word_1_86' title='bbox 410 681 444 698; x_wconf 82'><strong>the</strong></span> <span class='ocrx_word' id='word_1_87' title='bbox 456 681 524 701; x_wconf 67'><strong>papers</strong></span> <span class='ocrx_word' id='word_1_88' title='bbox 531 680 592 697; x_wconf 79'><strong>which</strong></span> <span class='ocrx_word' id='word_1_89' title='bbox 605 680 736 702; x_wconf 69'><strong>accompanied</strong></span> <span class='ocrx_word' id='word_1_90' title='bbox 744 680 765 702; x_wconf 75'><strong>it,</strong></span> <span class='ocrx_word' id='word_1_91' title='bbox 774 685 858 698; x_wconf 80'><strong>concern-</strong></span>
|
||||
<span class='ocr_line' id='line_1_13' title="bbox 121 680 858 703; baseline 0 -6; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_81' title='bbox 121 680 155 697; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_82' title='bbox 163 680 259 702; x_wconf 94'><strong><em>Secretary</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_83' title='bbox 268 680 288 697; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_84' title='bbox 299 680 357 703; x_wconf 96'><strong><em>State,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_85' title='bbox 366 681 403 697; x_wconf 96'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_86' title='bbox 410 681 444 698; x_wconf 95'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_87' title='bbox 456 681 524 701; x_wconf 95'><strong><em>papers</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_88' title='bbox 531 680 592 697; x_wconf 94'><strong><em>which</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_89' title='bbox 605 680 736 702; x_wconf 94'><strong><em>accompanied</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_90' title='bbox 744 680 765 702; x_wconf 93'><strong><em>it,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_91' title='bbox 774 685 858 698; x_wconf 92'><strong><em>concern-</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_14' title="bbox 122 702 835 724; baseline 0.001 -5; x_size 21; x_descenders 4; x_ascenders 5"><span class='ocrx_word' id='word_1_92' title='bbox 122 703 155 723; x_wconf 80'><strong>ing</strong></span> <span class='ocrx_word' id='word_1_93' title='bbox 163 702 277 723; x_wconf 74'><strong>regulations</strong></span> <span class='ocrx_word' id='word_1_94' title='bbox 285 702 314 719; x_wconf 86'><strong>for</strong></span> <span class='ocrx_word' id='word_1_95' title='bbox 321 703 354 720; x_wconf 81'><strong>the</strong></span> <span class='ocrx_word' id='word_1_96' title='bbox 361 703 446 720; x_wconf 81'><strong>consular</strong></span> <span class='ocrx_word' id='word_1_97' title='bbox 453 703 516 720; x_wconf 77'><strong>courts</strong></span> <span class='ocrx_word' id='word_1_98' title='bbox 524 703 546 720; x_wconf 76'><strong>of</strong></span> <span class='ocrx_word' id='word_1_99' title='bbox 552 704 583 720; x_wconf 70'><strong>the</strong></span> <span class='ocrx_word' id='word_1_100' title='bbox 591 703 661 720; x_wconf 77'><strong>United</strong></span> <span class='ocrx_word' id='word_1_101' title='bbox 669 703 732 720; x_wconf 67'><strong>States</strong></span> <span class='ocrx_word' id='word_1_102' title='bbox 740 702 759 719; x_wconf 82'><strong>in</strong></span> <span class='ocrx_word' id='word_1_103' title='bbox 768 703 781 719; x_wconf 88'><strong>J</strong></span> <span class='ocrx_word' id='word_1_104' title='bbox 782 707 835 724; x_wconf 69'><strong>epan.</strong></span>
|
||||
<span class='ocr_line' id='line_1_14' title="bbox 122 702 835 724; baseline 0.001 -5; x_size 21; x_descenders 4; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_92' title='bbox 122 703 155 723; x_wconf 96'><strong><em>ing</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_93' title='bbox 163 702 277 723; x_wconf 96'><strong><em>regulations</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_94' title='bbox 285 702 314 719; x_wconf 96'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_95' title='bbox 321 703 354 720; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_96' title='bbox 361 703 446 720; x_wconf 96'><strong><em>consular</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_97' title='bbox 453 703 516 720; x_wconf 95'><strong><em>courts</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_98' title='bbox 524 703 546 720; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_99' title='bbox 552 704 583 720; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_100' title='bbox 591 703 661 720; x_wconf 96'><strong><em>United</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_101' title='bbox 669 703 732 720; x_wconf 96'><strong><em>States</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_102' title='bbox 740 702 759 719; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_103' title='bbox 768 703 835 724; x_wconf 90'><strong><em>Japan.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_10' lang='eng' title="bbox 682 724 835 743">
|
||||
<span class='ocr_line' id='line_1_15' title="bbox 682 724 835 743; baseline 0 -1; x_size 23.573172; x_descenders 5.5365853; x_ascenders 5.5"><span class='ocrx_word' id='word_1_105' title='bbox 682 725 705 743; x_wconf 87'><strong>U.</strong></span> <span class='ocrx_word' id='word_1_106' title='bbox 715 724 734 743; x_wconf 84'><strong>S.</strong></span> <span class='ocrx_word' id='word_1_107' title='bbox 743 725 814 742; x_wconf 67'><strong>GRAN</strong></span> <span class='ocrx_word' id='word_1_108' title='bbox 815 725 835 743; x_wconf 84'><strong>1‘.</strong></span>
|
||||
<span class='ocr_line' id='line_1_15' title="bbox 682 724 835 743; baseline 0 -1; x_size 23.573172; x_descenders 5.5365853; x_ascenders 5.5">
|
||||
<span class='ocrx_word' id='word_1_104' title='bbox 682 725 705 743; x_wconf 85'><strong><em>U.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_105' title='bbox 715 724 734 743; x_wconf 89'><strong><em>8.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_106' title='bbox 743 725 835 743; x_wconf 83'><strong><em>GRANT.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_11' lang='eng' title="bbox 144 746 482 770">
|
||||
<span class='ocr_line' id='line_1_16' title="bbox 144 746 482 770; baseline 0 -6; x_size 24; x_descenders 6; x_ascenders 5"><span class='ocrx_word' id='word_1_109' title='bbox 144 746 293 769; x_wconf 68'><strong>WASHINGTON,</strong></span> <span class='ocrx_word' id='word_1_110' title='bbox 302 746 385 768; x_wconf 76'><strong><em>January</em></strong></span> <span class='ocrx_word' id='word_1_111' title='bbox 393 748 422 770; x_wconf 85'><strong>27,</strong></span> <span class='ocrx_word' id='word_1_112' title='bbox 431 747 482 764; x_wconf 86'>1871.</span>
|
||||
<span class='ocr_line' id='line_1_16' title="bbox 144 746 482 770; baseline 0 -6; x_size 24; x_descenders 6; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_107' title='bbox 144 746 293 769; x_wconf 78'><strong><em>‘WASHINGTON,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_108' title='bbox 302 746 385 768; x_wconf 96'><strong><em>January</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_109' title='bbox 393 748 422 770; x_wconf 92'><strong><em>27,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_110' title='bbox 431 747 482 764; x_wconf 92'><strong><em>1871.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_9' title="bbox 120 846 865 1225">
|
||||
<p class='ocr_par' id='par_1_12' lang='eng' title="bbox 443 846 834 891">
|
||||
<span class='ocr_line' id='line_1_17' title="bbox 443 846 710 869; baseline 0.004 -7; x_size 23; x_descenders 6; x_ascenders 4"><span class='ocrx_word' id='word_1_113' title='bbox 443 846 586 863; x_wconf 75'><strong>DEPARTMENT</strong></span> <span class='ocrx_word' id='word_1_114' title='bbox 599 849 624 863; x_wconf 79'><strong>OF</strong></span> <span class='ocrx_word' id='word_1_115' title='bbox 636 846 710 869; x_wconf 74'><strong>STATE,</strong></span>
|
||||
<span class='ocr_line' id='line_1_17' title="bbox 443 846 710 869; baseline 0.004 -7; x_size 23; x_descenders 6; x_ascenders 4">
|
||||
<span class='ocrx_word' id='word_1_111' title='bbox 443 846 586 863; x_wconf 95'><strong><em>DEPARTMENT</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_112' title='bbox 599 849 624 863; x_wconf 96'><strong><em>OF</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_113' title='bbox 636 846 710 869; x_wconf 95'><strong><em>STATE,</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_18' title="bbox 529 868 834 891; baseline 0 -5; x_size 23.255997; x_descenders 5.2559972; x_ascenders 6"><span class='ocrx_word' id='word_1_116' title='bbox 529 868 649 891; x_wconf 62'><strong>Waahinyton,</strong></span> <span class='ocrx_word' id='word_1_117' title='bbox 657 868 740 889; x_wconf 74'><strong><em>Ja/nuary</em></strong></span> <span class='ocrx_word' id='word_1_118' title='bbox 748 868 775 891; x_wconf 79'><strong>26,</strong></span> <span class='ocrx_word' id='word_1_119' title='bbox 784 868 834 886; x_wconf 87'><strong>1870.</strong></span>
|
||||
<span class='ocr_line' id='line_1_18' title="bbox 529 868 834 891; baseline 0 -5; x_size 23.255997; x_descenders 5.2559972; x_ascenders 6">
|
||||
<span class='ocrx_word' id='word_1_114' title='bbox 529 868 649 891; x_wconf 95'><strong><em>Washington,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_115' title='bbox 657 868 740 889; x_wconf 96'><strong><em>January</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_116' title='bbox 748 868 775 891; x_wconf 94'><strong><em>26,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_117' title='bbox 784 868 834 886; x_wconf 85'><strong><em>1870,</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_13' lang='eng' title="bbox 121 894 865 1051">
|
||||
<span class='ocr_line' id='line_1_19' title="bbox 146 894 857 917; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_120' title='bbox 146 895 184 912; x_wconf 79'><strong>The</strong></span> <span class='ocrx_word' id='word_1_121' title='bbox 193 895 290 917; x_wconf 69'><strong>Secretary</strong></span> <span class='ocrx_word' id='word_1_122' title='bbox 297 895 319 912; x_wconf 79'><strong>of</strong></span> <span class='ocrx_word' id='word_1_123' title='bbox 328 895 381 913; x_wconf 77'><strong>State</strong></span> <span class='ocrx_word' id='word_1_124' title='bbox 389 896 422 913; x_wconf 69'><strong>has</strong></span> <span class='ocrx_word' id='word_1_125' title='bbox 430 894 462 912; x_wconf 79'><strong>the</strong></span> <span class='ocrx_word' id='word_1_126' title='bbox 469 895 528 912; x_wconf 78'><strong>honor</strong></span> <span class='ocrx_word' id='word_1_127' title='bbox 535 897 555 912; x_wconf 80'><strong>1:0</strong></span> <span class='ocrx_word' id='word_1_128' title='bbox 564 895 633 912; x_wconf 77'><strong>submit</strong></span> <span class='ocrx_word' id='word_1_129' title='bbox 640 895 730 913; x_wconf 75'><strong>herewith</strong></span> <span class='ocrx_word' id='word_1_130' title='bbox 739 895 768 912; x_wconf 78'><strong>for</strong></span> <span class='ocrx_word' id='word_1_131' title='bbox 776 895 857 912; x_wconf 76'><strong>revision</strong></span>
|
||||
<span class='ocr_line' id='line_1_19' title="bbox 146 894 857 917; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_118' title='bbox 146 895 184 912; x_wconf 96'><strong><em>The</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_119' title='bbox 193 895 290 917; x_wconf 96'><strong><em>Secretary</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_120' title='bbox 297 895 319 912; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_121' title='bbox 328 895 381 913; x_wconf 96'><strong><em>State</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_122' title='bbox 389 896 422 913; x_wconf 96'><strong><em>has</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_123' title='bbox 430 894 462 912; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_124' title='bbox 469 895 528 912; x_wconf 96'><strong><em>honor</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_125' title='bbox 535 897 555 912; x_wconf 96'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_126' title='bbox 564 895 633 912; x_wconf 96'><strong><em>submit</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_127' title='bbox 640 895 730 913; x_wconf 90'><strong><em>herewith,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_128' title='bbox 739 895 768 912; x_wconf 90'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_129' title='bbox 776 895 857 912; x_wconf 95'><strong><em>revision</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_20' title="bbox 122 907 857 940; baseline 0 -5; x_size 23; x_descenders 5; x_ascenders 6"><span class='ocrx_word' id='word_1_132' title='bbox 122 918 148 939; x_wconf 83'><strong>by</strong></span> <span class='ocrx_word' id='word_1_133' title='bbox 160 917 258 940; x_wconf 74'><strong>Congress,</strong></span> <span class='ocrx_word' id='word_1_134' title='bbox 266 918 285 935; x_wconf 85'><strong>in</strong></span> <span class='ocrx_word' id='word_1_135' title='bbox 294 918 403 939; x_wconf 76'><strong>conformity</strong></span> <span class='ocrx_word' id='word_1_136' title='bbox 412 917 456 935; x_wconf 74'><strong>with</strong></span> <span class='ocrx_word' id='word_1_137' title='bbox 464 917 496 934; x_wconf 79'><strong>the</strong></span> <span class='ocrx_word' id='word_1_138' title='bbox 505 918 607 939; x_wconf 77'>provisions</span> <span class='ocrx_word' id='word_1_139' title='bbox 615 917 636 934; x_wconf 79'><strong>of</strong></span> <span class='ocrx_word' id='word_1_140' title='bbox 646 918 715 935; x_wconf 81'><strong>section</strong></span> <span class='ocrx_word' id='word_1_141' title='bbox 724 907 736 934; x_wconf 47'><strong>(5</strong></span> <span class='ocrx_word' id='word_1_142' title='bbox 749 917 770 934; x_wconf 81'><strong>of</strong></span> <span class='ocrx_word' id='word_1_143' title='bbox 779 918 812 935; x_wconf 69'><strong>the</strong></span> <span class='ocrx_word' id='word_1_144' title='bbox 826 919 857 935; x_wconf 68'><strong>act.</strong></span>
|
||||
<span class='ocr_line' id='line_1_20' title="bbox 122 907 857 940; baseline 0 -5; x_size 23; x_descenders 5; x_ascenders 6">
|
||||
<span class='ocrx_word' id='word_1_130' title='bbox 122 918 148 939; x_wconf 95'><strong><em>by</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_131' title='bbox 160 917 258 940; x_wconf 96'><strong><em>Congress,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_132' title='bbox 266 918 285 935; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_133' title='bbox 294 918 403 939; x_wconf 96'><strong><em>conformity</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_134' title='bbox 412 917 456 935; x_wconf 96'><strong><em>with</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_135' title='bbox 464 917 496 934; x_wconf 97'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_136' title='bbox 505 918 607 939; x_wconf 96'><strong><em>provisions</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_137' title='bbox 615 917 636 934; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_138' title='bbox 646 918 715 935; x_wconf 97'><strong><em>section</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_139' title='bbox 724 907 736 934; x_wconf 92'><strong><em>6</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_140' title='bbox 749 917 770 934; x_wconf 94'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_141' title='bbox 779 918 812 935; x_wconf 94'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_142' title='bbox 826 919 857 935; x_wconf 96'><strong><em>act</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_21' title="bbox 121 939 857 962; baseline -0.001 -5; x_size 21; x_descenders 4; x_ascenders 5"><span class='ocrx_word' id='word_1_145' title='bbox 121 940 217 961; x_wconf 79'><strong>approved</strong></span> <span class='ocrx_word' id='word_1_146' title='bbox 229 940 265 957; x_wconf 85'><strong>22d</strong></span> <span class='ocrx_word' id='word_1_147' title='bbox 278 939 299 957; x_wconf 82'><strong>of</strong></span> <span class='ocrx_word' id='word_1_148' title='bbox 313 940 368 962; x_wconf 83'><strong>June,</strong></span> <span class='ocrx_word' id='word_1_149' title='bbox 383 940 432 962; x_wconf 81'><strong>1860,</strong></span> <span class='ocrx_word' id='word_1_150' title='bbox 441 944 453 956; x_wconf 78'><strong>a.</strong></span> <span class='ocrx_word' id='word_1_151' title='bbox 466 944 513 961; x_wconf 78'><strong>copy</strong></span> <span class='ocrx_word' id='word_1_152' title='bbox 525 940 546 957; x_wconf 82'><strong>of</strong></span> <span class='ocrx_word' id='word_1_153' title='bbox 555 940 686 961; x_wconf 74'><strong>“regulations</strong></span> <span class='ocrx_word' id='word_1_154' title='bbox 693 940 722 957; x_wconf 77'><strong>for</strong></span> <span class='ocrx_word' id='word_1_155' title='bbox 730 940 762 956; x_wconf 75'><strong>the</strong></span> <span class='ocrx_word' id='word_1_156' title='bbox 770 940 857 957; x_wconf 75'><strong>consular</strong></span>
|
||||
<span class='ocr_line' id='line_1_21' title="bbox 121 939 857 962; baseline -0.001 -5; x_size 21; x_descenders 4; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_143' title='bbox 121 940 217 961; x_wconf 96'><strong><em>approved</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_144' title='bbox 229 940 265 957; x_wconf 95'><strong><em>22d</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_145' title='bbox 278 939 299 957; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_146' title='bbox 313 940 368 962; x_wconf 96'><strong><em>June,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_147' title='bbox 383 940 432 962; x_wconf 57'><strong><em>1860,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_148' title='bbox 441 944 453 956; x_wconf 57'><strong><em>a</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_149' title='bbox 466 944 513 961; x_wconf 96'><strong><em>copy</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_150' title='bbox 525 940 546 957; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_151' title='bbox 555 940 686 961; x_wconf 82'><strong><em>“regulations</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_152' title='bbox 693 940 722 957; x_wconf 95'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_153' title='bbox 730 940 762 956; x_wconf 97'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_154' title='bbox 770 940 857 957; x_wconf 95'><strong><em>consular</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_22' title="bbox 121 962 857 983; baseline -0.001 -3; x_size 21; x_descenders 4; x_ascenders 5"><span class='ocrx_word' id='word_1_157' title='bbox 121 963 184 980; x_wconf 77'><strong>courts</strong></span> <span class='ocrx_word' id='word_1_158' title='bbox 198 962 219 979; x_wconf 86'><strong>of</strong></span> <span class='ocrx_word' id='word_1_159' title='bbox 228 963 261 979; x_wconf 82'><strong>the</strong></span> <span class='ocrx_word' id='word_1_160' title='bbox 272 962 342 980; x_wconf 80'><strong>United</strong></span> <span class='ocrx_word' id='word_1_161' title='bbox 356 962 419 980; x_wconf 69'><strong>States</strong></span> <span class='ocrx_word' id='word_1_162' title='bbox 430 962 450 979; x_wconf 82'><strong>in</strong></span> <span class='ocrx_word' id='word_1_163' title='bbox 465 962 544 983; x_wconf 74'><strong>Japan,”</strong></span> <span class='ocrx_word' id='word_1_164' title='bbox 556 962 633 979; x_wconf 77'><strong>decreed</strong></span> <span class='ocrx_word' id='word_1_165' title='bbox 645 963 683 979; x_wconf 79'><strong>and</strong></span> <span class='ocrx_word' id='word_1_166' title='bbox 695 962 759 980; x_wconf 76'><strong>issued</strong></span> <span class='ocrx_word' id='word_1_167' title='bbox 772 962 797 983; x_wconf 77'><strong>by</strong></span> <span class='ocrx_word' id='word_1_168' title='bbox 806 962 826 979; x_wconf 83'><strong>C.</strong></span> <span class='ocrx_word' id='word_1_169' title='bbox 835 962 857 979; x_wconf 76'><strong>E.</strong></span>
|
||||
<span class='ocr_line' id='line_1_22' title="bbox 121 962 857 983; baseline -0.001 -3; x_size 21; x_descenders 4; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_155' title='bbox 121 963 184 980; x_wconf 96'><strong><em>courts</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_156' title='bbox 198 962 219 979; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_157' title='bbox 228 963 261 979; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_158' title='bbox 272 962 342 980; x_wconf 96'><strong><em>United</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_159' title='bbox 356 962 419 980; x_wconf 96'><strong><em>States</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_160' title='bbox 430 962 450 979; x_wconf 95'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_161' title='bbox 465 962 544 983; x_wconf 95'><strong><em>Japan,”</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_162' title='bbox 556 962 633 979; x_wconf 96'><strong><em>decreed</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_163' title='bbox 645 963 683 979; x_wconf 96'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_164' title='bbox 695 962 759 980; x_wconf 93'><strong><em>issued</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_165' title='bbox 772 962 797 983; x_wconf 92'><strong><em>by</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_166' title='bbox 806 962 826 979; x_wconf 81'><strong><em>C.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_167' title='bbox 835 962 857 979; x_wconf 47'><strong><em>BE.</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_23' title="bbox 122 984 858 1007; baseline 0 -6; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_170' title='bbox 122 985 152 1001; x_wconf 84'><strong>De</strong></span> <span class='ocrx_word' id='word_1_171' title='bbox 158 984 217 1007; x_wconf 77'><strong>Long,</strong></span> <span class='ocrx_word' id='word_1_172' title='bbox 226 985 258 1002; x_wconf 74'><strong>the</strong></span> <span class='ocrx_word' id='word_1_173' title='bbox 266 985 350 1002; x_wconf 75'><strong>minister</strong></span> <span class='ocrx_word' id='word_1_174' title='bbox 361 985 383 1002; x_wconf 84'><strong>of</strong></span> <span class='ocrx_word' id='word_1_175' title='bbox 391 985 423 1002; x_wconf 80'><strong>the</strong></span> <span class='ocrx_word' id='word_1_176' title='bbox 431 984 501 1001; x_wconf 78'><strong>United</strong></span> <span class='ocrx_word' id='word_1_177' title='bbox 509 985 572 1002; x_wconf 71'><strong>States</strong></span> <span class='ocrx_word' id='word_1_178' title='bbox 579 984 597 1001; x_wconf 88'><strong>in</strong></span> <span class='ocrx_word' id='word_1_179' title='bbox 606 984 648 1002; x_wconf 71'><strong>that</strong></span> <span class='ocrx_word' id='word_1_180' title='bbox 656 986 740 1006; x_wconf 80'><strong>country,</strong></span> <span class='ocrx_word' id='word_1_181' title='bbox 749 984 768 1001; x_wconf 81'><strong>in</strong></span> <span class='ocrx_word' id='word_1_182' title='bbox 777 984 858 1005; x_wconf 81'><strong>Septem-</strong></span>
|
||||
<span class='ocr_line' id='line_1_23' title="bbox 122 984 858 1007; baseline 0 -6; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_168' title='bbox 122 985 152 1001; x_wconf 96'><strong><em>De</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_169' title='bbox 158 984 217 1007; x_wconf 96'><strong><em>Long,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_170' title='bbox 226 985 258 1002; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_171' title='bbox 266 985 350 1002; x_wconf 96'><strong><em>minister</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_172' title='bbox 361 985 383 1002; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_173' title='bbox 391 985 423 1002; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_174' title='bbox 431 984 501 1001; x_wconf 97'><strong><em>United</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_175' title='bbox 509 985 572 1002; x_wconf 96'><strong><em>States</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_176' title='bbox 579 984 597 1001; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_177' title='bbox 606 984 648 1002; x_wconf 96'><strong><em>that</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_178' title='bbox 656 986 740 1006; x_wconf 96'><strong><em>country,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_179' title='bbox 749 984 768 1001; x_wconf 92'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_180' title='bbox 777 984 858 1005; x_wconf 91'><strong><em>Septem-</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_24' title="bbox 121 1006 865 1034; baseline 0 -11; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_183' title='bbox 121 1007 160 1028; x_wconf 80'><strong>ber,</strong></span> <span class='ocrx_word' id='word_1_184' title='bbox 169 1007 223 1029; x_wconf 76'><strong>1870;</strong></span> <span class='ocrx_word' id='word_1_185' title='bbox 236 1008 273 1024; x_wconf 71'><strong>and</strong></span> <span class='ocrx_word' id='word_1_186' title='bbox 287 1007 326 1024; x_wconf 70'><strong>also</strong></span> <span class='ocrx_word' id='word_1_187' title='bbox 339 1007 371 1024; x_wconf 78'><strong>the</strong></span> <span class='ocrx_word' id='word_1_188' title='bbox 383 1011 450 1029; x_wconf 79'><strong>papers</strong></span> <span class='ocrx_word' id='word_1_189' title='bbox 461 1007 568 1024; x_wconf 77'><strong>mentioned</strong></span> <span class='ocrx_word' id='word_1_190' title='bbox 576 1006 595 1023; x_wconf 83'><strong>in</strong></span> <span class='ocrx_word' id='word_1_191' title='bbox 604 1007 635 1024; x_wconf 77'><strong>the</strong></span> <span class='ocrx_word' id='word_1_192' title='bbox 643 1007 741 1029; x_wconf 74'><strong>subjoiued</strong></span> <span class='ocrx_word' id='word_1_193' title='bbox 748 1006 786 1028; x_wconf 79'><strong>list,</strong></span> <span class='ocrx_word' id='word_1_194' title='bbox 794 1007 865 1034; x_wconf 52'><strong>which.</strong></span>
|
||||
<span class='ocr_line' id='line_1_24' title="bbox 121 1006 865 1034; baseline 0 -11; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_181' title='bbox 121 1007 160 1028; x_wconf 91'><strong><em>ber,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_182' title='bbox 169 1007 223 1029; x_wconf 95'><strong><em>1870;</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_183' title='bbox 236 1008 273 1024; x_wconf 84'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_184' title='bbox 287 1007 326 1024; x_wconf 95'><strong><em>also</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_185' title='bbox 339 1007 371 1024; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_186' title='bbox 383 1011 450 1029; x_wconf 96'><strong><em>papers</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_187' title='bbox 461 1007 568 1024; x_wconf 96'><strong><em>mentioned</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_188' title='bbox 576 1006 595 1023; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_189' title='bbox 604 1007 635 1024; x_wconf 93'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_190' title='bbox 643 1007 727 1029; x_wconf 92'><strong><em>subjoined</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_191' title='bbox 728 1006 786 1028; x_wconf 96'><strong><em>list,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_192' title='bbox 794 1007 865 1034; x_wconf 86'><strong><em>which,</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_25' title="bbox 122 1029 557 1051; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_195' title='bbox 122 1029 197 1046; x_wconf 74'><strong>contain</strong></span> <span class='ocrx_word' id='word_1_196' title='bbox 205 1029 324 1051; x_wconf 72'><strong>suggestions</strong></span> <span class='ocrx_word' id='word_1_197' title='bbox 332 1034 355 1046; x_wconf 87'><strong>on</strong></span> <span class='ocrx_word' id='word_1_198' title='bbox 363 1029 394 1046; x_wconf 72'><strong>the</strong></span> <span class='ocrx_word' id='word_1_199' title='bbox 402 1029 473 1050; x_wconf 75'><strong>subject</strong></span> <span class='ocrx_word' id='word_1_200' title='bbox 480 1029 557 1046; x_wconf 79'><strong>thereof.</strong></span>
|
||||
<span class='ocr_line' id='line_1_25' title="bbox 122 1029 557 1051; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_193' title='bbox 122 1029 197 1046; x_wconf 96'><strong><em>contain</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_194' title='bbox 205 1029 324 1051; x_wconf 96'><strong><em>suggestions</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_195' title='bbox 332 1034 355 1046; x_wconf 96'><strong><em>on</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_196' title='bbox 363 1029 394 1046; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_197' title='bbox 402 1029 473 1050; x_wconf 93'><strong><em>subject</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_198' title='bbox 480 1029 557 1046; x_wconf 85'><strong><em>thereof.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_14' lang='eng' title="bbox 120 1051 857 1185">
|
||||
<span class='ocr_line' id='line_1_26' title="bbox 144 1051 855 1074; baseline -0.001 -6; x_size 21; x_descenders 4; x_ascenders 5"><span class='ocrx_word' id='word_1_201' title='bbox 144 1052 164 1067; x_wconf 74'><strong>A</strong></span> <span class='ocrx_word' id='word_1_202' title='bbox 171 1056 218 1073; x_wconf 84'><strong>copy</strong></span> <span class='ocrx_word' id='word_1_203' title='bbox 226 1052 247 1068; x_wconf 80'><strong>of</strong></span> <span class='ocrx_word' id='word_1_204' title='bbox 253 1051 325 1068; x_wconf 73'><strong>Article</strong></span> <span class='ocrx_word' id='word_1_205' title='bbox 332 1051 399 1068; x_wconf 78'><strong>XXVI</strong></span> <span class='ocrx_word' id='word_1_206' title='bbox 407 1052 427 1069; x_wconf 84'><strong>of</strong></span> <span class='ocrx_word' id='word_1_207' title='bbox 433 1051 464 1068; x_wconf 85'><strong>the</strong></span> <span class='ocrx_word' id='word_1_208' title='bbox 472 1052 558 1068; x_wconf 79'><strong>consular</strong></span> <span class='ocrx_word' id='word_1_209' title='bbox 562 1051 676 1072; x_wconf 78'><strong>regulations</strong></span> <span class='ocrx_word' id='word_1_210' title='bbox 682 1052 698 1068; x_wconf 79'><strong>is</strong></span> <span class='ocrx_word' id='word_1_211' title='bbox 703 1052 742 1068; x_wconf 75'><strong>also</strong></span> <span class='ocrx_word' id='word_1_212' title='bbox 749 1051 855 1074; x_wconf 73'><strong>submitted,</strong></span>
|
||||
<span class='ocr_line' id='line_1_26' title="bbox 144 1051 855 1074; baseline -0.001 -6; x_size 21; x_descenders 4; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_199' title='bbox 144 1052 164 1067; x_wconf 95'><strong><em>A</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_200' title='bbox 171 1056 218 1073; x_wconf 95'><strong><em>copy</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_201' title='bbox 226 1052 247 1068; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_202' title='bbox 253 1051 325 1068; x_wconf 93'><strong><em>Article</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_203' title='bbox 332 1051 389 1068; x_wconf 86'><strong><em>XXVI</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_204' title='bbox 389 1052 427 1069; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_205' title='bbox 433 1051 464 1068; x_wconf 95'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_206' title='bbox 472 1052 558 1068; x_wconf 95'><strong><em>consular</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_207' title='bbox 562 1051 676 1072; x_wconf 95'><strong><em>regulations</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_208' title='bbox 682 1052 698 1068; x_wconf 96'><strong><em>is</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_209' title='bbox 703 1052 742 1068; x_wconf 94'><strong><em>also</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_210' title='bbox 749 1051 855 1074; x_wconf 95'><strong><em>submitted,</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_27' title="bbox 121 1072 856 1096; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_213' title='bbox 121 1073 158 1091; x_wconf 64'><strong>and</strong></span> <span class='ocrx_word' id='word_1_214' title='bbox 171 1073 204 1090; x_wconf 72'><strong>the</strong></span> <span class='ocrx_word' id='word_1_215' title='bbox 218 1074 315 1095; x_wconf 76'><strong>Secretary</strong></span> <span class='ocrx_word' id='word_1_216' title='bbox 321 1074 342 1090; x_wconf 77'><strong>of</strong></span> <span class='ocrx_word' id='word_1_217' title='bbox 351 1074 404 1091; x_wconf 77'><strong>State</strong></span> <span class='ocrx_word' id='word_1_218' title='bbox 415 1073 534 1095; x_wconf 77'><strong>respectfully</strong></span> <span class='ocrx_word' id='word_1_219' title='bbox 542 1074 634 1096; x_wconf 75'><strong>suggests,</strong></span> <span class='ocrx_word' id='word_1_220' title='bbox 643 1074 672 1090; x_wconf 84'><strong>fur</strong></span> <span class='ocrx_word' id='word_1_221' title='bbox 679 1074 712 1091; x_wconf 87'><strong>the</strong></span> <span class='ocrx_word' id='word_1_222' title='bbox 720 1072 856 1091; x_wconf 71'><strong>consideration</strong></span>
|
||||
<span class='ocr_line' id='line_1_27' title="bbox 121 1072 856 1096; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_211' title='bbox 121 1073 158 1091; x_wconf 95'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_212' title='bbox 171 1073 204 1090; x_wconf 95'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_213' title='bbox 218 1074 315 1095; x_wconf 96'><strong><em>Secretary</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_214' title='bbox 321 1074 342 1090; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_215' title='bbox 351 1074 404 1091; x_wconf 96'><strong><em>State</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_216' title='bbox 415 1073 534 1095; x_wconf 96'><strong><em>respectfully</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_217' title='bbox 542 1074 634 1096; x_wconf 96'><strong><em>suggests,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_218' title='bbox 643 1074 672 1090; x_wconf 96'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_219' title='bbox 679 1074 712 1091; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_220' title='bbox 720 1072 856 1091; x_wconf 96'><strong><em>consideration</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_28' title="bbox 120 1095 854 1118; baseline -0.001 -5; x_size 23; x_descenders 5; x_ascenders 6"><span class='ocrx_word' id='word_1_223' title='bbox 120 1095 142 1113; x_wconf 83'><strong>of</strong></span> <span class='ocrx_word' id='word_1_224' title='bbox 151 1095 248 1118; x_wconf 75'><strong>Congress,</strong></span> <span class='ocrx_word' id='word_1_225' title='bbox 257 1097 289 1113; x_wconf 78'><strong>the</strong></span> <span class='ocrx_word' id='word_1_226' title='bbox 302 1096 397 1118; x_wconf 74'><strong>propriety</strong></span> <span class='ocrx_word' id='word_1_227' title='bbox 408 1096 429 1113; x_wconf 82'><strong>of</strong></span> <span class='ocrx_word' id='word_1_228' title='bbox 437 1096 518 1117; x_wconf 75'><strong>limiting</strong></span> <span class='ocrx_word' id='word_1_229' title='bbox 530 1095 562 1113; x_wconf 83'><strong>the</strong></span> <span class='ocrx_word' id='word_1_230' title='bbox 573 1100 635 1117; x_wconf 70'><strong>power</strong></span> <span class='ocrx_word' id='word_1_231' title='bbox 643 1096 664 1113; x_wconf 83'><strong>of</strong></span> <span class='ocrx_word' id='word_1_232' title='bbox 673 1096 766 1113; x_wconf 80'><strong>ministers</strong></span> <span class='ocrx_word' id='word_1_233' title='bbox 774 1095 854 1113; x_wconf 77'><strong>tomake</strong></span>
|
||||
<span class='ocr_line' id='line_1_28' title="bbox 120 1095 854 1118; baseline -0.001 -5; x_size 23; x_descenders 5; x_ascenders 6">
|
||||
<span class='ocrx_word' id='word_1_221' title='bbox 120 1095 142 1113; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_222' title='bbox 151 1095 248 1118; x_wconf 96'><strong><em>Congress,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_223' title='bbox 257 1097 289 1113; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_224' title='bbox 302 1096 397 1118; x_wconf 96'><strong><em>propriety</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_225' title='bbox 408 1096 429 1113; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_226' title='bbox 437 1096 518 1117; x_wconf 96'><strong><em>limiting</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_227' title='bbox 530 1095 562 1113; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_228' title='bbox 573 1100 635 1117; x_wconf 96'><strong><em>power</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_229' title='bbox 643 1096 664 1113; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_230' title='bbox 673 1096 766 1113; x_wconf 96'><strong><em>ministers</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_231' title='bbox 774 1096 793 1112; x_wconf 96'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_232' title='bbox 799 1095 854 1113; x_wconf 96'><strong><em>make</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_29' title="bbox 121 1117 856 1140; baseline 0 -6; x_size 22; x_descenders 4; x_ascenders 5"><span class='ocrx_word' id='word_1_234' title='bbox 121 1118 197 1135; x_wconf 60'><strong>deerees</strong></span> <span class='ocrx_word' id='word_1_235' title='bbox 208 1118 246 1135; x_wconf 66'><strong>and</strong></span> <span class='ocrx_word' id='word_1_236' title='bbox 250 1117 361 1140; x_wconf 68'><strong>regulation,</strong></span> <span class='ocrx_word' id='word_1_237' title='bbox 369 1118 388 1135; x_wconf 75'><strong>in</strong></span> <span class='ocrx_word' id='word_1_238' title='bbox 395 1119 428 1136; x_wconf 73'><strong>the</strong></span> <span class='ocrx_word' id='word_1_239' title='bbox 435 1122 489 1135; x_wconf 62'><strong>sense,</strong></span> <span class='ocrx_word' id='word_1_240' title='bbox 495 1118 516 1135; x_wconf 74'><strong>in</strong></span> <span class='ocrx_word' id='word_1_241' title='bbox 523 1118 584 1136; x_wconf 68'><strong>which</strong></span> <span class='ocrx_word' id='word_1_242' title='bbox 591 1118 608 1135; x_wconf 73'><strong>it</strong></span> <span class='ocrx_word' id='word_1_243' title='bbox 614 1118 632 1135; x_wconf 80'><strong>is</strong></span> <span class='ocrx_word' id='word_1_244' title='bbox 638 1117 711 1135; x_wconf 67'><strong>limited</strong></span> <span class='ocrx_word' id='word_1_245' title='bbox 718 1118 743 1139; x_wconf 79'><strong>by</strong></span> <span class='ocrx_word' id='word_1_246' title='bbox 750 1118 856 1139; x_wconf 65'><strong>paragraph</strong></span>
|
||||
<span class='ocr_line' id='line_1_29' title="bbox 121 1117 856 1140; baseline 0 -6; x_size 22; x_descenders 4; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_233' title='bbox 121 1118 197 1135; x_wconf 95'><strong><em>decrees</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_234' title='bbox 208 1118 246 1135; x_wconf 94'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_235' title='bbox 250 1117 361 1140; x_wconf 94'><strong><em>regulation,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_236' title='bbox 369 1118 388 1135; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_237' title='bbox 395 1119 428 1136; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_238' title='bbox 435 1122 489 1135; x_wconf 96'><strong><em>sense</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_239' title='bbox 495 1118 516 1135; x_wconf 96'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_240' title='bbox 523 1118 584 1136; x_wconf 96'><strong><em>which</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_241' title='bbox 591 1118 608 1135; x_wconf 96'><strong><em>it</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_242' title='bbox 614 1118 632 1135; x_wconf 96'><strong><em>is</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_243' title='bbox 638 1117 711 1135; x_wconf 95'><strong><em>limited</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_244' title='bbox 718 1118 743 1139; x_wconf 96'><strong><em>by</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_245' title='bbox 750 1118 856 1139; x_wconf 96'><strong><em>paragraph</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_30' title="bbox 122 1140 857 1162; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_247' title='bbox 122 1140 156 1157; x_wconf 74'><strong>431</strong></span> <span class='ocrx_word' id='word_1_248' title='bbox 164 1140 186 1157; x_wconf 84'><strong>of</strong></span> <span class='ocrx_word' id='word_1_249' title='bbox 195 1141 227 1157; x_wconf 77'><strong>the</strong></span> <span class='ocrx_word' id='word_1_250' title='bbox 235 1140 300 1158; x_wconf 66'><strong>article</strong></span> <span class='ocrx_word' id='word_1_251' title='bbox 307 1140 369 1158; x_wconf 78'><strong>before</strong></span> <span class='ocrx_word' id='word_1_252' title='bbox 377 1140 508 1158; x_wconf 75'><strong>named—that</strong></span> <span class='ocrx_word' id='word_1_253' title='bbox 516 1141 537 1161; x_wconf 78'><strong>is,</strong></span> <span class='ocrx_word' id='word_1_254' title='bbox 547 1141 557 1151; x_wconf 81'><strong>“</strong></span> <span class='ocrx_word' id='word_1_255' title='bbox 563 1142 582 1158; x_wconf 80'><strong>to</strong></span> <span class='ocrx_word' id='word_1_256' title='bbox 591 1141 631 1157; x_wconf 76'><strong>acts</strong></span> <span class='ocrx_word' id='word_1_257' title='bbox 638 1141 760 1162; x_wconf 75'><strong>neeessaryto</strong></span> <span class='ocrx_word' id='word_1_258' title='bbox 770 1140 857 1162; x_wconf 70'><strong>organize</strong></span>
|
||||
<span class='ocr_line' id='line_1_30' title="bbox 122 1140 857 1162; baseline 0 -5; x_size 22; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_246' title='bbox 122 1140 156 1157; x_wconf 96'><strong><em>431</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_247' title='bbox 164 1140 186 1157; x_wconf 97'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_248' title='bbox 195 1141 227 1157; x_wconf 95'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_249' title='bbox 235 1140 300 1158; x_wconf 95'><strong><em>article</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_250' title='bbox 307 1140 369 1158; x_wconf 93'><strong><em>before</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_251' title='bbox 377 1140 499 1158; x_wconf 92'><strong><em>named—that</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_252' title='bbox 499 1141 537 1161; x_wconf 96'><strong><em>is,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_253' title='bbox 547 1141 582 1158; x_wconf 85'><strong><em>“to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_254' title='bbox 591 1141 631 1157; x_wconf 96'><strong><em>acts</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_255' title='bbox 638 1144 736 1162; x_wconf 95'><strong><em>necessary</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_256' title='bbox 741 1141 760 1157; x_wconf 96'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_257' title='bbox 770 1140 857 1162; x_wconf 96'><strong><em>organize</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_31' title="bbox 121 1162 662 1185; baseline 0.002 -6; x_size 22; x_descenders 4; x_ascenders 5"><span class='ocrx_word' id='word_1_259' title='bbox 121 1162 159 1180; x_wconf 70'><strong>and</strong></span> <span class='ocrx_word' id='word_1_260' title='bbox 168 1162 210 1184; x_wconf 77'><strong>give</strong></span> <span class='ocrx_word' id='word_1_261' title='bbox 218 1163 312 1184; x_wconf 79'><strong>efficiency</strong></span> <span class='ocrx_word' id='word_1_262' title='bbox 320 1164 340 1180; x_wconf 76'><strong>to</strong></span> <span class='ocrx_word' id='word_1_263' title='bbox 348 1163 380 1180; x_wconf 77'><strong>the</strong></span> <span class='ocrx_word' id='word_1_264' title='bbox 388 1164 449 1181; x_wconf 79'><strong>courts</strong></span> <span class='ocrx_word' id='word_1_265' title='bbox 458 1163 533 1180; x_wconf 74'><strong>created</strong></span> <span class='ocrx_word' id='word_1_266' title='bbox 539 1163 564 1185; x_wconf 83'><strong>by</strong></span> <span class='ocrx_word' id='word_1_267' title='bbox 574 1162 607 1180; x_wconf 74'><strong>the</strong></span> <span class='ocrx_word' id='word_1_268' title='bbox 615 1163 662 1180; x_wconf 71'><strong>act.”</strong></span>
|
||||
<span class='ocr_line' id='line_1_31' title="bbox 121 1162 662 1185; baseline 0.002 -6; x_size 22; x_descenders 4; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_258' title='bbox 121 1162 159 1180; x_wconf 96'><strong><em>and</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_259' title='bbox 168 1162 210 1184; x_wconf 97'><strong><em>give</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_260' title='bbox 218 1163 312 1184; x_wconf 96'><strong><em>efficiency</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_261' title='bbox 320 1164 340 1180; x_wconf 96'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_262' title='bbox 348 1163 380 1180; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_263' title='bbox 388 1164 449 1181; x_wconf 96'><strong><em>courts</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_264' title='bbox 458 1163 533 1180; x_wconf 96'><strong><em>created</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_265' title='bbox 539 1163 564 1185; x_wconf 96'><strong><em>by</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_266' title='bbox 574 1162 607 1180; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_267' title='bbox 615 1163 662 1180; x_wconf 96'><strong><em>act.”</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_15' lang='eng' title="bbox 144 1184 386 1207">
|
||||
<span class='ocr_line' id='line_1_32' title="bbox 144 1184 386 1207; baseline 0 -5; x_size 23; x_descenders 5; x_ascenders 5"><span class='ocrx_word' id='word_1_269' title='bbox 144 1185 271 1207; x_wconf 77'><strong>Respectfully</strong></span> <span class='ocrx_word' id='word_1_270' title='bbox 279 1184 386 1202; x_wconf 76'><strong>submitted.</strong></span>
|
||||
<span class='ocr_line' id='line_1_32' title="bbox 144 1184 386 1207; baseline 0 -5; x_size 23; x_descenders 5; x_ascenders 5">
|
||||
<span class='ocrx_word' id='word_1_268' title='bbox 144 1185 271 1207; x_wconf 86'><strong><em>Respectfully</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_269' title='bbox 279 1184 386 1202; x_wconf 93'><strong><em>submitted.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class='ocr_par' id='par_1_16' lang='eng' title="bbox 625 1206 834 1225">
|
||||
<span class='ocr_line' id='line_1_33' title="bbox 625 1206 834 1225; baseline -0.005 0; x_size 23.69949; x_descenders 5.5158105; x_ascenders 5.590498"><span class='ocrx_word' id='word_1_271' title='bbox 625 1206 760 1225; x_wconf 80'><strong>HAMILTON</strong></span> <span class='ocrx_word' id='word_1_272' title='bbox 768 1207 834 1224; x_wconf 77'>FISH.</span>
|
||||
<span class='ocr_line' id='line_1_33' title="bbox 625 1206 834 1225; baseline -0.005 0; x_size 23.69949; x_descenders 5.5158105; x_ascenders 5.590498">
|
||||
<span class='ocrx_word' id='word_1_270' title='bbox 625 1206 760 1225; x_wconf 96'><strong><em>HAMILTON</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_271' title='bbox 768 1207 834 1224; x_wconf 95'><strong><em>FISH.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_10' title="bbox 143 1229 317 1247">
|
||||
<p class='ocr_par' id='par_1_17' lang='eng' title="bbox 143 1229 317 1247">
|
||||
<span class='ocr_line' id='line_1_34' title="bbox 143 1229 317 1247; baseline 0.006 -1; x_size 22.296295; x_descenders 5.2962961; x_ascenders 4"><span class='ocrx_word' id='word_1_273' title='bbox 143 1229 183 1246; x_wconf 83'><strong>The</strong></span> <span class='ocrx_word' id='word_1_274' title='bbox 191 1230 317 1247; x_wconf 74'><strong>PRESIDENT.</strong></span>
|
||||
<span class='ocr_line' id='line_1_34' title="bbox 143 1229 317 1247; baseline 0.006 -1; x_size 22.296295; x_descenders 5.2962961; x_ascenders 4">
|
||||
<span class='ocrx_word' id='word_1_272' title='bbox 143 1229 183 1246; x_wconf 96'><strong><em>The</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_273' title='bbox 191 1230 317 1247; x_wconf 74'><strong><em>PRESIDENT,</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_11' title="bbox 345 1308 632 1331">
|
||||
<p class='ocr_par' id='par_1_18' lang='eng' title="bbox 345 1308 632 1331">
|
||||
<span class='ocr_line' id='line_1_35' title="bbox 345 1308 632 1331; baseline 0 -6; x_size 22; x_descenders 5; x_ascenders 4"><span class='ocrx_word' id='word_1_275' title='bbox 345 1308 387 1325; x_wconf 73'><strong>List</strong></span> <span class='ocrx_word' id='word_1_276' title='bbox 393 1308 415 1331; x_wconf 77'><strong>of</strong></span> <span class='ocrx_word' id='word_1_277' title='bbox 423 1308 557 1330; x_wconf 67'><strong>accompanying</strong></span> <span class='ocrx_word' id='word_1_278' title='bbox 561 1312 632 1331; x_wconf 70'><strong>papers.</strong></span>
|
||||
<span class='ocr_line' id='line_1_35' title="bbox 345 1308 632 1331; baseline 0 -6; x_size 22; x_descenders 5; x_ascenders 4">
|
||||
<span class='ocrx_word' id='word_1_274' title='bbox 345 1308 387 1325; x_wconf 91'><strong><em>List</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_275' title='bbox 393 1308 415 1331; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_276' title='bbox 423 1308 557 1330; x_wconf 96'><strong><em>accompanying</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_277' title='bbox 561 1312 632 1331; x_wconf 87'><strong><em>papers.</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_12' title="bbox 142 1340 857 1393">
|
||||
<p class='ocr_par' id='par_1_19' lang='eng' title="bbox 142 1340 857 1393">
|
||||
<span class='ocr_line' id='line_1_36' title="bbox 142 1340 857 1370; baseline 0 -5; x_size 23; x_descenders 5; x_ascenders 6"><span class='ocrx_word' id='word_1_279' title='bbox 142 1348 159 1365; x_wconf 88'><strong>1.</strong></span> <span class='ocrx_word' id='word_1_280' title='bbox 170 1348 293 1370; x_wconf 66'><strong>Regulations</strong></span> <span class='ocrx_word' id='word_1_281' title='bbox 300 1348 329 1365; x_wconf 79'><strong>for</strong></span> <span class='ocrx_word' id='word_1_282' title='bbox 338 1340 370 1366; x_wconf 49'><strong>the</strong></span> <span class='ocrx_word' id='word_1_283' title='bbox 378 1348 463 1366; x_wconf 63'><strong>consular</strong></span> <span class='ocrx_word' id='word_1_284' title='bbox 470 1350 533 1366; x_wconf 75'><strong>courts</strong></span> <span class='ocrx_word' id='word_1_285' title='bbox 541 1349 562 1366; x_wconf 81'><strong>of</strong></span> <span class='ocrx_word' id='word_1_286' title='bbox 570 1348 603 1365; x_wconf 80'><strong>the</strong></span> <span class='ocrx_word' id='word_1_287' title='bbox 611 1348 682 1366; x_wconf 76'><strong>United</strong></span> <span class='ocrx_word' id='word_1_288' title='bbox 690 1348 753 1366; x_wconf 74'><strong>States</strong></span> <span class='ocrx_word' id='word_1_289' title='bbox 761 1347 781 1365; x_wconf 82'><strong>in</strong></span> <span class='ocrx_word' id='word_1_290' title='bbox 788 1348 857 1370; x_wconf 63'>Japan.</span>
|
||||
<span class='ocr_line' id='line_1_36' title="bbox 142 1340 857 1370; baseline 0 -5; x_size 23; x_descenders 5; x_ascenders 6">
|
||||
<span class='ocrx_word' id='word_1_278' title='bbox 142 1348 159 1365; x_wconf 96'><strong><em>1,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_279' title='bbox 170 1348 293 1370; x_wconf 96'><strong><em>Regulations</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_280' title='bbox 300 1348 329 1365; x_wconf 96'><strong><em>for</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_281' title='bbox 338 1340 370 1366; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_282' title='bbox 378 1348 463 1366; x_wconf 96'><strong><em>consular</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_283' title='bbox 470 1350 533 1366; x_wconf 96'><strong><em>courts</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_284' title='bbox 541 1349 562 1366; x_wconf 96'><strong><em>of</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_285' title='bbox 570 1348 603 1365; x_wconf 96'><strong><em>the</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_286' title='bbox 611 1348 682 1366; x_wconf 95'><strong><em>United</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_287' title='bbox 690 1348 753 1366; x_wconf 96'><strong><em>States</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_288' title='bbox 761 1347 781 1365; x_wconf 95'><strong><em>in</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_289' title='bbox 788 1348 857 1370; x_wconf 93'><strong><em>Japan.</em></strong></span>
|
||||
</span>
|
||||
<span class='ocr_line' id='line_1_37' title="bbox 142 1371 644 1393; baseline 0.004 -7; x_size 30.84; x_descenders 5; x_ascenders 8.8400002"><span class='ocrx_word' id='word_1_291' title='bbox 142 1371 159 1387; x_wconf 88'><strong>2.</strong></span> <span class='ocrx_word' id='word_1_292' title='bbox 170 1371 205 1387; x_wconf 82'><strong>Mr.</strong></span> <span class='ocrx_word' id='word_1_293' title='bbox 214 1371 260 1388; x_wconf 78'><strong>Fish</strong></span> <span class='ocrx_word' id='word_1_294' title='bbox 268 1372 288 1389; x_wconf 79'><strong>to</strong></span> <span class='ocrx_word' id='word_1_295' title='bbox 295 1371 330 1388; x_wconf 74'><strong>Mr.</strong></span> <span class='ocrx_word' id='word_1_296' title='bbox 338 1371 368 1388; x_wconf 83'><strong>De</strong></span> <span class='ocrx_word' id='word_1_297' title='bbox 375 1371 433 1393; x_wconf 81'><strong>Long,</strong></span> <span class='ocrx_word' id='word_1_298' title='bbox 442 1371 550 1392; x_wconf 79'><strong>September</strong></span> <span class='ocrx_word' id='word_1_299' title='bbox 557 1371 585 1393; x_wconf 87'><strong>10,</strong></span> <span class='ocrx_word' id='word_1_300' title='bbox 594 1371 644 1388; x_wconf 84'><strong>1870.</strong></span>
|
||||
<span class='ocr_line' id='line_1_37' title="bbox 142 1371 644 1393; baseline 0.004 -7; x_size 30.84; x_descenders 5; x_ascenders 8.8400002">
|
||||
<span class='ocrx_word' id='word_1_290' title='bbox 142 1371 159 1387; x_wconf 90'><strong><em>2,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_291' title='bbox 170 1371 205 1387; x_wconf 96'><strong><em>Mr.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_292' title='bbox 214 1371 260 1388; x_wconf 95'><strong><em>Fish</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_293' title='bbox 268 1372 288 1389; x_wconf 95'><strong><em>to</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_294' title='bbox 295 1371 330 1388; x_wconf 95'><strong><em>Mr.</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_295' title='bbox 338 1371 368 1388; x_wconf 96'><strong><em>De</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_296' title='bbox 375 1371 433 1393; x_wconf 96'><strong><em>Long,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_297' title='bbox 442 1371 550 1392; x_wconf 95'><strong><em>September</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_298' title='bbox 557 1371 585 1393; x_wconf 95'><strong><em>10,</em></strong></span>
|
||||
<span class='ocrx_word' id='word_1_299' title='bbox 594 1371 644 1388; x_wconf 79'><strong><em>1870,</em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_13' title="bbox 0 0 1000 1520">
|
||||
<p class='ocr_par' id='par_1_20' lang='eng' title="bbox 0 0 1000 1520">
|
||||
<span class='ocr_line' id='line_1_38' title="bbox 0 0 1000 1520; baseline 0 2; x_size 763; x_descenders -381.5; x_ascenders 381.5"><span class='ocrx_word' id='word_1_301' title='bbox 0 0 1000 1520; x_wconf 95'><strong> </strong></span>
|
||||
<span class='ocr_line' id='line_1_38' title="bbox 0 0 1000 1520; baseline 0 2; x_size 763; x_descenders -381.5; x_ascenders 381.5">
|
||||
<span class='ocrx_word' id='word_1_300' title='bbox 0 0 1000 1520; x_wconf 95'><strong><em> </em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_14' title="bbox 24 1504 845 1520">
|
||||
<p class='ocr_par' id='par_1_21' lang='eng' title="bbox 24 1504 845 1520">
|
||||
<span class='ocr_line' id='line_1_39' title="bbox 24 1504 845 1520; baseline 0 0; x_size 8; x_descenders -4; x_ascenders 4"><span class='ocrx_word' id='word_1_302' title='bbox 24 1504 845 1520; x_wconf 95'><strong> </strong></span>
|
||||
<span class='ocr_line' id='line_1_39' title="bbox 24 1504 845 1520; baseline 0 0; x_size 8; x_descenders -4; x_ascenders 4">
|
||||
<span class='ocrx_word' id='word_1_301' title='bbox 24 1504 845 1520; x_wconf 95'><strong><em> </em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class='ocr_carea' id='block_1_15' title="bbox 982 987 1000 1500">
|
||||
<p class='ocr_par' id='par_1_22' lang='eng' title="bbox 982 987 1000 1500">
|
||||
<span class='ocr_line' id='line_1_40' title="bbox 982 987 1000 1500; baseline 0 0; x_size 256.5; x_descenders -128.25; x_ascenders 128.25"><span class='ocrx_word' id='word_1_303' title='bbox 982 987 1000 1500; x_wconf 95'><strong> </strong></span>
|
||||
<span class='ocr_line' id='line_1_40' title="bbox 982 987 1000 1500; baseline 0 0; x_size 256.5; x_descenders -128.25; x_ascenders 128.25">
|
||||
<span class='ocrx_word' id='word_1_302' title='bbox 982 987 1000 1500; x_wconf 95'><strong><em> </em></strong></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1 +1 @@
|
||||
Tesseract Open Source OCR Engine v3.05.01 with Leptonica
|
||||
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user