PPT 视觉复刻

v1.4.1

将PPT截图或信息图转换为可编辑的PPTX文件。此技能基于Images2Slides论文(arXiv:2602.07645)实现, 利用视觉-语言模型(VLM)进行区域理解,通过坐标映射算法将像素坐标转换为PPTX坐标。 支持复杂形状降级处理策略(custGeom/渐变/透明等无法直接还原的形状转为PNG嵌入)。...

0· 141·0 current·0 all-time
byAllegro@allergro

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for allergro/ppt-vision-replica.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "PPT 视觉复刻" (allergro/ppt-vision-replica) from ClawHub.
Skill page: https://clawhub.ai/allergro/ppt-vision-replica
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install ppt-vision-replica

ClawHub CLI

Package manager switcher

npx clawhub@latest install ppt-vision-replica
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description align with included code (coordinate_mapper.js, ppt_generator.js, complex_shape.py) and the declared runtime needs (pptxgenjs, Pillow, filesystem, network). There are no unrelated environment variables, binaries, or config paths requested that would be disproportionate to the conversion task.
Instruction Scope
SKILL.md explicitly instructs sending images to an external VLM service for region analysis (OpenClaw image tool / MiniMax / GPT-4V). The code files themselves do not contain network calls; the network usage is part of the architecture described in the instructions. The instructions also require writing temporary PNGs and output PPTX files and include optional unzipping of original PPTX for XML extraction—these are proportional but mean image data and (optionally) PPTX contents will be transmitted/processed.
Install Mechanism
There is no automated install spec (instruction-only install), which is lowest-risk. The SKILL.md asks users to install pptxgenjs via npm and Pillow via pip for optional PNG rendering; these are standard, known packages. No remote archive downloads or obscure installers are present.
Credentials
The skill does not declare any required environment variables or credentials, which is consistent with shipping as agent-side code that uses the platform's image/VLM tooling. However, runtime image analysis requires a configured VLM endpoint (implicit credentials/auth are expected to be provided by the platform or agent configuration). Users should confirm where images will be sent and what credentials the agent/platform uses.
Persistence & Privilege
The skill does not request always:true or any special persistent privileges. It reads and writes temporary files in the filesystem (explicitly declared) and does not modify other skills or global agent config.
Assessment
This skill appears coherent for converting PPT screenshots to editable PPTX: it includes the JS/Python code you'd expect and warns that images are sent to an external VLM. Before installing, ensure you (1) do not process sensitive/confidential slides because images are transmitted to the configured VLM endpoint, (2) verify which VLM/service the agent will use and that its privacy/security posture is acceptable, (3) install the optional dependencies (npm pptxgenjs and Python Pillow) in a controlled environment, and (4) allow filesystem read/write only in a safe temp directory. If you need assurance about where data is sent, ask the skill author how the VLM endpoint is configured or inspect the agent/platform image tool settings.

Like a lobster shell, security has layers — review code before you run it.

latestvk97f1e2zrv4ab9sj071vkghqzh83nxzg
141downloads
0stars
2versions
Updated 1mo ago
v1.4.1
MIT-0

⚠️ 使用前须知

  • 图片数据发送:第一步 VLM 图像分析会将截图发送到配置的 VLM 服务端点(如 OpenClaw image 工具 / MiniMax Vision / GPT-4V 等)。请勿使用本技能处理涉密或敏感的幻灯片。
  • 文件系统:技能会生成临时 PNG 文件和输出 PPTX 文件,确保运行环境允许文件读写操作。
  • 运行时依赖:需提前安装 npm install -g pptxgenjs;如需复杂形状降级,还需安装 Python + Pillow。

PPT视觉复刻技能 (v1.5)

将静态PPT截图/信息图转换为可编辑PPTX文件的完整工作流。

核心算法 (Images2Slides论文适配)

坐标映射 (Pixel → EMU)

