
    )kiD                    &   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lZddl	m
Z
  ee      j                  Z ed      Zedz  dz  Zed	z  Zed
z  ZdZdZdZdZdZ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e dk(  r e        yy)!u  컨셉 #35 (Bottom-Anchored Content Stack) 프로덕션 배너 생성기
- c35-1200x628.png  (가로형, Meta/Google Ads)
- c35-1200x1200.png (정사각형, Meta Ads)
- c35-1200x628.html
- c35-1200x1200.html

디자인:
- Gemini 야경 사무실 배경
- 하단 네이비 그라디언트 오버레이
- Pretendard 900 헤드라인 + 오렌지 키워드 하이라이트
- 프로스티드 글라스 서브카피 블록 (blur 20px)
- 오렌지 아웃라인 CTA 필 버튼
    )annotationsN)Path)sync_playwrightzM/home/jay/workspace/output/meta-ads/production-banners/35-hybrid-v4-refined-Aoutputz	v4-hybridzbg_c35_landscape.jpgzbg_c35_square.jpgz0https://generativelanguage.googleapis.com/v1betazgemini-3-pro-image-previewzgemini-3.1-flash-image-previewam  Modern Korean office interior at night, dark and moody atmosphere, a desk with a laptop, large window showing city lights in the background, soft ambient lighting from monitors, cool blue-grey color grading, cinematic depth of field, photorealistic, no people, no text, no logos. Wide landscape composition 16:9 aspect ratio, the lower half darker for text overlay.aa  Modern Korean office interior at night, dark and moody atmosphere, a desk with a laptop, large window showing city lights in the background, soft ambient lighting from monitors, cool blue-grey color grading, cinematic depth of field, photorealistic, no people, no text, no logos. Square composition, the lower half significantly darker for text overlay.c                     t         j                  j                  dt        t                     dd l} | j                         S )Nr   )syspathinsertstrBASE_DIRgcloud_authget_access_token)r   s    L/home/jay/workspace/tools/ai-image-gen/_backup/gen_c35_production_banners.pyget_auth_tokenr   <   s*    HHOOAs8}%''))    c                     t         j                  j                  dt        t                     dd l} | j                  d      S )Nr   GEMINI_API_KEY)r   r	   r
   r   r   r   get_api_key)gas    r   r   r   B   s+    HHOOAs8}%>>*++r   c                    t          d| d}d|  dd}t        j                  |||d      }|j                  dk(  r|S |r+t          d| d	| }d
di}t        j                  |||d      S |S )Nz/models/z:generateContentzBearer zapplication/json)AuthorizationContent-Typei,  )headersjsontimeout   z:generateContent?key=r   )GEMINI_API_BASErequestspoststatus_code)	tokenapi_keymodelpayload
url_bearerr   respurl_keyhdrs_keys	            r   _call_modelr)   H   s    #$HUG3CDJ%,UG#4FXYG==W7CPD3%&hug5J7)T"$67}}WhWcRRKr   c           	     f   |j                         r-|j                         j                  dkD  rt        d|        |S t        d|j                          t               }t               }dd| igigdddgid	}t        t        fD ]m  }t        d
|        	 t        ||||      }|j                  dv r)t        d|j                   d|j                  dd         X|j                  dk7  r)t        d|j                   d|j                  dd         |j                         }|j                  dg       }	|	st        d       |	d   j                  di       j                  dg       }
t        d |
D        d      }|t        d       t!        j"                  |d   d         }|j$                  j'                  dd       |j)                  |       t        d| dt+        |      d d!       |c S  t-        d"|j                         # t        $ r}t        d|        Y d}~d}~ww xY w)#uZ   Gemini API로 배경 이미지를 생성합니다. 이미 존재하면 재사용합니다.iP  u     [배경] 기존 재사용: u"     [배경] Gemini API 생성 중: partstextresponseModalitiesIMAGETEXT)contentsgenerationConfigu       모델: u       요청 예외: N)i  i  i  u       접근 불가 (z):    r   z	    HTTP : 
candidatesu       candidates 없음r   contentc              3  *   K   | ]  }d |v s|  yw)
inlineDataN ).0ps     r   	<genexpr>z&generate_background.<locals>.<genexpr>z   s     A|q/@1As   	u       이미지 파트 없음r7   dataTparentsexist_oku       저장 완료:  (,z bytes)u   배경 생성 실패: )existsstatst_sizeprintnamer   r   MODEL_IDFALLBACK_MODELr)   	Exceptionr    r,   r   getnextbase64	b64decodeparentmkdirwrite_byteslenRuntimeError)promptout_pathr!   r"   r$   r#   r&   er<   r4   r+   img_part	img_bytess                r   generate_backgroundrX   U   s@   X]]_44v=-hZ89	.x}}o
>?EmG  01231GV3DEG
 N+ UG$%	ugug>D
 .'(8(8'9TYYt_<MNOs"Id../r$))DS/1BCDYY[XXlB/
)+]&&y"599'2FAeA4H/1$$Xl%;F%CD	dT:Y'#H:RIq/AIJ?B /?
@@;  	's+,	s   H	H0H++H0a\  
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Black.otf') format('opentype');
    font-weight: 900;
    font-style: normal;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-ExtraBold.otf') format('opentype');
    font-weight: 800;
    font-style: normal;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
    font-style: normal;
  }
