o
    Ԧ/fX                     @  s  d dl mZ 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	m
Z
mZmZmZmZmZ ddlmZ ddlmZ ddlmZ G d	d
 d
eZejZdd ZG dd dejZddddZdd Zdd Zdd Zdd Zdd Z dd Z!d<dd Z"d!d" Z#d#d$ Z$d%d& Z%dZ&d'd( Z'd)d* Z(d+d, Z)d-d. Z*d/d0 Z+d1d2 Z,d3d4 Z-d=d5d6Z.d>d8d9Z/e	0ej1ee e	2ej1e" e	3ej1e! e	4ej1d: e	5ej1d; dS )?    )annotationsN)IntEnum   )Image
ImageChops	ImageFile	ImageMathImageOpsImagePaletteImageSequence)i16le)o8)o16lec                   @  s   e Zd ZdZdZdZdZdS )LoadingStrategyz.. versionadded:: 9.1.0r   r      N)__name__
__module____qualname____doc__RGB_AFTER_FIRST RGB_AFTER_DIFFERENT_PALETTE_ONLY
RGB_ALWAYS r   r   2lib/python3.10/site-packages/PIL/GifImagePlugin.pyr   0   s
    r   c                 C  s   | d d dv S )N   )s   GIF87as   GIF89ar   )prefixr   r   r   _accept?      r   c                      s~   e Zd ZdZdZdZdZdd Zdd Zd	d
 Z	e
dd Ze
dd Zdd ZdddZ fddZdd Zdd Z  ZS )GifImageFileZGIFzCompuserve GIFFNc                 C  s,   | j d}|r|d r| j |d S d S )Nr   r   )fpread)selfsr   r   r   dataO   s   zGifImageFile.datac                 C  s\   t dt|dD ]#}|d ||   kr'||d    kr'||d  ks+ dS   dS qdS )Nr      r   r   TF)rangelen)r!   pir   r   r   _is_palette_neededU   s   4zGifImageFile._is_palette_neededc                 C  s   | j d}t|sd}t||d d | jd< t|dt|df| _g | _|d }|d@ d }|d	@ rU|d
 | jd< | j d|> }| |rUt	
d|}| | _| _| j | _| j  | _d | _d | _| d d S )N   znot a GIF filer   version   
      r         
backgroundr$   RGBr   )r   r    r   SyntaxErrorinfoi16_sizetiler)   r
   rawglobal_palettepalette_fptell_GifImageFile__rewind	_n_frames_is_animated_seek)r!   r"   msgflagsbitsr'   r   r   r   _open[   s(   
zGifImageFile._openc                 C  s\   | j d u r+|  }z	 | |  d d q ty%   |  d | _ Y nw | | | j S )NTr   F)r>   r<   r@   EOFErrorseekr!   Zcurrentr   r   r   n_framesw   s   

zGifImageFile.n_framesc                 C  s~   | j d u r<| jd ur| jdk| _ | j S |  }|rd| _ | j S z| dd d| _ W n ty6   d| _ Y nw | | | j S )Nr   TF)r?   r>   r<   r@   rE   rF   rG   r   r   r   is_animated   s    

	


zGifImageFile.is_animatedc                 C  s   |  |sd S || jk rd | _| d | j}t| jd |d D ]!}z| | W q! tyB } z| | d}t||d }~ww d S )Nr   r   no more images in GIF file)Z_seek_check_GifImageFile__frameimr@   r%   rE   rF   )r!   frameZ
last_frameferA   r   r   r   rF      s    