EMU = Pixel × (914400 / DPI)
Slide_X = (Image_X / Image_Width) × Slide_Width_EMU
Slide_Y = (Image_Y / Image_Height) × Slide_Height_EMU

标准16:9幻灯片尺寸: 9144000 × 5143500 EMU

工作流程

阶段1: 图像分析(开放式 VLM 调用)

第一步的图片识别为开放式设计,可灵活接入任意具备图像理解能力的工具—— 如 OpenClaw 内置 image 工具(默认,MiniMax Vision VLM)、MCP VLM 服务、GPT-4V 等。 后续坐标映射和 PPT 生成逻辑与具体 VLM 解耦,保持稳定。

必须使用以下增强版 Prompt,以确保符号精度和格式完整性:

const ENHANCED_PROMPT = `分析这张PPT截图,精确输出所有可见区域的信息。

输出格式为JSON数组,每个元素包含:
{
  "id": "数字",
  "type": "rectangle | roundedRect | text | line | image",
  "role": "header_bar | title | subtitle | body | data_card | footer | decorator | bullet_list",
  "bounds": { "x": 像素, "y": 像素, "width": 像素, "height": 像素 },
  "color": "#十六进制颜色(文字颜色或形状填充色)",
  "backgroundColor": "#背景填充色(仅形状适用)",
  "lineColor": "#边框颜色(如有边框)",
  "lineWidth": 边框宽度,
  "content": "文字内容(保持原版的所有标点符号,全角/半角符号原样保留)",
  "fontSize": 字号数字(磅),
  "fontFamily": "字体名称",
  "fontWeight": "normal | bold",
  "align": "left | center | right",
  "lineSpacing": 行间距倍数(1.0/1.5/2.0),
  "charSpacing": 字符间距(磅),
  "bulletType": "无bullet则null,有bullet则填 ■ / ✓ / - 等符号",
  "cornerRadius": 圆角大小(仅roundedRect适用),
  "zIndex": 叠加层级(从0开始)
}

⚠️ 特别注意:
1. content 必须保持原版的所有标点符号,包括全角括号()和半角括号()的区别
2. 不要添加或删除任何字符
3. 项目符号(■、✓、1.、-)必须原样记录在 bulletType 字段
4. 识别所有行间距较大的文本框,填写 lineSpacing
5. 边框矩形必须填写 lineColor,填充矩形填写 backgroundColor
6. zIndex按照视觉层叠顺序从后到前递增`;

阶段2: 结构化数据解析

调用 scripts/coordinate_mapper.js,支持4种JSON提取策略,自动容错:

const { parseAnalysisToRegions, mapAllRegions } = require('./coordinate_mapper');

// 解析分析结果(自动处理全角符号校正和bullet识别)
const regions = parseAnalysisToRegions(analysisText);

// 批量映射坐标
const mappedRegions = mapAllRegions(regions, imageWidth, imageHeight);

新增功能(v1.1):

  • normalizeSymbols(text) — 全角/半角符号校正
  • detectBullet(text) — 识别并提取bullet符号类型
  • 4策略JSON解析容错(直接解析 → 数组提取 → 对象提取 → 代码块提取)

阶段3: PPT生成

调用 scripts/ppt_generator.js

const { saveFromRegions } = require('./ppt_generator');

await saveFromRegions(mappedRegions, 'output.pptx', {
  imageWidth: 2100,
  imageHeight: 1192,
  background: '#FFFFFF'  // 可选背景色
});

区域类型映射

VLM输出PptxGenJS方法v1.1新增支持
rectangle (filled)slide.addShape('rect')backgroundColor / lineColor
rectangle (border)slide.addShape('rect')lineWidth / dashType
roundedRectslide.addShape('roundRect')✅ 新增 cornerRadius
textslide.addText()✅ lineSpacing / charSpacing / bullet
lineslide.addShape('line')dashType
imageslide.addImage()data(base64) / path
复杂形状slide.addImage() + Python绘制PNG✅ v1.2新增