c                B    d| j                          }dt         d| dS )u   1200x628 가로형 배너 HTML.file://G<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<style>
u	  

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    width: 1200px;
    height: 628px;
    overflow: hidden;
    font-family: 'Pretendard', sans-serif;
    background: #001E3C;
  }

  .card {
    position: relative;
    width: 1200px;
    height: 628px;
    overflow: hidden;
  }

  /* 배경 포토 */
  .bg-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
  }

  /* 하단 그라디언트 오버레이 (50% 높이 = 314px) */
  .gradient-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 314px;
    background: linear-gradient(
      to bottom,
      transparent 0%,
      rgba(0, 30, 60, 0.55) 40%,
      rgba(0, 30, 60, 0.88) 100%
    );
  }

  /* 콘텐츠 스택 (하단 좌측 앵커) */
  .content-stack {
    position: absolute;
    bottom: 48px;
    left: 56px;
    right: 56px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }

  /* 메인 헤드라인 */
  .headline {
    font-size: 54px;
    font-weight: 900;
    color: #FFFFFF;
    line-height: 1.2;
    letter-spacing: -1.2px;
    word-break: keep-all;
    text-shadow:
      0 2px 8px rgba(0, 0, 0, 0.70),
      0 4px 24px rgba(0, 30, 60, 0.60);
  }

  .headline .highlight {
    color: #EA580C;
  }

  /* 프로스티드 글라스 서브카피 블록 */
  .sub-copy-block {
    background: rgba(0, 30, 60, 0.45);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow:
      0 4px 32px rgba(0, 30, 60, 0.35),
      inset 0 1px 0 rgba(255, 255, 255, 0.12);
    border-radius: 16px;
    padding: 18px 28px;
  }

  .sub-copy-text {
    font-size: 44px;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.95);
    line-height: 1.3;
    letter-spacing: -0.5px;
    word-break: keep-all;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.50);
  }

  /* CTA 필 버튼 */
  .cta-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 14px 40px;
    border: 2.5px solid #EA580C;
    border-radius: 9999px;
    background: transparent;
    font-size: 40px;
    font-weight: 800;
    color: #EA580C;
    letter-spacing: -0.3px;
    white-space: nowrap;
  }
</style>
</head>
<body>
<div class="card">

  <!-- 배경 포토 -->
  <img class="bg-photo" src="u  " alt="background">

  <!-- 하단 그라디언트 오버레이 -->
  <div class="gradient-overlay"></div>

  <!-- 콘텐츠 스택 (하단 좌측 앵커) -->
  <div class="content-stack">

    <!-- 메인 헤드라인 -->
    <div class="headline">
      열심히는 하는데,<br>
      소득은 <span class="highlight">제자리걸음?</span>
    </div>

    <!-- 프로스티드 글라스 서브카피 블록 -->
    <div class="sub-copy-block">
      <div class="sub-copy-text">정착지원금이 시작을 바꿉니다</div>
    </div>

    <!-- CTA 필 버튼 -->
    <div class="cta-pill">지금 조건 확인하기 →</div>

  </div>
