微信小程序页面迁移校验之前 P5任务处理之前
This commit is contained in:
165
scripts/ops/page_compare.py
Normal file
165
scripts/ops/page_compare.py
Normal file
@@ -0,0 +1,165 @@
|
||||
"""
|
||||
通用页面像素对比脚本。
|
||||
支持长页面分页裁剪:将 H5 截图按 MP 一屏高度分段裁剪,逐段对比。
|
||||
用法:python scripts/ops/page_compare.py <page_name> [--segment]
|
||||
--segment: 长页面分段模式,按 MP 一屏高度切割 H5 截图
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SCREENSHOTS = ROOT / "docs" / "h5_ui" / "screenshots"
|
||||
|
||||
# DPR 常量
|
||||
H5_DPR = 3
|
||||
MP_DPR = 1.5
|
||||
LOGICAL_WIDTH = 430
|
||||
TARGET_W = 1290 # H5 原始宽度,MP ×2 缩放到此
|
||||
|
||||
|
||||
def resize_to_width(img: Image.Image, target_w: int) -> Image.Image:
|
||||
if img.width == target_w:
|
||||
return img.copy()
|
||||
ratio = target_w / img.width
|
||||
new_h = int(img.height * ratio)
|
||||
return img.resize((target_w, new_h), Image.LANCZOS)
|
||||
|
||||
|
||||
def compare_default(page: str) -> dict:
|
||||
"""默认态对比:统一到 1290px 宽,裁剪到 MP 一屏高度"""
|
||||
h5_path = SCREENSHOTS / f"{page}.png"
|
||||
mp_path = SCREENSHOTS / f"mp-{page}.png"
|
||||
|
||||
for p in [h5_path, mp_path]:
|
||||
if not p.exists():
|
||||
return {"error": f"文件不存在: {p.name}"}
|
||||
|
||||
h5_img = Image.open(h5_path)
|
||||
mp_img = Image.open(mp_path)
|
||||
|
||||
print(f"[{page}] H5: {h5_img.width}×{h5_img.height} (DPR {H5_DPR})")
|
||||
print(f"[{page}] MP: {mp_img.width}×{mp_img.height} (DPR {MP_DPR})")
|
||||
|
||||
# 缩放到统一宽度
|
||||
h5_scaled = resize_to_width(h5_img, TARGET_W)
|
||||
mp_scaled = resize_to_width(mp_img, TARGET_W)
|
||||
|
||||
# MP 逻辑高度 → H5 物理高度
|
||||
mp_logical_h = mp_img.height / MP_DPR
|
||||
h5_crop_h = int(mp_logical_h * H5_DPR)
|
||||
|
||||
# 裁剪到相同高度
|
||||
final_h = min(h5_scaled.height, mp_scaled.height, h5_crop_h)
|
||||
h5_final = h5_scaled.crop((0, 0, TARGET_W, final_h))
|
||||
mp_final = mp_scaled.crop((0, 0, TARGET_W, final_h))
|
||||
|
||||
# 保存
|
||||
h5_out = SCREENSHOTS / "cmp-h5.png"
|
||||
mp_out = SCREENSHOTS / "cmp-mp.png"
|
||||
h5_final.save(h5_out)
|
||||
mp_final.save(mp_out)
|
||||
|
||||
print(f"[{page}] 对比尺寸: {TARGET_W}×{final_h}")
|
||||
print(f"[{page}] 逻辑高度: {final_h / H5_DPR:.0f}px")
|
||||
|
||||
return {
|
||||
"h5_out": str(h5_out),
|
||||
"mp_out": str(mp_out),
|
||||
"width": TARGET_W,
|
||||
"height": final_h,
|
||||
"logical_height": final_h / H5_DPR,
|
||||
}
|
||||
|
||||
|
||||
def compare_segments(page: str, segment_logical_h: int = 752) -> list:
|
||||
"""
|
||||
长页面分段对比。
|
||||
segment_logical_h: 每段逻辑高度(默认 752px = MP 一屏 1128px / DPR 1.5)
|
||||
返回每段的裁剪文件路径列表。
|
||||
"""
|
||||
h5_path = SCREENSHOTS / f"{page}.png"
|
||||
mp_path = SCREENSHOTS / f"mp-{page}.png"
|
||||
|
||||
for p in [h5_path, mp_path]:
|
||||
if not p.exists():
|
||||
return [{"error": f"文件不存在: {p.name}"}]
|
||||
|
||||
h5_img = Image.open(h5_path)
|
||||
mp_img = Image.open(mp_path)
|
||||
|
||||
h5_scaled = resize_to_width(h5_img, TARGET_W)
|
||||
mp_scaled = resize_to_width(mp_img, TARGET_W)
|
||||
|
||||
# 计算 MP 总逻辑高度
|
||||
mp_logical_total = mp_img.height / MP_DPR
|
||||
h5_logical_total = h5_img.height / H5_DPR
|
||||
|
||||
print(f"[{page}] H5 逻辑高度: {h5_logical_total:.0f}px")
|
||||
print(f"[{page}] MP 逻辑高度: {mp_logical_total:.0f}px")
|
||||
|
||||
# 按段裁剪
|
||||
seg_h5_px = int(segment_logical_h * H5_DPR) # H5 物理像素
|
||||
seg_mp_px = int(segment_logical_h * MP_DPR * 2) # MP 缩放后物理像素(×2)
|
||||
|
||||
segments = []
|
||||
seg_idx = 0
|
||||
y_h5 = 0
|
||||
y_mp = 0
|
||||
|
||||
while y_h5 < h5_scaled.height and y_mp < mp_scaled.height:
|
||||
end_h5 = min(y_h5 + seg_h5_px, h5_scaled.height)
|
||||
end_mp = min(y_mp + seg_mp_px, mp_scaled.height)
|
||||
|
||||
# 确保两段高度一致
|
||||
actual_h = min(end_h5 - y_h5, end_mp - y_mp)
|
||||
|
||||
h5_seg = h5_scaled.crop((0, y_h5, TARGET_W, y_h5 + actual_h))
|
||||
mp_seg = mp_scaled.crop((0, y_mp, TARGET_W, y_mp + actual_h))
|
||||
|
||||
h5_seg_path = SCREENSHOTS / f"seg-h5-{page}-{seg_idx}.png"
|
||||
mp_seg_path = SCREENSHOTS / f"seg-mp-{page}-{seg_idx}.png"
|
||||
h5_seg.save(h5_seg_path)
|
||||
mp_seg.save(mp_seg_path)
|
||||
|
||||
logical_y_start = y_h5 / H5_DPR
|
||||
segments.append({
|
||||
"index": seg_idx,
|
||||
"h5_path": str(h5_seg_path),
|
||||
"mp_path": str(mp_seg_path),
|
||||
"logical_y": f"{logical_y_start:.0f}-{logical_y_start + actual_h / H5_DPR:.0f}px",
|
||||
"height": actual_h,
|
||||
})
|
||||
|
||||
print(f" 段 {seg_idx}: 逻辑 Y={logical_y_start:.0f}-{logical_y_start + actual_h / H5_DPR:.0f}px, 高度={actual_h}px")
|
||||
|
||||
y_h5 += seg_h5_px
|
||||
y_mp += seg_mp_px
|
||||
seg_idx += 1
|
||||
|
||||
return segments
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("用法: python page_compare.py <page_name> [--segment]")
|
||||
sys.exit(1)
|
||||
|
||||
page = sys.argv[1]
|
||||
segment_mode = "--segment" in sys.argv
|
||||
|
||||
if segment_mode:
|
||||
print(f"\n=== 分段对比: {page} ===")
|
||||
segments = compare_segments(page)
|
||||
print(f"\n共 {len(segments)} 段")
|
||||
else:
|
||||
print(f"\n=== 默认态对比: {page} ===")
|
||||
result = compare_default(page)
|
||||
if "error" in result:
|
||||
print(f"❌ {result['error']}")
|
||||
else:
|
||||
print(f"✅ 输出: cmp-h5.png + cmp-mp.png ({result['width']}×{result['height']})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user