复杂形状降级处理策略 (v1.2)

核心思路:pptxgenjs 无法还原的复杂图形,改用 Python/Pillow 绘制精确 PNG(透明背景)→ 嵌入 PPT 的方式替代。

何时触发降级

遇到以下情况时,应将该形状标记为 type: "complex_shape",使用降级策略处理:

形状特征判断依据
自定义多边形路径XML中存在 <a:custGeom> 标签,包含贝塞尔曲线、不规则路径
透明渐变填充多色渐变(3个以上 stop)或带透明度通道(alpha < 100%)的渐变
复合渐变方向渐变角度非水平/垂直(非0/90/180/270度),如斜向渐变
发光/阴影特效<a:outerShdw>, <a:glow> 等复杂效果 pptxgenjs 渲染误差大
不规则遮罩/裁切图片经过自定义路径裁切(<p:spPr><a:custGeom> 包裹图片)
VLM识别为渐变箭头/装饰图形从截图分析中识别出类型为装饰性渐变形状

降级处理工作流

┌─────────────────────────────────────────────────────┐
│ 1. 判断是否为复杂形状(见上表)                          │
│    ├── 有原版PPTX → 从XML提取精确路径和颜色参数            │
│    └── 仅截图 → 用VLM估算形状轮廓和渐变颜色                │
│                                                     │
│ 2. 用Python/Pillow绘制透明背景PNG                       │
│    ├── 绘制精确路径(参考XML坐标 或 VLM估算像素)           │
│    ├── 应用渐变/透明/特效                               │
│    └── 输出 RGBA 透明背景 PNG                          │
│                                                     │
│ 3. 嵌入PPT(addImage)                               │
│    └── 坐标与原版对应(EMU换算或比例缩放)                  │
└─────────────────────────────────────────────────────┘

从原版XML提取形状参数(有源文件时优先)

当有原版 .pptx 可解包时,可获取最精确的参数:

# 解包PPTX
unzip original.pptx -d pptx_unpacked/
# 查看形状XML
cat pptx_unpacked/ppt/slides/slide1.xml

关键字段提取:

<!-- 自定义路径形状 -->
<a:custGeom>
  <a:pathLst>
    <a:path w="5725" h="1294">   <!-- 路径画布尺寸(EMU相对坐标)-->
      <a:moveTo><a:pt x="2852" y="0"/></a:moveTo>  <!-- 起点 -->
      <a:cubicBezTo>...</a:cubicBezTo>              <!-- 贝塞尔曲线 -->
      <a:lnTo>...</a:lnTo>                          <!-- 直线段 -->
    </a:path>
  </a:pathLst>
</a:custGeom>

<!-- 渐变填充 -->
<a:gradFill>
  <a:gsLst>
    <a:gs pos="0"><a:srgbClr val="FFFFFF"/></a:gs>    <!-- 白色,pos=0% -->
    <a:gs pos="100000"><a:srgbClr val="C00000"/></a:gs> <!-- 红色,pos=100% -->
  </a:gsLst>
  <a:lin ang="16200000" scaled="0"/>  <!-- ang=16200000 = 270°(EMU角度单位:60000/度)-->
</a:gradFill>

<!-- 形状在组合(grpSp)中的位置 -->
<a:off x="696" y="2680"/>  <!-- 相对于组的偏移 -->
<a:ext cx="5725" cy="1294"/>  <!-- 形状尺寸 -->

EMU角度转换公式:

实际角度(度)= EMU角度值 / 60000
例: 16200000 / 60000 = 270°(即从上到下的渐变方向)

组合坐标转绝对坐标公式:

// grp = { off: {x, y}, ext: {cx, cy}, chOff: {x, y}, chExt: {cx, cy} }
function absPos(grp, shape) {
  const scaleX = grp.ext.cx / grp.chExt.cx;
  const scaleY = grp.ext.cy / grp.chExt.cy;
  return {
    x: grp.off.x + (shape.x - grp.chOff.x) * scaleX,
    y: grp.off.y + (shape.y - grp.chOff.y) * scaleY,
    cx: shape.cx * scaleX,
    cy: shape.cy * scaleY,
  };
}

