Fix all issues with rotations

All tests now pass
This commit is contained in:
James R. Barlow
2018-05-01 22:50:20 -07:00
parent f3b6d9dcdf
commit b5d7e9cbb0
3 changed files with 54 additions and 22 deletions
+22 -5
View File
@@ -49,7 +49,7 @@ def _gs_error_reported(stream):
def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
pageno=1, page_dpi=None):
pageno=1, page_dpi=None, rotation=None):
"""
Rasterize one page of a PDF at resolution (xres, yres) in canvas units.
@@ -71,6 +71,9 @@ def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
int_res = round(xres), round(yres)
if not page_dpi:
page_dpi = res
autorotate = '/PageByPage' if rotation is None else '/None'
with NamedTemporaryFile(delete=True) as tmp:
args_gs = [
'gs',
@@ -83,9 +86,12 @@ def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
'-dLastPage=%i' % pageno,
'-r{0}x{1}'.format(str(int_res[0]), str(int_res[1])),
'-o', tmp.name,
'-dAutoRotatePages=%s' % autorotate,
'-f',
fspath(input_file)
]
log.debug(args_gs)
p = run(args_gs, stdout=PIPE, stderr=STDOUT,
universal_newlines=True)
if _gs_error_reported(p.stdout):
@@ -110,10 +116,21 @@ def rasterize_pdf(input_file, output_file, xres, yres, raster_device, log,
log.debug(
"Ghostscript: resize output image {} -> {}".format(
im.size, expected_size))
im.resize(expected_size).save(
fspath(output_file), dpi=page_dpi)
else:
copy(tmp.name, fspath(output_file))
im = im.resize(expected_size)
if rotation is not None:
log.debug("Rotating output by %i", rotation)
# rotation is a clockwise angle and Image.ROTATE_* is
# counterclockwise so this cancels out the rotation
# if rotation == 90:
# im = im.transpose(Image.ROTATE_90)
# elif rotation == 180:
# im = im.transpose(Image.ROTATE_180)
# elif rotation == 270:
# im = im.transpose(Image.ROTATE_270)
# if rotation % 180 == 90:
# page_dpi = page_dpi[1], page_dpi[0]
im.save(fspath(output_file), dpi=page_dpi)
def generate_pdfa(pdf_pages, output_file, compression, log,
+28 -11
View File
@@ -66,6 +66,7 @@ class JobContext:
self.pdfinfo = None
self.options = None
self.work_folder = None
self.rotations = {}
def generate_pdfinfo(self, infile):
self.pdfinfo = PdfInfo(infile)
@@ -89,6 +90,12 @@ class JobContext:
def set_work_folder(self, work_folder):
self.work_folder = work_folder
def get_rotation(self, pageno):
return self.rotations.get(pageno, 0)
def set_rotation(self, pageno, value):
self.rotations[pageno] = value
from multiprocessing.managers import SyncManager
class JobContextManager(SyncManager):
@@ -418,7 +425,7 @@ def rasterize_preview(
ghostscript.rasterize_pdf(
input_file, output_file, xres=canvas_dpi, yres=canvas_dpi,
raster_device='jpeggray', log=log, page_dpi=(page_dpi, page_dpi),
pageno=page_number(input_file))
pageno=page_number(input_file), rotation=pageinfo.rotation)
def orient_page(
@@ -475,8 +482,8 @@ def orient_page(
if apply_correction:
pageno = page_number(page_pdf) - 1
pdfinfo = context.get_pdfinfo()
pdfinfo[pageno].rotation = orient_conf.angle
context.set_pdfinfo(pdfinfo) # This is expensive for large files
correction = (pdfinfo[pageno].rotation - orient_conf.angle) % 360
context.set_rotation(pageno, correction)
def rasterize_with_ghostscript(
@@ -507,10 +514,12 @@ def rasterize_with_ghostscript(
canvas_dpi = get_canvas_square_dpi(pageinfo, options)
page_dpi = get_page_square_dpi(pageinfo, options)
correction = context.get_rotation(page_number(input_file))
ghostscript.rasterize_pdf(
input_file, output_file, xres=canvas_dpi, yres=canvas_dpi,
raster_device=device, log=log, page_dpi=(page_dpi, page_dpi),
pageno=page_number(input_file))
pageno=page_number(input_file), rotation=correction)
def preprocess_remove_background(
@@ -720,7 +729,7 @@ def render_hocr_debug_page(
interwordSpaces=True)
def _weave_layers_graft(pdf_base, page_num, text, font, font_key, log):
def _weave_layers_graft(pdf_base, page_num, text, font, font_key, rotation, log):
from math import cos, sin, pi
log.info("Graft")
@@ -732,8 +741,6 @@ def _weave_layers_graft(pdf_base, page_num, text, font, font_key, log):
pdf_text_contents = pdf_text.pages[0].Contents.read_bytes()
base_page = pdf_base.pages.p(page_num)
rotation = int(base_page.get('/Rotate', 0))
rotation = rotation % 360
# The text page always will be oriented up by this stage but the original
# content may have a rotation applied. Wrap the text stream with a rotation
@@ -878,15 +885,25 @@ def weave_layers(
keep_open.append(pdf_image)
image_page = pdf_image.pages[0]
pdf_base.pages[page_num - 1] = image_page
#pdfinfo[page_num - 1].rotation = 0
log.info("Content rotation " + str(pdfinfo[page_num - 1].rotation))
text_content_rotation = 0 #pdfinfo[page_num - 1].rotation
log.info("Text content rotation ±" + str(text_content_rotation))
ctx_rotation = context.get_rotation(page_num - 1)
log.info("Saved correction ±" + str(ctx_rotation))
if text and font:
# Graft the text layer onto this page, whether new or old
_weave_layers_graft(
pdf_base, page_num, text, font, font_key, log)
pdf_base, page_num, text, font, font_key, text_content_rotation,
log
)
# Correct the rotation
rotation = pdfinfo[page_num - 1].rotation
rotation = -rotation % 360
# Correct the rotation if applicable
rotation = context.get_rotation(page_num - 1)
if rotation != 0:
pdf_base.pages[page_num - 1].Rotate = rotation
+4 -6
View File
@@ -639,15 +639,16 @@ def test_rotated_skew_timeout(resources, outpdf):
'--deskew', '--tesseract-timeout', '0')
out_pageinfo = PdfInfo(out)[0]
w, h = out_pageinfo.width_pixels, out_pageinfo.height_pixels
assert out_pageinfo.height_pixels > out_pageinfo.width_pixels, \
assert h > w, \
"Expected the output page to be portrait"
assert out_pageinfo.rotation == 0, \
"Expected no page rotation for output"
assert in_pageinfo.width_pixels == out_pageinfo.height_pixels and \
in_pageinfo.height_pixels == out_pageinfo.width_pixels, \
assert in_pageinfo.width_pixels == h and \
in_pageinfo.height_pixels == w, \
"Expected page rotation to be baked in"
@@ -986,9 +987,6 @@ def test_bad_utf8(spoof_tess_bad_utf8, renderer, resources, no_outpdf):
assert '\\x96' in err, 'should repeat backslash encoded output'
@pytest.mark.skipif(
not tesseract.has_textonly_pdf(),
reason="issue only affects sandwich")
def test_rotate_deskew_timeout(resources, outdir):
check_ocrmypdf(
resources / 'rotated_skew.pdf',