
    (<i@                    $   d Z 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	Z	ddl
mZ  ee      j                  Zej                  j!                  d ee             ddlZddlmZmZmZ eZdZdZd	ZeZd
ZdZedz  Zej?                  dd       edz  dz  dz  Z e j?                  dd       dZ!dZ"dZ#dZ$dZ%de de de de de de de de dZ&d e d!e de d"e d#e d$e d%e d&Z'd+d'Z(	 	 	 	 	 	 	 	 	 	 	 	 d,d(Z)d-d)Z*e+d*k(  r e*        yy).u|  인카다이렉트 M1-2 '관리자 비전' Google 광고 배너 생성기.

Gemini API로 포토리얼 오피스 배경을 생성하고,
HTML/CSS + Playwright로 한글 텍스트를 정밀하게 오버레이합니다.

출력:
  - /home/jay/workspace/output/google-ads/banners/incar-leader-1200x628.png
  - /home/jay/workspace/output/google-ads/banners/incar-leader-1080x1080.png
    )annotationsN)Path)sync_playwright)
CTA_MIN_PXHEAD_SUB_RATIOWORKSPACE_ROOT.   4   g333333?g?gffffff?zoutput/google-ads/bannersTparentsexist_okoutputz	v4-hybridzincar-leaderz0https://generativelanguage.googleapis.com/v1betaz3https://www.googleapis.com/auth/generative-languagezgemini-2.5-flash-imagezgemini-3.1-flash-image-previewu  Photorealistic professional office interior, premium quality photography. Modern private executive office with floor-to-ceiling glass windows showing a sweeping urban skyline view. Warm natural afternoon sunlight streaming through the large windows, filling the room with golden light. Clean wooden desk with a laptop and neatly arranged documents. A sense of ownership and pride — this is MY office, MY space. Minimalist, upscale interior design with navy and warm wood tones. Shallow depth of field, professional DSLR quality. Bright, confident, aspirational atmosphere. NOT a crowded conference room. NOT a factory or construction site. NO keys or locks as metaphors. NO icons, graphics, or illustrations. Pure photorealistic office interior with city view. Wide composition showing the expanse of the space on the right side. Shot in the style of a corporate real estate or executive lifestyle advertisement.u  <!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1200">
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700;900&display=swap');

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

  body {
    width: 1200px;
    height: 628px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
  }

  .banner {
    position: relative;
    width: 1200px;
    height: 628px;
    overflow: hidden;
    background: #1B365D;
  }

  /* 배경 이미지 - 전체 */
  .bg-image {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background-image: url('{bg_url}');
    background-size: cover;
    background-position: center right;
  }

  /* 좌측 네이비 반투명 패널 (텍스트 영역) */
  .left-overlay {
    position: absolute;
    top: 0; left: 0;
    width: 660px; /* 55% */
    height: 100%;
    background: linear-gradient(
      to right,
      rgba(27, 54, 93, 0.88) 0%,
      rgba(27, 54, 93, 0.82) 70%,
      rgba(27, 54, 93, 0.40) 90%,
      rgba(27, 54, 93, 0.00) 100%
    );
  }

  /* 텍스트 콘텐츠 영역 */
  .text-area {
    position: absolute;
    top: 0; left: 0;
    width: 620px;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 50px 60px;
    gap: 0;
  }

  /* 브랜드명 */
  .brand {
    font-size: ztpx;
    font-weight: 500;
    color: #5B9BD5;
    letter-spacing: 0.02em;
    margin-bottom: 20px;
    line-height: u@   ;
  }

  /* 메인 헤드라인 */
  .headline {
    font-size: z?px;
    font-weight: 700;
    color: #FFFFFF;
    line-height: u   ;
    letter-spacing: -0.01em;
    margin-bottom: 20px;
    word-break: keep-all;
  }

  /* 서브카피 */
  .subcopy {
    font-size: z?px;
    font-weight: 500;
    color: #5B9BD5;
    line-height: u  ;
    letter-spacing: 0.01em;
    margin-bottom: 36px;
    word-break: keep-all;
  }

  /* CTA 버튼 */
  .cta-btn {
    display: inline-block;
    background: linear-gradient(135deg, #C5A572 0%, #D4B87A 50%, #C5A572 100%);
    color: #1A0E00;
    font-size: zpx;
    font-weight: 700;
    padding: 14px 36px;
    border-radius: 6px;
    letter-spacing: 0.02em;
    min-width: 220px;
    text-align: center;
    line-height: u  ;
    box-shadow: 0 4px 16px rgba(197, 165, 114, 0.35);
  }

  /* 우측 하단 골드 액센트 라인 */
  .accent-line {
    position: absolute;
    bottom: 0; right: 540px;
    width: 3px;
    height: 80px;
    background: linear-gradient(to bottom, transparent, #C5A572);
  }
</style>
</head>
<body>
<div class="banner">
  <div class="bg-image"></div>
  <div class="left-overlay"></div>
  <div class="text-area">
    <div class="brand">인카금융서비스</div>
    <div class="headline">모든 권한으로<br>조직 운영하세요</div>
    <div class="subcopy">사무실 개설비 전액 지원 | 리쿠르팅 협업</div>
    <div class="cta-btn">지점 개설 조건 확인</div>
  </div>
  <div class="accent-line"></div>
</div>
</body>
</html>u  <!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1080">
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700;900&display=swap');

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

  body {
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
  }

  .banner {
    position: relative;
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #1B365D;
  }

  /* 배경 이미지 전체 */
  .bg-image {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background-image: url('{bg_url}');
    background-size: cover;
    background-position: center center;
  }

  /* 상단 네이비 그라데이션 오버레이 */
  .top-overlay {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 70%;
    background: linear-gradient(
      to bottom,
      rgba(27, 54, 93, 0.85) 0%,
      rgba(27, 54, 93, 0.70) 40%,
      rgba(27, 54, 93, 0.50) 70%,
      rgba(27, 54, 93, 0.00) 100%
    );
  }

  /* 하단 어두운 오버레이 (CTA 영역) */
  .bottom-overlay {
    position: absolute;
    bottom: 0; left: 0;
    width: 100%;
    height: 38%;
    background: linear-gradient(
      to top,
      rgba(27, 54, 93, 0.92) 0%,
      rgba(27, 54, 93, 0.70) 60%,
      rgba(27, 54, 93, 0.00) 100%
    );
  }

  /* 전체 텍스트 레이아웃 */
  .content {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 60px 80px 60px 80px;
  }

  /* 브랜드명 */
  .brand {
    font-size: u   px;
    font-weight: 500;
    color: #5B9BD5;
    letter-spacing: 0.05em;
    text-align: center;
    margin-bottom: 32px;
    margin-top: 0;
  }

  /* 메인 헤드라인 */
  .headline {
    font-size: u  ;
    letter-spacing: -0.01em;
    text-align: center;
    margin-bottom: 36px;
    word-break: keep-all;
  }

  /* 골드 구분선 */
  .divider {
    width: 60px;
    height: 3px;
    background: linear-gradient(to right, #C5A572, #D4B87A);
    margin: 0 auto 36px auto;
    border-radius: 2px;
  }

  /* 혜택 목록 */
  .benefits {
    display: flex;
    flex-direction: column;
    gap: 18px;
    width: 100%;
    margin-bottom: auto;
  }

  .benefit-item {
    font-size: z?px;
    font-weight: 500;
    color: #E8F0FA;
    line-height: u  ;
    text-align: center;
    word-break: keep-all;
    padding: 0 20px;
  }

  /* CTA 버튼 컨테이너 */
  .cta-wrap {
    margin-top: 0;
    padding-top: 20px;
    display: flex;
    justify-content: center;
  }

  /* CTA 버튼 */
  .cta-btn {
    display: inline-block;
    background: linear-gradient(135deg, #C5A572 0%, #D4B87A 50%, #C5A572 100%);
    color: #1A0E00;
    font-size: zpx;
    font-weight: 700;
    padding: 18px 56px;
    border-radius: 6px;
    letter-spacing: 0.03em;
    min-width: 300px;
    text-align: center;
    line-height: u  ;
    box-shadow: 0 6px 24px rgba(197, 165, 114, 0.40);
  }
</style>
</head>
<body>
<div class="banner">
  <div class="bg-image"></div>
  <div class="top-overlay"></div>
  <div class="bottom-overlay"></div>
  <div class="content">
    <div class="brand">인카금융서비스</div>
    <div class="headline">모든 권한으로<br>조직 운영하세요</div>
    <div class="divider"></div>
    <div class="benefits">
      <div class="benefit-item">사무실 개설비 전액 지원</div>
      <div class="benefit-item">리쿠르팅 협업 시스템</div>
      <div class="benefit-item">조직 확장 시스템 뒷받침</div>
    </div>
    <div class="cta-wrap">
      <div class="cta-btn">지점 개설 조건 확인</div>
    </div>
  </div>
</div>
</body>
</html>c           	        t        dt         d       t        j                         }t         dt         d}d|  dd}dd	t        igigd
ddgid}t        j                  |||d      }|j                  dv rOt        dt         d|j                   dt                t         dt         d}t        j                  |||d      }|j                  s8t        d|j                   d|j                  dd         |j                          |j                         }|j                  dg       }	|	s$t        dt        j                  |      dd        |	d   j                  di       j                  dg       }
t!        d |
D        d      }|5|
D cg c]  }d	|v s|j                  d	d       }}t        d|dd        |d    j                  d!d"      }t#        j$                  |d    d#         }d$|v rd%nd&}|j'                  |      }|j)                  |       t        j                         |z
  }t        d'|j*                   d(t-        |      d)d*|d+d,       |S c c}w )-u?   Gemini API로 배경 이미지를 생성하고 저장합니다.u?   [배경] Gemini API로 오피스 배경 생성 중... (모델: )z/models/z:generateContentzBearer zapplication/json)AuthorizationzContent-TypepartstextresponseModalitiesIMAGETEXT)contentsgenerationConfigi,  )headersjsontimeout)  i  i  u   [배경] 모델 u    실패 (HTTP z). Fallback: u   [배경] API 오류: z - Nr   
