
    Di{H                    T   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d      Zej                  j                  d ee             ddlZ ed      Zedz  Zed	z  Zed
z  Z ej(                         dz  ZdZdZdZg dZddZddZddZddZddZedk(  r e        yy)u  GA 배너 M2-2 'GA × 관리자 비전' 세트 생성 — 하이브리드 방식 (Gemini 배경 + Playwright 오버레이).

산출물:
  /home/jay/workspace/output/google-ads/banners/m2/m2-2-1200x628.png
  /home/jay/workspace/output/google-ads/banners/m2/m2-2-1080x1080.png
    )annotationsN)Path)sync_playwrightz&/home/jay/workspace/tools/ai-image-genz0/home/jay/workspace/output/google-ads/banners/m2zm2-2-bg.jpgzm2-2-1200x628.pngzm2-2-1080x1080.pngz.local/share/fonts/Pretendardu^  Photographic scene of a modern open-plan office space in Seoul. Medium shot, slightly elevated angle (eye-level standing), looking across a clean workspace. One male professional in his late 30s, business casual (white shirt, dark slacks), standing near a clean white standing desk, looking at a laptop screen slightly angled away. His posture is upright and purposeful but relaxed. Face in 3/4 profile, partially visible but not identifiable. The background shows a well-lit open office with glass-walled meeting rooms — empty. Green potted plants (monstera) visible in two spots. Warm morning natural light from windows on the right side. The overall composition has the person on the right half of frame, leaving the left half open for text. Shallow depth of field, background office slightly out of focus. 사진 품질, 실사, 오피스 관리자 장면.z0https://generativelanguage.googleapis.com/v1betaz3https://www.googleapis.com/auth/generative-language)z)gemini-2.0-flash-preview-image-generationzgemini-3-pro-image-previewzgemini-3.1-flash-image-previewc                    t        d       t        j                  d      } | rJt        d       t        D ]5  }t        d|        	 t         d| d|  }ddt
        igigd	d
dgid}t        j                  ||d      }|j                  dk(  r|j                         }|j                  dg       }|r|d   j                  di       j                  dg       }|D ]b  }d|v s|d   d   }	t        j                  |	      }
t        j                  |
       t        dt         dt        |
      dd       t        c c S  t        d| d|j                   d|j                   dd         8 t        d       	 t        j$                  t&              }t        D ]   }	 t         d| d}d | d!d"}ddt
        igigd	d
dgid}t        j                  |||d#      }|j                  dk(  r|j                         }|j                  dg       }|r~|d   j                  di       j                  dg       }|D ]T  }d|v s|d   d   }	t        j                  |	      }
t        j                  |
       t        d$t                t        c c S  t        d%| d|j                   d|j                   dd         # 	 t)        d'      # t"        $ r}t        d| d|        Y d}~d}~ww xY w# t"        $ r}t        d%| d|        Y d}~xd}~ww xY w# t"        $ r"}t        d&|        Y d}~t)        d'      d}~ww xY w)(u?   Gemini API로 배경 이미지를 생성하고 저장합니다.u(   [배경 생성] Gemini API 호출 중...GEMINI_API_KEYu     인증: API 키 사용u     모델 시도: z/models/z:generateContent?key=partstextresponseModalitiesIMAGETEXT)contentsgenerationConfigx   )jsontimeout   
candidatesr   content
inlineDatadatau     배경 생성 완료:  (, bytes)  u    응답 z: Nu	    오류: u%     API 키 실패, SA 토큰 시도...z:generateContentzBearer zapplication/json)AuthorizationzContent-Type)headersr   r   u     배경 생성 완료 (SA): z  SA/u     SA 토큰 오류: uZ   모든 Gemini API 인증 방법 실패 — 배경 이미지를 생성할 수 없습니다.)printgcloud_authget_api_keyMODELS_TO_TRYGEMINI_API_BASEGEMINI_BG_PROMPTrequestspoststatus_coder   getbase64	b64decodeBG_IMAGE_PATHwrite_byteslenr	   	Exceptionget_service_account_tokenGEMINI_SCOPERuntimeError)api_keymodelurlpayloadrespr   r   r   partimg_b64	img_bytesetokenr   s                 </home/jay/workspace/output/google-ads/banners/m2/gen_m2_2.pygenerate_backgroundr;   ?   s   	
45 %%&67G()" 	0E%eW-.0()%8MgYW")V5E,F+G!H I)=?P(Q  }}SwD##s*99;D!%,!;J! *1 1 1)R @ D DWb Q$) 5D+t3*.|*<V*D,2,<,<W,E	 - 9 9) D %(@rRUV_R`abQccj&k l'4 45 5'$*:*:);2diio=NOP+	04 

