U
    ڲga                     @  sh  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ dZd	Zd
ZddddddZddddddZdddddZdd ZG dd de
ZG dd dejZG d d! d!ZG d"d# d#eZG d$d% d%Zd8d&d'd(d)Zd9d*d+d,d-Zd.d/ ZG d0d1 d1Z G d2d3 d3Z!G d4d5 d5e!Z"G d6d7 d7e!Z#dS ):    )annotationsN)IOAny
NamedTuple   )Image)	deprecate)is_pathi   i   Fzimage buffer overrun errorzdecoding errorzunknown errorzbad configurationzout of memory error)iintboolOSError)errorencoderreturnc                C  sj   zt j| }W n tk
r.   t| }Y nX |sJ|r<dnd d|  }|d|rVdnd d7 }t|S )Nr   decoderz error z when writingreadingz image file)r   coreZgetcodecstatusAttributeErrorERRORSgetr   )r   r   msg r   1/tmp/pip-unpacked-wheel-xela2va7/PIL/ImageFile.py_get_oserrorD   s    r   )r   r   c                 C  s   t dddd t| ddd S )Nraise_oserror   zIt is only useful for translating error codes returned by a codec's decode() method, which ImageFile already does automatically.)actionFr   )r   r   )r   r   r   r   r   O   s    r   c                 C  s   | d S )N   r   )tr   r   r   	_tilesortY   s    r%   c                   @  s.   e Zd ZU ded< ded< ded< ded< d	S )
_TilestrZ
codec_nametuple[int, int, int, int]extentsr   offsetztuple[Any, ...] | str | NoneargsN)__name__
__module____qualname____annotations__r   r   r   r   r&   ^   s   
r&   c                      sv   e Zd ZdZd fdd	ZddddZ fd	d
ZddddZdd ZddddZ	ddddZ
dd Z  ZS )	ImageFilez*Base class for image file format handlers.Nc                   s  t    d| _d | _d | _d| _d| _t| _t	|rPt
|d| _|| _d| _n|| _|| _d | _zxz|   W n8 tttttjfk
r } zt||W 5 d }~X Y nX | jr| jd dks| jd dkrd}t|W n( tk
r   | jr| j   Y nX d S )Nr   r   r   rbTznot identified by this driver)super__init__
_min_framecustom_mimetypetilereadonlydecoderconfigMAXBLOCKdecodermaxblockr	   openfpfilename_exclusive_fp_open
IndexError	TypeErrorKeyErrorEOFErrorstructr   SyntaxErrormodesizeBaseExceptionclose)selfr<   r=   vr   	__class__r   r   r3   m   s@    
"
zImageFile.__init__z
str | Noner   c                 C  s,   | j r| j S | jd k	r(tj| j S d S N)r5   formatr   ZMIMEr   upperrJ   r   r   r   get_format_mimetype   s
    
zImageFile.get_format_mimetypec                   s   g | _ t | d S rO   )r6   r2   __setstate__)rJ   staterL   r   r   rT      s    zImageFile.__setstate__Nonec                 C  s   | j r| j  d| _dS )zCheck file integrityN)r>   r<   rI   rR   r   r   r   verify   s    
zImageFile.verifyc                 C  s  | j dkrd}t|tj| }| j s,|S d| _| joDt| j dk}|oTttd }d}z| j	}d}W n t
k
r   | jj}Y nX z| j}d}W n t
k
r   | jj}Y nX |r| j d \}}}	}
t|
tr|
ddf}
|dkrt|
dkr|
d | jkr|
d tjkrzddl}t| j}|j| d|jd	| _W 5 Q R X |	| jd |
d   | j kr|d
}t|tj| j| j||	|
| _d}| jrd| j_W n" t
ttfk
r   d| _Y nX |   d}| jsh| j jt d z
| j!}W n t
k
r   d}Y nX dd t"#| j dd D | _ | j D ](\}}}	}
||	 t$| j||
| j%}z|'| j| |j(r|)| j |*dd }n|}z|| j+}W nJ t,t-j.fk
r } z$t/rW Y qVnd}t||W 5 d}~X Y nX |s"t/r
qVndt| d}t||| }|*|\}}|dk rFqV||d }qW 5 |&  X q<g | _ || _0| 1  | j2r| j3r| j4  d| _| jst/s|dk rt5|ddtj| S )z"Load image data based on tile listNzcannot load this imager   pypy_version_infor   Fraw   )accesszbuffer is not large enoughr   key    c                 S  s   g | ]\}}t |d  qS )r
   )list).0_Ztilesr   r   r   