zGifImageFile.seekTc                   s  |dkr!d _ d  _d _ j j d _d jv r  jd= n	 jr*|r* 	  | jd kr:d| }t
| j _ j rT j j    rQ	   sLd _  jd}|r`|dkrfd}t|d }i }d }d }d }		 |sy jd}|r|dkrn9|d	kr' jd}  }
|d d
kr|
d }|d@ r|
d }t|
dd |d< d|@ }|d? }|r| _nb|d dkrd}|
r||
7 }  }
|
sd|v r|d  d| 7  < n||d< d }qp|d dkr|dkr|
 j f|d< |
d d dkr  }
t|
dkr|
d dkrt|
d jd<   r&	   s n|dkr jd}t|dt|d}}|t|d |t|d }}| jd ks\| jd krv|rvt| jd t| jd f _t j ||||f}	|d }|d@ dk}|d@ r|d@ d } jd|> } |rtd |}nd!} jdd } j  _ nd }qq|d u rd"}t|| _|sd S g  _ jr݈ j j j |d ur|n j _| _|dkr" jr	t t!j"kr|d urd#nd  _#nd$ _#nd% _#|s jrdd&l$m$} | j}| _%nA j&d$krct t!j'ks1|rcd  _(d' jv rV j) jd' d  j*d#tj+j, _d# _# jd'= nd  _# j*d tj+j, _ fd(d)}|	 _z jdk rwd  _n jdkrˈ j\}}}}|| || f}t| d$} j-d'|}|d ur j&d*v rd#}||d+ }n j-d,d} j&d*v rd }||}tj./||| _nD jd urۈ 0 j j _n4|d ur j\}}}}|| || f}t| d$}|} j&d*v rd#}||d+ }tj./||| _W n
 t1y   Y nw |d urPd}|d ur@|dkr8t t!j"kr7| jd'< n j&d*vr@|}d-||||f j |||ffg _|-dr]|d  jd< d.D ]}||v ro||  j|< q_| jv ry j|= q_d S )/Nr   commentr   zcannot seek to frame    ;rJ   T   !   r$   r-   duration   r             
   	extensionr0      NETSCAPE2.0loop   ,	      r   r,   @   r/   r.   r2   Fzimage not found in GIF frameRGBAPL)copytransparencyc                   sT    j r#| d d t j jkrd} t j j| d | d d  } | S | | | f} | S )Nr$   r   )_frame_paletter&   r:   tuple)colorr!   r   r   _rgbT  s    
z GifImageFile._seek.<locals>._rgbr2   rb   )r   r1   gif)rU   r[   )2Z_GifImageFile__offsetZdisposerK   r;   rF   r=   Zdisposal_methodr4   r7   load
ValueErrorr   r#   r    rE   r5   r<   r&   sizemaxr6   r   Z_decompression_bomb_checkr)   r
   r8   rL   pastedispose_extentr9   rg   _frame_transparencyLOADING_STRATEGYr   r   _modere   r:   moder   ZpyaccessputpalettealphaconvertDitherFLOYDSTEINBERGgetcorefill_cropAttributeError)r!   rM   Zupdate_imagerA   r"   r:   r4   Zframe_transparency	interlaceZframe_dispose_extentblockrB   Zdispose_bitsrQ   Zx0Zy0Zx1Zy1rC   r'   re   rk   Zdispose_sizeZdispose_moderi   rf   kr   rj   r   r@      sp  






&"

[


	








	
zGifImageFile._seekc                   s   | j rdnd}d | _| jdkr | jd urtj|| j| j| _n&| j	dv rF| j| _| j rCtjd| j| jp6d| _| jj
| j    nd | _|| _d | _ t   d S )Nrc   rd   r   rl   )rg   _prev_imrK   rt   r   r}   r~   rp   rL   rw   
putpalettegetdatarv   superload_prepare)r!   Z	temp_mode	__class__r   r   r     s"   



zGifImageFile.load_preparec                 C  s   | j dkr0| jdkr.ttjkr.| jd ur | j| jd d| _nd| _| j	| jt
jj| _d S | js5d S | jd urI| j| jd | j	d}n| j	d}| || j}| j| _| jj| _|jdkro| j|| j| d S | j|| j d S )Nr   rc   rb   r2   )rK   rw   ru   r   r   rt   rL   rx   rv   ry   r   rz   r{   r   r   rs   rr   )r!   Zframe_imr   r   r   load_end  s(   




zGifImageFile.load_endc                 C  s   | j S N)rK   rj   r   r   r   r<     s   zGifImageFile.tell)T)r   r   r   formatZformat_descriptionZ!_close_exclusive_fp_after_loadingr9   r#   r)   rD   propertyrH   rI   rF   r@   r   r   r<   __classcell__r   r   r   r   r   H   s$    


 r   rd   rc   )1rd   rc   c                 C  s   | j tv r|   | S t| j dkr=| jdtjjd} | jj dkr;| jj	D ]}|d dkr:| jj	| | j
d<  | S q&| S | dS )	a  
    Takes an image (or frame), returns an image in a mode that is appropriate
    for saving in a Gif.

    It may return the original image, or it may return an image converted to
    palette or 'L' mode.

    :param im: Image object
    :returns: Image object
    r2   rc   r:   rb   r$   r   rf   rd   )rw   RAWMODErn   r   Zgetmodebasery   ZPaletteZADAPTIVEr:   colorsr4   )rL   Zrgbar   r   r   _normalize_mode  s   

r   c           	      C  s  d}|rt |tttfrt|dd }t |tjrt|j}| jdkr1|s0| jddd }n|s>tdd t	dD }tjd|d| _|rg }t	dt
|d	D ]}t|||d	  }| jj|}||v rkd}|| qRt|D ]\}}|du rt	t
|D ]}||vr|||<  nqqu| |} n/t| |}|dur| ||} d
|v rz||d
 |d
< W | S  ty   |d
= Y | S w | S || j_| S )at  
    Normalizes the palette for image.
      - Sets the palette to the incoming palette, if provided.
      - Ensures that there's a palette for L mode images
      - Optimizes the palette if necessary/desired.

    :param im: Image object
    :param palette: bytes object containing the source palette, or ....
    :param info: encoderinfo
    :returns: Image object
    Ni   rc   r2   c                 s  s    | ]}|d  V  qdS )r$   Nr   ).0r(   r   r   r   	<genexpr>  s    z%_normalize_palette.<locals>.<genexpr>r   r   r$   rf   )
isinstancebytes	bytearraylistr
   r:   rw   rL   Z
getpaletter%   r&   rh   r   r|   append	enumerateZremap_palette_get_optimizeindexro   )	rL   r:   r4   Zsource_paletteused_palette_colorsr(   Zsource_colorr   jr   r   r   _normalize_palette  s\   



r   c              	   C  s   t | }|j D ]\}}| j|| q	t||| j}t|| jD ]}|| q"d}t| r4|dB }t	|| d| dt| f|_
t||dd| j dt|j fg |d d S )Nr   ra   r   r   r,   rm       )r   r4   itemsencoderinfo
setdefaultr   _get_global_headerwriteget_interlace_write_local_headerZencoderconfigr   _saverp   r   rw   )rL   r   r:   Zim_outr   vr"   rB   r   r   r   _write_single_frame2  s   $r   c                 C  s@   t |t | kr|d}| d} t|| }||jddfS )Nrb   F)Z
alpha_only)_get_palette_bytesry   r   Zsubtract_moduloZgetbbox)Zbase_imim_framedeltar   r   r   _getbboxG  s
   

r   c              
   C  s  | j d}| j d| jd}g }d }d}d }t| g| j dg D ]]}	t|	D ]T}
t|
 }
|dkrP|
j	 D ]\}}|dkrHq?| j 
|| q?| j  }d|
jv rc|
d|
jd  t|
||}
t|ttfrw|| |d< n|d u rd|
jv r|
jd |d< t|ttfr|| |d< |d7 }d }|rrt||
\}}|s|dr|d d d  |d 7  < q-|d d dd	kr|d u r| j d| jdd
}t|
|}td|
j|}||d d j t||
d }n|drq|
jdkrqd|vrz
|
j|
|d< W n
 ty   Y nw d|v rq|
 }td|j|d }|jdkrH| \}}}}tjdd ||||d}n|jdkr^td|j}||  |}tjdd |d}|j|t |d nd }|
}|!|p||
||d q-q%t"|dkrd| j v r|d d d | j d< d S |D ]@}|d }
|d st#|
|d D ]}|$| qd}n|sd|d d< |
%|d }
|d d d	 }t&||
||d  qdS )NrU   disposalr   Zappend_imagesrf   r   rP   r   r   )r   r   r   rc   rL   optimizer   rb   c                 S  s@   | d | d | d | d | d | d | d | d d dS )	Nry   rq   rgbarZ   r   r   argsr   r   r   <lambda>  s    z(_write_multiple_frames.<locals>.<lambda>)r   r   r   r   rd   c                 S  s   | d | d d dS )Nry   rL   rZ   r   r   r   r   r   r   r     s    rL   )mask)rL   bboxr   r   r   Tinclude_color_table)'r   r|   r4   	itertoolschainr   Iteratorr   re   r   r   r   r   r   rh   r   _get_backgroundr   newrp   r   r:   rw   Z_new_color_indexro   splitr   Zlambda_evalZputdatar   rr   r	   invertr   r&   r   r   Zcrop_write_frame_data)rL   r   r:   rU   r   Z	im_framesZprevious_imZframe_countZbackground_imZ
imSequencer   r   r   r   Z
diff_framer   r   ri   r1   r~   r   r   r   r   r   Zdelta_lZ
frame_datar"   offsetr   r   r   _write_multiple_framesO  s   








Y
r   c                 C  s   t | ||dd d S )NT)save_all)r   )rL   r   filenamer   r   r   	_save_all  s   r   Fc                 C  s~   d| j v s
d| jv r| j d| jd}n	d }| j dd |r't| ||s-t| || |d t|dr=|  d S d S )Nr:   r   TrR   flush)	r   r4   r|   r   r   r   r   hasattrr   )rL   r   r   r   r:   r   r   r   r     s   

r   c                 C  s$   | j dd}t| jdk rd}|S )Nr   r      r   )r   r|   minrp   )rL   r   r   r   r   r     s   r   c                 C  sj  z|j d }W n ty   d }Y nw d|j v r"t|j d d }nd}t|j dd}|d us7|dks7|rd|d ur=dnd}||d> O }| dtd	 td
 t| t| t|p\d td  |j d}|r~t|}	t|	}
|
r~|dB }||
B }| dt|d  t|d  t|j	d  t|j	d  t|  |r|
r| t
|	 | td d S )Nrf   rU   r-   r   r   r   r   rS   rT   r`   r   r/   r^   r,   )r   KeyErrorintr|   r   r   o16r   _get_color_table_sizerp   _get_header_palette)r   rL   r   rB   rf   rU   r   Zpacked_flagr   palette_bytescolor_table_sizer   r   r   r     sd   




