如何在Deno/TypeScript生成的JPEG图片上添加尺寸标记?
在生成的图片上添加尺寸标记的方案(基于你的Deno/TypeScript代码)
由于你当前使用的jpegts库仅提供基础JPEG编码功能,没有内置文本渲染API,我们需要通过手动操作像素数组的方式绘制尺寸标记。下面是修改后的完整代码,实现了在图片右下角添加W×H格式的尺寸文本:
// Import jpeg encoder import { encode as pixelsToBin } from "https://deno.land/x/jpegts@1.1/mod.ts"; // Import std base64 encoder import { encode as binTob64 } from "https://deno.land/std/encoding/base64.ts"; // Material Design Colors | Range 500 const COLORS = { RED: "#f44336", GREEN: "#4caf50", BLUE: "#2196f3", }; // 简单的8x8单色字体:仅包含数字和×符号 const FONT_8X8 = { '0': [0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x63, 0x3E, 0x00], '1': [0x1C, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00], '2': [0x3E, 0x63, 0x03, 0x1E, 0x60, 0x63, 0x3F, 0x00], '3': [0x3E, 0x63, 0x03, 0x1E, 0x03, 0x63, 0x3E, 0x00], '4': [0x06, 0x0E, 0x16, 0x36, 0x7F, 0x06, 0x06, 0x00], '5': [0x3F, 0x60, 0x60, 0x3E, 0x03, 0x63, 0x3E, 0x00], '6': [0x3E, 0x63, 0x60, 0x3E, 0x63, 0x63, 0x3E, 0x00], '7': [0x3F, 0x03, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x00], '8': [0x3E, 0x63, 0x63, 0x3E, 0x63, 0x63, 0x3E, 0x00], '9': [0x3E, 0x63, 0x63, 0x3F, 0x03, 0x03, 0x3E, 0x00], '×': [0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00], }; // Convert HEX color to RGB color function hexToRgb(cHex: string): [number, number, number] { const r = parseInt(cHex.slice(1, 3), 16); const g = parseInt(cHex.slice(3, 5), 16); const b = parseInt(cHex.slice(5, 7), 16); return [r, g, b]; } // 在像素数组中绘制8x8字体的文本 function drawText( pixels: number[], width: number, height: number, text: string, textColor: [number, number, number], x: number, y: number ) { // 遍历每个字符 for (let charIndex = 0; charIndex < text.length; charIndex++) { const char = text[charIndex]; const charData = FONT_8X8[char]; if (!charData) continue; // 遍历字符的每个像素行 for (let row = 0; row < 8; row++) { const rowData = charData[row]; // 遍历行内的每个像素 for (let col = 0; col < 8; col++) { // 判断当前像素是否需要绘制(字体数据中对应位为1) if (rowData & (1 << (7 - col))) { const pixelPos = ((y + row) * width + (x + charIndex * 8 + col)) * 4; // 确保像素位置在图片范围内 if (pixelPos + 3 < pixels.length) { pixels[pixelPos] = textColor[0]; // R pixels[pixelPos + 1] = textColor[1]; // G pixels[pixelPos + 2] = textColor[2]; // B pixels[pixelPos + 3] = 1; // Alpha(JPEG忽略) } } } } } } async function saveJpeg(w: number, h: number, cHex: string, fileName: string) { const jpegWidth = w; const jpegHeight = h; const jpegArea = jpegWidth * jpegHeight; const bgColor = hexToRgb(cHex); // 文本用白色,和深色背景对比明显;如果背景是浅色,可改成黑色[0,0,0] const textColor: [number, number, number] = [255, 255, 255]; // 初始化背景像素数组 let jpegPixels: number[] = []; for (let i = 0; i < jpegArea; i++) { jpegPixels.push(bgColor[0]); jpegPixels.push(bgColor[1]); jpegPixels.push(bgColor[2]); jpegPixels.push(1); } // 绘制尺寸文本到右下角,预留10像素边距 const text = `${w}×${h}`; const textX = jpegWidth - text.length * 8 - 10; const textY = jpegHeight - 8 - 10; drawText(jpegPixels, jpegWidth, jpegHeight, text, textColor, textX, textY); // 编码并保存图片 const jpegImage = { width: jpegWidth, height: jpegHeight, data: new Uint8Array(jpegPixels) }; const jpegRaw = pixelsToBin(jpegImage, 100); await Deno.writeFile(`${fileName}.jpg`, jpegRaw.data); } // 示例调用 await saveJpeg(640, 360, COLORS.RED, "red-500"); await saveJpeg(640, 360, COLORS.GREEN, "green-500"); await saveJpeg(640, 360, COLORS.BLUE, "blue-500");
关键说明
- 字体定义:用8x8二进制数据定义了数字和
×符号的像素图案,每个字节代表一行的像素状态 - 文本绘制逻辑:
drawText函数遍历文本字符,将字体像素数据覆盖到背景像素数组的对应位置 - 位置控制:尺寸文本固定绘制在右下角,通过计算预留10像素边距,避免超出图片范围
- 颜色适配:默认用白色文本,若使用浅色背景,直接修改
textColor为黑色即可保证可读性
内容的提问来源于stack exchange,提问作者suchislife801
相关产品推荐
相关产品推荐

