Typecho编辑器粘贴图片自动转换为JPG

问题背景

在使用Typecho后台编辑器(Markdown编辑器)写文章时,从剪贴板粘贴图片(例如截图、复制网页图片等),默认会保存为PNG格式。这会导致:

  1. 文件体积大:PNG是无损压缩,比JPG大很多
  2. 加载速度慢:大图片影响页面加载性能
  3. 存储浪费:占用宝贵的服务器空间

解决方案

通过修改 /admin/editor-js.php 文件中的剪贴板图片处理逻辑,实现了:

  • PNG图片粘贴时自动转换为JPG格式
  • 透明区域自动填充白色背景
  • 压缩质量设置为90%,保持较好画质
  • 文件后缀自动从 .png 改为 .jpg

代码修改

修改文件:/admin/editor-js.php

/**
 * 剪贴板图片粘贴处理
 * 
 * 功能说明:
 * - 监听编辑器的粘贴事件,处理从剪贴板粘贴的图片
 * - PNG图片自动转换为JPG格式,节省存储空间
 * - PNG透明区域自动填充白色背景
 * - 压缩质量设置为90%,保持较好画质
 * 
 * 技术实现:
 * 1. 使用 pastableTextarea 插件捕获 pasteImage 事件
 * 2. 通过 Canvas API 将 PNG 转换为 JPG
 * 3. fillRect 填充白色背景,因为 JPG 不支持透明
 * 4. toBlob 生成新的 JPG Blob 对象
 * 5. 修改文件后缀为 .jpg
 */
textarea.pastableTextarea().on("pasteImage", function (e, data) {
    var name = data.name ? data.name.replace(/[()[]*#!]/g, "") : (new Date()).toISOString().replace(/..+$/, "");
    
    // 检测是否为PNG格式图片
    if (data.blob.type === "image/png") {
        var canvas = document.createElement("canvas");
        var img = new Image();
        
        img.onload = function() {
            canvas.width = img.width;
            canvas.height = img.height;
            var ctx = canvas.getContext("2d");
            
            // 填充白色背景(PNG支持透明,JPG不支持)
            ctx.fillStyle = "#FFFFFF";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(img, 0, 0);
            
            // 转换为JPG格式,压缩质量90%
            canvas.toBlob(function(jpgBlob) {
                var jpgName = name.replace(/.png$/i, ".jpg");
                if (!jpgName.match(/.jpg$/i)) {
                    jpgName += ".jpg";
                }
                Typecho.uploadFile(new File([jpgBlob], jpgName), jpgName);
            }, "image/jpeg", 0.9);
        };
        img.src = URL.createObjectURL(data.blob);
    } else {
        // 非PNG图片保持原格式
        if (!name.match(/.[a-z0-9]{2,}$/i)) {
            var ext = data.blob.type.split("/").pop();
            name += "." + ext;
        }
        Typecho.uploadFile(new File([data.blob], name), name);
    }
});

实现原理

  1. 事件监听:使用 pastableTextarea 插件监听 pasteImage 事件
  2. 格式检测:通过 data.blob.type 判断是否为 image/png
  3. Canvas转换

    • 创建与原图相同尺寸的Canvas
    • 填充白色背景(处理透明区域)
    • 绘制原图
  4. 格式转换:使用 canvas.toBlob() 生成JPG格式
  5. 上传文件:调用 Typecho.uploadFile() 上传转换后的文件

效果对比

格式典型截图大小透明支持
PNG200KB-500KB
JPG50KB-150KB否(填充白色)

压缩率约 70-80%

适用场景

  • 截图粘贴
  • 网页图片复制
  • 其他PNG格式图片

GIF、WebP等非PNG格式保持原样上传,不受影响。


本文档记录于 2026-04-08

暂无评论