← back to Corkwallcovering
scripts/crop_cork_headers.py
80 lines
#!/usr/bin/env python3
"""
Batch: for every CORK product in data/products.json, download its image, detect
the PHILLIPE ROMANO logo-header banner, and (if found) crop it off. Cropped
files are saved into public/cropped/<sku>.jpg. Originals are downloaded to a
cache dir. Remote-image, so re-hosting/replacing the live Shopify URL is a
SEPARATE GATED prod step — this only produces local cropped files + a manifest.
Usage:
python3 scripts/crop_cork_headers.py [--vendor "Phillipe Romano"] [--limit N]
"""
import os, sys, json, urllib.request, ssl
from crop_logo_header import detect_band, crop
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATA = os.path.join(ROOT, 'data', 'products.json')
CACHE = os.path.join(ROOT, '.image-cache') # gitignored originals
OUTDIR = os.path.join(ROOT, 'public', 'cropped') # cropped results (served)
MANIFEST = os.path.join(ROOT, 'data', 'cropped-manifest.json')
vendor_filter = None
limit = None
args = sys.argv[1:]
for i,a in enumerate(args):
if a == '--vendor': vendor_filter = args[i+1]
if a == '--limit': limit = int(args[i+1])
def is_cork(p):
s = (str(p.get('handle',''))+' '+str(p.get('sku',''))+' '+str(p.get('title',''))).lower()
return 'cork' in s
def main():
os.makedirs(CACHE, exist_ok=True)
os.makedirs(OUTDIR, exist_ok=True)
d = json.load(open(DATA))
cork = [p for p in d if is_cork(p)]
if vendor_filter:
cork = [p for p in cork if p.get('vendor') == vendor_filter]
if limit: cork = cork[:limit]
ctx = ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
manifest = []
cropped = downloaded = errors = nobanner = 0
for i, p in enumerate(cork):
sku = p.get('sku') or p.get('handle')
url = p.get('image_url')
if not url: continue
cachefile = os.path.join(CACHE, sku + '.jpg')
try:
if not os.path.exists(cachefile):
req = urllib.request.Request(url, headers={'User-Agent':'Mozilla/5.0'})
with urllib.request.urlopen(req, context=ctx, timeout=30) as r, open(cachefile,'wb') as f:
f.write(r.read())
downloaded += 1
except Exception as e:
errors += 1
print(f'[{i}] ERR download {sku}: {e}')
continue
try:
b, info = detect_band(cachefile)
except Exception as e:
errors += 1; print(f'[{i}] ERR detect {sku}: {e}'); continue
if b:
out = os.path.join(OUTDIR, sku + '.jpg')
crop(cachefile, out, b)
cropped += 1
manifest.append(dict(sku=sku, handle=p.get('handle'), vendor=p.get('vendor'),
band_row=b, frac=info.get('frac'),
image_url=url, cropped_file=f'cropped/{sku}.jpg'))
print(f'[{i}] CROP {sku} band@{b} ({info.get("frac")})')
else:
nobanner += 1
json.dump(manifest, open(MANIFEST,'w'), indent=2)
print(f'\n=== DONE === scanned={len(cork)} downloaded={downloaded} '
f'CROPPED={cropped} no-banner={nobanner} errors={errors}')
print('manifest ->', MANIFEST, '| cropped files ->', OUTDIR)
if __name__ == '__main__':
main()