r   c           
      C  s  |   }ztt|dS}| jdkrtjd|g|tjd n:dd|g}dg}tj|tjtjd}tj||j|tjd}|j	  |
 }	|	rJt|	||
 }	|	rVt|	|W d    n1 s`w   Y  W zt| W d S  tyx   Y d S w zt| W w  ty   Y w w )Nwbr2   Zppmtogif)stdoutstderrZppmquantZ256)stdinr   r   )Z_dumpopenrw   
subprocessZ
check_callZDEVNULLPopenPIPEr   closewaitZCalledProcessErrorosunlinkOSError)
rL   r   r   ZtempfilerN   Z	quant_cmdZ	togif_cmdZ
quant_procZ
togif_procZretcoder   r   r   _save_netpbm  sL   



r   c                 C  s   | j dv r`|rb|drdtp| j dk}|s| j| j dk rfg }t|  D ]\}}|r0|| q%|s;t|t	|kr=|S t	| j
j
t| j
j  }d|d  > }t	||d krh|dkrj|S dS dS dS dS dS dS )aL  
    Palette optimization is a potentially expensive operation.

    This function determines if the palette should be optimized using
    some heuristics, then returns the list of palette entries in use.

    :param im: Image object
    :param info: encoderinfo
    :returns: list of indexes of palette entries in use, or None
    )rc   rd   r   rd   i   r   r   N)rw   r|   _FORCE_OPTIMIZEwidthZheightr   Z	histogramr   rq   r&   r:   r   Zgetmodebands
