
    j5jG                       d Z ddlmZ ddlZddl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mZ ddlmZmZ ddlmZ ddl m!Z! ddl"m#Z# ddl$m%Z%m&Z&m'Z' ddl(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1m2Z2  ejf                         Z4d dZ5d!dZ6	 	 	 	 	 	 d"dZ7 G d de      Z8 G d d      Z9 e       Z: G d d      Z;d Z<e=dk(  r e<        yy)#z/Extract information about the content of a PDF.    )annotationsN)Callable	ContainerIterableIterator)nullcontext)Decimal)PathLike)Path)
NamedTuple)LTPage	LTTextBox)NamePagePdf)ExecutorSerialExecutor
coerce_box)EncryptedPdfError)
Resolution)TextboxInfo
TextMarkerVectorMarker)	ImageInfo_process_content_streams)	FloatRect)_pdf_pageinfo_concurrent)LTStateAwareCharPdfMinerStateget_text_boxesc                <    t        |       }|d   |d   |d   |d   fS )z:Coerce a page box to a normalized ``FloatRect`` (4-tuple).r            r   )valuesbs     K/var/www/html/qr/venv/lib/python3.12/site-packages/ocrmypdf/pdfinfo/info.py	_box_rectr)   &   s+    6AaD!A$!ad##    c                    t        |      t        |      }}d}||z  d|z
  |z  d|z
  |z  ||z  f}dd}d}| D ]  }	 ||	|      sd} |S  |S )z4Smarter text detection that ignores text in margins.g      ?r#   c                f    | d   |d   k  xr% | d   |d   kD  xr | d   |d   kD  xr | d   |d   k  S )a  Check if two 4-tuple rects intersect.

        Where (a,b) are 4-tuple rects (left-0, top-1, right-2, bottom-3)
        https://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other
        Formula assumes all boxes are in first quadrant.
        r   r$   r#   r%    )ar'   s     r(   rects_intersectz'_page_has_text.<locals>.rects_intersect8   sI     tad{Jqtad{Jqtad{Jqtad{Jr*   FT)r.   r   r'   r   returnbool)float)
text_blocks
page_widthpage_heightpwphmargin_ratiointerior_bboxr/   has_textbboxs
             r(   _page_has_textr<   ,   s    :k 2BLr	
\	R	
\	Rr	MK H 4/HO	 Or*   c              #     K    ||       D ]l  }|j                   d   }|j                   d   }t        |t              s2|j                  dk7  }|j	                         dk(  }t        |j                  ||       n yw)z}Extract only limited content from text boxes.

    We do this to save memory and ensure that our objects are pickleable.
    r   r%   u   �N)_objs
isinstancer   
rendermodeget_textr   r;   )
miner_pagetextbox_getterbox
first_line
first_charvisiblecorrupts          r(   simplify_textboxesrI   I   s}      j) 6YYq\
%%a(
*&67''1,%%'83#((GW556s   A9A;c                  @    e Zd ZU dZded<   	 ded<   	 ded<   	 ded<   y)PageResolutionProfilez,Information about the resolutions of a page.r2   weighted_dpimax_dpiaverage_to_max_dpi_ratio
area_ratioN)__name__
__module____qualname____doc____annotations__r-   r*   r(   rK   rK   Z   s.    6SN2## r*   rK   c                     e Zd ZU dZded<   ded<   g Zded<   	 	 d 	 	 	 	 	 	 	 	 	 	 	 d!dZ	 	 	 	 	 	 	 	 	 	 	 	 d!d	Zed"d
       Z	ed#d       Z
ed#d       Zed#d       Zed$d       Zed$d       Zed"d       Zed"d       Zed"d       Zej$                  d        Zed%d       Zed%d       Zed%d       Zed%d       Zed%d       Zed&d       Zd'd(dZed)d       Zed$d       Zed*d       Zd+dZd Zy),PageInfoz9Information about type of contents on each page in a PDF.bool | None	_has_text_has_vectorlist[ImageInfo]_imagesNc                Z    || _         || _        || _        | j                  ||||||       y)zInitialize a PageInfo object.N)_pageno_infile_detailed_analysis_gather_pageinfo)selfpdfpagenoinfilecheck_pagesdetailed_analysisminer_states          r(   __init__zPageInfo.__init__{   s6     "3.?	
r*   c                Z   |j                   |   }t        |j                  j                               D cg c]  }t	        t        |             }	}|	d   |	d   z
  }