Python/Pillow 绘制复杂形状 PNG(模板)

"""
复杂形状PNG生成模板
适用于:自定义多边形 + 渐变填充 + 透明背景
"""
from PIL import Image, ImageDraw
import numpy as np

# ========== 配置区 ==========
OUTPUT_PATH = "complex_shape.png"
# 画布尺寸(可按EMU比例或屏幕像素设定,建议宽度1000+)
CANVAS_W = 1200
CANVAS_H = 280

# 渐变颜色(从上到下,可扩展多个停止点)
GRADIENT_STOPS = [
    (0.0,   (255, 255, 255)),   # 白色 #FFFFFF
    (1.0,   (192,   0,   0)),   # 深红 #C00000
]

# 形状路径点(归一化坐标 0~1,按原版路径节点填写)
# 说明:从XML的 custGeom 路径坐标除以路径画布宽高即可归一化
SHAPE_POINTS_NORMALIZED = [
    (0.498, 0.0),   # 顶部尖角
    (1.0,   0.25),  # 右上
    (1.0,   1.0),   # 右下
    (0.0,   1.0),   # 左下
    (0.0,   0.25),  # 左上
]
# ========== 配置区结束 ==========

def lerp_color(c1, c2, t):
    return tuple(int(c1[i] + (c2[i] - c1[i]) * t) for i in range(3))

def gradient_color(y_ratio, stops):
    """根据y比例插值渐变颜色"""
    for i in range(len(stops) - 1):
        p0, c0 = stops[i]
        p1, c1 = stops[i + 1]
        if p0 <= y_ratio <= p1:
            t = (y_ratio - p0) / (p1 - p0)
            return lerp_color(c0, c1, t)
    return stops[-1][1]

# 创建透明画布
img = Image.new("RGBA", (CANVAS_W, CANVAS_H), (0, 0, 0, 0))

# 构建蒙版(形状区域)
mask = Image.new("L", (CANVAS_W, CANVAS_H), 0)
draw_mask = ImageDraw.Draw(mask)
pixel_points = [(int(x * CANVAS_W), int(y * CANVAS_H)) for x, y in SHAPE_POINTS_NORMALIZED]
draw_mask.polygon(pixel_points, fill=255)

# 逐行填充渐变色
pixels = img.load()
mask_pixels = mask.load()
for row in range(CANVAS_H):
    y_ratio = row / CANVAS_H
    color = gradient_color(y_ratio, GRADIENT_STOPS)
    for col in range(CANVAS_W):
        if mask_pixels[col, row] > 0:
            pixels[col, row] = (*color, mask_pixels[col, row])

img.save(OUTPUT_PATH)
print(f"已生成: {OUTPUT_PATH} ({CANVAS_W}x{CANVAS_H})")

贝塞尔曲线采样(针对含 cubicBezTo 的复杂路径):

完整实现已打包在 scripts/complex_shape.py,支持命令行直接调用:

python scripts/complex_shape.py \
    --output complex_shape.png \
    --width 1200 --height 280 \
    --gradient-stops "0.0:#FFFFFF,1.0:#C00000" \
    --polygon "0.498,0.0 1.0,0.25 1.0,1.0 0.0,1.0 0.0,0.25"

嵌入PPT(addImage)

const PptxGenJS = require('pptxgenjs');

// EMU → 英寸(pptxgenjs坐标单位为英寸)
const EMU_PER_INCH = 914400;
function emuToInch(emu) { return emu / EMU_PER_INCH; }

// 嵌入生成的PNG(坐标来自absPos计算结果)
slide.addImage({
  path: './complex_shape.png',    // 或 data: base64String
  x: emuToInch(absPos.x),
  y: emuToInch(absPos.y),
  w: emuToInch(absPos.cx),
  h: emuToInch(absPos.cy),
});

