chineseclass/test_center_scaling.py
StillHammer acbe1b4769 Clean up project structure and update content
Remove ClassGenSystem and obsolete tools from tracking, update course content files with latest revisions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:24:41 +08:00

123 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""
Test scaling FROM CENTER (not from top).
If center is aligned but extremes are off, we need to scale from center point.
Also test with top margin offset.
"""
import json
from pdf2image import convert_from_path
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from reportlab.lib.colors import red, blue
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import tempfile
import os
# Font
try:
pdfmetrics.registerFont(TTFont('CF', 'C:/Windows/Fonts/msyh.ttc'))
font = 'CF'
except:
font = 'Helvetica'
# Load
with open('Raw/DevelopChinese/OCR/听力Intro.json') as f:
data = json.load(f)
# Convert
imgs = convert_from_path('Raw/DevelopChinese/PDF/听力Intro.pdf', dpi=300, first_page=1, last_page=1)
img = imgs[0]
w, h = img.size
print(f'Image: {w}x{h}')
# Find OCR coordinate range
details = data['pages'][0]['details']
max_y_ocr = max(max(p[1] for p in d['bbox']) for d in details if d.get('bbox'))
min_y_ocr = min(min(p[1] for p in d['bbox']) for d in details if d.get('bbox'))
center_y_ocr = (min_y_ocr + max_y_ocr) / 2
print(f'OCR Y range: {min_y_ocr} to {max_y_ocr}, center: {center_y_ocr}')
# Save image
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp:
img.save(tmp.name, 'PNG')
tmp_path = tmp.name
# Create PDF
c = canvas.Canvas('test_CENTER_SCALING.pdf')
# Detected top margin
TOP_MARGIN = 199
# Test different Y scale factors (around 1.0)
# Since center is good, we want to compress/expand from center
test_scales = [0.90, 0.92, 0.94, 0.96, 0.98, 1.00, 1.02, 1.04, 1.06, 1.08, 1.10]
for y_scale in test_scales:
c.setPageSize((w, h))
c.drawImage(ImageReader(tmp_path), 0, 0, width=w, height=h)
# Draw title
c.setFont('Helvetica', 18)
c.setFillColorRGB(1, 0, 0)
c.drawString(50, h - 50, f'Y_SCALE: {y_scale:.2f} (from center) + margin: {TOP_MARGIN}px')
# Draw boxes
count = 0
for d in details:
text = d.get('text', '').strip()
if not text or count >= 30:
continue
bbox = d.get('bbox', [])
if not bbox or len(bbox) != 4:
continue
xs = [p[0] for p in bbox]
ys = [p[1] for p in bbox]
x = min(xs)
width = max(xs) - x
y_ocr_max = max(ys)
y_ocr_min = min(ys)
# CRITICAL: Scale from center, not from top!
# 1. Subtract margin offset
y_ocr_max_adj = y_ocr_max - TOP_MARGIN
y_ocr_min_adj = y_ocr_min - TOP_MARGIN
center_y_adj = center_y_ocr - TOP_MARGIN
# 2. Calculate distance from center
dist_from_center_max = y_ocr_max_adj - center_y_adj
dist_from_center_min = y_ocr_min_adj - center_y_adj
# 3. Scale the distance from center
scaled_max = center_y_adj + (dist_from_center_max * y_scale)
scaled_min = center_y_adj + (dist_from_center_min * y_scale)
# 4. Map to PDF coordinates (flip Y, scaled space height = max_y_ocr)
scaled_space_height = max_y_ocr - TOP_MARGIN
y_pdf = h - ((scaled_max / scaled_space_height) * h)
height_pdf = ((scaled_max - scaled_min) / scaled_space_height) * h
c.setStrokeColor(red)
c.setLineWidth(0.5)
c.rect(x, y_pdf, width, height_pdf, stroke=1, fill=0)
font_size = max(1, height_pdf * 0.7)
c.setFont(font, font_size)
c.setFillColor(blue)
c.drawString(x, y_pdf, text)
count += 1
c.showPage()
print(f'Page with Y scale {y_scale:.2f} done')
c.save()
os.unlink(tmp_path)
print(f'\nCreated test_CENTER_SCALING.pdf with {len(test_scales)} pages')
print('Find which Y_SCALE gives alignment at top, center AND bottom!')
print(f'Scale < 1.0 = compress from center (bring extremes closer)')
print(f'Scale > 1.0 = expand from center (push extremes further)')