|	d   |	d   z
  }t        |j                  j                               | _        t        |j                  j                               | _
        t        |j                  j                               | _        t        |j                  j                               | _        t        |j                  j                               | _        ||v }|ra|r_|j!                  |      }|t#        t%        |t&                    | _        ng | _        d | j(                  D        }t+        ||
|      | _        ng | _        d | _        |j/                  t0        j2                  t	        d            }t5        |t              st	        |      }|| _        |
|z  t	        d      z  | _        ||z  t	        d      z  | _        t=        t?        |j@                  dd            | _!        |dd|ddf}|rd	| _"        d	| _        g | _#        tI        |||
      D ]g  }t5        |tJ              rd| _"        t5        |tL              rd| _        3t5        |tN              r| jF                  jQ                  |       _tS                nd | _"        d | _        g | _#        d | _*        | jF                  rtW        dd      jY                  d | jF                  D              }|| _*        t=        t[        |j\                  t_        | j8                        z              | _0        t=        t[        |jb                  t_        | j:                        z              | _2        y y c c}w )Nr$   r   r%   r#   c              3  4   K   | ]  }|j                     y wNr;   ).0rD   s     r(   	<genexpr>z,PageInfo._gather_pageinfo.<locals>.<genexpr>   s     :3chh:         ?g      R@RotateF)rb   	container	shorthandT        c              3  N   K   | ]  }|j                   s|j                    y wrk   )
