
    ji$                        d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
 dddZddZddd	Z	 	 d	 	 	 	 	 	 	 dd
ZddZddZddZddZddZy)u   IPTC IIM + XMP 메타데이터 자동 삽입 유틸리티 모듈.

PNG: PngInfo를 이용해 XMP 메타데이터 삽입
JPEG: APP13(IPTC IIM) + APP1(XMP) 마커를 JPEG 바이트에 직접 삽입
    )annotationsN)Path)Image)PngInfoc                `    |dg}dj                  d |D              }dt        |        d| dS )u  XMP 패킷 XML 문자열 생성. digitalsourcetype=trainedAlgorithmicMedia 포함.

    Args:
        title: 이미지 제목
        keywords: 키워드 목록 (None이면 ["AI-generated"] 사용)

    Returns:
        UTF-8 인코딩 가능한 XMP XML 문자열
    AI-generated c              3  :   K   | ]  }d t        |       d  yw)z      <rdf:li>z
</rdf:li>
N)_xml_escape).0kws     5/home/jay/workspace/tools/ai-image-gen/iptc_tagger.py	<genexpr>z"make_xmp_packet.<locals>.<genexpr>"   s     XB'8DXs   u  <?xpacket begin="ï»¿" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description rdf:about=""
      xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/"
      xmlns:dc="http://purl.org/dc/elements/1.1/"
      Iptc4xmpExt:DigitalSourceType="http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia"
    >
      <dc:title><rdf:Alt><rdf:li xml:lang="x-default">zD</rdf:li></rdf:Alt></dc:title>
      <dc:subject>
        <rdf:Bag>
zk        </rdf:Bag>
      </dc:subject>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>)joinr   )titlekeywordskw_itemss      r   make_xmp_packetr      sS     "#wwXxXXH
	( )4E(:'; <
 *	!	    c                |    dt        j                  d| |      z   t        j                  dt        |            z   |z   S )u$   단일 IPTC IIM 레코드 인코딩.   BB>Hstructpacklen)recorddatasetdatas      r   _encode_iim_recordr!   C   s5    V[[vw77&++dCPTI:VVY]]]r   c           	         |dg}d}| r|t        dd| j                  d            z  }|D ]!  }|t        dd|j                  d            z  }# |S )uV  IPTC IIM (Application2) 바이트 인코딩.

    - Record 2, Dataset 5: ObjectName (title)
    - Record 2, Dataset 25: Keywords (각 keyword마다 별도 레코드)

    Args:
        title: 이미지 제목 (ObjectName)
        keywords: 키워드 목록 (None이면 ["AI-generated"] 사용)

    Returns:
        IPTC IIM 바이트열
    r   r         utf-8   )r!   encode)r   r   resultr   s       r   encode_iptc_iimr)   H   sp     "#F $Q5<<+@AA  @$QBIIg,>??@ Mr   c                    |dg}| j                   j                         }|dk(  rt        | ||       | S |dv rt        | ||       | S t        | ||       | S )u  이미지에 IPTC + XMP 메타데이터 삽입. 동일 경로에 덮어씀. image_path 반환.

    PNG: Pillow PngInfo.add_itxt("XML:com.adobe.xmp", xmp_packet) 사용
    JPEG: APP13 (IPTC IIM) + APP1 (XMP) 마커를 JPEG 바이트에 직접 삽입

    Args:
        image_path: 태깅할 이미지 파일 경로
        title: 이미지 제목
        keywords: 키워드 목록 (None이면 ["AI-generated"] 사용)

    Returns:
        image_path (동일 경로)
    r   z.png)z.jpgz.jpeg)suffixlower_tag_png	_tag_jpeg)
image_pathr   r   r+   s       r   	tag_imager0   j   su    $ "#$$&FUH-  
$	$*eX.
  	UH-r   c                   t        ||      }t        j                  t        |             }t	               }|j                  d|d       |r!|j                  ddj                  |             |j                  t        |       |       y)u,   PNG 이미지에 XMP 메타데이터 삽입.zXML:com.adobe.xmpr	   Keywordsz, )pnginfoN)	r   r   openstrr   add_itxtadd_textr   save)r/   r   r   xmp_strimgr3   s         r   r-   r-      sj    eX.G
**S_
%CiG('26TYYx%89HHS_gH.r   c                    d}d}d}t        j                  dt        |             }d|z   |z   |z   | z   }t        |       dz  dk7  r|dz  }||z   }t        j                  d	t        |      dz         }d
|z   |z   S )uj   Photoshop APP13 블록 구성.

    구조:
      APP13 marker (2) + length (2) + header + 8BIM block
    s   Photoshop 3.0 s   s     z>Is   8BIMr#   r       r   s   r   )	iptc_dataheaderresource_idpascal_string	iptc_size	bim_blockpayloadlengths           r   _build_app13_blockrE      s     "FKMD#i.1I+%5	AIMI
9~QW	y G[[s7|a/0F'))r   c                    d}| j                  d      }||z   }t        j                  dt        |      dz         }d|z   |z   S )un   XMP APP1 블록 구성.

    구조:
      APP1 marker (2) + length (2) + XMP namespace header + xmp data
    s   http://ns.adobe.com/xap/1.0/ r%   r   r#   s   )r'   r   r   r   )r9   	ns_header	xmp_bytesrC   rD   s        r   _build_app1_xmp_blockrI      sJ     4Iw'I)#G[[s7|a/0F'))r   c                
   t        ||      }t        ||      }| j                         }|j                  d      st	        d|        |dd }|dd }t        |      }t        |      }	||z   |	z   |z   }
| j                  |
       y)u   JPEG 이미지에 APP13(IPTC) + APP1(XMP) 마커 삽입.

    최종 구조: SOI → APP13(IPTC) → APP1(XMP) → 원본 SOI 이후 나머지 내용
    s   u!   유효하지 않은 JPEG 파일: Nr#   )r   r)   
read_bytes
startswith
ValueErrorrE   rI   write_bytes)r/   r   r   r9   r=   
jpeg_bytessoirestapp13_blockapp1_xmp_blocknew_jpegs              r   r.   r.      s    
 eX.Gx0I &&(J   -<ZLIJJ
Ra.Cab>D %Y/K +73N [ >1D8H8$r   c                    | j                  dd      j                  dd      j                  dd      j                  dd      j                  d	d
      S )u!   XML 특수문자 이스케이프.&z&amp;<z&lt;>z&gt;"z&quot;'z&apos;)replace)texts    r   r   r      sG     	S'"	f		f		h		h	r   )r	   N)r   r5   r   list[str] | Nonereturnr5   )r   intr   r_   r    bytesr^   r`   )r   r5   r   r]   r^   r`   )r/   r   r   r5   r   r]   r^   r   )r/   r   r   r5   r   z	list[str]r^   None)r=   r`   r^   r`   )r9   r5   r^   r`   )r\   r5   r^   r5   )__doc__
__future__r   ior   pathlibr   PILr   PIL.PngImagePluginr   r   r!   r)   r0   r-   rE   rI   r.   r    r   r   <module>ri      s|    # 	    &&\^
H !%  
	N	/"*,*%Fr   