仅有截图时的降级策略

当没有原版PPTX只有截图时:

  1. 用VLM分析形状:在分析Prompt中要求输出形状类型为 complex_shape,描述渐变颜色和方向
  2. 坐标估算:从像素坐标按比例转换为PPT EMU坐标(精度约±5%)
  3. 颜色提取:要求VLM输出渐变起止色的十六进制值
  4. 形状近似:若路径复杂,可用多边形近似(顶点数≥6通常足够)

更新VLM分析Prompt中的type枚举,增加:

"type": "complex_shape",
"shapeDescription": "渐变方向/颜色/形状类型的文字描述,供Python绘制参考",
"gradientStops": [{"pos": 0, "color": "#FFFFFF"}, {"pos": 1, "color": "#C00000"}],
"gradientAngle": 270

短期优化清单(v1.1已实现)

优先级问题解决方案
P0括号全角/半角差异增强Prompt要求保留原版符号
P0bullet符号丢失或错误新增 detectBullet() + bulletType字段
P0行间距不一致支持 lineSpacing 参数映射
P0字符间距丢失支持 charSpacing 参数映射
P1JSON解析失败4策略容错解析
P1圆角矩形显示为直角新增 roundedRect 类型

快速执行命令

const { parseAnalysisToRegions, mapAllRegions } = require('./coordinate_mapper');
const { saveFromRegions } = require('./ppt_generator');

async function main(analysisResult, imageWidth, imageHeight, outputPath) {
  // 1. 解析区域(含符号校正)
  const regions = parseAnalysisToRegions(analysisResult);
  // 2. 坐标映射
  const mapped = mapAllRegions(regions, imageWidth, imageHeight);
  // 3. 生成PPTX
  await saveFromRegions(mapped, outputPath, { imageWidth, imageHeight });
}

输出规范

生成的PPTX必须包含:

  • 所有可见区域精确复刻
  • 正确的叠加顺序(zIndex)
  • 准确的颜色值
  • 可编辑的文本内容(含正确的符号和行间距)

依赖

  • Node.js + pptxgenjs
  • 图像理解工具(开放式,默认 OpenClaw 内置 image 工具 / MiniMax Vision MCP)
  • coordinate_mapper.js(坐标转换 + 符号校正)
  • ppt_generator.js(PPT生成 + 格式支持)

方案B:基于原版PPTX的内容替换(ZIP直接操作法)

适用场景:用户有原版 .pptx 文件,只需替换文字内容,保留所有样式、母版、配色、custGeom、媒体文件。
优点:100%保留原版视觉效果,无需重建任何形状,文件结构完整可靠。
与方案A的选择原则:有原版PPTX → 优先方案B;仅有截图 → 方案A(从零生成)。


核心思路

PPTX 本质是一个 ZIP 压缩包。直接用 Python zipfile 操作:

  • 只替换 ppt/slides/slide1.xml(幻灯片内容)
  • 完整保留其他所有文件(母版/布局/主题/媒体/标签等)
原版PPTX (89个文件)
  └── ppt/slides/slide1.xml  ← 只替换这一个文件
  └── ppt/slideMasters/      ← 保留
  └── ppt/slideLayouts/      ← 保留
  └── ppt/theme/             ← 保留
  └── ppt/media/             ← 保留(图片、SVG等)
  └── [Content_Types].xml    ← 保留
  └── ...所有其他文件         ← 保留

⚠️ 关键注意事项

  1. 必须用完整原版PPTX为基础,不能用手动解包再重新打包的目录(极易缺失文件)
  2. 中文文本被拆散在多个 <a:r> 标签中,不能直接字符串替换,需整段 <a:p> 替换
  3. XML中特殊字符必须转义<&lt;>&gt;&&amp;
  4. 替换前先用 xmllint --nooutxml.etree.ElementTree 验证XML有效性

