const fs = require('fs'); const path = require('path'); const sharp = require('sharp'); // 配置 const CONFIG = { pixelSize: 100, // 马赛克块大小 inputImage: path.join(__dirname, '../参考图.png'), outputMosaic: path.join(__dirname, '../mosaic.png'), outputReport: path.join(__dirname, '../report.html') }; // 主函数 async function main() { try { console.log('开始处理图片...'); // 获取图片信息 const metadata = await sharp(CONFIG.inputImage).metadata(); const { width, height } = metadata; // 创建马赛克图片 console.log('创建马赛克图片...'); const mosaicBuffer = await createMosaic(CONFIG.inputImage, CONFIG.pixelSize); await fs.promises.writeFile(CONFIG.outputMosaic, mosaicBuffer); // 提取颜色 console.log('提取颜色信息...'); const colorData = await extractColors(mosaicBuffer, CONFIG.pixelSize, width, height); // 生成报告 console.log('生成HTML报告...'); await generateReport(colorData); console.log('处理完成! 报告已生成: ' + CONFIG.outputReport); } catch (error) { console.error('处理过程中出错:', error); } } // 创建马赛克图片 async function createMosaic(inputPath, pixelSize) { // 获取图片信息 const metadata = await sharp(inputPath).metadata(); const { width, height } = metadata; // 计算缩小后的尺寸 const smallWidth = Math.ceil(width / pixelSize); const smallHeight = Math.ceil(height / pixelSize); // 先缩小图片 const smallBuffer = await sharp(inputPath) .resize(smallWidth, smallHeight, { fit: 'fill' }) .toBuffer(); // 再放大回原尺寸 return sharp(smallBuffer) .resize(width, height, { fit: 'fill', kernel: 'nearest' }) .toBuffer(); } // 提取颜色并按频率排序 async function extractColors(imageBuffer, pixelSize, originalWidth, originalHeight) { // 计算缩小后的尺寸 const smallWidth = Math.ceil(originalWidth / pixelSize); const smallHeight = Math.ceil(originalHeight / pixelSize); // 缩小图片以获取马赛克块的颜色 const smallBuffer = await sharp(imageBuffer) .resize(smallWidth, smallHeight, { fit: 'fill' }) .raw() .toBuffer({ resolveWithObject: true }); const { data, info } = smallBuffer; const { width, height, channels } = info; // 颜色映射: 颜色值 -> 出现次数 const colorMap = new Map(); // 遍历像素 for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const idx = (y * width + x) * channels; const r = data[idx]; const g = data[idx + 1]; const b = data[idx + 2]; // 创建颜色键 const colorKey = `rgb(${r},${g},${b})`; // 更新颜色映射 if (colorMap.has(colorKey)) { colorMap.set(colorKey, colorMap.get(colorKey) + 1); } else { colorMap.set(colorKey, 1); } } } // 转换为数组并排序 const sortedColors = Array.from(colorMap.entries()) .map(([color, count]) => ({ color, count })) .sort((a, b) => b.count - a.count); return sortedColors; } // 生成HTML报告 async function generateReport(colorData) { // 创建HTML内容 const htmlContent = ` 图片颜色分析报告

图片颜色分析报告

原始图片

原始图片

马赛克图片

马赛克图片

颜色分布

从马赛克图中提取的主要颜色(按出现频率排序):

${colorData.slice(0, 20).map((item, index) => `
${item.color}
频率: ${((item.count / colorData.reduce((sum, c) => sum + c.count, 0)) * 100).toFixed(1)}%
`).join('')}

颜色频率分布图

${colorData.slice(0, 10).map(item => { const percentage = (item.count / colorData.reduce((sum, c) => sum + c.count, 0)) * 100; return `
${percentage.toFixed(1)}%
`; }).join('')}
`; // 写入HTML文件 await fs.promises.writeFile(CONFIG.outputReport, htmlContent); } // 运行主函数 main();