B
    zbX                 @   s   d dl Z d dlZd dlZd dl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 Zdd ZG dd dejZG dd deZG dd dZd$ddZdd ZG dd dZG dd dZG d d! d!eZG d"d# d#eZdS )%    N   )Image)is_pathi   i   Fzimage buffer overrun errorzdecoding errorzunknown errorzbad configurationzout of memory error)iic             C   sN   yt j| }W n tk
r.   t| }Y nX |s>d|  }t|d d S )Nzdecoder error z when reading image file)r   coreZgetcodecstatusAttributeErrorERRORSgetOSError)errormessage r   ,lib/python3.7/site-packages/PIL/ImageFile.pyraise_oserror@   s    
r   c             C   s   | d S )N   r   )tr   r   r   	_tilesortJ   s    r   c                   sR   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Zdd Z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 | _yty|   W n8 tttttjfk
r } zt||W d d }~X Y nX | jr| jd dks| jd dkrtd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"   v)	__class__r   r   r   W   s<    
"
zImageFile.__init__c             C   s,   | j r| j S | jd k	r(tj| j S d S )N)r   formatr   ZMIMEr   upper)r/   r   r   r   get_format_mimetype   s    
zImageFile.get_format_mimetypec             C   s   | j r| j  d| _dS )zCheck file integrityN)r#   r!   r.   )r/   r   r   r   verify   s    
zImageFile.verifyc             C   sx  | j dkrtdtj| }| j s(|S d| _| jo@t| j dk}|oPttd }d}y| j	}d}W n t
k
r   | jj}Y nX y| j}d}W n t
k
r   | jj}Y nX |r| j d \}}}}	|dkrt|	dkr|	d | jkr|	d tjkryhddl}
t| j}|
j| d|
jd	| _W dQ R X tj| j| j|||	| _d}| jrdd| j_W n" t
ttfk
r   d| _Y nX |   d
}| js| j jtd y
| j}W n t
k
r   d}Y nX dd t !| j dd D | _ x$| j D ]\}}}}	|| t"| j||	| j#}z|$| j| |j%rX|&| j |'dd }n|}xy|| j(}W n> t)t*j+fk
r } zt,rP n
td|W dd}~X Y nX |st,rP ntdt| d|| }|'|\}}|dk rP ||d }q^W W d|-  X qW g | _ || _.| /  | j0rF| j1rF| j2  d| _| jslt,sl|dk rlt3| tj| S )z"Load image data based on tile listNzcannot load this imager   Zpypy_version_infor   Fraw   )accessr   )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   r7   r   )r   r   r   r   <lambda>   r:   z ImageFile.load.<locals>.<lambda>zimage file is truncatedzimage file is truncated (z bytes not processed))4r   r   r   loadmapr"   lenhasattrsys	load_readr	   r!   read	load_seekseekr+   Z	_MAPMODESmmapr    filenoZACCESS_READr   Z
map_bufferr,   imZpaletteZdirtyImportErrorload_preparesortr   Ztile_prefix	itertoolsgroupby_getdecoderr   setimagepulls_fdsetfddecoder   r%   r)   r   LOAD_TRUNCATED_IMAGEScleanupr   load_endr#   Z!_close_exclusive_fp_after_loadingr.   r   )r/   ZpixelZuse_mmapr   rF   rH   Zdecoder_nameextentsoffsetargsrI   r!   Zerr_codeprefixdecoderbsenr   r   r   r@      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)rK   r+   r,   r   r   newr@   )r/   r   r   r   rM     s    "
zImageFile.load_preparec             C   s   d S )Nr   )r/   r   r   r   rX      s    zImageFile.load_endc             C   sB   || j k s.t| dr| jd ks6|| j| j  kr6td|  |kS )N	_n_framesz attempt to seek outside sequence)r   rC   rd   Zn_framesr(   tell)r/   framer   r   r   _seek_check,  s
    
zImageFile._seek_check)NN)__name__
__module____qualname____doc__r   r4   r5   r@   rM   rX   rg   __classcell__r   r   )r1   r   r   T   s   /	 r   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	StubImageFilez
    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.
    c             C   s   t dd S )Nz+StubImageFile subclass must implement _open)NotImplementedError)r/   r   r   r   r$   C  s    zStubImageFile._openc             C   sP   |   }|d kr"td| j d|| }|d k	s8t|j| _|j| _| S )Nzcannot find loader for this z file)_loadr   r2   r@   AssertionErrorr1   __dict__)r/   loaderimager   r   r   r@   F  s    
zStubImageFile.loadc             C   s   t ddS )z (Hook) Find actual image loader.z+StubImageFile subclass must implement _loadN)rn   )r/   r   r   r   ro   Q  s    zStubImageFile._loadN)rh   ri   rj   rk   r$   r@   ro   r   r   r   r   rm   ;  s   rm   c               @   sP   e Zd ZdZdZdZdZdZdZdZ	dd Z
dd Zdd	 Zd
d Zdd ZdS )Parserzj
    Incremental image parser.  This class implements the standard
    feed/close consumer interface.
    Nr   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)datarp   )r/   r   r   r   resetc  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| ndS | j|d | _n| jrny&t	