12*55lC" 	3E3()%8HI.5eW,=Oab")V5E,F+G!H I)=?P(Q  }}S'QTU##s*99;D!%,!;J! *1 1 1)R @ D DWb Q$) 5D+t3*.|*<V*D,2,<,<W,E	 - 9 9) D %(Em_&U V'4 45 eWHT-=-=,>b4C@QRS+	36 s
ttE  05'1#.//0:  3eWIaS1223 *$QC())
s
tt*s|   BK	#AK	?,K	:#L B!K1 AK1L ,K1:L 		K.K))K.1	L:LL LL 	M"L??Mc                F    dt          dt          dt          dt          d|  dS )N<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///Pretendard-SemiBold.otf') format('opentype');
    font-weight: 600;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file://uW  /Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
  }

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

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

  .canvas {
    width: 1200px;
    height: 628px;
    position: relative;
    overflow: hidden;
    border-radius: 4px;
  }

  /* 전체 배경 이미지 (우측 인물이 보이도록) */
  .bg-full {
    position: absolute;
    top: 0;
    left: 0;
    width: 1200px;
    height: 628px;
    background-image: url('file://u	  ');
    background-size: cover;
    background-position: center center;
  }

  /* 좌측 660px 미드 그린 그라데이션 오버레이 opacity 0.72 */
  .overlay-left {
    position: absolute;
    top: 0;
    left: 0;
    width: 660px;
    height: 628px;
    background: linear-gradient(
      to right,
      rgba(45, 80, 22, 0.72) 0%,
      rgba(45, 80, 22, 0.72) 75%,
      rgba(45, 80, 22, 0.36) 90%,
      rgba(45, 80, 22, 0.0) 100%
    );
  }

  /* 텍스트 영역 — 좌측 660px, 패딩 좌 60px 상 52px */
  .text-area {
    position: absolute;
    top: 0;
    left: 0;
    width: 660px;
    height: 628px;
    padding-left: 60px;
    padding-top: 52px;
    padding-right: 40px;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: flex-start;
  }

  /* 헤드라인: 58px Bold #FAFAFA, line-height 1.2 */
  .headline {
    font-size: 58px;
    font-weight: 700;
    color: #FAFAFA;
    line-height: 1.2;
    letter-spacing: -1px;
    margin-top: 20px;
    white-space: pre-line;
  }

  /* 지원 항목: 44px Medium #A5D6A7, gap 20px */
  .support-items {
    font-size: 44px;
    font-weight: 500;
    color: #A5D6A7;
    line-height: 1.3;
    margin-top: 20px;
    letter-spacing: -0.5px;
  }

  /* 보조 정보: 40px Medium #FAFAFA, gap 16px */
  .aux-info {
    font-size: 40px;
    font-weight: 500;
    color: #FAFAFA;
    line-height: 1.3;
    margin-top: 16px;
    letter-spacing: -0.5px;
  }

  /* CTA: y:530px 고정, 높이 56px, 너비 auto, round 4px, 다크그린 #1B5E20 (AAA 대비율) */
  .cta-btn {
    position: absolute;
    top: 530px;
    left: 60px;
    width: auto;
    height: 56px;
    background: #1B5E20;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 44px;
    font-weight: 700;
    color: #FAFAFA;
    white-space: nowrap;
    letter-spacing: -0.5px;
    padding: 0 32px;
  }
</style>
</head>
<body>
<div class="canvas">

  <!-- 전체 배경 -->
  <div class="bg-full"></div>

  <!-- 좌측 미드 그린 그라데이션 오버레이 -->
  <div class="overlay-left"></div>

  <!-- 텍스트 영역 -->
  <div class="text-area">
    <div class="headline">GA 지점장,&#10;가장 빠른 경로 안내</div>
    <div class="support-items">교육  |  인프라  |  운영 지원</div>
    <div class="aux-info">독립 운영 + GA의 안정적 지원</div>
  </div>

  <!-- CTA 버튼 (y:530px 고정) -->
  <div class="cta-btn">지점장 경로 확인 →</div>