candidatesu   응답에 candidates 없음: r   contentc              3  *   K   | ]  }d |v s|  yw)
inlineDataN ).0ps     \/home/jay/workspace/.worktrees/task-2057-dev2/tools/ai-image-gen/gen_incar_leader_banners.py	<genexpr>z$generate_bg_image.<locals>.<genexpr>  s     =Q<1+<q=s   	 u'   이미지 데이터 없음. 텍스트:    r    mimeTypez
image/jpegdatajpegz.jpgz.pngu   [배경] 완료:  (,z bytes, z.1fu   초))printMODEL_IDtimeGEMINI_API_BASE	BG_PROMPTrequestspoststatus_codeFALLBACK_MODEL_IDokr   raise_for_statusr   getRuntimeErrordumpsnextbase64	b64decodewith_suffixwrite_bytesnamelen)tokenoutput_pathstarturlr   payloadresponseurl2r)   r   r   
image_partr#   
text_parts	mime_typeimage_bytesext
final_pathelapseds                      r$   generate_bg_imagerP     s   	KH:UV
WXIIKEXhZ/?
@C"5'**G
  34561GV3DEG
 }}S'MH . 
.9M9M8Nm\m[nop!"(+<*==MN==wWcR;;%h&:&:%;3x}}Tc?R>STU!!#==?D,+J:4::d;KDS;Q:RSTTqMi,00"=E=%=tDJ16FA&A+aeeFB'F
FDZPRQR^DTUVV<(,,ZFI"":l#;F#CDKi'&VC((-J;'iikE!G	joo.b[1A!0DHWUXMY]
^_ Gs   	I!I!c           
        d|j                          }| j                  |      }t        d| d| dz  }|j                  |d       t	        d| d| d	       t               5 }|j                  j                  d
