
    j5jOF                       d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddl
mZmZmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZ ddlmZmZ ddlm Z m!Z! ddl"m#Z# ddl$m%Z%  ejL                  e'      Z(ddZ) G d de      Z*ed        Z+ed        Z,ed        Z-ed        Z.edd       Z/ G d de#      Z0ed        Z1y)z1Built-in plugin to implement OCR using Tesseract.    )annotationsN)	Annotated)Image)	BaseModelFieldfield_validatormodel_validator)hookimpl	tesseract)ThresholdingMethod)PageContext)numeric)BadArgsErrorMissingDependencyError)available_cpu_countclamp)calculate_downsampledownsample_image)	OcrEngine)check_external_programc                @   t         j                  t         j                  t         j                  t         j                  d}| j                         |vr;ddl}dj                  |j                               } |j                  d|  d|       || j                            S )a+  Convert string argument to ThresholdingMethod enum.

    Args:
        value: String name of thresholding method (auto, otsu, adaptive-otsu, sauvola)

    Returns:
        ThresholdingMethod enum value

    Raises:
        argparse.ArgumentTypeError: If value is not a valid thresholding method
    )autootsuzadaptive-otsusauvolar   N, zInvalid thresholding method 'z'. Must be one of: )
r   AUTOOTSUADAPTIVE_OTSUSAUVOLAlowerargparsejoinkeysArgumentTypeError)value
method_mapr"   valids       \/var/www/html/qr/venv/lib/python3.12/site-packages/ocrmypdf/builtin_plugins/tesseract_ocr.py_thresholding_method_converterr*      s     #''"''+99%--	J {{}J&		*//+,(h((+E72EeWM
 	
 ekkm$$    c                  H   e Zd ZU dZg Zded<   dZded<   dZded<   ej                  Z
d	ed
<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   ed#d$d       Z edd      ed               Z ed      ed               Z ed       d!        Zd%d"Zy)&TesseractOptionsz)Options specific to Tesseract OCR engine.zSAnnotated[list[str], Field(description='Additional Tesseract configuration files')]configNz]Annotated[int | None, Field(ge=0, le=13, description='Set Tesseract page segmentation mode')]pagesegmodezUAnnotated[int | None, Field(ge=0, le=3, description='Set Tesseract OCR engine mode')]oemz_Annotated[ThresholdingMethod, Field(description='Set Tesseract input image thresholding mode')]thresholding     f@zRAnnotated[float, Field(ge=0, description='Timeout for OCR operations in seconds')]timeoutzVAnnotated[float, Field(ge=0, description='Timeout for non-OCR operations in seconds')]non_ocr_timeoutTzHAnnotated[bool, Field(description='Downsample large images before OCR')]downsample_large_images  zdAnnotated[int, Field(ge=100, le=32767, description='Downsample images larger than this pixel size')]downsample_abovezMAnnotated[str | None, Field(description='Path to Tesseract user words file')]
user_wordszPAnnotated[str | None, Field(description='Path to Tesseract user patterns file')]user_patternszpAnnotated[int | None, Field(description='Calculated OMP_THREAD_LIMIT for Tesseract subprocesses', exclude=True)]omp_thread_limitc           
     0   |j                  dd      }|j                  d| dddg | dd	       |j                  d| d
