コード例 #1
0
def cropImage(src,dest_folder,info,dest=None,to_tif=False):
    '''
    Crops src and outputs it to dest_folder or specified dest. Optionally
    output cropped image as bitonal tif-file.
    :param src: image to crop
    :param dest_folder: folder to output cropped image
    :param info: contains the coordinates for cropping 
    :param dest: possible path to output iamge to
    :param to_tif: output cropped as bitonal, group4 tif-file
    '''
    coordinates = info['crop_coordinates']
    w = info['image_width']
    h = info['image_height']
    file_name = os.path.basename(src)
    file_name,ext = os.path.splitext(file_name)
    if dest is None: dest = os.path.join(dest_folder,file_name+'_cropped'+ext)
    nw_x = coordinates['nw_x'] if info['l_crop'] else 0
    nw_y = coordinates['nw_y'] if info['t_crop'] else 0
    se_x = coordinates['se_x'] if info['r_crop'] else w
    se_y = coordinates['se_y'] if info['b_crop'] else h
    width = se_x-nw_x
    height = se_y-nw_y
    to_tif = '-threshold 60% -compress Group4' if to_tif else ''
    settings = '-crop {0}x{1}+{2}+{3}'.format(width,height,nw_x,nw_y)
    cmd = 'convert {0} {1} {2} {3}'.format(src,settings,to_tif,dest)
    processing.run_cmd(cmd,shell=True)
    return dest
コード例 #2
0
def mergePdfFilesInFolder(input_folder,pdf_dest):
    '''
    Merges all the pdf-files in a folder and outputs to a specified path
    '''
    src = os.path.join(input_folder,'*.pdf')
    cmd = 'pdftk {0} cat output {1}'.format(src,pdf_dest)
    processing.run_cmd(cmd,shell=True)
コード例 #3
0
def convertToBw(src,dest,threshold=10):
    '''
    Converts src to a bitonal tif-file compressed with Group4
    :param src: image file to convert/compress
    :param dest: where to output file to
    :param threshold: threshold for bitonal conversion
    '''
    cmd = 'convert {0} -threshold {1}% -compress Group4 {2}'
    cmd = cmd.format(src,threshold,dest)
    processing.run_cmd(cmd,shell=True)
    return dest
コード例 #4
0
    def runImport(self):
        '''
        NOTE - this script depends on the Goobi user (tomcat_user) being able to 
        ssh into the aleph server without password authentication, i.e. through a 
        public/private key setup. See the wiki for more details.
        '''

        # Build parameters to be send with call to aleph script
        barcode      = 'barcode={0} '.format(self.barcode)
        color        = 'color={0},{1} '.format(self.color_pdf, round(self.color_pdf_size))
        blackwhite   = 'blackwhite={0},{1} '.format(self.bw_pdf, round(self.bw_pdf_size))
        multivolumes = '{0}'.format(self.multivolumes) 
        login        = "******".format(self.aleph_server_user, self.aleph_server)
        script_path  = '/kb/bin/digitization_item.csh'
        parameters   = barcode+color+blackwhite+multivolumes
        cmd          = 'ssh {0} sudo -u aleph {1} {2}'.format(login, script_path, parameters)
        print(cmd)
        # Call aleph script
        result = processing.run_cmd(cmd,shell=True,print_output=False,raise_errors=False)
        if result['erred'] or 'error' in str(result['stderr']):
            err = ('Der opstod en fejl ved kald af aleph-scriptet '
                    ' ved koersel af kommandoen: {0}. '
                    'Fejlen er: {1}.')
            err = err.format(cmd,('stderr:'+result['output']+' output:'+result['output']))
            raise RuntimeError(err)
コード例 #5
0
def compressFile(input_file,output_file,quality=50,resize=None,resize_type='pct',
                 density=None):
    '''
    Converts an image file to jpeg. Resize image if selected. Compress image
    to selected quality percentage.

    :param input_file: image file to convert
    :param output_file: location for converted image file
    :param quality: percentage of compression
    :param resize: width or percentage to resize image to 
    :param resize_type: resize by width (keeping ratio) or by percentage
    '''
    if resize is not None:
        if resize_type == 'width':
            resize = '-resize {0}'.format(resize)
        elif resize != 100: # resize by percentage, only if it is set to anything else than 100 (=no resize)
            resize = '-resize {0}%'.format(resize)
        else:
            resize = ''
    else:
        resize = ''
    if density is not None: # Scale image correctly
        density = '-units PixelsPerInch -density {0}'.format(density)
    else:
        density = ''
    cmd = 'gm convert {0} {1} -quality {2} {3} {4}'.format(input_file,resize,quality,density,output_file)
    result = processing.run_cmd(cmd,shell=True,print_output=False,raise_errors=False)
    if result['erred']:
        err = ('An error occured when converting files with command {0}. '
               'Error: {1}.')
        err = err.format(cmd,result['output'])
        raise ConvertError(err)