renderabledpi)rm   images     r(   rn   z,PageInfo._gather_pageinfo.<locals>.<genexpr>   s!      0#u7G7G		0s   %%)3pagesr   mediaboxas_listr	   strr)   artbox_artboxbleedbox	_bleedboxcropbox_cropbox	_mediaboxtrimbox_trimboxget_page_analysislistrI   r!   
_textboxesr<   rX   getr   UserUnitr?   	_userunit_width_inches_height_inchesintgetattrobj_rotaterY   r[   r   r   r   r   appendNotImplementedError_dpir   take_maxroundxr2   _width_pixelsy_height_pixels)ra   rb   rc   rd   re   rf   rg   pagedrz   width_pt	height_ptcheck_this_pagepage_analysisbboxesuserunituserunit_shorthandinforw   s                      r(   r`   zPageInfo._gather_pageinfo   s
    YYv&-78M8M8O-PQGCFOQQA;!,QK(1+-	 !4!4!67"4==#8#8#:;!$,,"6"6"89"4==#8#8#:;!$,,"6"6"89 K/0'99&AM("&&}nE# #%:$//:F+FHiHDN DO!DN88DMM73<8(G,x(H!%074=@'(2WT]B7488Xq9:&1h1=$D"DNDL043E 
0 dL1'+D$j1%)DNi0LL''--//
0  $D!DNDL	<<S#&// 0'+||0 C DI!$U35559K9K3L+L%M!ND"%eCEEE$:M:M4N,N&O"PD u Rs   N(c                    | j                   S )zReturn page number (0-based).)r]   ra   s    r(   rc   zPageInfo.pageno        ||r*   c                ,    t        | j                        S )z6Return True if page has text, False if not or unknown.)r1   rX   r   s    r(   r:   zPageInfo.has_text   s     DNN##r*   c                h    | j                   st        d      t        d | j                  D              S )z>Return True if page has corrupt text, False if not or unknown.zDid not do detailed analysisc              3  4   K   | ]  }|j                     y wrk   )
is_corrupt)rm   tboxs     r(   rn   z,PageInfo.has_corrupt_text.<locals>.<genexpr>   s     ?t4???ro   )r_   r   anyr   r   s    r(   has_corrupt_textzPageInfo.has_corrupt_text   s.     &&%&DEE?t???r*   c                ,    t        | j                        S )zReturn True if page has vector graphics, False if not or unknown.

        Vector graphics are sometimes used to draw fonts, so it may not be
        obvious on visual inspection whether a page has text or not.
        )r1   rY   r   s    r(   
has_vectorzPageInfo.has_vector   s     D$$%%r*   c                    | j                   S )zReturn width of page in inches.)r   r   s    r(   width_incheszPageInfo.width_inches        !!!r*   c                    | j                   S )z Return height of page in inches.)r   r   s    r(   height_incheszPageInfo.height_inches        """r*   c                ~    t        t        t        | j                        | j                  j
                  z              S )zReturn width of page in pixels.)r   r   r2   r   rw   r   r   s    r(   width_pixelszPageInfo.width_pixels   s,     5t001DHHJJ>?@@r*   c                ~    t        t        t        | j                        | j                  j
                  z              S )z Return height of page in pixels.)r   r   r2   r   rw   r   r   s    r(   height_pixelszPageInfo.height_pixels  s,     5t112TXXZZ?@AAr*   c                    | j                   S )zTReturn rotation of page in degrees.

        Will only be a multiple of 90.
        )r   r   s    r(   rotationzPageInfo.rotation  s     ||r*   c                0    |dv r|| _         y t        d      )N)r   Z      i  ih  iiLiz!rotation must be a cardinal angle)r   
ValueError)ra   values     r(   r   zPageInfo.rotation  s    ;; DL@AAr*   c                    | j                   S )z*Return cropbox of page in PDF coordinates.)r   r   s    r(   r   zPageInfo.cropbox       }}r*   c                    | j                   S )z+Return mediabox of page in PDF coordinates.)r   r   s    r(   rz   zPageInfo.mediabox       ~~r*   c                    | j                   S )z*Return trimbox of page in PDF coordinates.)r   r   s    r(   r   zPageInfo.trimbox  r   r*   c                    | j                   S )z)Return artbox of page in PDF coordinates.)r~   r   s    r(   r}   zPageInfo.artbox$  r   r*   c                    | j                   S )z+Return bleedbox of page in PDF coordinates.)r   r   s    r(   r   zPageInfo.bleedbox)  r   r*   c                    | j                   S )zReturn images.)r[   r   s    r(   imageszPageInfo.images.  r   r*   c                    	 	 	 	 	 	 	 	 dd| j                   st        d      | j                   S fd| j                   D        S )z?Return textareas bounding boxes in PDF coordinates on the page.c                V    d}|| j                   |k7  rd}|| j                  |k7  rd}|S )NTF)
is_visibler   )r   want_visiblewant_corruptresults       r(   	predicatez)PageInfo.get_textareas.<locals>.predicate6  s:     F'CNNl,J'CNNl,JMr*   z#Incomplete information on textboxesc              3  L   K   | ]  } |      s|j                     y wrk   rl   )rm   r   rH   r   rG   s     r(   rn   z)PageInfo.get_textareas.<locals>.<genexpr>E  s      XSygw7WXs   $$)r   r   r   rW   r   rW   r0   r1   )r   r   )ra   rG   rH   r   s    ``@r(   get_textareaszPageInfo.get_textareas3  sa    		,7	GR		 "w':)*OPP??"XDOOXXr*   c                J    | j                   t        dd      S | j                   S )z3Return DPI needed to render all images on the page.rt   )r   r   r   s    r(   rw   zPageInfo.dpiG  s%     99c3''yyr*   c                    | j                   S )zReturn user unit of page.)r   r   s    r(   r   zPageInfo.userunitN  r   r*   c                    | j                   yy)z6Return minimum PDF version needed to render this page.z1.6z1.5r   r   s    r(   min_versionzPageInfo.min_versionS  s     ==$r*   c                   g }g }| j                   D ]S  }|j                  s|j                  |j                  j	                                |j                  |j
                         U t        |      }|dk(  ry|D cg c]  }||z  	 }}t        j                  ||      }t        |      }||z  }	|j                  |      }
||
   |z  }t        |||	|      S c c}w )a  Return information about the DPIs of the page.

        This is useful to detect pages with a small proportion of high-resolution
        content that is forcing us to use a high DPI for the whole page. The ratio
        is weighted by the area of each image. If images overlap, the overlapped
        area counts.

        Vector graphics and text are ignored.

        Returns None if there is no meaningful DPI for the page.
        r   N)r[   rv   r   rw   	to_scalarprinted_areasum
statisticsharmonic_meanmaxindexrK   )ra   
image_dpisimage_areasrx   total_drawn_areaareaweightsrL   rM   dpi_average_max_ratioarg_max_dpimax_area_ratios               r(   page_dpi_profilezPageInfo.page_dpi_profile[  s     
\\ 	3E##eii1134u112		3 {+q 7BCt4**CC!//
GDj/ ,w 6 &&w/$[14DD$!	
 	
 Ds   <Cc                    d| j                    d| j                   d| j                   d| j                   d| j                   d| j
                   dS )Return string representation.z<PageInfo pageno= z"xz" rotation=z dpi=z
 has_text=>)rc   r   r   r   rw   r:   r   s    r(   __repr__zPageInfo.__repr__  sZ    kk]!D$5$5#6b9K9K8L MeDHH:ZaQ	
r*   )FN)rb   r   rc   r   rd   r
   re   zContainer[int]rf   r1   rg   zPdfMinerState | None)r0   r   r0   r1   )r0   r	   )r0   r   )r0   rZ   )NN)rG   rW   rH   rW   )r0   r   r0   r|   )r0   zPageResolutionProfile | None)rP   rQ   rR   rS   rT   r[   rh   r`   propertyrc   r:   r   r   r   r   r   r   r   setterr   rz   r   r}   r   r   r   rw   r   r   r   r   r-   r*   r(   rV   rV   t   sI   C!G_! #(,0

 
 	

 $
  
 *
"JQJQ JQ 	JQ
 $JQ  JQ *JQX   $ $ @ @ & & " " # # A A B B   __B B            Y(      %
N
r*   rV   c                  .   e Zd ZU dZdZded<   dZded<   dZded<   dZded<   dddd	de	d
	 	 	 	 	 	 	 	 	 	 	 ddZ
edd       Zedd       Zedd       Zedd       Zedd       Zedd       Zedd       Zedd       Zedd       ZddZd Zd Zy)PdfInfozExtract summary information about a PDF without retaining the PDF itself.

    Crucially this lets us get the information in a pure Python format so that
    it can be pickled and passed to a worker process.
    Fr1   _has_acroform_has_signature_needs_rendering_has_structure_treeNT)rf   progbarmax_workersuse_threadsre   executorc                  || _         |t        dd      }t        j                  |      5 }|j                  r