<listcomp>   s   z"ImageFile.load.<locals>.<listcomp>c                 S  s   | d | d | d fS )Nr   r   rZ   r   r6   r   r   r   <lambda>   r^   z ImageFile.load.<locals>.<lambda>zimage file is truncatedzimage file is truncated (z bytes not processed)r"   )6r6   r   r   loadmapr=   lenhasattrsys	load_readr   r<   read	load_seekseek
isinstancer'   rF   Z	_MAPMODESmmapr;   filenoZACCESS_READrG   r   Z
map_bufferimZpaletteZdirtyImportErrorload_preparesortr%   Ztile_prefix	itertoolsgroupby_getdecoderr8   cleanupsetimagepulls_fdsetfddecoder:   r@   rD   r   LOAD_TRUNCATED_IMAGESr7   load_endr>   Z!_close_exclusive_fp_after_loadingrI   r   )rJ   r   ZpixelZuse_mmapr7   rk   rm   Zdecoder_namer)   r*   r+   ro   r<   Zerr_codeprefixr   bsenr   r   r   re      s    



""    

    

zImageFile.loadc                 C  sP   | j r"| j j| jks"| j j| jkr6tj| j| j| _ | jdkrLtj|  d S )NP)rq   rF   rG   r   r   newre   rR   r   r   r   rs   <  s    "
zImageFile.load_preparec                 C  s   d S rO   r   rR   r   r   r   r~   D  s    zImageFile.load_endc                 C  sF   || j k s.t| dr| jd ks:|| j| j  kr:d}t||  |kS )N	_n_framesz attempt to seek outside sequence)r4   rh   r   Zn_framesrC   tell)rJ   framer   r   r   r   _seek_checkP  s    	zImageFile._seek_check)NN)r,   r-   r.   __doc__r3   rS   rT   rW   re   rs   r~   r   __classcell__r   r   rL   r   r0   j   s   0	 r0   c                   @  s2   e Zd ZdddddZejdddddZd	S )
StubHandlerStubImageFilerV   )rq   r   c                 C  s   d S rO   r   rJ   rq   r   r   r   r;   a  s    zStubHandler.openzImage.Imagec                 C  s   d S rO   r   r   r   r   r   re   d  s    zStubHandler.loadN)r,   r-   r.   r;   abcabstractmethodre   r   r   r   r   r   `  s   r   c                   @  s4   e Zd ZdZddddZdd Zddd	d
ZdS )r   z
    Base class for stub image loaders.

    A stub loader is an image loader that can identify files of a
    certain format, but relies on external code to load the file.
    rV   rN   c                 C  s   d}t |d S )Nz+StubImageFile subclass must implement _openNotImplementedErrorrJ   r   r   r   r   r?   q  s    zStubImageFile._openc                 C  sT   |   }|d kr&d| j d}t||| }|d k	s<t|j| _|j| _| S )Nzcannot find loader for this z file)_loadrP   r   re   AssertionErrorrM   __dict__)rJ   loaderr   imager   r   r   re   u  s    
zStubImageFile.loadzStubHandler | Nonec                 C  s   d}t |dS )z (Hook) Find actual image loader.z+StubImageFile subclass must implement _loadNr   r   r   r   r   r     s    zStubImageFile._loadN)r,   r-   r.   r   r?   re   r   r   r   r   r   r   i  s   r   c                   @  sh   e Zd ZU dZdZdZded< dZdZdZ	dZ
dddd	Zd
d Zdd ZdddddZdd ZdS )Parserzj
    Incremental image parser.  This class implements the standard
    feed/close consumer interface.
    NzImage.Image | Noner   r   rV   rN   c                 C  s   | j dkstddS )z
        (Consumer) Reset the parser.  Note that you can only call this
        method immediately after you've created a parser; parser
        instances cannot be reused.
        Nzcannot reuse parsers)datar   rR   r   r   r   reset  s    zParser.resetc              	   C  s  | j r
dS | jdkr|| _n| j| | _| jr| jdkrztt| j| j}| j|d | _| j| | _| jdksv| jszdS | j| j\}}|dk rd| _d| _ |dk rd| _t|ddndS | j|d | _n| jrnz&t	
| j}t|}W 5 Q R X W n tk
r   Y nX t|dp,t|d}|sDt|jdkrLd| _nv|  |jd \}}}	}
g |_t|j||
|j| _| j|j| |	| _| jt| jkr| j| jd | _d| _|| _dS )z
        (Consumer) Feed data to the parser.

        :param data: A string buffer.
        :exception OSError: If the parser failed to parse the image file.
        Nr   r   Fr"   rl   rj   )finishedr   r   r*   minrg   r|   r   r   ioBytesIOr   r;   r   rh   r6   rs   rw   rF   r8   ry   rq   )rJ   r   skipr   r   r<   rq   flagdoar   r   r   feed  sR    	

zParser.feedc                 C  s   | S rO   r   rR   r   r   r   	__enter__  s    zParser.__enter__object)r+   r   c                 G  s   |    d S rO   )rI   rJ   r+   r   r   r   __exit__  s    zParser.__exit__c              	   C  s   | j r.| d d | _| _ | js.d}t|| js@d}t|| jr|t| j$}zt	
|| _W 5 | j  X W 5 Q R X | jS )a  
        (Consumer) Close the stream.

        :returns: An image object.
        :exception OSError: If the parser failed to parse the image file either
                            because it cannot be identified or cannot be
                            decoded.
        r^   Nzimage was incompletezcannot parse this image)r   r   r   r   r   r   r   r   re   r   r;   )rJ   r   r<   r   r   r   rI     s    

zParser.close)r,   r-   r.   r   incrementalr   r/   r   r   r*   r   r   r   r   r   rI   r   r   r   r   r     s   
Lr   rV   rN   c              
   C  s   |    t| dsd| _|jtd tt|| jd d }z$| }|	  t
| |||| W n: ttjfk
r } zt
| |||d| W 5 d}~X Y nX t|dr|	  dS )zHelper to save image based on tile list

    :param im: Image object.
    :param fp: File object.
    :param tile: Tile list.
    :param bufsize: Optional buffer size
    encoderconfigr   r\   r      Nflush)re   rh   r   rt   r%   maxr9   rG   rp   r   _encode_tiler   r   UnsupportedOperation)rq   r<   r6   bufsizefhexcr   r   r   _save  s    	
$
r   zlist[_Tile]rc   c              	   C  s   |D ]\}}}}	|dkr"| | t| j||	| j}
z|
| j| |
jrd|
	| |

 d }n:|r|
|dd  \}}|| |rhqqhn|
||}|dk rt|dd|W 5 |
  X qd S )Nr   r   Tr"   )rm   r   Z_getencoderrF   r   rx   ry   rq   	pushes_fdr{   encode_to_pyfdencodewriteencode_to_filer   )rq   r<   r6   r   r   r   Zencoder_namer)   r*   r+   r   errcoder   r   r   r   r   ,  s$    


r   c                 C  s   |dkrdS |t kr:| |}t||k r6d}t||S g }|}|dkrx| t|t }|s`qx|| |t|8 }qBtdd |D |k rd}t|d|S )a  
    Reads large blocks in a safe way.  Unlike fp.read(n), this function
    doesn't trust the user.  If the requested size is larger than
    SAFEBLOCK, the file is read block by block.

    :param fp: File handle.  Must implement a <b>read</b> method.
    :param size: Number of bytes to read.
    :returns: A string containing <i>size</i> bytes of data.

    Raises an OSError if the file is truncated and the read cannot be completed

    r   r^   zTruncated File Readc                 s  s   | ]}t |V  qd S rO   )rg   )r`   r   r   r   r   	<genexpr>d  s     z_safe_read.<locals>.<genexpr>)	SAFEBLOCKrk   rg   r   r   appendsumjoin)r<   rG   r   r   Zremaining_sizeblockr   r   r   
_safe_readG  s(    

r   c                   @  s(   e Zd ZddddZddddZdS )	PyCodecStaterV   rN   c                 C  s   d| _ d| _d| _d| _d S )Nr   )xsizeysizexoffyoffrR   r   r   r   r3   k  s    zPyCodecState.__init__r(   c                 C  s    | j | j| j | j | j| j fS rO   )r   r   r   r   rR   r   r   r   r)   q  s    zPyCodecState.extentsN)r,   r-   r.   r3   r)   r   r   r   r   r   j  s   r   c                   @  sN   e Zd ZU ded< dd Zdd Zddd	d
Zdd ZddddddZdS )PyCodeczIO[bytes] | Nonefdc                 G  s(   d | _ t | _d | _|| _| | d S rO   )rq   r   rU   r   rF   init)rJ   rF   r+   r   r   r   r3   x  s
    zPyCodec.__init__c                 C  s
   || _ dS )z
        Override to perform codec specific initialization

        :param args: Array of args items from the tile entry
        :returns: None
        N)r+   r   r   r   r   r     s    zPyCodec.initrV   rN   c                 C  s   dS )zT
        Override to perform codec specific cleanup

        :returns: None
        Nr   rR   r   r   r   rx     s    zPyCodec.cleanupc                 C  s
   || _ dS )z
        Called from ImageFile to set the Python file-like object

        :param fd: A Python file-like object
        :returns: None
        N)r   )rJ   r   r   r   r   r{     s    zPyCodec.setfdNz tuple[int, int, int, int] | None)r)   r   c                 C  s   || _ |r|\}}}}nd\}}}}|dkrJ|dkrJ| j j\| j_| j_n(|| j_|| j_|| | j_|| | j_| jjdks| jjdkrd}t|| jj| jj | j jd ks| jj| jj | j jd krd}t|dS )z
        Called from ImageFile to set the core output image for the codec

        :param im: A core image object
        :param extents: a 4 tuple of (x0, y0, x1, y1) defining the rectangle
            for this tile
        :returns: None
        )r   r   r   r   r   zSize cannot be negativer   z Tile cannot extend outside imageN)rq   rG   rU   r   r   r   r   
ValueError)rJ   rq   r)   Zx0Zy0x1y1r   r   r   r   ry     s&    zPyCodec.setimage)N)	r,   r-   r.   r/   r3   r   rx   r{   ry   r   r   r   r   r   u  s   
		r   c                   @  sH   e Zd ZdZdZeddddZddd	d
dZddddddZdS )	PyDecoderz
    Python implementation of a format decoder. Override this class and
    add the decoding logic in the :meth:`decode` method.

    See :ref:`Writing Your Own File Codec in Python<file-codecs-py>`
    Fr   rN   c                 C  s   | j S rO   )	_pulls_fdrR   r   r   r   rz     s    zPyDecoder.pulls_fdbytestuple[int, int])bufferr   c                 C  s   d}t |dS )a=  
        Override to perform the decoding process.

        :param buffer: A bytes object with the data to be decoded.
        :returns: A tuple of ``(bytes consumed, errcode)``.
            If finished with decoding return -1 for the bytes consumed.
            Err codes are from :data:`.ImageFile.ERRORS`.
        zunavailable in base decoderNr   )rJ   r   r   r   r   r   r|     s    	zPyDecoder.decodeNrV   )r   r   c                 C  sz   |s
| j }t| j d|}| jdk	s(t|| j| j  ||}|d dkr^d}t	||d dkrvd}t	|dS )a  
        Convenience method to set the internal image from a stream of raw data

        :param data: Bytes to be set
        :param rawmode: The rawmode to be used for the decoder.
            If not specified, it will default to the mode of the image
        :returns: None
        rY   Nr   znot enough image datar   zcannot decode image data)
rF   r   rw   rq   r   ry   rU   r)   r|   r   )rJ   r   rawmoder   r   r   r   r   r   
set_as_raw  s    

zPyDecoder.set_as_raw)N)	r,   r-   r.   r   r   propertyrz   r|   r   r   r   r   r   r     s   r   c                   @  sL   e Zd ZdZdZeddddZddd	d
dZddddZdd Z	dS )	PyEncoderz
    Python implementation of a format encoder. Override this class and
    add the decoding logic in the :meth:`encode` method.

    See :ref:`Writing Your Own File Codec in Python<file-codecs-py>`
    Fr   rN   c                 C  s   | j S rO   )
_pushes_fdrR   r   r   r   r     s    zPyEncoder.pushes_fdr   ztuple[int, int, bytes])r   r   c                 C  s   d}t |dS )a   
        Override to perform the encoding process.

        :param bufsize: Buffer size.
        :returns: A tuple of ``(bytes encoded, errcode, bytes)``.
            If finished with encoding return 1 for the error code.
            Err codes are from :data:`.ImageFile.ERRORS`.
        zunavailable in base encoderNr   )rJ   r   r   r   r   r   r      s    	zPyEncoder.encoder   c                 C  s@   | j s
dS | d\}}}|r8| jdk	s,t| j| ||fS )z
        If ``pushes_fd`` is ``True``, then this method will be used,
        and ``encode()`` will only be called once.

        :returns: A tuple of ``(bytes consumed, errcode)``.
            Err codes are from :data:`.ImageFile.ERRORS`.
        )r   r   r   N)r   r   r   r   r   )rJ   Zbytes_consumedr   r   r   r   r   r     s    zPyEncoder.encode_to_pyfdc                 C  s<   d}|dkr8|  |\}}}|dkr|||d  q|S )z
        :param fh: File handle.
        :param bufsize: Buffer size.

        :returns: If finished successfully, return 0.
            Otherwise, return an error code. Err codes are from
            :data:`.ImageFile.ERRORS`.
        r   N)r   r   )rJ   r   r   r   statusbufr   r   r   r     s    	zPyEncoder.encode_to_fileN)
r,   r-   r.   r   r   r   r   r   r   r   r   r   r   r   r     s   r   )r   )N)$
__future__r   r   r   ru   rD   ri   typingr   r   r    r   Z
_deprecater   Z_utilr	   r9   r   r}   r   r   r   r%   r&   r0   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sF   
 w	 
#J3