bit_length)rL   r4   Zoptimiser   r(   countZnum_palette_colorsZcurrent_palette_sizer   r   r   r   L  s*   
r   c                 C  s6   | sdS t | dk rdS ttt | d dd S )Nr   r_   r   r$   r   )r&   mathZceillog)r   r   r   r   r   z  s
   r   c                 C  s<   t | }d|> t| d  }|dkr| tdd | 7 } | S )z
    Returns the palette, null padded to the next power of 2 (*3) bytes
    suitable for direct inclusion in the GIF header

    :param palette_bytes: Unpadded palette bytes, in RGBRGB form
    :returns: Null padded palette
    r   r$   r   )r   r&   r   )r   r   Zactual_target_size_diffr   r   r   r     s
   r   c                 C  s   | j r| j j S dS )z
    Gets the palette for inclusion in the gif header

    :param im: Image object
    :returns: Bytes, len<=768 suitable for inclusion in gif header
    rX   r   r   r   r   r   r     s   r   c              
   C  sd   d}|r0t |tr.z
| j|| }W |S  ty- } zt|dvr" W Y d }~|S d }~ww |}|S )Nr   )z$cannot allocate more than 256 colorsz/cannot add non-opaque RGBA color to RGB palette)r   rh   r:   Zgetcolorro   str)rL   Zinfo_backgroundr1   rO   r   r   r   r     s   



