| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import zlib, struct, os, re
- PNG = r"E:/cfc/docs/品牌资产/assets/cf_logo_primary.png"
- with open(PNG,"rb") as f: data=f.read()
- pos=8; idat=b""
- while pos<len(data):
- ln=struct.unpack(">I",data[pos:pos+4])[0]; ctype=data[pos+4:pos+8]; chunk=data[pos+8:pos+8+ln]
- if ctype==b"IHDR": width,height,bit_depth,color_type=struct.unpack(">IIBB",chunk[:10])
- elif ctype==b"IDAT": idat+=chunk
- elif ctype==b"IEND": break
- pos+=12+ln
- channels=4; raw=zlib.decompress(idat); stride=width*channels
- out=bytearray(); prev=bytearray(stride); i=0
- def paeth(a,b,c):
- p=a+b-c; pa,pb,pc=abs(p-a),abs(p-b),abs(p-c)
- if pa<=pb and pa<=pc: return a
- if pb<=pc: return b
- return c
- for y in range(height):
- ft=raw[i]; i+=1; line=bytearray(raw[i:i+stride]); i+=stride
- for x in range(stride):
- a=line[x-channels] if x>=channels else 0; b=prev[x]; c=prev[x-channels] if x>=channels else 0
- if ft==1: line[x]=(line[x]+a)&255
- elif ft==2: line[x]=(line[x]+b)&255
- elif ft==3: line[x]=(line[x]+((a+b)>>1))&255
- elif ft==4: line[x]=(line[x]+paeth(a,b,c))&255
- out+=line; prev=line
- def px(x,y):
- o=y*stride+x*channels; return (out[o],out[o+1],out[o+2],out[o+3])
- def is_logo(r,g,b,a):
- if a<128: return False
- if abs(r-220)<24 and abs(g-240)<24 and abs(b-249)<24: return False
- return True
- mask=[[is_logo(*px(x,y)) for x in range(width)] for y in range(height)]
- def run_rects(y0,y1,x0,x1,exclude=None):
- rects=[]
- for y in range(max(0,y0), min(height,y1)):
- if exclude and exclude[0]<=y<exclude[1]: continue
- x=max(0,x0)
- while x<min(width,x1):
- if mask[y][x]:
- x0r=x
- while x<min(width,x1) and mask[y][x]:
- x+=1
- rects.append((x0r,y,x-x0r))
- else:
- x+=1
- return rects
- def build_svg(name, y0,y1,x0,x1, with_bg=False, exclude=None, text=None):
- rects=run_rects(y0,y1,x0,x1,exclude)
- ys=[y for (_,y,_) in rects]
- if text: ys += [text["y"]-text["size"], text["y"]]
- loy,hiy=(min(ys),max(ys)) if ys else (0,height)
- grad=(f'<linearGradient id="cfBlue" x1="0" y1="{loy}" x2="0" y2="{hiy}" gradientUnits="userSpaceOnUse">\n'
- f' <stop offset="0" stop-color="#6FB6E3"/>\n'
- f' <stop offset="1" stop-color="#3A8FCC"/>\n </linearGradient>')
- body="".join(f'<rect x="{x}" y="{y}" width="{w}" height="1" fill="url(#cfBlue)"/>' for (x,y,w) in rects)
- bgrect='' if not with_bg else f'<rect x="0" y="0" width="{width}" height="{height}" rx="28" fill="#DCF0F9"/>'
- txt=''
- if text:
- txt=(f'<text x="{text["x"]}" y="{text["y"]}" text-anchor="middle" '
- f'font-family="\'Segoe UI\',\'Helvetica Neue\',Arial,\'Noto Sans SC\',sans-serif" '
- f'font-size="{text["size"]}" font-weight="600" letter-spacing="0.5" fill="url(#cfBlue)">{text["content"]}</text>')
- svg=(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {width} {height}" width="{width}" height="{height}">\n'
- f' <defs>{grad}</defs>\n {bgrect}\n {body}\n {txt}\n</svg>\n')
- return svg
- outdir=r"E:/cfc/docs/品牌资产/assets"
- # wordmark bbox in 144 canvas: x[42,103] y[112,120]; baseline ~121, size ~13, center x=72
- WM={"x":72,"y":121,"size":13,"content":"Care Family"}
- # primary: monogram pixel-trace (exclude wordmark rows) + smooth vector wordmark text
- prim=build_svg("primary",0,height,0,width,with_bg=False,exclude=(108,144),text=WM)
- icon=build_svg("icon",36,107,25,119)
- primbg=build_svg("primary_bg",0,height,0,width,with_bg=True,exclude=(108,144),text=WM)
- # standalone wordmark: smooth vector text on its own clean canvas
- wm_svg=(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 44" width="220" height="44">\n'
- f' <defs><linearGradient id="cfBlue" x1="0" y1="6" x2="0" y2="38" gradientUnits="userSpaceOnUse">\n'
- f' <stop offset="0" stop-color="#6FB6E3"/>\n <stop offset="1" stop-color="#3A8FCC"/>\n </linearGradient></defs>\n'
- f' <text x="110" y="32" text-anchor="middle" '
- f'font-family="\'Segoe UI\',\'Helvetica Neue\',Arial,\'Noto Sans SC\',sans-serif" '
- f'font-size="28" font-weight="600" letter-spacing="1" fill="url(#cfBlue)">Care Family</text>\n</svg>\n')
- files={"cf_logo_primary.svg":prim,"cf_logo_icon.svg":icon,"cf_logo_wordmark.svg":wm_svg,"cf_logo_primary_bg.svg":primbg}
- for nm,content in files.items():
- with open(os.path.join(outdir,nm),"w",encoding="utf-8") as f:
- f.write(content)
- print("wrote",nm,len(content),"bytes")
- # verify primary monogram region still pixel-exact vs original
- svg=open(os.path.join(outdir,"cf_logo_primary.svg"),encoding="utf-8").read()
- rects=[(int(x),int(y),int(w)) for (x,y,w) in re.findall(r'<rect x="(\d+)" y="(\d+)" width="(\d+)"',svg)]
- recon=[[False]*width for _ in range(height)]
- for (x,y,w) in rects:
- for xx in range(x,min(width,x+w)): recon[y][xx]=True
- diff=sum(1 for y in range(36,107) for x in range(25,119) if mask[y][x]!=recon[y][x])
- print("primary monogram-region diff vs original:",diff,"(0 = pixel-exact)")
- print("done")
|