</div>
</body>
</html>FONT_DIRbg_image_paths    r:   build_html_1200x628rE      sR     Z  
 Z  
 Z  
 Z   #@ $1/ n2md d    c                F    dt          dt          dt          dt          d|  dS )Nr=   r>   r?   r@   ut  /Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
  }

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

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

  .canvas {
    width: 1080px;
    height: 1080px;
    position: relative;
    overflow: hidden;
    border-radius: 4px;
  }

  /* 전체 배경 이미지 — 인물 상반신이 하단 40% 영역에 보이도록 */
  .bg-full {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    background-image: url('file://uR
  ');
    background-size: cover;
    background-position: center 70%;
  }

  /* 미드 그린 그라데이션: 상단 opacity 0.71 → 하단 투명 (하단 인물/오피스 노출) */
  .overlay-top {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    background: linear-gradient(
      to bottom,
      rgba(45, 80, 22, 0.71) 0%,
      rgba(45, 80, 22, 0.71) 45%,
      rgba(45, 80, 22, 0.35) 70%,
      rgba(45, 80, 22, 0.0) 100%
    );
  }

  /* 콘텐츠 영역: 패딩 좌우 72px, 상 88px, 하 80px, 중앙 정렬 */
  .content-area {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    padding: 88px 72px 80px 72px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
  }

  /* 헤드라인: 60px Bold #FAFAFA, 중앙 정렬, line-height 1.2 */
  .headline {
    font-size: 60px;
    font-weight: 700;
    color: #FAFAFA;
    line-height: 1.2;
    letter-spacing: -1.5px;
    text-align: center;
    white-space: pre-line;
  }

  /* 지원 항목: 44px Medium #A5D6A7, 중앙 정렬, gap 24px */
  .support-items {
    font-size: 44px;
    font-weight: 500;
    color: #A5D6A7;
    line-height: 1.3;
    text-align: center;
    margin-top: 24px;
    letter-spacing: -0.5px;
  }

  /* 보조 정보: 40px Medium #FAFAFA, 중앙 정렬, gap 16px */
  .aux-info {
    font-size: 40px;
    font-weight: 500;
    color: #FAFAFA;
    line-height: 1.3;
    text-align: center;
    margin-top: 16px;
    letter-spacing: -0.5px;
  }

  /* CTA: 중앙, 높이 68px, 너비 auto, round 4px, 다크그린 #1B5E20 (AAA 대비율), gap 36px */
  .cta-btn {
    margin-top: 36px;
    width: auto;
    height: 76px;
    background: #1B5E20;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 48px;
    font-weight: 700;
    color: #FAFAFA;
    white-space: nowrap;
    letter-spacing: -0.5px;
    padding: 0 40px;
  }
</style>
</head>
<body>
<div class="canvas">

  <!-- 전체 배경 -->
  <div class="bg-full"></div>

  <!-- 미드 그린 그라데이션 오버레이 (상→하 투명) -->
  <div class="overlay-top"></div>

  <!-- 콘텐츠 영역 (상단 정렬, 중앙 텍스트) -->
  <div class="content-area">
    <div class="headline">GA 지점장,&#10;가장 빠른 경로 안내</div>
    <div class="support-items">교육  |  인프라  |  운영 지원</div>
    <div class="aux-info">독립 운영 + GA의 안정적 지원</div>
    <div class="cta-btn">지점장 경로 확인 →</div>
  </div>

</div>
</body>
</html>rA   rC   s    r:   build_html_1080x1080rH   A  sR     Z  
 Z  
 Z  
 Z   #@ $1/ k2ma arF   c                b   |j                   d|j                   dz  }|j                  | d       t        d|        t	               5 }|j
                  j                         }	 |j                  ||d      }|j                  d|j                          d	
       |j                  d       |j                  t        |      d       t        d| d|j                         j                  dd       |j                          	 d d d        y # |j                          w xY w# 1 sw Y   y xY w)N_tmp_z.htmlzutf-8)encodingu     HTML 템플릿 저장: )widthheight)viewportzfile://networkidle)
wait_untili	  png)pathtypeu     캡처 완료: r   r   r   )parentstem
write_textr   r   chromiumlaunchnew_pagegotoresolvewait_for_timeout
screenshotstrstatst_sizeclose)html_contentoutput_pathrL   rM   	html_filepbrowserpages           r:   capturerh     s   ""u[-=-=,>e%DDI8	%i[
12		 	a**##%	##u-O#PDII	 1 1 345-IP!!$'OO[!1O>%k]"[5E5E5G5O5OPQ4RRYZ[MMO	 	 MMO	 	s%   	D%%BD6D%D""D%%D.c                 n   t         j                  dd       t        d       t        d       t        d       t        j                         } t	               }t        dt        j                         | z
  dd       t        |j                               }t        d       t        j                         }t        |      }t        |t        d	d
       t        dt        j                         |z
  dd       t        d       t        j                         }t        |      }t        |t        dd       t        dt        j                         |z
  dd       t        d       t        d       t        dt                t        dt                t        dt        j                         | z
  dd       y )NT)parentsexist_okz<============================================================uH   GA 배너 M2-2 'GA × 관리자 비전' 하이브리드 이미지 생성u     배경 생성 소요: z.1fu   초
u)   [1/2] 1200x628 가로형 배너 생성...i  it  u
     소요: u-   [2/2] 1080x1080 정사각형 배너 생성...i8  u   완료!r   u     총 소요: u   초)
OUTPUT_DIRmkdirr   timer;   r^   r[   rE   rh   OUTPUT_1200x628rH   OUTPUT_1080x1080)t0bg_pathbg_strt1	html_widet2html_sqs          r:   mainrx     sX   TD1	(O	
TU	(O 
B!#G	$TYY[^C$8
>?"#F 

56	B#F+IIc2	Jtyy{2~c*%
01 

9:	B"6*GG%tT2	Jtyy{2~c*%
01	(O	)	B
 !	B 
!"	N499;r>#.c
23rF   __main__)returnr   )rD   r^   rz   r^   )
rb   r^   rc   r   rL   intrM   r{   rz   None)rz   r|   ) __doc__
__future__r   r'   sysrn   pathlibr   r#   playwright.sync_apir   TOOL_DIRrR   insertr^   r   rl   r)   ro   rp   homerB   r"   r!   r.   r    r;   rE   rH   rh   rx   __name__ rF   r:   <module>r      s    #  
    /
 89 3x= ! DE
]*22 44 499;88b  EDAu^efbP(4D zF rF   