
    UHj{"                        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ZddZ		 	 	 	 	 	 	 	 	 	 	 	 ddZ
	 d	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddd	Zdd
ZdddZddZedk(  r e        yy)zDecode Compile .cns images to PNG.

This implements the LZ-style decoder used by cns110.exe and writes a
plain RGB PNG using only the Python standard library.
    )annotationsN)Pathc                    dt               d fd}dfd}	 t               k\  rt        d          }dz  |dk(  rt              S |dk\  rD ||dz  dz	         t               k\  rt        d	      |d
z  dz   }    }dz   |||       nb|dk\  r6t               k\  rt        d      |dz  dz      z   }dz   ||       n'|dk\  r ||dz         n|dk\  rMdz   t               kD  rt        d      |d
z  dz      z   } dz       dz      dz  z  }dz   |||       n|dk\  rAdz   t               kD  rt        d      |d
z  dz      z   } dz      }dz   |||       n}|dk\  rDdz   t               kD  rt        d      |d
z  dz   }     dz      dz  z  }dz   |||       n4t               k\  rt        d      |d
z  dz   }    }dz   |||       )zDecompress a CNS byte stream.

    The stream is a command byte followed by literal bytes and/or a
    backwards copy. A zero command terminates the stream.
    r   c                    | dk  s| z   t              kD  rt        d      j                  | z           | z  y )Nr   zliteral run exceeds input)len
ValueErrorextend)countdataoutsrcs    '/home/exedev/hwanse/tools/decode_cns.pyliteralzdecompress_cns.<locals>.literal   sE    19ec$i/899

4cEk*+u    c                    | dk  s| t              kD  rt        d|  dt                     t              | z
  }t        |      D ]  }j                  ||z              y )Nr   zbad back-reference offset z at output )r   r   rangeappend)offsetr
   startir   s       r   	copy_backz!decompress_cns.<locals>.copy_back   sh    Q;&3s8+9&SQTXJWXXC6!u 	'AJJs519~&	'r   zmissing CNS end marker      p      z!truncated one-byte back-reference      `   ztruncated long literal      @   0      z&truncated long two-byte back-reference    z&truncated long one-byte back-reference   z'truncated short two-byte back-referencez'truncated short one-byte back-reference)r
   intreturnNone)r   r&   r
   r&   r'   r(   )	bytearrayr   r   bytes)r   r   r   coder
   r   r   r   s   `     @@r   decompress_cnsr,      s{    C
+C' #d)566Cyq19:4<TD[Q&'c$i !DEED[A%E#YF1HCfe$T\c$i !9::Tka'494E1HCENT\D4K T\QwT" !IJJTka'494E#']d37mq&89F1HCfe$T\QwT" !IJJTka'494E#']F1HCfe$T\QwT" !JKKD[A%E#Y$sQw-1"45F1HCfe$c$i !JKKD[A%E#YF1HCfe$i r   c                Z   t        |       dk  rt        d      t        j                  d| d      \  }}}}|dz   }|dkD  rdnd}d|dz  z   }|t        |       kD  rt        d      g }t	        |      D ],  }	| d|	dz  z   d	|	dz  z    \  }
}}}|j                  |||
f       . | |d  }|||||fS )
Nr    zdecoded CNS is too shortz<HHHHr   r   r%   r   zpalette exceeds decoded data   )r   r   structunpack_fromr   r   )decoded_unknownwidthheightpalette_lastpalette_countbpppalette_endpaletter   bgr_pixelss                  r   parse_imager?   ]   s    
7|a344,2,>,>wQR,S)HeV\ 1$Mr!!qCma''KS\!788*,G=! "QQYa!e4
1a1ay!" [\"F&'63..r   c                @   | |z  dz   dz  dz  }||z  }t        |      |k  rt        dt        |       d|       t               }t        |      D ]  }||dz
  |z
  |z  ||z
  |z   }	|dk(  r|	d |  }
ne|dk(  rRt               }
|	d | dz   dz   D ]9  }|
j	                  |dz	         t        |
      | k  s&|
j	                  |d	z         ; nt        d
|       |
D ]6  }|t        |      k\  r|j                  d       #|j                  ||          8  t        |      S )Nr   r$   r   pixel data too short: got , expected r   r    r   r   unsupported bit depth )   r   rD   r   r   r)   r   r   r	   r*   )r3   r4   r9   r>   r7   strideexpectedrgbyrowindicesbyteidxs                r   indices_to_rgbrN   o   sN    s{RB&!+FH
6{X5c&k]+hZXYY
+C6] )fqj1n.&1*1FG!8&5kGAXkG.uqyQ./ 0tqy)w<%'NN4$;/0
 5cU;<< 	)Cc'l"

=)

73<(		))$ :r   c                f   | |z  dz   dz  dz  }||z  }t        |      |k  rt        dt        |       d|       t               }t        |      D ]  }	||dz
  |	z
  |z  ||	z
  |z   }
