46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
"""Patch only U+3002 pixels in an existing CJK atlas; preserve its TGA bytes."""
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
from build_cjk import lower_full_stop, tga_to_image, tga_geometry
|
|
|
|
|
|
def patch_atlas(raw, metadata):
|
|
image, desc = tga_to_image(raw)
|
|
cell = metadata['cell']
|
|
if list(image.size) != metadata['atlas']:
|
|
raise ValueError('atlas geometry mismatch')
|
|
entry = metadata['cells'][str(int.from_bytes('。'.encode('gb2312'), 'big'))]
|
|
if entry['uni'] != '。':
|
|
raise ValueError('full-stop cell mismatch')
|
|
x, y = entry['x'], entry['y']
|
|
tile = image.crop((x, y, x + cell, y + cell))
|
|
fixed = lower_full_stop(tile)
|
|
idlen, _, w, h, _, _ = tga_geometry(raw)
|
|
result = bytearray(raw)
|
|
for j in range(cell):
|
|
row = y + j if desc & 0x20 else h - 1 - y - j
|
|
for i in range(cell):
|
|
offset = 18 + idlen + (row * w + x + i) * 4
|
|
r, g, b, a = fixed.getpixel((i, j))
|
|
result[offset:offset + 4] = bytes((b, g, r, a))
|
|
return bytes(result)
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description=__doc__)
|
|
p.add_argument('--source', type=Path, required=True)
|
|
p.add_argument('--cells', type=Path, required=True)
|
|
p.add_argument('--out', type=Path, required=True)
|
|
args = p.parse_args()
|
|
if args.source.resolve() == args.out.resolve():
|
|
p.error('output must differ from source')
|
|
result = patch_atlas(args.source.read_bytes(), json.loads(args.cells.read_text(encoding='utf-8')))
|
|
args.out.parent.mkdir(parents=True, exist_ok=True)
|
|
args.out.write_bytes(result)
|
|
print('Full stop anchored at cell bottom; other atlas bytes preserved.')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|