コード例 #6
0
 def process(self,cmd):
     """
     cmds is simply the of arguments from sys.arg.
     The first element is the filename of the calling client.
     The second argument is the path to the python script to be called and
     the arguments to this call.
     """
     cmd_list = cmd.split()
     if len(cmd_list) >= 1:
         step_job_filename = os.path.basename(cmd_list[1])
         msg = 'Starting step job: {0}'.format(step_job_filename)
         self.logger.info(msg)
         try:
             result = processing.run_cmd(cmd, shell=True, print_output=False)
         except Exception as e:
             err = 'An error occured when processing step job {0}'
             err = err.format(cmd)
             if self.logger: self.logger.error(err)
             err = 'Error from failed step job: {0}'
             err = err.format(str(e))
             if self.logger: 
                 self.logger.error(err)
                 self.logger.error(traceback.format_exc())
             return
         msg = 'Step job {0} completed with result{1}.'
         msg = msg.format(step_job_filename,result['output'])
         self.logger.info(msg)
     else:
         if self.logger: self.logger.error('An empty job placed on queue.')
コード例 #7
0
    def runImport(self):
        """
        Using the supplied variables - call the script on the OJS server through ssh
        throws a CalledProcessError if the script failed.

        NOTE - this script depends on the Goobi user (tomcat_user) being able to
        ssh into the OJS server without password authentication, i.e. through a
        public/private key setup. See the wiki for more details.

        On the ojs server, disable 'requiretty' in visudo, otherwise, ssh user@server sudo ..., won't work
        """
        login = "******".format(self.ojs_server_user, self.ojs_server)
        cmd = "ssh {0} sudo php {1} NativeImportExportPlugin import {2} {3} {4}"
        if self.issn_missing:
            # Old method:
            cmd = cmd.format(login, self.tool_path, self.xml_path, self.volume_title, self.ojs_app_user)
        else:
            # New method:
            cmd = cmd.format(login, self.tool_path, self.xml_path, self.ojs_journal_path, self.ojs_app_user)
        self.debug_message(cmd)
        result = processing.run_cmd(cmd, shell=True, print_output=False, raise_errors=False)
        if (result["erred"]) or ("error" in str(result["stderr"])) or ("FEJL" in str(result["stderr"])):
            err = (
                "Der opstod en fejl ved import af OJS-xml-filen på "
                " www.tidsskrift.dk ved kørsel af kommandoen: {0}. "
                "Fejlen er: {1}."
            )
            err = err.format(cmd, ("stderr:" + result["output"] + " output:" + result["output"]))
            raise RuntimeError(err)
コード例 #8
0
def getDeskewAngle(src,threshold=75):
    '''
    Get deskew angle for an image using ImageMagick's "deskew". Threshold is
    suggested by ImageMagick to be set to 40, but I think I have experience
    that 75 is better for books.
      
    :param src:
    :param threshold:
    '''
    cmd = "convert {0} -deskew {1} -format '%[deskew:angle]' info:".format(src,threshold)
    output = processing.run_cmd(cmd,shell=True)
    return float(output['stdout'])
コード例 #9
0
ファイル: misc.py プロジェクト: akademy/goobi-scripts
def deskewImage(src,dest_folder,angle,quality=None,resize=None):
    '''
    Deskews an image with a given angle.
    
    :param src: path to image to deskew
    :param dest_folder: where to output deskewed image
    :param angle: what to deskew image with
    :param quality: what to compress output image with
    :param resize: what to resize output image with (pct)
    '''
    file_name,ext = os.path.splitext(os.path.basename(src))
    dest = os.path.join(dest_folder,file_name+'deskewed'+ext)
    if quality is not None:
        quality = '-quality {0}%'.format(quality)
    else:
        quality = ''
    if resize is not None:
        resize = '-resize {0}%'.format(resize)
    else:
        resize = ''
    cmd = 'convert {0} -rotate {1} {2} {3} {4}'.format(src,angle,resize,quality,dest)
    processing.run_cmd(cmd,shell=True)
    return dest
