Resolved conflits with jbarlow83 pull request

This commit is contained in:
fritz-hh
2014-01-12 15:37:14 +01:00
2 changed files with 115 additions and 24 deletions
+104 -20
View File
@@ -6,12 +6,95 @@
# Initial version by Jonathan Brinley, jonathanbrinley@gmail.com
##############################################################################
from reportlab.pdfgen.canvas import Canvas
from reportlab.pdfgen.pdfimages import PDFImage
from reportlab.lib.units import inch
from lxml import etree as ElementTree
from PIL import Image
import re, sys
import argparse
def monkeypatch_method(cls):
'''
Override a class method at runtime.
Rationale:
https://mail.python.org/pipermail/python-dev/2008-January/076194.html
'''
def decorator(func):
setattr(cls, func.__name__, func)
return func
return decorator
@monkeypatch_method(PDFImage)
def PIL_imagedata(self):
'''
Add ability to output greyscale and 1-bit PIL images without conversion to RGB.
The upstream Python 2.7 version of reportlab converts 1-bit PIL images to RGB
instead of saving them in a lower BPP format. They have since added the following
fix to their Python 3.3 branch, but it has not been back-ported.
https://bitbucket.org/rptlab/reportlab/commits/177ddcbe4df6f9b461dac62612df9b8da3966a5d
'''
image = self.image
if image.format == 'JPEG':
fp = image.fp
fp.seek(0)
return self._jpg_imagedata(fp)
from reportlab.lib.utils import import_zlib
from reportlab import rl_config
from reportlab.pdfbase.pdfutils import _AsciiBase85Encode, _chunker
self.source = 'PIL'
zlib = import_zlib()
if not zlib:
return
bpc = 8
# Use the colorSpace in the image
if image.mode == 'CMYK':
myimage = image
colorSpace = 'DeviceCMYK'
bpp = 4
elif image.mode == '1':
myimage = image
colorSpace = 'DeviceGray'
bpp = 1
bpc = 1
elif image.mode == 'L':
myimage = image
colorSpace = 'DeviceGray'
bpp = 1
else:
myimage = image.convert('RGB')
colorSpace = 'RGB'
bpp = 3
imgwidth, imgheight = myimage.size
# this describes what is in the image itself
# *NB* according to the spec you can only use the short form in inline images
imagedata = ['BI /W %d /H %d /BPC %d /CS /%s /F [%s/Fl] ID' %
(imgwidth, imgheight, bpc, colorSpace, rl_config.useA85 and '/A85 ' or '')]
# use a flate filter and, optionally, Ascii Base 85 to compress
raw = myimage.tostring()
rowstride = (imgwidth * bpc * bpp + 7) / 8
assert len(raw) == rowstride * imgheight, "Wrong amount of data for image"
data = zlib.compress(raw) # this bit is very fast...
if rl_config.useA85:
# ...sadly this may not be
data = _AsciiBase85Encode(data)
# append in blocks of 60 characters
_chunker(data, imagedata)
imagedata.append('EI')
return (imagedata, imgwidth, imgheight)
class hocrTransform():
"""
A class for converting documents from the hOCR format.
@@ -24,20 +107,20 @@ class hocrTransform():
self.hocr = ElementTree.ElementTree()
self.hocr.parse(hocrFileName)
# if the hOCR file has a namespace, ElementTree requires its use to find elements
matches = re.match('({.*})html', self.hocr.getroot().tag)
self.xmlns = ''
if matches:
self.xmlns = matches.group(1)
# get dimension in pt (not pixel!!!!) of the OCRed image
for div in self.hocr.findall(".//%sdiv[@class='ocr_page']"%(self.xmlns)):
coords = self.element_coordinates(div)
self.width = self.px2pt(coords[2]-coords[0])
self.height = self.px2pt(coords[3]-coords[1])
break # there shouldn't be more than one, and if there is, we don't want it
# no width and heigh definition in the ocr_image element of the hocr file
if self.width is None:
print("No page dimension found in the hocr file")
@@ -54,7 +137,7 @@ class hocrTransform():
return self._get_element_text(body).encode('utf-8') # XML gives unicode
else:
return ''
def _get_element_text(self, element):
"""
Return the textual content of the element and its children
@@ -67,7 +150,7 @@ class hocrTransform():
if element.tail is not None:
text = text + element.tail
return text
def element_coordinates(self, element):
"""
Returns a tuple containing the coordinates of the bounding box around
@@ -80,13 +163,13 @@ class hocrTransform():
coords = matches.group(1).split()
out = (int(coords[0]),int(coords[1]),int(coords[2]),int(coords[3]))
return out
def px2pt(self, pxl):
"""
Returns the length in pt given length in pxl
"""
return float(pxl)/self.dpi*inch
def to_pdf(self, outFileName, imageFileName, showBoundingboxes, fontname="Helvetica"):
"""
Creates a PDF file with an image superimposed on top of the text.
@@ -97,13 +180,13 @@ class hocrTransform():
"""
# create the PDF file
pdf = Canvas(outFileName, pagesize=(self.width, self.height), pageCompression=1) # page size in points (1/72 in.)
# draw bounding box for each paragraph
pdf.setStrokeColorRGB(0,1,1) # light blue for bounding box of paragraph
pdf.setFillColorRGB(0,1,1) # light blue for bounding box of paragraph
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:
continue
@@ -113,12 +196,12 @@ class hocrTransform():
y1=self.px2pt(coords[1])
x2=self.px2pt(coords[2])
y2=self.px2pt(coords[3])
# draw the bbox border
if showBoundingboxes == True:
pdf.rect(x1, self.height-y2, x2-x1, y2-y1, fill=1)
pdf.rect(x1, self.height-y2, x2-x1, y2-y1, fill=1)
# check if element with class 'ocrx_word' are available
# otherwise use 'ocr_line' as fallback
elemclass="ocr_line"
@@ -141,7 +224,7 @@ class hocrTransform():
y1=self.px2pt(coords[1])
x2=self.px2pt(coords[2])
y2=self.px2pt(coords[3])
# draw the bbox border
if showBoundingboxes == True:
pdf.rect(x1, self.height-y2, x2-x1, y2-y1, fill=0)
@@ -152,7 +235,7 @@ class hocrTransform():
# set cursor to bottom left corner of bbox (adjust for dpi)
text.setTextOrigin(x1, self.height-y2)
# scale the width of the text to fill the width of the bbox
text.setHorizScale(100*(x2-x1)/pdf.stringWidth(elemtxt, fontname, fontsize))
@@ -162,13 +245,14 @@ class hocrTransform():
# put the image on the page, scaled to fill the page
if imageFileName != None:
im = Image.open(imageFileName)
im = Image.open(imageFileName)
pdf.drawInlineImage(im, 0, 0, width=self.width, height=self.height)
# finish up the page and save it
pdf.showPage()
pdf.save()
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')
@@ -181,5 +265,5 @@ if __name__ == "__main__":
hocr = hocrTransform(args.hocrfile, args.resolution)
hocr.to_pdf(args.outputfile, args.image, args.boundingboxes)
Executable → Regular
+11 -4
View File
@@ -43,7 +43,7 @@ FORCE_OCR="${14}" # Force to OCR, even if the page already contains fonts
# - 2: in case the page contains more than one image
##################################
getImgInfo() {
local page widthPDF heightPDF curImgInfo nbImg curImg propCurImg widthCurImg heightCurImg colorspaceCurImg dpi
local page widthPDF heightPDF curImgInfo nbImg curImg propCurImg widthCurImg heightCurImg colorspaceCurImg depthCurImg dpi
# page number
page="$1"
@@ -73,10 +73,11 @@ getImgInfo() {
fi
# Get characteristics of the extracted image
curImg=`ls -1 "$curOrigImg"* 2>/dev/null`
propCurImg=`identify -format "%w %h %[colorspace]" "$curImg"`
propCurImg=`identify -format "%w %h %[colorspace] %[depth]" "$curImg"`
widthCurImg=`echo "$propCurImg" | cut -f1 -d" "`
heightCurImg=`echo "$propCurImg" | cut -f2 -d" "`
colorspaceCurImg=`echo "$propCurImg" | cut -f3 -d" "`
depthCurImg=`echo "$propCurImg" | cut -f4 -d" "`
[ $VERBOSITY -ge $LOG_DEBUG ] && echo "Page $page: Size ${heightCurImg}x${widthCurImg} (in pixel)"
# compute the resolution of the image (making the assumption that x & y resolution are equal)
@@ -87,6 +88,7 @@ getImgInfo() {
# save the image characteristics
echo "DPI=$dpi" > "$curImgInfo"
echo "COLOR_SPACE=$colorspaceCurImg" >> "$curImgInfo"
echo "DEPTH=$depthCurImg" >> "$curImgInfo"
return 0
}
@@ -109,6 +111,7 @@ curImgInfo="$TMP_FLD/${page}.orig-img-info.txt" # Detected characteristics of
# auto-detect the characteristics of the embedded image
depthCurImg="8"
getImgInfo "$page" "$widthPDF" "$heightPDF" "$curImgInfo"
ret_code="$?"
# in case the page contains text do not OCR, unless the FORCE_OCR flag is set
@@ -127,6 +130,7 @@ else
# read the image characteristics from the file
dpi=`cat "$curImgInfo" | grep "^DPI=" | cut -f2 -d"="`
colorspaceCurImg=`cat "$curImgInfo" | grep "^COLOR_SPACE=" | cut -f2 -d"="`
depthCurImg=`cat "$curImgInfo" | grep "^DEPTH=" | cut -f2 -d"="`
fi
# perform oversampling if the resolution is not sufficient to get good OCR results
@@ -137,10 +141,13 @@ elif [ "$dpi" -lt "200" ]; then
[ $VERBOSITY -ge $LOG_WARN ] && echo "Page $page: Low image resolution detected ($dpi dpi). If needed, please use the \"-o\" to try to get better OCR results."
fi
# Identify if page image should be saved as ppm (color) or pgm (gray)
# Identify if page image should be saved as ppm (color), pgm (gray) or pbm (b&w)
ext="ppm" # by default (color image) the extension of the extracted image is ppm
opt="" # by default (color image) no option as to be passed to pdftoppm
if [ "$colorspaceCurImg" = "Gray" ]; then
if [ "$colorspaceCurImg" = "Gray" ] && [ "$depthCurImg" = "1" ]; then
ext="pbm"
opt="-mono"
elif [ "$colorspaceCurImg" = "Gray" ]; then
ext="pgm"
opt="-gray"
fi