
    tj                    j    d Z ddlmZ ddlZddlZ ej
                  e      ZdZd
dZ	ddddZ
dd	Zy)u)  생성 이미지 바이트 형식 정규화 (2026-08-06 사용자 지시 — PNG 로 정규화).

발단은 실측이다. 프로젝트의 생성 산출은 전부 `.png` 이름으로 저장되는데,
멀티롤 롤(`_a`/`_b`/`_c`)·선정본(`_sel`)·수정본(`_fix`) 의 **내용은 JPEG**
였다 (C 실행 1,149장 전건, A 실행 888장 전건 — 7월부터 같은 상태).
Gemini 이미지 모델이 `inlineData.mimeType: image/jpeg` 로 돌려주는데
클라이언트가 mimeType 을 읽지 않고 바이트를 그대로 `.png` 에 썼기 때문이다.

두 가지가 걸린다.

① **이름과 내용이 어긋난다.** Gemini 판정은 media type 불일치를 조용히
   받아줬지만 Anthropic 은 400 으로 거부한다("specified using the image/png
   media type, but the image appears to be a image/jpeg image"). 선정 판정을
   Claude 로 옮기는 순간 전 호출이 죽는다.

② **i2i 체인마다 재압축된다.** 롤 → 선정본 → 수정본으로 이어지는 편집
   체인이 JPEG 를 매번 다시 인코딩한다. 손실이 누적된다.

그래서 **생성 경로의 반환 지점에서 PNG 로 정규화**한다. 이미 PNG 면 바이트를
그대로 돌려준다(무손실·무변경). 이미 잃은 화질은 되돌아오지 않지만 그 뒤로
더 잃지는 않는다.
    )annotationsNs   PNG

c                F    t        |       xr | j                  t              S )N)bool
startswith
_PNG_MAGICdatas    R/Users/manta/Documents/Projects/TheRoad-I1/backend/app/modules/llm/image_format.pyis_pngr   !   s    :5$//*55     )contextc          	     ~   | rt        |       r| S 	 ddlm} |j                  t	        j
                  |             5 }|j                  dv r|j                  d      }n |j                  dk(  r|j                  d      }t	        j
                         }|j                  |dd	       d
d
d
       j                         }t        j                  dt        |       t        |       t        |      |rd| d       |S d       |S # 1 sw Y   ]xY w# t        $ r'}t        j                  d|xs d|       | cY d
}~S d
}~ww xY w)u  이미지 바이트를 PNG 로 정규화한다.

    이미 PNG 면 **같은 객체를 그대로** 돌려준다 — 재인코딩하지 않으므로
    기존 산출과 byte-identical 이다.

    디코드하지 못하는 바이트(빈 값·손상·미지원 포맷)는 손대지 않고 그대로
    돌려준다. 여기서 예외를 올리면 이미 유료로 받아 온 이미지를 버리게 된다 —
    형식 정규화가 생성 실패로 번지면 안 된다.
    r   )Image)PLAPARGBACMYKRGBPNGF)formatoptimizeNuK   ensure_png_bytes: PNG 정규화 실패 — 원본 바이트 유지 (%s): %r?u:   ensure_png_bytes: %s → PNG 정규화 (%d → %d bytes)%sz []r   )r   PILr   openioBytesIOmodeconvertsavegetvalue	Exceptionloggerwarninginfo_snifflen)r	   r   r   imbufoutexcs          r
   ensure_png_bytesr.   %   s    6$<ZZ

4()R ww++ZZ'F"ZZ&**,CGGCG6 * lln KKDtc$iS""WIQ
 J )+
 J+ *)  YNsC	
 s5   *D A)D $D  D	D 	D<D71D<7D<c                n    | j                  d      ry| j                  d      ry| d d dk(  r	| dd d	k(  ry
y)Ns   JPEG)s   GIF87as   GIF89aGIF   s   RIFF      s   WEBPWEBPunknown)r   r   s    r
   r(   r(   L   sB    '-.BQx7tAbzW4r   )r	   bytesreturnr   )r	   r7   r   strr8   r7   )r	   r7   r8   r9   )__doc__
__future__r   r   logging	getLogger__name__r%   r   r   r.   r(    r   r
   <module>r@      sA   , # 	 			8	$!
6 57 $Nr   