コード例 #10
0
def getImageDimensions(image_path):
    '''
    Use ImageMagicks "identify" to get the dimensions (width and height) of an 
    image file.
    :param image_path: image file to get dimensions for
    '''
    try:
        # Use identify instead
        cmd = 'identify {0}'.format(image_path)
        identify_info = processing.run_cmd(cmd = cmd,shell=True,print_output = False)
        size = str(identify_info['stdout']).split()[2].split('x')
    except Exception as e:
        # Ye, I know
        raise e
    width, height = int(size[0]),int(size[1])
    return width, height
コード例 #11
0
def joinPdfFiles(pdf_list,dest_path):
    '''
    Adds a list of pdf-files in front of a master pdf. It creates a new temp
    pdf in the temp_folder and if everything goes right, it overwrites the
    master with the outputted pdf-file.
    '''
    if len(pdf_list) == 0:
        raise ValueError('No pdf files to join')
    # Make sure that all pdf-files exists
    for pdf in pdf_list:
        if not os.path.exists(pdf):
            raise OSError('{0} does not exists.'.format(pdf))
    pdfs = ' '.join(pdf_list)
    cmd = 'pdftk {0} cat output {1}'.format(pdfs, dest_path)
    output = processing.run_cmd(cmd,shell=True)
    if output['erred'] or 'error' in str(output['stdout']):
        raise OSError('An error occured when converting files to pdf with ' 
                      'command {0}. Error: {1}.'.format(cmd,output))
コード例 #12
0
def innercrop(src,dest_folder,w,h,innercrop_path,mode='box',fuzzval=75):
    '''
    Returns the crop coordinates for src as a dictionary together with 
    a path to a cropped version of src.
    
    Uses "innercrop" from Fred's ImageMagick Scripts to get coordinates for
    cropping the image. "innercrop" also outputs a cropped image file.
    
    http://www.fmwconcepts.com/imagemagick/innercrop/index.php
    '''
    file_name,ext = os.path.splitext(os.path.basename(src))
    if mode == 'box':
        dest = os.path.join(dest_folder,file_name+'_innercrop.jpg')
    else:
        dest = os.path.join(dest_folder,file_name+'_innercrop'+ext)
    cmd = '{0} -f {1} -m {2} {3} {4}'
    cmd = cmd.format(innercrop_path,fuzzval,mode,src,dest)
    output = processing.run_cmd(cmd,shell=True)
    if output['erred'] or 'error' in str(output['stderr']).lower():
        raise InnerCropError(output['stderr'].decode("utf-8"))
    coordinates = getInnercropCoordinates(output['stdout'],w,h)
    return dest,coordinates
コード例 #13
0
def getDensity(src, layer):
    '''
    Use identify to get information about a pdf-file. Use some simple text
    search to get resolution fra raw identify-output
    :param src:
    :param layer:
    
    Notes: consider to output a default density (DPI), e.g. 72, if using 
    "identify" fails.
    '''
    
    cmd = 'identify -verbose {0}[{1}]'.format(src,layer)
    output = processing.run_cmd(cmd,shell=True)
    if output['erred'] or 'error' in str(output['stdout']):
        raise OSError('An error occured when identifying pdf-file with ' 
                      'command {0}. Error: {1}.'.format(cmd,output))
    # txt = (output['stdout'].decode('utf-8')).splitlines()
    txt_raw_list = (output['stdout']).splitlines()
    line_counter = 0
    txt = []
    for t in txt_raw_list:
        line_counter += 1
        try:
            t = t.decode('utf-8')
        except UnicodeError as e:
            t = "[skipped line {0} - Error: {1}]".format(line_counter, e)
            print(t)
        txt.append(t)
    res_s = 'Resolution: '
    res_e = 'x'
    rl = [l for l in txt if res_s in l]
    error = ('Resolusion could not be found with identify. Cmd: '
             '"{0}". Output: "{1}"'.format(cmd,txt))
    if len(rl) == 0: raise ValueError(error)
    rl = rl[0]
    res = rl[rl.find(res_s)+len(res_s):rl.find(res_e)]
    if not res.isdigit(): raise ValueError(error)
    res = int(res)
    return res