t               t        |j                  j                  t        j                  d            j                  d      }	|rt        ||	      n	t               | _        | j                  5 }
t        |||||||||
	      | _        ddd       |j"                  j                  t        j$                  d      | _        t        j(                  |j"                  v rt+        |j"                  j(                  j                  t        j,                  g             dkD  s&t        j.                  |j"                  j(                  v rd| _        t3        |j"                  j(                  j                  t        j4                  d      d	z        | _        t3        |j"                  j                  t        j8                  i       j                  t        j:                  d            | _        t        j>                  |j"                  v | _         ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)
zInitialize.Nr   i ʚ; PScript5)re   rf   rg   FTr#   )!r^   ranger   openis_encryptedr   r|   docinfor   r   Creator
startswithr    r   _miner_stater   _pagesRootNeedsRenderingr   AcroFormlenFieldsXFAr   r1   SigFlagsr   MarkInfoMarked
_is_taggedStructTreeRootr   )ra   rd   rf   r   r   r   re   r   rb   pscript5_moderg   s              r(   rh   zPdfInfo.__init__  s    =1KXXf "	G'))b ABMMM
 % fm4 ] 
 "" k6 +&7 +
 %(HHLL1D1De$LD!}}())--dkk2>?!Cxx388#4#44)-D&&*388+<+<+@+@PQ+RUV+V&W#"T]]B/33DKKGDO (,':':chh'FD$E"	G "	G "	G "	Gs%   BI-IE<II	II"c                    | j                   S )z9Return list of PageInfo objects, one per page in the PDF.r  r   s    r(   ry   zPdfInfo.pages  s     {{r*   c                :    t        d | j                  D              S )z5Return minimum PDF version needed to render this PDF.c              3  :   K   | ]  }|s|j                     y wrk   )r   rm   r   s     r(   rn   z&PdfInfo.min_version.<locals>.<genexpr>  s     Cd4##Cs   )r   ry   r   s    r(   r   zPdfInfo.min_version  s     C