dt        dt        dd      | dd       |j                  d| ddt        dt        dd      | dd       |j                  d| ddt        d| dd       |j                  d| ddt        t        d      d| dd | d!"       |j                  d| d#dt        t        d      d| d$d%| d&"       |j                  d| d't        j                  d(| d)d*| d+,       |j                  d| d-dt        t        d.d/      d/| d0d1| d2       |j                  d3d4d5d67       |j                  d8d4d9d:7       y;)<zAdd Tesseract-specific arguments to the argument parser.

        Args:
            parser: The argument parser to add arguments to
            namespace: The namespace prefix for argument names
        	Tesseractz!Advanced control of Tesseract OCRz--z-configappendCFG_configz>Additional Tesseract configuration files -- see documentation.)actionmetavardefaultdesthelpz-pagesegmodestorePSMr      _pagesegmodez<Set Tesseract page segmentation mode (see tesseract --help).)r@   typerA   choicesrC   rD   z-oemMODE   _oemz|Set Tesseract 4+ OCR engine mode: 0 - original Tesseract only; 1 - neural nets LSTM only; 2 - Tesseract + LSTM; 3 - default.z-thresholdingr   _thresholdingay  Set Tesseract 5.0+ input image thresholding mode. This may improve OCR results on low quality images or those that contain high contrast color. Options: auto, otsu, adaptive-otsu, sauvola. auto/otsu is the Tesseract default (legacy Otsu); adaptive-otsu is an improved Otsu algorithm with improved sort for background color changes; sauvola is based on local standard deviation.)r@   rI   rB   rC   rD   z-timeoutr2   SECONDS_timeoutzGive up on OCR after the timeout, but copy the preprocessed page into the final output. This timeout is only used when using Tesseract for OCR. When Tesseract is used for other operations such as deskewing and orientation, the timeout is controlled by --z-non-ocr-timeout.)rB   rI   rA   rC   rD   z-non-ocr-timeout_non_ocr_timeoutzqGive up on non-OCR operations such as deskewing and orientation after timeout. This is a separate timeout from --z>-timeout because these operations are not as expensive as OCR.z-downsample-large-imagesT_downsample_large_imagesa  Downsample large images before OCR. Tesseract has an upper limit on the size images it will support. If this argument is given, OCRmyPDF will downsample large images to fit Tesseract. This may reduce OCR quality, on large images the most desirable text is usually larger. If this parameter is not supplied, Tesseract will error out and produce no OCR on the page in question. This argument should be used with a high value of --z0-timeout to ensure Tesseract has enough to time.)r@   rB   rC   rD   z-downsample-aboved   r6   _downsample_abovezTDownsample images larger than this size pixel size (either dimension) before OCR. --a  -downsample-large-images downsamples when an image exceeds Tesseract's internal limits. This argument causes downsampling to occur when an image exceeds the given size. This may reduce OCR quality, but on large images the most desirable text is usually larger.z--user-wordsFILEr8   a  Specify the location of the Tesseract user words file. This is a list of words Tesseract should consider while performing OCR in addition to its standard language dictionaries. This can improve OCR quality especially for specialized and technical documents.)rA   rC   rD   z--user-patternsr9   z9Specify the location of the Tesseract user patterns file.N)	add_argument_groupadd_argumentintranger*   r   floatr"   BooleanOptionalAction)clsparser	namespacetesss       r)   add_arguments_to_parserz(TesseractOptions.add_arguments_to_parseri   s    ((<
 	7#;g&Q 	 	
 	<(!RL;l+O 	 	
 	4 !QK;d# 	 	
  	=)/;m,O 	 	
  	8$";h' K0	2 	 	
 	+,";./DDM; OHH 	 	
 	3411;67	 "{ #&
& 	 	
( 	,-c5);/0!!* ,"" 	 	
  	N	 	 	
 	 L	 	 	
r+   c                B    |dkD  rt         j                  d| d       |S )z'Validate timeout values are reasonable.i  zTimeout of z* seconds is very long and may cause issueslogwarningr\   vs     r)   validate_timeout_reasonablez,TesseractOptions.validate_timeout_reasonable   s&     t8KK+aS(RSTr+   c                8    |dv rt         j                  d       |S )zBValidate page segmentation mode and warn about problematic values.)r      z[The tesseract-pagesegmode you selected will disable OCR. This may cause processing to fail.rb   re   s     r)   validate_pagesegmode_warningz-TesseractOptions.validate_pagesegmode_warning   s#     ;KK5 r+   after)modec                f    | j                   dk7  r!| j                  st        j                  d       | S )z+Validate downsample options are consistent.r6   wThe --tesseract-downsample-above argument will have no effect unless --tesseract-downsample-large-images is also given.)r7   r5   rc   rd   selfs    r)   validate_downsample_consistencyz0TesseractOptions.validate_downsample_consistency  s3       E)$2N2NKKE r+   c           	     |    ddh}|t        |      z  r*t        ddj                  |t        |      z         d      y)zValidate options that require external context.

        Args:
            languages: List of languages being used for OCR
        equosdz^The following languages are for Tesseract's internal use and should not be issued explicitly: r   z-