</div>
</body>
</html>resolve
FONT_FACESbg_pathbg_uris     r   make_html_1200x628rb      sB    w()*F
  uj %X &uS Sr   c                B    d| j                          }dt         d| dS )u#   1200x1200 정사각형 배너 HTML.rZ   r[   u	  

  * { margin: 0; padding: 0; box-sizing: border-box; }

  body {
    width: 1200px;
    height: 1200px;
    overflow: hidden;
    font-family: 'Pretendard', sans-serif;
    background: #001E3C;
  }

  .card {
    position: relative;
    width: 1200px;
    height: 1200px;
    overflow: hidden;
  }

  /* 배경 포토 */
  .bg-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
  }

  /* 하단 그라디언트 오버레이 (50% 높이 = 600px) */
  .gradient-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 600px;
    background: linear-gradient(
      to bottom,
      transparent 0%,
      rgba(0, 30, 60, 0.55) 40%,
      rgba(0, 30, 60, 0.88) 100%
    );
  }

  /* 콘텐츠 스택 (하단 앵커) */
  .content-stack {
    position: absolute;
    bottom: 72px;
    left: 64px;
    right: 64px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 28px;
  }

  /* 메인 헤드라인 */
  .headline {
    font-size: 96px;
    font-weight: 900;
    color: #FFFFFF;
    line-height: 1.15;
    letter-spacing: -1.8px;
    word-break: keep-all;
    text-shadow:
      0 2px 8px rgba(0, 0, 0, 0.70),
      0 4px 24px rgba(0, 30, 60, 0.60);
  }

  .headline .highlight {
    color: #EA580C;
  }

  /* 프로스티드 글라스 서브카피 블록 */
  .sub-copy-block {
    background: rgba(0, 30, 60, 0.45);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow:
      0 4px 32px rgba(0, 30, 60, 0.35),
      inset 0 1px 0 rgba(255, 255, 255, 0.12);
    border-radius: 16px;
    padding: 28px 40px;
    align-self: stretch;
  }

  .sub-copy-text {
    font-size: 68px;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.95);
    line-height: 1.3;
    letter-spacing: -0.8px;
    word-break: keep-all;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.50);
  }

  /* CTA 필 버튼 */
  .cta-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 18px 52px;
    border: 2.5px solid #EA580C;
    border-radius: 9999px;
    background: transparent;
    font-size: 44px;
    font-weight: 800;
    color: #EA580C;
    letter-spacing: -0.3px;
    white-space: nowrap;
  }
</style>
</head>
<body>
<div class="card">

  <!-- 배경 포토 -->
  <img class="bg-photo" src="u  " alt="background">

  <!-- 하단 그라디언트 오버레이 -->
  <div class="gradient-overlay"></div>

  <!-- 콘텐츠 스택 (하단 앵커) -->
  <div class="content-stack">

    <!-- 메인 헤드라인 -->
    <div class="headline">
      열심히는 하는데,<br>
      소득은 <span class="highlight">제자리걸음?</span>
    </div>

    <!-- 프로스티드 글라스 서브카피 블록 -->
    <div class="sub-copy-block">
      <div class="sub-copy-text">정착지원금이 시작을 바꿉니다</div>
    </div>

    <!-- CTA 필 버튼 -->
    <div class="cta-pill">지금 조건 확인하기 →</div>

  </div>
</div>
</body>
</html>r\   r_   s     r   make_html_1200x1200rd   9  sB    w()*F
  vl %X &wT Tr   c           
        |j                   j                  dd       |j                  | d       t        d|        t	               5 }|j
                  j                         }	 |j                  ||d      }|j                  d|j                          d	
       |j                  d       |j                   j                  dd       |j                  t        |      ddd||d       |j                         j                  dz  }t        d| d|dd       |j                          	 ddd       y# |j                          w xY w# 1 sw Y   yxY w)uB   HTML을 파일로 저장한 뒤 Playwright로 PNG 캡처합니다.Tr=   zutf-8)encodingu     [HTML] 저장: )widthheight)viewportrZ   networkidle)