| j}t|}W dQ R X W n tk
r   Y nX t|dp(t|d}|s@t|jdkrHd| _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   rG   rE   )finishedru   r]   rZ   minrB   rU   rs   r   ioBytesIOr   r    r   rC   r   rM   rQ   r+   r   rR   rK   )r/   ru   skipra   r`   r!   rK   flagdoar   r   r   feedk  sR    	


zParser.feedc             C   s   | S )Nr   )r/   r   r   r   	__enter__  s    zParser.__enter__c             G   s   |    d S )N)r.   )r/   r[   r   r   r   __exit__  s    zParser.__exit__c          	   C   sz   | j r*| d d | _| _ | js*td| js8td| jrtt| j$}zt	|| _W d| j
  X W d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   ru   rw   r   rs   ry   rz   r   r    r@   )r/   r!   r   r   r   r.     s    

zParser.close)rh   ri   rj   rk   Zincrementalrs   ru   r]   rZ   rw   rv   r   r   r   r.   r   r   r   r   rt   V  s   Prt   c          
   C   sf  |    t| dsd| _|jtd tt|| jd d }y| }|	  d}W n, t
tjfk
r~ } z|}W dd}~X Y nX x|D ]\}}}}	|dkr|| t| j||	| j}
z|
| j| |
jr|
| |
 \}}n:|rx2|
|\}}}|| |rP qW n|
||}|dk r<td| d|W d|
  X qW t|d	rb|	  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   )r9   r      Nzencoder error z when writing image fileflush)r@   rC   r   rN   r   maxr   r,   rJ   r   r	   ry   UnsupportedOperationrH   r   Z_getencoderr+   rR   rK   	pushes_fdrT   encode_to_pyfdencodewriteencode_to_filer   rW   )rK   r!   r   bufsizefhexcr`   r^   r~   r   encoderlr_   r}   r   r   r   _save  s@    	




r   c             C   s   |dkrdS |t kr6| |}t||k r2td|S g }|}x8|dkrv| t|t }|s^P || |t|8 }q@W tdd |D |k rtd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 )N)rB   )r<   r}   r   r   r   	<genexpr>1  s    z_safe_read.<locals>.<genexpr>)	SAFEBLOCKrF   rB   r   rx   appendsumjoin)r!   r,   ru   Zremaining_sizeblockr   r   r   
_safe_read  s$    


r   c               @   s   e Zd Zdd Zdd ZdS )PyCodecStatec             C   s   d| _ d| _d| _d| _d S )Nr   )xsizeysizexoffyoff)r/   r   r   r   r   7  s    zPyCodecState.__init__c             C   s    | j | j| j | j | j| j fS )N)r   r   r   r   )r/   r   r   r   rY   =  s    zPyCodecState.extentsN)rh   ri   rj   r   rY   r   r   r   r   r   6  s   r   c               @   s6   e Zd Zdd Zdd Zdd Zdd Zdd
dZd	S )PyCodecc             G   s(   d | _ t | _d | _|| _| | d S )N)rK   r   statefdr+   init)r/   r+   r[   r   r   r   r   B  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   r   I  s    zPyCodec.initc             C   s   dS )zT
        Override to perform codec specific cleanup

        :returns: None
        Nr   )r/   r   r   r   rW   R  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   )r/   r   r   r   r   rT   Z  s    zPyCodec.setfdNc             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rtd| jj| jj | j jd ks| jj| jj | j jd krtd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)rK   r,   r   r   r   r   r   
ValueError)r/   rK   rY   Zx0Zy0Zx1Zy1r   r   r   rR   c  s    zPyCodec.setimage)N)rh   ri   rj   r   r   rW   rT   rR   r   r   r   r   r   A  s
   		r   c               @   s2   e Zd ZdZdZedd Zdd Z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>`
    Fc             C   s   | j S )N)	_pulls_fd)r/   r   r   r   rS     s    zPyDecoder.pulls_fdc             C   s
   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`.
        N)rn   )r/   bufferr   r   r   rU     s    	zPyDecoder.decodeNc             C   sd   |s
| j }t| j d|}|| j| j  ||}|d dkrLtd|d dkr`td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
        r6   r   znot enough image datar   zcannot decode image dataN)	r+   r   rQ   rR   rK   r   rY   rU   r   )r/   ru   Zrawmoder}   r_   r   r   r   
set_as_raw  s    

zPyDecoder.set_as_raw)N)	rh   ri   rj   rk   r   propertyrS   rU   r   r   r   r   r   r     s
   r   c               @   s8   e Zd ZdZdZedd Zdd Z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>`
    Fc             C   s   | j S )N)
_pushes_fd)r/   r   r   r   r     s    zPyEncoder.pushes_fdc             C   s
   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`.
        N)rn   )r/   r   r   r   r   r     s    	zPyEncoder.encodec             C   s2   | j s
dS | d\}}}|r*| 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   ir   )r   r   r   r   )r/   Zbytes_consumederrcoderu   r   r   r   r     s    zPyEncoder.encode_to_pyfdc             C   s@   d}x6|dkr:|  |\}}}|dkr|||d  qW |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   )r/   r   r   r   ZstatusZbufr   r   r   r     s    	
zPyEncoder.encode_to_fileN)
rh   ri   rj   rk   r   r   r   r   r   r   r   r   r   r   r     s   r   )r   )ry   rO   r)   rD    r   Z_utilr   r   r   rV   r
   r   r   r   rm   rt   r   r   r   r   r   r   r   r   r   r   <module>   s4   

 h 
4!F/