'Performs OCR on a given set of pages'

def parse(self, form_uuid, set_uuid, **kwargs):

    raw_images = {}
    images = {}
    self.set_uuid = set_uuid
    db = current.db
    T = current.T
    request = self.request
    metatable = 'ocr_meta'
    query = (db[metatable]['form_uuid'] == form_uuid)
    row = db(query).select(limitby=(0, 1)).first()
    revision = row['revision']
    resourcename = row['resource_name']
    layoutfilename = row['layout_file']
    pages = int(row['pages'])
    is_component = (True if (len(self.r.resource.components) == 1) else False)
    for eachpage in xrange(1, (pages + 1)):
        payloadtable = 'ocr_payload'
        row = db(((db[payloadtable]['image_set_uuid'] == set_uuid) & (db[payloadtable]['page_number'] == eachpage))).select().first()
        pageimagefile = row['image_file']
        raw_images[eachpage] = Image.open(os.path.join(self.r.folder, 'uploads', 'ocr_payload', pageimagefile))
    for each_img_index in raw_images.keys():
        images[each_img_index] = {}
        images[each_img_index]['image'] = self.__convertImage2binary(raw_images[each_img_index])
        images[each_img_index]['markers'] = self.__getMarkers(images[each_img_index]['image'])
        images[each_img_index]['orientation'] = self.__getOrientation(images[each_img_index]['markers'])
        if (images[each_img_index]['orientation'] != 0.0):
            images[each_img_index]['image'] = images[each_img_index]['image'].rotate(images[each_img_index]['orientation'])
            images[each_img_index]['markers'] = self.__getMarkers(images[each_img_index]['image'])
            images[each_img_index]['orientation'] = self.__getOrientation(images[each_img_index]['markers'])
        images[each_img_index]['scalefactor'] = self.__scaleFactor(images[each_img_index]['markers'])
    layout_file = open(os.path.join(self.r.folder, 'uploads', 'ocr_meta', layoutfilename), 'rb')
    layout_xml = layout_file.read()
    layout_file.close()
    layout_etree = etree.fromstring(layout_xml)
    s3xml_root_etree = etree.Element('s3xml')
    parent_resource_exist = False
    SubElement = etree.SubElement
    for resource in layout_etree:
        if (not is_component):
            if (parent_resource_exist == False):
                s3xml_parent_resource_etree = SubElement(s3xml_root_etree, 'resource')
                s3xml_resource_etree = s3xml_parent_resource_etree
                parent_resource_exist = True
            else:
                s3xml_resource_etree = SubElement(s3xml_parent_resource_etree, 'resource')
        else:
            s3xml_resource_etree = SubElement(s3xml_root_etree, 'resource')
        s3xml_resource_etree.set('name', resource.attrib.get('name', None))
        for field in resource:
            field_name = field.attrib.get('name', None)
            field_type = field.attrib.get('type', None)
            field_reference = field.attrib.get('reference')
            if (field_reference == '1'):
                field_is_reference = True
                field_resource = field.attrib.get('resource')
            else:
                field_is_reference = False
            if field_is_reference:
                s3xml_reference_etree = SubElement(s3xml_resource_etree, 'reference')
                s3xml_reference_etree.set('field', field_name)
                s3xml_reference_etree.set('resource', field_resource)
                s3xml_sub_reference_etree = SubElement(s3xml_reference_etree, 'resource')
                s3xml_sub_reference_etree.set('name', field_resource)
                s3xml_field_etree = SubElement(s3xml_sub_reference_etree, 'data')
                s3xml_field_etree.set('field', 'name')
            else:
                s3xml_field_etree = SubElement(s3xml_resource_etree, 'data')
                s3xml_field_etree.set('field', field_name)
            components = field.getchildren()
            numcomponents = len(components)
            null_field = False
            if (numcomponents == 0):
                continue
            else:
                component_type = components[0].tag
                if (component_type in ('optionbox', 'textbox')):
                    if (component_type == 'optionbox'):
                        linenum = 0
                        OCRText = []
                        OCRValue = []
                        for component in components:
                            get = component.attrib.get
                            comp_x = float(get('x'))
                            comp_y = float(get('y'))
                            comp_boxes = int(get('boxes'))
                            comp_radius = float(get('radius'))
                            comp_page = int(get('page'))
                            comp_value = str(get('value'))
                            comp_text = str(component.text)
                            try:
                                page_origin = images[comp_page]['markers']
                            except KeyError:
                                self.r.error(501, T('insufficient    number    of    pages    provided'))
                            crop_box = (int(((page_origin[0][0] + (comp_x * images[comp_page]['scalefactor']['x'])) - (comp_radius * images[comp_page]['scalefactor']['x']))), int(((page_origin[0][1] + (comp_y * images[comp_page]['scalefactor']['y'])) - (comp_radius * images[comp_page]['scalefactor']['y']))), int(((page_origin[0][0] + (comp_x * images[comp_page]['scalefactor']['x'])) + (comp_radius * images[comp_page]['scalefactor']['x']))), int(((page_origin[0][1] + (comp_y * images[comp_page]['scalefactor']['y'])) + (comp_radius * images[comp_page]['scalefactor']['y']))))
                            temp_image = images[comp_page]['image'].crop(crop_box)
                            cropped_image = images[comp_page]['image'].crop(crop_box)
                            result = self.__ocrIt(cropped_image, form_uuid, resourcename, linenum, content_type='optionbox', resource_table=resource.attrib.get('name'), field_name=field.attrib.get('name'), field_value=comp_value)
                            if result:
                                OCRText.append(unicode.strip(comp_text.decode('utf-8')))
                                OCRValue.append(unicode.strip(comp_value.decode('utf-8')))
                            linenum += 1
                        if (len(OCRValue) in [0, 1]):
                            uOCRValue = '|'.join(OCRValue)
                            uOCRText = '|'.join(OCRText)
                        else:
                            uOCRValue = ('|%s|' % '|'.join(OCRValue))
                            uOCRText = ('|%s|' % '|'.join(OCRText))
                        s3xml_field_etree.set('value', uOCRValue)
                        s3xml_field_etree.text = uOCRText
                        if (len(OCRValue) == 0):
                            null_field = True
                        else:
                            null_field = False
                    elif (component_type == 'textbox'):
                        linenum = 1
                        if (field_type in ['date', 'datetime']):
                            OCRedValues = {}
                            comp_count = 1
                            for component in components:
                                get = component.attrib.get
                                comp_x = float(get('x'))
                                comp_y = float(get('y'))
                                comp_boxes = int(get('boxes'))
                                comp_side = float(get('side'))
                                comp_page = int(get('page'))
                                comp_meta = str(component.text)
                                try:
                                    page_origin = images[comp_page]['markers']
                                except KeyError:
                                    self.r.error(501, T('insufficient    number    of    pages    provided'))
                                crop_box = (int((page_origin[0][0] + (comp_x * images[comp_page]['scalefactor']['x']))), int((page_origin[0][1] + (comp_y * images[comp_page]['scalefactor']['y']))), int(((page_origin[0][0] + (comp_x * images[comp_page]['scalefactor']['x'])) + ((comp_side * comp_boxes) * images[comp_page]['scalefactor']['x']))), int(((page_origin[0][1] + (comp_y * images[comp_page]['scalefactor']['y'])) + (comp_side * images[comp_page]['scalefactor']['y']))))
                                cropped_image = images[comp_page]['image'].crop(crop_box)
                                output = self.__ocrIt(cropped_image, form_uuid, resourcename, linenum, resource_table=resource.attrib.get('name'), field_name=field.attrib.get('name'), field_seq=comp_count)
                                linenum += 1
                                comp_count += 1
                                OCRedValues[comp_meta] = unicode.strip(output.decode('utf-8'))
                            yyyy = datetime.now().year
                            try:
                                if (int(OCRedValues['YYYY']) in range(1800, 2300)):
                                    yyyy = int(OCRedValues['YYYY'])
                            except:
                                pass
                            if ((yyyy % 4) == 0):
                                leapyear = True
                            else:
                                leapyear = False
                            try:
                                if (int(OCRedValues['MO']) in range(1, 13)):
                                    mo = int(OCRedValues['MO'])
                            except:
                                mo = 1
                            try:
                                if (int(OCRedValues['DD']) in range(1, 32)):
                                    dd = int(OCRedValues['DD'])
                            except:
                                dd = 1
                            if (mo in [4, 6, 9, 11]):
                                if (dd == 31):
                                    dd = 1
                            elif (mo == 2):
                                if leapyear:
                                    if (dd > 29):
                                        dd = 1
                                elif (dd > 28):
                                    dd = 1
                            if (field_type == 'datetime'):
                                try:
                                    if (int(OCRedValues['MM']) in range(0, 60)):
                                        mm = int(OCRedValues['MM'])
                                except:
                                    mm = 0
                                try:
                                    if (int(OCRedValues['HH']) in range(0, 24)):
                                        hh = int(OCRedValues['HH'])
                                except:
                                    hh = 0
                            if (field_type == 'date'):
                                s3xml_field_etree.set('value', ('%s-%s-%s' % (yyyy, mo, dd)))
                                s3xml_field_etree.text = ('%s-%s-%s' % (yyyy, mo, dd))
                            elif (field_type == 'datetime'):
                                utctime = self.__convert_utc(yyyy, mo, dd, hh, mm)
                                utcftime = utctime.strftime('%Y-%m-%dT%H:%M:%SZ')
                                s3xml_field_etree.set('value', utcftime)
                                s3xml_field_etree.text = utcftime
                        else:
                            ocrText = ''
                            comp_count = 1
                            for component in components:
                                comp_x = float(component.attrib.get('x'))
                                comp_y = float(component.attrib.get('y'))
                                comp_boxes = int(component.attrib.get('boxes'))
                                comp_side = float(component.attrib.get('side'))
                                comp_page = int(component.attrib.get('page'))
                                comp_meta = str(component.text)
                                try:
                                    page_origin = images[comp_page]['markers']
                                except KeyError:
                                    self.r.error(501, T('insufficient    number    of    pages    provided'))
                                crop_box = (int((page_origin[0][0] + (comp_x * images[comp_page]['scalefactor']['x']))), int((page_origin[0][1] + (comp_y * images[comp_page]['scalefactor']['y']))), int(((page_origin[0][0] + (comp_x * images[comp_page]['scalefactor']['x'])) + ((comp_side * comp_boxes) * images[comp_page]['scalefactor']['x']))), int(((page_origin[0][1] + (comp_y * images[comp_page]['scalefactor']['y'])) + (comp_side * images[comp_page]['scalefactor']['y']))))
                                cropped_image = images[comp_page]['image'].crop(crop_box)
                                output = self.__ocrIt(cropped_image, form_uuid, resourcename, linenum, resource_table=resource.attrib.get('name'), field_name=field.attrib.get('name'), field_seq=comp_count)
                                ocrText += output
                                linenum += 1
                                comp_count += 1
                            output = unicode.strip(ocrText.decode('utf-8'))
                            if (field_type in ['double', 'integer']):
                                try:
                                    output = int(self.__strip_spaces(output))
                                except:
                                    output = 0
                                s3xml_field_etree.set('value', ('%s' % output))
                                s3xml_field_etree.text = ('%s' % output)
                            else:
                                s3xml_field_etree.text = output
                            if (len(('%s' % output)) == 0):
                                null_field = True
                            else:
                                null_field = False
                else:
                    continue
            if null_field:
                if field_is_reference:
                    s3xml_resource_etree.remove(s3xml_reference_etree)
                else:
                    s3xml_resource_etree.remove(s3xml_field_etree)
    output = etree.tostring(s3xml_root_etree, pretty_print=True)
    return output