dg      }		 |	j                  ||d      }
|
j                  d|j                          d       |
j                  d       |j                  j                  dd       |
j                  t        |      ddd||d       t	        d|        |	j                          	 ddd       |j!                  d       y# |	j                          w xY w# 1 sw Y   1xY w)uY   HTML 템플릿에 배경 이미지 URL을 삽입하고 Playwright로 PNG 캡처합니다.zfile://)bg_urltmp_xz.htmlzutf-8)encodingu   [캡처] Playwright로 u    캡처 중...z--no-sandboxz--disable-gpu)args)widthheight)viewportnetworkidle)
wait_untili	  Tr   pngr   )rT   yrW   rX   )pathtypeclipu   [캡처] 저장 완료: N)
missing_ok)resolveformatTMP_DIR
write_textr-   r   chromiumlaunchnew_pagegotowait_for_timeoutparentmkdir
screenshotstrcloseunlink)html_contentbg_pathrC   rW   rX   rR   html_filledtmp_htmlr#   browserpages              r$   capture_html_to_pngrw     sm    w()*F%%V%4K 4waxu55Hg6	#E7!F8>
BC		 a**##./)J#K	##u-O#PDII 0 0 234IO!!$'$$TD$AOO[!1Q&EO  ,[M:;MMO OOtO$ MMO s%   %EBEEEEE&c                 d   t        d       t        d       t        d       t        d       	 t        j                         } t        dt        |        d       t        d       t        d	z  }	 t        | |      }t        d       t        dz  }	 t        t        ||dd       |j                         j                  dz  }t        d| d|dd       t        d       t        dz  }	 t        t        ||dd       |j                         j                  dz  }t        d| d|dd       t        d       t        d       t        d|        t        d|        t        d       y # t        $ r}t        d|        t        d      |d }~ww xY w# t        $ r}t        d
|        t        d      |d }~ww xY w# t        $ r-}t        d|        dd l}|j                          Y d }~d }~ww xY w# t        $ r,}t        d|        dd l}|j                          Y d }~d }~ww xY w) Nz<============================================================uF   인카다이렉트 M1-2 '관리자 비전' Google 배너 생성 시작u!   
[인증] SA 토큰 획득 중...u'   [인증] 토큰 획득 성공 (길이: z chars)u   [인증] 실패:    u(   
[배경] 배경 이미지 생성 중...	bg_leaderu   [배경] 생성 실패: u,   
[배너 1] 1200x628 가로형 생성 중...zincar-leader-1200x628.pngi  it  )rq   rr   rC   rW   rX   i   u   [배너 1] 완료: r+   z.0fz KB)u   [배너 1] 실패: r   u0   
[배너 2] 1080x1080 정사각형 생성 중...zincar-leader-1080x1080.pngi8  u   [배너 2] 완료: u   [배너 2] 실패: z=
============================================================u   생성 완료u     배너 1: u     배너 2: )r-   gcloud_authget_access_tokenrA   	Exception
SystemExitrd   rP   
OUTPUT_DIRrw   HTML_1200x628statst_size	traceback	print_excHTML_1080x1080)rB   ebg_tmp_pathrr   output_1200size_kbr   output_1080s           r$   mainr     s8   	(O	
RS	(O 

./#,,.7E
|7KL 

56K'K##E;7 

9:::K0&#	
 ""$,,t3#K=73-tDE 

=>;;K0'#	
 ""$,,t3#K=73-tDE
 
/	/	L
&'	L
&'	(Og  #!!%&m"#  #(,-m"#"  0#A3'()--//0"  0#A3'()--//0sa   ,E+ /F AG )AG: +	F4FF	F>F99F>	G7
"G22G7:	H/"H**H/__main__)rB   rn   rC   r   returnr   )rq   rn   rr   r   rC   r   rW   intrX   r   r   None)r   r   ),__doc__
__future__r   r<   r   sysr/   pathlibr   r2   playwright.sync_apir   __file__rk   TOOL_DIRr^   insertrn   r{   
gen_configr   r   r   _CTA_PX
_SIZE_46PX
_SIZE_52PX_LH_1_2	_LH_RATIO_LH_1_35_LH_1_4r   rl   rd   r0   GEMINI_SCOPEr.   r5   r1   r   r   rP   rw   r   __name__r!       r$   <module>r      s   #   
    / >   3x= !  A A 


	
 99
 
    -
X

+n
< dT * ED#4 
Y 
$AB y 
  
 |    y    y   WFPMZ y  |   4 y   & y   ek`0j%%% % 	%
 % 
%H=@ zF r   