完整替换脚本模板

import zipfile, re, io

src = '/path/to/original.pptx'   # 原版完整PPTX
out = '/path/to/output.pptx'      # 输出路径

# 1. 读取 slide1.xml
with zipfile.ZipFile(src, 'r') as z:
    xml = z.read('ppt/slides/slide1.xml').decode('utf-8')

# =============================================
# 2. 文本替换(两种策略,按情况选用)
# =============================================

# --- 策略A:简单单Run替换(文本完整在一个 <a:t> 标签内)---
# 格式:(旧文本含尖括号定位符, 新文本含尖括号定位符)
simple_replacements = [
    ('>旧文本1<', '>新文本1<'),
    ('>旧文本2<', '>新文本2<'),
    # ⚠️ 如果新文本含 < 或 > 必须转义:
    ('>旧文本3<', '>误差&lt;1%<'),
]
for old, new in simple_replacements:
    xml = xml.replace(old, new)

# --- 策略B:整段替换(中文被拆散在多个 <a:r> 中时使用)---
def replace_para_containing(xml_str, search_text, new_text, rPr_override=None):
    """
    找到包含 search_text 的整个 <a:p> 段落,替换为只含 new_text 的新段落。
    保留原段落的 pPr(段落格式)和 rPr(文字格式)。
    """
    idx = xml_str.find(f'>{search_text}<')
    if idx < 0:
        print(f'⚠️  未找到文本:{search_text}')
        return xml_str
    start = xml_str.rfind('<a:p>', 0, idx)
    end = xml_str.find('</a:p>', idx) + 6
    old_para = xml_str[start:end]
    # 提取段落格式
    pPr_match = re.search(r'<a:pPr.*?</a:pPr>', old_para, re.DOTALL)
    pPr = pPr_match.group() if pPr_match else ''
    # 提取文字格式(优先自闭合 rPr)
    if rPr_override:
        rPr = rPr_override
    else:
        rPr_match = re.search(r'<a:rPr(?:\s[^>]*)*/>', old_para)
        if not rPr_match:
            rPr_match = re.search(r'<a:rPr.*?</a:rPr>', old_para, re.DOTALL)
        rPr = rPr_match.group() if rPr_match else '<a:rPr/>'
    new_para = f'<a:p>{pPr}<a:r>{rPr}<a:t>{new_text}</a:t></a:r></a:p>'
    return xml_str.replace(old_para, new_para, 1)

# 调用示例
xml = replace_para_containing(xml, '原始文本片段', '替换后的完整文本')
# 如果连 search_text 的定位符也找不到,说明文本被拆散更细,
# 此时需检查XML原文,找到任意未被拆散的子串作为 search_text

# =============================================
# 3. 验证XML有效性(替换后必做)
# =============================================
import xml.etree.ElementTree as ET
try:
    ET.fromstring(xml)
    print('✅ XML验证通过')
except ET.ParseError as e:
    print(f'❌ XML解析错误:{e}')
    # 定位错误行列,检查是否有未转义的特殊字符

# =============================================
# 4. 打包输出(保留原文件所有内容)
# =============================================
buf = io.BytesIO()
with zipfile.ZipFile(src, 'r') as zin:
    with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zout:
        for item in zin.infolist():
            if item.filename == 'ppt/slides/slide1.xml':
                zout.writestr(item, xml.encode('utf-8'))
            else:
                zout.writestr(item, zin.read(item.filename))

with open(out, 'wb') as f:
    f.write(buf.getvalue())
print(f'✅ 已生成:{out}')

调试技巧

查找文本在XML中的实际位置:

# 先解包查看原始XML结构
with zipfile.ZipFile(src, 'r') as z:
    xml = z.read('ppt/slides/slide1.xml').decode('utf-8')

# 搜索目标文本(注意:可能是片段,不是完整句子)
target = '要查找的文本'
idx = xml.find(target)
if idx >= 0:
    print(xml[max(0, idx-200):idx+200])  # 打印前后200字符上下文