Remove them from the -l/--language argument.N)setr   r#   )rp   	languagesDENIED_LANGUAGESs      r)   validate_with_contextz&TesseractOptions.validate_with_context  sU     "5>c)n,899-I>?@ A??  -r+   r   )r^   str)rv   z	list[str]returnNone)__name__
__module____qualname____doc__r.   __annotations__r/   r0   r   r   r1   r3   r4   r5   r7   r8   r9   r:   classmethodr`   r   rg   rj   r	   rq   rx    r+   r)   r-   r-   9   sa   3 	    	    	  
  	     	   
 	   
 	    	    	   
 	    	    L
 L
\ Y 12  3 ]#  $ '" #r+   r-   c                     dt         iS )z Register Tesseract option model.r   )r-   r   r+   r)   register_optionsr   &  s     )**r+   c                .    t         j                  |        y N)r-   r`   )r]   s    r)   add_optionsr   ,  s     ,,V4r+   c                r   t        dddit        j                  dt        j                         t        j                         }|t        j                  d      k(  rt	        d      t        j
                         s>| j                  j                  t        j                  k7  rt        j                  d       y	y	y	)
zDCheck external dependencies and version compatibility for Tesseract.r   linuxztesseract-ocrz4.1.1)programpackageversion_checkerneed_versionversion_parserz5.4.0zzTesseract 5.4.0 is not supported due to regressions in this version. Please upgrade to a newer or supported older version.zThe installed version of Tesseract does not support changes to its thresholding method. The --tesseract-threshold argument will be ignored.N)r   r   versionTesseractVersionr   has_thresholdingr1   r   r   rc   rd   )optionstess_versions     r)   check_optionsr   2  s     /*!)) 11 $$&Ly11'::$D
 	
 &&(**.@.E.EE	
 F )r+   c                   t         j                  j                  dd      j                         s2|j                  xs
 t               }t        |t        |       z  dd      }nt        t         j                  d         }||j                  _
        t        j                  d|       |j                  j                  dk7  r-|j                  j                  st        j                  d       y y y )NOMP_THREAD_LIMIT       z&Using Tesseract OpenMP thread limit %dr6   rn   )osenvironget	isnumericjobsr   r   lenrX   r   r:   rc   debugr7   r5   rd   )pdfinfor   r   tess_threadss       r)   validater   O  s     ::>>,b1;;=||424TS\11a82::&89:)5G&II6E 	**e3!!99A	
 : 	4r+   c                    | j                   }t        |dd      |S t        |j                  j                  d      }|j                  j
                  rt        |||fd      }t        ||      }|S )zFilter the image before OCR.

    Tesseract cannot handle images with more than 32767 pixels in either axis,
    or more than 2**31 bytes. This function resizes the image to fit within
    those limits.
    r   Nr6   i)max_size	max_bytes)r   getattrminr   r7   r5   r   r   )pageimager   	thresholdsizes        r)   filter_ocr_imager   l  sq     llGwT*2G%%66>I00#Y	2k
 !-Lr+   c                      e Zd ZdZed        Zed        Zed        Zd Zed        Z	ed        Z
edd       Zed	        Zed
        Zy)TesseractOcrEnginezImplements OCR with Tesseract.c                 <    t        t        j                               S r   )ry   r   r   r   r+   r)   r   zTesseractOcrEngine.version  s    9$$&''r+   c                :    | j                   dk(  ry| j                   S )zADetermine the PDF renderer to use based on options and languages.r   fpdf2)pdf_rendererr   s    r)   _determine_rendererz&TesseractOcrEngine._determine_renderer  s!     6)###r+   c                   t         j                  |       }|xdk(  r dt         j                          S xdk(  r dt         j                          S dk(  rdt         j                          S 	 dt         j                          S )NhocrzOCRmyPDF hOCR + Tesseract OCR r   zOCRmyPDF fpdf2 + Tesseract OCR sandwichzTesseract OCR + PDF Tesseract OCR )r   r   r   )r   renderers     r)   creator_tagzTesseractOcrEngine.creator_tag  s    %99'B78J8R8R8T7UVV89K9S9S9U8VWW-.@.H.H.J-KLL'(:(B(B(D'EFFr+   c                0    dt         j                          S )Nr   )r   r   ro   s    r)   __str__zTesseractOcrEngine.__str__  s     2 : : <=>>r+   c                *    t        j                         S r   )r   get_languagesr   s    r)   rv   zTesseractOcrEngine.languages  s    &&((r+   c                    t        j                  | |j                   j                  |j                   j                  |j                   j                        S )N)engine_moder3   r:   )r   get_orientationr0   r4   r:   
input_filer   s     r)   r   z"TesseractOcrEngine.get_orientation  sE    (())--%%55$..??	
 	
r+   c                    t        j                  | |j                  |j                   j                  |j                   j                  |j                   j
                        S )N)rv   r   r3   r:   )r   
get_deskewrv   r0   r4   r:   r   s     r)   r   zTesseractOcrEngine.get_deskew  sN    ##''))--%%55$..??
 	
r+   c                   t        j                  | |||j                  |j                   j                  |j                   j                  |j                   j
                  |j                   j                  |j                   j                  |j                   j                  |j                   j                  |j                   j                         y )N)r   output_hocroutput_textrv   r   
tessconfigr3   r/   r1   r8   r9   r:   )r   generate_hocrrv   r0   r.   r3   r/   r1   r8   r9   r:   )r   r   r   r   s       r)   r   z TesseractOcrEngine.generate_hocr  s    !##''))--((//%%--))55 **77((33!++99$..??	
r+   c                   t        j                  | |||j                  |j                   j                  |j                   j                  |j                   j
                  |j                   j                  |j                   j                  |j                   j                  |j                   j                  |j                   j                         y )N)r   
output_pdfr   rv   r   r   r3   r/   r1   r8   r9   r:   )r   generate_pdfrv   r0   r.   r3   r/   r1   r8   r9   r:   )r   r   r   r   s       r)   r   zTesseractOcrEngine.generate_pdf  s    !!#''))--((//%%--))55 **77((33!++99$..??	
r+   N)rz   rZ   )r|   r}   r~   r   staticmethodr   r   r   r   rv   r   r   r   r   r   r+   r)   r   r     s    (( ( $ $ 
G 
G? ) ) 
 
 
 
 
 
  
 
r+   r   c                >    | t        | dd      }|dvryt               S )z6Return TesseractOcrEngine when selected or as default.N
ocr_enginer   )r   r   )r   r   )r   r   s     r)   get_ocr_enginer     s-     WlF;
22r+   )r&   ry   rz   r   )r   r   r   Image.Imagerz   r   )2r   
__future__r   r"   loggingr   typingr   PILr   pydanticr   r   r   r	   ocrmypdfr
   ocrmypdf._execr   ocrmypdf._exec.tesseractr   ocrmypdf._jobcontextr   ocrmypdf.clir   ocrmypdf.exceptionsr   r   ocrmypdf.helpersr   r   ocrmypdf.imageopsr   r   ocrmypdf.pluginspecr   ocrmypdf.subprocessr   	getLoggerr|   rc   r*   r-   r   r   r   r   r   r   r   r   r+   r)   <module>r      s    8 "   	   G G  $ 7 ,   D 7 D ) 6g!%8jy jZ 
+ 
+
 
5 
5
 

 

8 

 

8 
 
(U
 U
p 
  
 r+   