From 997c2f53a013814dad338b36665b75a019c418b4 Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Wed, 10 Sep 2025 06:37:34 +0900 Subject: [PATCH] =?UTF-8?q?feat(assets):=20=EB=94=94=EC=A7=80=ED=84=B8?= =?UTF-8?q?=EB=A0=8C=ED=8A=B8=EB=A7=A4=EB=8B=88=EC=A0=80=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98(=EC=A7=91+=EC=B2=B4=ED=81=AC=C2=B7=EC=8A=A4?= =?UTF-8?q?=ED=80=B4=ED=81=B4)=20PNG=20=EC=84=B8=ED=8A=B8=20=EB=B0=8F=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80\n\n-=20=EA=B2=BD=EB=A1=9C:=20assets/app=5Fic?= =?UTF-8?q?on/house=5Fcheck/{32..1024}.png\n-=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8:=20scripts/render=5Ficon.py=20(=EB=AC=B4?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=20PNG=20=EB=A0=8C=EB=8D=94)=20/=20scripts/ge?= =?UTF-8?q?nerate=5Ficons.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/app_icon/house_check/1024.png | Bin 0 -> 11834 bytes assets/app_icon/house_check/128.png | Bin 0 -> 985 bytes assets/app_icon/house_check/192.png | Bin 0 -> 1491 bytes assets/app_icon/house_check/256.png | Bin 0 -> 2057 bytes assets/app_icon/house_check/32.png | Bin 0 -> 312 bytes assets/app_icon/house_check/48.png | Bin 0 -> 439 bytes assets/app_icon/house_check/512.png | Bin 0 -> 4608 bytes assets/app_icon/house_check/64.png | Bin 0 -> 558 bytes assets/app_icon/house_check/96.png | Bin 0 -> 776 bytes scripts/generate_icons.sh | 10 ++ scripts/render_icon.py | 236 +++++++++++++++++++++++++++ 11 files changed, 246 insertions(+) create mode 100644 assets/app_icon/house_check/1024.png create mode 100644 assets/app_icon/house_check/128.png create mode 100644 assets/app_icon/house_check/192.png create mode 100644 assets/app_icon/house_check/256.png create mode 100644 assets/app_icon/house_check/32.png create mode 100644 assets/app_icon/house_check/48.png create mode 100644 assets/app_icon/house_check/512.png create mode 100644 assets/app_icon/house_check/64.png create mode 100644 assets/app_icon/house_check/96.png create mode 100755 scripts/generate_icons.sh create mode 100644 scripts/render_icon.py diff --git a/assets/app_icon/house_check/1024.png b/assets/app_icon/house_check/1024.png new file mode 100644 index 0000000000000000000000000000000000000000..3aaab2c908f324e7845e535e322f118f32b6fdc1 GIT binary patch literal 11834 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 AnE(I) literal 0 HcmV?d00001 diff --git a/assets/app_icon/house_check/128.png b/assets/app_icon/house_check/128.png new file mode 100644 index 0000000000000000000000000000000000000000..5d5a587c60d16deacc3a2447fbc57bdfee9f2f7b GIT binary patch literal 985 zcmV;~119{5P)PrG5QXao@s2xiia7wMh~NZVVA!D`RvZDbW5W_K@(JJ!c*l|(IBCm4#>$N6r>keG z-`7$}k)=eMdSAWjnXYln7F;*ap0_=5s4P0K)oNaqi|P(bM8O-xc7vipbYeX)oP^&Y z$YQZu1O$W^1_9yM4FXk9A_$h)*dAUz@LOKd3!Y8HRJ06ZjaNP@i~m?M7rU1kEEs=ovT zbHz^!0Hy*kBH3wAutxC#pb!ALA;={@0A$|%mw+Ir_yAB~6POc%+~Na3AP79f2Y?_D zc!>`H0U+=c9{_T`DfA#_Zjrpj2Y}3{fjJ>4AwB>&90%uspp^Ik;4}{~2ZEB~1AyZ| z$W#bQiVpzJ6G5dQm~+?!0L~*}-Vn?^X^a9u8x?>#J-x&+a{vI^&;WQrkZZ;O018b7 z=Y$~VfC&H;91G6@LGI}y04V%kKm?itufr zW8>Ag4_C$i^!>}EzdbZo{|w-9)$}h=hK`p zS^xk50002?0owf^004kCpl<&s02&e_6OBE!NQ|ic(+0%tpEiK~pF^-CN!7;At}R?Z zxcYGc@#@C~sD4~Pz50Ow@o5Fh)(-@T4+Mzc2?2Y806jmu_-qUXHhj1NRSyUVKMMqo zk_#T`u0nWVK=dI%v}b{k!^LiUhc{|i7jU$d!_s-JOKNZrUB&$taba0800000NkvXX Hu0mjf%y*e; literal 0 HcmV?d00001 diff --git a/assets/app_icon/house_check/192.png b/assets/app_icon/house_check/192.png new file mode 100644 index 0000000000000000000000000000000000000000..f785963c9e5d72187d04683a44e19a5701d0c88a GIT binary patch literal 1491 zcmZuxX;f237@hZgzzZZ~0WpA(2L#cmxS*nxk_SdvY5_4+J)A%Q1xu7g!37CK3|p~+ ztqX1>E(k^ri^@T93+8}|8*M>Q(MYXJBSMTUA%vt4fA`0H-^`u!&AoGHDTxdZrdT^! z0{|$YA-pIeE2kQ2NyMnWtyTb7oCxIw@^`=Z{OVSQUEs{ZFQ1f8KJMex0fiQ~Sc17T zeRzk#Cbm@QqfmAUlcky1awUuDXcM~YM)S~6Ql(>|vUOa%Q*Exy9Bf%#x8I67!J4;B zIKF@Sv&(&2*U{6Lwp=S{3Jx>zR_pM zDsQ2_Ab!K-KBx00?7HPeZgE|phI&?1UKW5E&e2nC&wc>DR*mpSb8+P~RFVmimG@nw zuk3kGp;YSx3oXL@BSK117Q0GG0KVpiIw&cDgV;cl1ON!YU#0;aZTcdL_eXgWog{7sX-JeBz?%0I`;0ND?mgqczJ}pe>TXDGRDKx#t ze@wux(0;{JgN}FXP**YNSW0)ZGfh4xJc3(4nnmG0{N5A)>qxMtyQJeBgRWGh`C|CW zzM>1zOdzN@lnW36Y#gxee@f0f1-R;MJMJwIqkpzF*WYE? zn`T3WaRalUiiZaY+TOkT1sBC$Ob?^#*x$FDudZ_CzTnWB!WOR97s-wr6vIz6To$R_ z+MG_8M?*WwA@dmr9CKl$((ouWzmZS`^XInO_j^gK`Blie0vSMh=lJiSa-lA{f?YxA zY_Q>b1eR#+l&S^}d-n8PxLke>@gxcv_DAHIdJ>+W!04jo!qSW!UDD8*m+u_|=l6Tz zZ`QltL)GSx$aQ)W&2ain6r;<5pv{|;n?gzqSS9ra~ErEnVD#EG;6KnbG+# zR5EYnZ=k2=wfgEpI5CIp!I!+ll=%eGkWgK~-5{}mlGv>kvLH_YDUJ#UhTLcp&>gn0 z?N~aBOE{ht8c_v;;aQ9|<1U+E+8Z^rf-71^91niocky~cCr$1|3X^gLl1h*j63H>P z!o#l!Z*CHMl5y}|d+737q-x3+``_h-T005&PB3K$%(aR&M$g@sS6-I{Ii%i~GSEDi zU^&7J%%3pLdS2==RstY*a{Xo&Q>vd#8@mt-W&0wBsIBC?#jX-Qr& zvMBQA=o;5tA1J}^jz<*FCF_KZeCQ=b*zJp{0X(^C;yf&E74u`qYr~od?b<5=D!N P&l-fT3g^`Y3G@F0gg=9~ literal 0 HcmV?d00001 diff --git a/assets/app_icon/house_check/256.png b/assets/app_icon/house_check/256.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff92713115f7a00018975d0e26e41b98a6a0aa7 GIT binary patch literal 2057 zcmXw3dt4J&7Ctk%z$CneAPVAchDrnxH9xU+@s)`W6zU39T6X~r4J+mj%QL^i&26H83-n*+ zUh+6ih3y%6YWFTb@14hP_e#|6E3Xv(0gVVgapmi&n-j8Xx+-f9C#?|&)K$NG#!(-(LZvJ{+O&L%b=`D@hyM|! z*2h68vEeWDw`DO-`v*iFl7n*acU_QkRH>B+eJ-(7r45G+p_$#D=SP?tl%_=7D>FFz z+Nhn`*EGDp*6Omn9iA%L|2YTSvrV7qQ>cHeClqFbh=HGn;{tk7J5-=ti9TP0O`a~D zgcOeZ?YyuZDn#fewa$YL0TIt-va5kXp0wDJH3j&t3aFsTe!YYTXh9|)jM#-_WX3Vp;84f_Z2Achu=tnXVjKX%IrW3)t4FV1 zy{cKQIU9tqR*+4Qa)1n#mWe0c8DDu(+Vm#-gBB?ZyL$w|+f)jdWi{0BU z4$y7)ckNXf2-+w2h+&J%cIR9Ka$OmQ!kI6^xIhU0wGJWNr>dd? zD88vi&OxB(fEy!*sI2i6#cemN;^)JVgzLkn zVyAfV14-ta(l(`vPj+vZ`KVcnRY`9tbB598Z%NW={3dZA*Qh9KPkZ?e4PTu1W&t>F z_i@hA*|#mSL}H?8HV08e$ko$6Pt3xN%W<2R8jYL9ngMkoFx&9sKP5O5lhEU=}*Ald-O;-QzaY_Dk+uNgptCEWKu&vd_ z+-@ukq|HH?S@=G+dbpc;L>A4sX>t%r$W_MDM9|Ny`>Atd=D0|8fpG4??l<${x~uka zz)3E5wCF+&pSh12~^#m(hP)NSRHH11IkbTWzx_=>* z%4@IOD-Zt)DGotMl=?*Xgs-15>L@C}5@BuPu#qzy9eCn{WA#S@ z6)T21`q*r~_)+~^SGmu&00 zojiL?iT>d)sb=G+vn@SUOE6M|5Aw3l-Crdy)A7(cE=M%I=gZ@e;7qqnptg7e(oq~> zsF$EcNz_P0Ul8#$F!~DMdfc&!W2eJp1~t0iXTYc1qsbk(Uj*O2SCYF@>kf;qYx*gy z@3%hy{?{6JXt}Og4{U;Mtq2RfN&bM!3BsMX_M18G$wj4umFCO%+Pw@aDvJ%F!qHmm+w(V)k4y+w)-okEtsR_$p5m3Bo*5KTO bPs;BZ(@I}A)JgIe0C^(kE}V06mOAJE+pshX literal 0 HcmV?d00001 diff --git a/assets/app_icon/house_check/32.png b/assets/app_icon/house_check/32.png new file mode 100644 index 0000000000000000000000000000000000000000..c04842ba41f5287c5aea77739ee1641c4b86df36 GIT binary patch literal 312 zcmV-80muG{P)holsLj+_1!FIjn5d1gmTc6}*^{@DFE;;bWZpJuX&z>%0Vrkq>TOsEHJ>4^*4|wcd?8FY2bJ~@i^!j%0LhVJRNk;dIMB0vd~>p z%;czl3!T|uI!3(+yl6s4Hkj#>Fa zI@R*;z-XXkA`iY<1EDsDT`rsqzHtNea2oL}NELW13`Ct}h6xpTYYapn*Gpk|s|={t zya@x-D&GSHAWG~m={o&;S{1(s%&g2&M_IJ1{OP4d?B#X%4USf9F~M*0wPKqUexth; hM-5tW*aPjj%>&59DY%1(Y6$=U002ovPDHLkV1gpR#CQMz literal 0 HcmV?d00001 diff --git a/assets/app_icon/house_check/512.png b/assets/app_icon/house_check/512.png new file mode 100644 index 0000000000000000000000000000000000000000..786b93d4b1a9a622fb03af3d356072cc9833ecdd GIT binary patch literal 4608 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 G+x}l%KAR%| literal 0 HcmV?d00001 diff --git a/assets/app_icon/house_check/64.png b/assets/app_icon/house_check/64.png new file mode 100644 index 0000000000000000000000000000000000000000..851e9eabeadda06d7a9ea18e80357a7ab6c81799 GIT binary patch literal 558 zcmV+}0@3}6P)Gf|*a2IXogGVV5XKP^Wo9zTxOv-_ zELG~L&Hs(#IFTa+!WJi|>z>O*{%;&2l>Pp}E}_u5zViYk@!RzlB^cqW3WWE4MOnNX zgv!O+ArKI+yyk?5PmF}b52JwC+aE?jVMUI&Vu@_{52gWW07U2iUmjop41fVh%FX~% z{&~~9C?^S^ZCj}gK9d2kxxJGngYT*a0O4-4*i%Bpdh3TFZ!>r{Ry2r|A#bx75Jap* zhqcfNQsfZwDW`-;k?61%B0-AWLf&StpC59$y^_nvYq_{M%Ljn2>Ow+L;ydAoek_Dy zra=4sH4v}-=DdCYM)4E?Op5PvLDj23Xz^JCh#@{(0I|e-2cXwy@Xh;!ck!1`_Zb&L z-Fn;~@LUK};^DWlt^{E@G7a2^`20)ZkqB^w;3B?=y#NM+tN1biz*hKqYZTP%-_YWV z0RV%9!JCAEXpH!x0I1`v2?!7gn0!$b02>5MvMdh390)GUWsv|}Ah^~Fp#ZF7>;+5^ z=2VLT0Qm0@fYV!jJl6NI+TQf+mnxnJa45D zkq{F3zTGz)Z?w)87<&hYvt?Bqs!>v#{`Z-aI6ANwiU6n90xD$%-4gI2LS|!tuLyg0 ze3hEIK;g(4vKlBL zW2227k|W7YC33VzlGE5|QzA*)YH(AG98Hnrv^QGq4cbjPax_Gen^L3I*r1)2$QiO4 z_AidV>-MbuIXMAiHrn9E{C3~$Kc27GQUoJtgmLnus6yR&?AxMCPRQP5E_&1#jE(d(m0z8yhfVtqC7SMhhAwoh<_~r$KO2`eL0wN^j zgiiqlB!oWLqkxPOVxFp^1ys_`1Lp6qqrnFYs6+|~-RY#jr+^F+QV(+|AVETolQfe8 zay-049V6xzpyJZLwWCb`jb;7te{av_wK2Rm)VzQNfncvL=Dl%<2F&a01vFsx0dW4a z4}kNZF(e><7(?Lr;cf`D`{61OH2c{LfZ5L-5oqT_2}0phf&loGAOJoa^9T($Py|0G zr0(-Gt_Vg`Cu)k!_y8G|F(Hf9d&WQykkT(TF|whG!2SZ3^lIIg)I*g30000 float: + c = c / 255.0 + if c <= 0.04045: + return c / 12.92 + return ((c + 0.055) / 1.055) ** 2.4 + + +def lin_to_srgb(c: float) -> int: + if c <= 0.0031308: + v = 12.92 * c + else: + v = 1.055 * (c ** (1.0 / 2.4)) - 0.055 + return max(0, min(255, int(round(v * 255.0)))) + + +def over(dst: Tuple[float, float, float, float], src: Tuple[float, float, float, float]): + # dst, src in linear space RGBA (0..1) + dr, dg, db, da = dst + sr, sg, sb, sa = src + out_a = sa + da * (1.0 - sa) + if out_a == 0.0: + return (0.0, 0.0, 0.0, 0.0) + out_r = (sr * sa + dr * da * (1.0 - sa)) / out_a + out_g = (sg * sa + dg * da * (1.0 - sa)) / out_a + out_b = (sb * sa + db * da * (1.0 - sa)) / out_a + return (out_r, out_g, out_b, out_a) + + +def to_lin_rgba(color: Tuple[int, int, int, int], alpha_scale: float = 1.0): + r, g, b, a = color + return ( + srgb_to_lin(r), + srgb_to_lin(g), + srgb_to_lin(b), + (a / 255.0) * alpha_scale, + ) + + +def point_in_triangle(px, py, ax, ay, bx, by, cx, cy) -> bool: + # Barycentric technique + v0x, v0y = cx - ax, cy - ay + v1x, v1y = bx - ax, by - ay + v2x, v2y = px - ax, py - ay + dot00 = v0x * v0x + v0y * v0y + dot01 = v0x * v1x + v0y * v1y + dot02 = v0x * v2x + v0y * v2y + dot11 = v1x * v1x + v1y * v1y + dot12 = v1x * v2x + v1y * v2y + denom = dot00 * dot11 - dot01 * dot01 + if denom == 0: + return False + inv = 1.0 / denom + u = (dot11 * dot02 - dot01 * dot12) * inv + v = (dot00 * dot12 - dot01 * dot02) * inv + return (u >= 0) and (v >= 0) and (u + v <= 1) + + +def point_in_rect(px, py, x0, y0, x1, y1) -> bool: + return (x0 <= px <= x1) and (y0 <= py <= y1) + + +def dist_point_to_segment(px, py, ax, ay, bx, by) -> float: + abx, aby = bx - ax, by - ay + apx, apy = px - ax, py - ay + ab2 = abx * abx + aby * aby + if ab2 == 0: + dx, dy = px - ax, py - ay + return math.hypot(dx, dy) + t = (apx * abx + apy * aby) / ab2 + if t < 0: + t = 0 + elif t > 1: + t = 1 + hx, hy = ax + t * abx, ay + t * aby + dx, dy = px - hx, py - hy + return math.hypot(dx, dy) + + +def inside_superellipse(u: float, v: float, n: float = 4.5) -> bool: + # map [0,1] -> [-1,1] + x = 2.0 * u - 1.0 + y = 2.0 * v - 1.0 + return (abs(x) ** n + abs(y) ** n) <= 1.0 + + +def render_icon(size: int) -> bytes: + # 2x2 supersampling + samples = [(0.25, 0.25), (0.75, 0.25), (0.25, 0.75), (0.75, 0.75)] + + # House geometry (normalized 0..1) + roof = (0.28, 0.46, 0.50, 0.30, 0.72, 0.46) # (ax,ay,bx,by,cx,cy) + body = (0.32, 0.46, 0.68, 0.76) # (x0,y0,x1,y1) + + # Check path + chk_a = (0.33, 0.60) + chk_b = (0.46, 0.74) + chk_c = (0.72, 0.48) + thickness = 0.08 # relative to width + + lin_bg = to_lin_rgba(NAVY) + lin_white = to_lin_rgba(WHITE) + lin_green = to_lin_rgba(GREEN) + + out = bytearray(size * size * 4) + idx = 0 + for j in range(size): + for i in range(size): + # Accumulate in linear + dst = (0.0, 0.0, 0.0, 0.0) + + cov_bg = 0.0 + cov_house = 0.0 + cov_check = 0.0 + for (ox, oy) in samples: + u = (i + ox) / size + v = (j + oy) / size + + if inside_superellipse(u, v): + cov_bg += 1.0 + + hx = 0 + # house coverage (triangle or rect) + if point_in_triangle(u, v, *roof): + hx = 1 + elif point_in_rect(u, v, *body): + hx = 1 + cov_house += hx + + # check coverage by distance to segments + d1 = dist_point_to_segment(u, v, *chk_a, *chk_b) + d2 = dist_point_to_segment(u, v, *chk_b, *chk_c) + if min(d1, d2) <= (thickness * 0.5): + cov_check += 1.0 + + ss = float(len(samples)) + if cov_bg > 0.0: + dst = over(dst, (lin_bg[0], lin_bg[1], lin_bg[2], lin_bg[3] * (cov_bg / ss))) + if cov_house > 0.0: + dst = over(dst, (lin_white[0], lin_white[1], lin_white[2], lin_white[3] * (cov_house / ss))) + if cov_check > 0.0: + dst = over(dst, (lin_green[0], lin_green[1], lin_green[2], lin_green[3] * (cov_check / ss))) + + r = lin_to_srgb(dst[0]) + g = lin_to_srgb(dst[1]) + b = lin_to_srgb(dst[2]) + a = max(0, min(255, int(round(dst[3] * 255.0)))) + + out[idx + 0] = r + out[idx + 1] = g + out[idx + 2] = b + out[idx + 3] = a + idx += 4 + + return png_encode(size, size, bytes(out)) + + +def png_chunk(typ: bytes, data: bytes) -> bytes: + return struct.pack( + ">I", len(data) + ) + typ + data + struct.pack( + ">I", (zlib.crc32(typ + data) & 0xFFFFFFFF) + ) + + +def png_encode(width: int, height: int, rgba: bytes) -> bytes: + # Build raw scanlines with filter 0 + stride = width * 4 + raw = bytearray() + for y in range(height): + raw.append(0) # filter type 0 + start = y * stride + raw.extend(rgba[start : start + stride]) + comp = zlib.compress(bytes(raw), level=9) + + sig = b"\x89PNG\r\n\x1a\n" + ihdr = struct.pack( + ">IIBBBBB", + width, + height, + 8, # bit depth + 6, # color type RGBA + 0, # compression + 0, # filter + 0, # interlace + ) + out = bytearray() + out.extend(sig) + out.extend(png_chunk(b"IHDR", ihdr)) + out.extend(png_chunk(b"IDAT", comp)) + out.extend(png_chunk(b"IEND", b"")) + return bytes(out) + + +def main(): + if len(sys.argv) < 3: + print( + "Usage: python3 scripts/render_icon.py ", + file=sys.stderr, + ) + sys.exit(2) + out_dir = sys.argv[1] + sizes = [int(s) for s in sys.argv[2:]] + os.makedirs(out_dir, exist_ok=True) + for s in sizes: + data = render_icon(s) + path = os.path.join(out_dir, f"{s}.png") + with open(path, "wb") as f: + f.write(data) + print(f"wrote {path}") + + +if __name__ == "__main__": + main() +