else:
    # 中文被拆散时,尝试搜索其中一个汉字或标点
    print('未找到完整文本,尝试搜索子串')

判断应该用策略A还是B:

文本在XML中是连续的 <a:t>完整文本</a:t> → 用策略A(简单替换)
文本被拆散为多个 <a:r>...<a:t>片</a:t></a:r><a:r>...<a:t>段</a:t></a:r> → 用策略B(整段替换)

常见错误与解决

错误原因解决
PowerPoint无法读取文件打包基础文件不完整(缺media/theme等)必须用原版完整PPTX为基础,不能用手动解包目录
XML解析报错(column XXXX)替换文本含未转义的 < > &转义为 &lt; &gt; &amp;
替换未生效中文文本被拆散在多个 <a:r>改用 replace_para_containing() 整段替换
找不到 search_text数字/标点与汉字分开在不同 run搜索纯汉字或标点子串定位,再整段替换
slideMaster.xml.rels 为空解包时内容丢失(此问题仅在手动解包时出现)从原版PPTX直接操作,不会有此问题

变更日志

v1.5.0 (2026-03-27)

  • 修复 ClawHub 审查问题:新增 requires metadata 声明运行时依赖(npm:pptxgenjs, python:Pillow)
  • 新增完整脚本scripts/complex_shape.py 提供可直接执行的复杂形状 PNG 生成工具
  • 新增使用前须知:明确图片数据发送至外部 VLM 的隐私说明、文件系统读写说明、运行时依赖

v1.4.0 (2026-03-26)

  • VLM 调用方式升级:移除 minimax-understand-image 技能依赖,改为开放式 VLM 调用设计,默认 OpenClaw 内置 image 工具
  • 适配 MiniMax 作为模型提供商时的内置 Vision 能力

v1.3.0 (2026-03-26)

  • 新增"方案B:基于原版PPTX的内容替换(ZIP直接操作法)"
    • 明确方案A(从零生成)vs 方案B(原版替换)的选择原则
    • 提供完整的 Python zipfile 操作模板(只替换 slide1.xml,保留所有其他文件)
    • 提供两种替换策略:策略A(简单单Run替换)+ 策略B(整段 <a:p> 替换)
    • 提供 replace_para_containing() 通用函数,解决中文文本被拆散在多个 <a:r> 的问题
    • 提供调试技巧(XML上下文打印、策略A/B判断方法)
    • 提供常见错误排查表(文件损坏/XML解析报错/替换未生效等)
    • 总结关键注意事项:必须用完整原版PPTX、特殊字符必须转义等

v1.2.0 (2026-03-26)

  • 新增"复杂形状降级处理策略"(核心功能升级)
    • 明确7类需要降级的形状判断标准(custGeom/透明渐变/斜向渐变/特效/裁切等)
    • 提供完整的 Python/Pillow 绘制模板(含多边形 + 逐行渐变 + 透明背景)
    • 提供贝塞尔曲线采样函数(适配 XML cubicBezTo
    • 提供XML参数提取指南(路径坐标、渐变色、EMU角度转换、组合坐标变换)
    • 提供 addImage 嵌入代码模板
    • 补充仅有截图时的降级策略(VLM估算 + 多边形近似)
    • 区域类型映射表新增 complex_shape

v1.1.0 (2026-03-26)

  • 增强分析Prompt(短期优化P0方案)
  • 增加全角/半角符号校正 normalizeSymbols()
  • 增加bullet符号识别 detectBullet()
  • 增加行间距 lineSpacing 渲染支持
  • 增加字符间距 charSpacing 渲染支持
  • 增加圆角矩形 roundedRect 类型支持
  • 增加JSON解析4策略容错
  • 改进多行文本段落渲染

v1.0.0 (2026-03-26)

  • 初始版本,基于Images2Slides论文实现基本复刻流程

Comments

Loading comments...