r   c                 C  s~  d}| j ddks!|r#d|v s!|ddus!|ds!|dr#d}t| |d	}t| }t|}d
| t| jd  t| jd  t|d t|td t|g}|ddur}|	dtd td d td td t|d  td  |drdtd }|d }t
|tr| }tdt|dD ]}	||	|	d  }
|tt|
|
 7 }q|td7 }|	| |S )z2Return a list of strings representing a GIF headers   87ar+   s   89arf   r]   NrU   rQ   r1   s   GIFr   r   r/   rS   rZ   r0   r\   r$   rW   )r4   r|   r   r   r   r   rp   r   r   r   r   r   encoder%   r&   )rL   r4   r+   r1   r   r   headerZcomment_blockrQ   r(   Zsubblockr   r   r   r     sl   





r   c              	   C  sT   z&||_ t| ||d t|| dd|j dt|j fg | d W |` d S |` w )Nr   rm   r   r   )r   r   r   r   rp   r   rw   r   )r   r   r   paramsr   r   r   r     s   r   c                 C  sd   t | |}|du ri }d|vrd| jv r| jd |d< t| ||}|j| _|j| _t| |}||fS )a  
    Legacy Method to get Gif data from image.

    Warning:: May modify image data.

    :param im: Image object
    :param palette: bytes object containing the source palette, or ....
    :param info: encoderinfo
    :returns: tuple of(list of header items, optimized palette)

    Nr1   )r   r4   r   r:   rL   r   )rL   r:   r4   r   Zim_modr   r   r   r   	getheader	  s   

r   r   c                 K  s0   G dd d}|    | }t|| || |jS )a  
    Legacy Method

    Return a list of strings representing this image.
    The first string is a local image header, the rest contains
    encoded image data.

    To specify duration, add the time in milliseconds,
    e.g. ``getdata(im_frame, duration=1000)``

    :param im: Image object
    :param offset: Tuple of (x, y) pixels. Defaults to (0, 0)
    :param \**params: e.g. duration or other encoder info parameters
    :returns: List of bytes containing GIF encoded frame data

    c                   @  s   e Zd Zg Zdd ZdS )zgetdata.<locals>.Collectorc                 S  s   | j | d S r   )r#   r   )r!   r#   r   r   r   r   :  r   z getdata.<locals>.Collector.writeN)r   r   r   r#   r   r   r   r   r   	Collector7  s    r   )rn   r   r#   )rL   r   r   r   r   r   r   r   r   %  s
   r   z.gifz	image/gif)F)NN)r   )6Z
__future__r   r   r   r   r   enumr    r   r   r   r   r	   r
   r   Z_binaryr   r5   r   r   r   r   r   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Zregister_openr   Zregister_saveZregister_save_allZregister_extensionZregister_mimer   r   r   r   <module>   sV   $			   <z

01.

>

$