wait_untili	  pngr   )xyrg   rh   )r	   typeclipi   u     [PNG] 캡처 완료: r@   z.0fz KB)N)rN   rO   
write_textrE   r   chromiumlaunchnew_pagegotor]   wait_for_timeout
screenshotr   rC   rD   close)	html_contenthtml_save_pathrg   rh   png_pathr:   browserpagekbs	            r   capture_html_to_pngr     sE    t<lW=	n-
./		 a**##%	##u-O#PDII 6 6 89:}IU!!$'OO!!$!>OOXUQ&BO  ((4/B+H:R3xtDEMMO  MMO s%   	E%B9D8E8E

EEc            	        t        d       t        d       t        d       t        j                  dd       t        j                  dd       i } t        d       	 t	        t
        t              }t        |      }t        d	z  }t        d
z  }	 t        ||dd|       t        |      | d<   t        |      | d<   t        d       	 t	        t        t              }t        |      }t        dz  }t        dz  }		 t        ||dd|	       t        |	      | d<   t        |      | d<   t        d       t        d       | j                         D ]!  \  }
}d|
vrdnd}t        d| d|
 d|        # t        d       y # t        $ r/}t        d|        t        d       t        d      }Y d }~;d }~ww xY w# t        $ r'}t        d|        t        |      | d<   Y d }~%d }~ww xY w# t        $ r/}t        d|        t        d       t        d      }Y d }~@d }~ww xY w# t        $ r'}t        d|        t        |      | d<   Y d }~*d }~ww xY w) Nz@================================================================u,   컨셉 #35 프로덕션 배너 생성 시작Tr=   u    
[1/2] 1200x628 가로형 배너u!     [경고] 배경 생성 실패: u,     [폴백] 기존 bg.png (1024×1024) 사용zQ/home/jay/workspace/output/meta-ads/concept-catalog/35-hybrid-v4-refined-A/bg.pngzc35-1200x628.htmlzc35-1200x628.pngi  it  1200x628_png1200x628_htmlu#     [오류] 1200x628 캡처 실패: 1200x628_erroru$   
[2/2] 1200x1200 정사각형 배너zc35-1200x1200.htmlzc35-1200x1200.png1200x1200_png1200x1200_htmlu$     [오류] 1200x1200 캡처 실패: 1200x1200_errorzA
================================================================u   생성 결과:errorOKFAILz  [z] r3   )rE   TMP_DIRrO   
OUTPUT_DIRrX   BG_PROMPT_LANDSCAPEBG_LANDSCAPE_PATHrI   r   rb   r   r   BG_PROMPT_SQUAREBG_SQUARE_PATHrd   items)resultsbg_landrU   html_1200x628html_out_628png_out_628bg_sqhtml_1200x1200html_out_1200png_out_1200keyvalstatuss                r   mainr     sW   	(O	
89	(OMM$M.TD1 G 

-.l%&9;LM 'w/M!44L!33K+M<sKP#&{#3#&|#4  

12j#$4nE )/N"66M"55L,NM4|T$'$5 $'$6 ! 
/	
MMO ,S +F82cU"SE*+, 
(OW  l1!56<=jkl  +3A378$'F !+  j1!56<=hij  ,4QC89%(V!",s`   E: +F5 G( 9+H# :	F2$F--F25	G%>G  G%(	H 1$HH #	I,II__main__)returnr   )r   
str | None)
r!   r   r"   r   r#   r   r$   dictr   zrequests.Response)rS   r   rT   r   r   r   )r`   r   r   r   )ry   r   rz   r   rg   intrh   r   r{   r   r   None)r   r   )!__doc__
__future__r   rL   r   r   pathlibr   r   playwright.sync_apir   __file__rN   r   r   r   r   r   r   rG   rH   r   r   r   r   r)   rX   r^   rb   rd   r   r   __name__r8   r   r   <module>r      s    #   
   / >  ab

X

+44 11 F/3 P *,
0Aj
,VrWx #-0<@EI2:z zF r   