"""Remove generated white-background contamination from this bay horse's dark hair atlas."""
import bpy,json,numpy as np
from pathlib import Path
P=Path('/opt/creature-lib-20261017/realistic/horse');bpy.ops.wm.read_factory_settings(use_empty=True);bpy.context.scene.render.fps=30;bpy.ops.import_scene.gltf(filepath=str(P/'clearance-v6.glb'))
o=next(o for o in bpy.context.scene.objects if o.type=='MESH' and any(m.type=='ARMATURE' for m in o.modifiers));mat=o.data.materials[0];bs=mat.node_tree.nodes.get('Principled BSDF');im=bs.inputs['Base Color'].links[0].from_node.image;a=np.array(im.pixels[:],dtype=np.float32).reshape(im.size[1],im.size[0],4);rgb=a[:,:,:3];mx=rgb.max(axis=2);mn=rgb.min(axis=2);sat=(mx-mn)/(mx+1e-5)
# Bay reference has no white forelock or mane. Warm coat pixels are outside this chroma mask.
mask=np.clip((mx-.34)/.20,0,1)*np.clip((.30-sat)/.16,0,1)
# Leave tiny highlights in place; the artifact is large connected pale paper around hair strands.
# Flat dark colour still retains existing black strand texture and its bright/dark variation.
target=np.stack([.050+.025*mx,.041+.021*mx,.034+.018*mx],axis=-1)
a[:,:,:3]=rgb*(1-mask[:,:,None])+target*mask[:,:,None];im.pixels.foreach_set(a.reshape(-1));im.update();im.pack()
rig=next(x for x in bpy.context.scene.objects if x.type=='ARMATURE')
for t in rig.animation_data.nla_tracks:t.mute=True
rig.animation_data.action=bpy.data.actions['Idle'];rig.animation_data.action_slot=rig.animation_data.action.slots[0];bpy.context.scene.frame_set(0);bpy.context.view_layer.update();bpy.ops.object.select_all(action='DESELECT')
for x in bpy.context.scene.objects:
 if x.type in ['ARMATURE','EMPTY'] or x==o:x.select_set(True)
out=P/'hair-v7.glb';assert not out.exists()
bpy.ops.export_scene.gltf(filepath=str(out),export_format='GLB',use_selection=True,export_yup=True,export_animations=True,export_animation_mode='ACTIONS',export_anim_single_armature=True,export_force_sampling=True,export_optimize_animation_size=True,export_influence_nb=4,export_all_influences=False,export_leaf_bone=False,export_image_format='JPEG',export_jpeg_quality=90)
e=json.loads((P/'entry-v6.json').read_text());e['file']='../realistic/horse/hair-v7.glb';(P/'entry-v7.json').write_text(json.dumps(e,indent=2));(P/'hair-repair.json').write_text(json.dumps({'reason':'Generator copied the white reference background around dark forelock and mane into the opaque colour texture. Bay reference has no white hair.','method':'Low-chroma pale pixels darkened continuously; warm coat colours unchanged. No alpha holes, no new geometry.','pixels_affected_gt_half':int((mask>.5).sum()),'texture_pixels':int(mask.size)},indent=2));print('HAIR_REPAIR',int((mask>.5).sum()),out.stat().st_size)