|dk(  r|
d |  }ne|dk(  rRt               }|
d | dz   dz   D ]9  }|j	                  |dz	         t        |      | k  s&|j	                  |d	z         ; nt        d
|       |D ]I  }|t        |      k\  r|j                  d       #||   \  }}}||k(  rdnd}|j                  ||||f       K  t        |      S )Nr   r$   r   rA   rB   r   r    r   r   rC   )rD   r   rD   rD   r   rD   rE   )r3   r4   r9   r>   r7   transparent_indexrF   rG   rgbarI   rJ   rK   rL   rM   r<   r;   r:   alphas                     r   indices_to_rgbarS      sr    s{RB&!+FH
6{X5c&k]+hZXYY;D6] .fqj1n.&1*1FG!8&5kGAXkG.uqyQ./ 0tqy)w<%'NN4$;/0
 5cU;<< 	.Cc'l"./!#,1a $553Q1e,-	..( ;r   c                   dd}t               }|dnd}|dz  }t        |      D ]}  }	|j                  d       ||	|z  |	dz   |z   }
||j                  |
       6t        dt	        |
      d      D ]/  }|
||dz    \  }}}|||f|k(  rdnd}|j                  ||||f       1  t        d      }|dk(  rdnd	}|j                   |d
t        j                  d||d|ddd                   |j                   |dt        j                  t        |      d                   |j                   |dd             | j                  |       y )Nc                    t        j                  dt        |            | z   |z   t        j                  dt        j                  | |z         dz        z   S Nz>Il    r/   packr   zlibcrc32kindpayloads     r   chunkzwrite_png.<locals>.chunk   Q    KKc'l+ kk$

4'> :Z GHI	
r   r   r#   r   r   rD      PNG

   r      IHDR>IIBBBBBr       IDAT	      IENDr   r\   r*   r]   r*   r'   r*   )r)   r   r   r	   r   r/   rX   rY   compressr*   write_bytes)pathr3   r4   rH   transparent_rgbr^   	scanlineschannelsrow_lenrI   rJ   r   r<   r;   r:   rR   png
color_types                     r   	write_pngrq      sZ   
 I#/qQHaiG6] 	3!g+Q' 12"S!1c#h* 3a!a%.1aAY/9s  !Q5!123	3 (
)C!mJJJuWfkk*eVQ
TUWXZ[\]^JJuWdmmE),<a@ABJJuWc"#Sr   c                   dd}t               }|dz  }t        |      D ]0  }|j                  d       |j                  |||z  |dz   |z          2 t        d      }|j                   |dt	        j
                  d||dd	ddd                   |j                   |d
t        j                  t        |      d                   |j                   |dd             | j                  |       y )Nc                    t        j                  dt        |            | z   |z   t        j                  dt        j                  | |z         dz        z   S rV   rW   r[   s     r   r^   zwrite_rgba_png.<locals>.chunk   r_   r   r   r   r   r`   rb   rc   r    ra   rd   re   rf   r   rg   )
r)   r   r   r	   r/   rX   rY   rh   r*   ri   )	rj   r3   r4   rQ   r^   rl   rn   rI   ro   s	            r   write_rgba_pngrt      s    
 IaiG6] @a'kQUg,=>?@ (
)CJJuWfkk*eVQ1aQRSTUJJuWdmmE),<a@ABJJuWc"#Sr   c                t   t        | j                               }t        |      \  }}}}}|j                  j	                  dd       |r t        |||||d      }	t        ||||	       nt        |||||      }
t        ||||
       t        |  d| d| d| d| d	t        |       d
t        |       d       y )NT)parentsexist_okr   )rP   z -> z (xz, zbpp, z colors, decoded z bytes))r,   
read_bytesr?   parentmkdirrS   rt   rN   rq   printr   )r   dsttransparent_palette0r1   r3   r4   r9   r>   r7   rQ   rH   s              r   decode_filer      s    S^^-.G*5g*>'E67FCJJTD1ufgvsVWXsE640UFGVSA#ufc*	%tC55'6("SEw<.)#g,w	@r   c                 >   t        j                  t              } | j                  ddt               | j                  ddt        t	        d             | j                         }|j                  D ]*  }|j                  |j                  d	z   z  }t        ||       , y )
N)descriptioninputs+)nargstypez-oz	--out-dirr   )r   defaultz.png)
argparseArgumentParser__doc__add_argumentr   
parse_argsr   out_dirstemr   )parserargsr   r}   s       r   mainr      s    $$9F
$7
kd5kJD{{ llchh/0Cr   __main__)r   r*   r'   r*   )r1   r*   r'   z7tuple[int, int, list[tuple[int, int, int]], bytes, int])r3   r&   r4   r&   r9   list[tuple[int, int, int]]r>   r*   r7   r&   r'   r*   )r   )r3   r&   r4   r&   r9   r   r>   r*   r7   r&   rP   r&   r'   r*   )N)rj   r   r3   r&   r4   r&   rH   r*   rk   ztuple[int, int, int] | Noner'   r(   )
rj   r   r3   r&   r4   r&   rQ   r*   r'   r(   )F)r   r   r}   r   r~   boolr'   r(   )r'   r(   )r   
__future__r   r   r/   rY   pathlibr   r,   r?   rN   rS   rq   rt   r   r   __name__ r   r   <module>r      s   
 #    K%\/$&@JOVY
H """ (" 	"
 
" " "J>,  zF r   