CCCr*   c                :    t        d | j                  D              S )z(Return True if any page has a user unit.c              3  @   K   | ]  }|s|j                   d k7    yw)rp   Nr   r  s     r(   rn   z'PdfInfo.has_userunit.<locals>.<genexpr>  s     GD$4==C'Gs   )r   ry   r   s    r(   has_userunitzPdfInfo.has_userunit  s     GDJJGGGr*   c                    | j                   S )z4Return True if the document catalog has an AcroForm.)r   r   s    r(   has_acroformzPdfInfo.has_acroform  r   r*   c                    | j                   S )z@Return True if the document annotations has a digital signature.)r   r   s    r(   has_signaturezPdfInfo.has_signature  r   r*   c                    | j                   S )zCReturn True if the document catalog indicates this is a Tagged PDF.)r  r   s    r(   	is_taggedzPdfInfo.is_tagged  s     r*   c                    | j                   S )zAReturn True if the document catalog has a logical structure tree.)r   r   s    r(   has_structure_treezPdfInfo.has_structure_tree  s     '''r*   c                r    t        | j                  t        t        z        st	        d      | j                  S )zReturn filename of PDF.zcan't get filename from stream)r?   r^   r|   r   r   r   s    r(   filenamezPdfInfo.filename  s,     $,,d
3%&FGG||r*   c                    | j                   S )zReturn True if PDF contains XFA forms.

        XFA forms are not supported by most standard PDF renderers, so we
        need to detect and suppress them.
        )r   r   s    r(   needs_renderingzPdfInfo.needs_rendering  s     $$$r*   c                     | j                   |   S )z.Return PageInfo object for page number `item`.r  )ra   items     r(   __getitem__zPdfInfo.__getitem__  s    {{4  r*   c                ,    t        | j                        S )zReturn number of pages in PDF.)r  r  r   s    r(   __len__zPdfInfo.__len__  s    4;;r*   c                     dt        |        dS )r   z<PdfInfo('...'), page count=r   )r  r   s    r(   r   zPdfInfo.__repr__
  s    -c$i[::r*   )rd   r   rf   r1   r   r1   r   z
int | Noner   r1   r   r   )r0   zlist[PageInfo | None]r   r   )r0   z
str | Path)r0   rV   )rP   rQ   rR   rS   r   rT   r   r   r   DEFAULT_EXECUTORrh   r   ry   r   r  r  r  r!  r#  r%  r'  r*  r,  r   r-   r*   r(   r   r     sU     M4 ND "d" %% #("& -2G2G  	2G
 2G  2G 2G 2Gh   D D
 H H " " # #   ( (   % %! ;r*   r   c                    ddl } ddlm} | j                         }|j                  d       |j	                         }t        |j                        } ||       |j                  D ]#  } ||       |j                  D ]
  } ||        % y)zRun as a script.r   N)pprintrd   )	argparser0  ArgumentParseradd_argument
parse_argsr   rd   ry   r   )r1  r0  parserargspdfinfor   ims          r(   mainr9    s{    $$&F
!Ddkk"G
7O t++ 	B2J	r*   __main__)r&   r   r0   r   )r3   zIterable[FloatRect]r0   r1   )rB   r   rC   z'Callable[[LTPage], Iterator[LTTextBox]]r0   zIterator[TextboxInfo])>rS   
__future__r   loggingr   collections.abcr   r   r   r   
contextlibr   decimalr	   osr
   pathlibr   typingr   pdfminer.layoutr   r   pikepdfr   r   r   ocrmypdf._concurrentr   r   ocrmypdf._pageboxesr   ocrmypdf.exceptionsr   ocrmypdf.helpersr   ocrmypdf.pdfinfo._contentstreamr   r   r   ocrmypdf.pdfinfo._imager   r   ocrmypdf.pdfinfo._typesr   ocrmypdf.pdfinfo._workerr   ocrmypdf.pdfinfo.layoutr   r    r!   	getLoggerloggerr)   r<   rI   rK   rV   r.  r   r9  rP   r-   r*   r(   <module>rP     s   
 6 "   C C "     - # # 9 * 1 ' Q Q G - =  
			$:66(O66"J 4T
 T
n "# ~; ~;B" zF r*   