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 = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片颜色分析报告</title>
  <style>
    body {
      font-family: 'Arial', sans-serif;
      line-height: 1.6;
      color: #333;
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px;
    }
    h1, h2 {
      color: #2c3e50;
    }
    .image-container {
      display: flex;
      justify-content: space-between;
      margin-bottom: 30px;
      flex-wrap: wrap;
    }
    .image-box {
      width: 48%;
      margin-bottom: 20px;
    }
    .image-box img {
      max-width: 100%;
      height: auto;
      border: 1px solid #ddd;
    }
    .color-cards {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin-top: 20px;
    }
    .color-card {
      width: 100px;
      height: 100px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      border-radius: 5px;
      color: white;
      text-shadow: 0 0 2px #000;
      font-size: 12px;
      position: relative;
    }
    .color-info {
      background: rgba(0,0,0,0.7);
      padding: 3px 6px;
      border-radius: 3px;
    }
    .color-distribution {
      margin-top: 30px;
    }
    .color-bar {
      height: 30px;
      margin: 5px 0;
      display: flex;
    }
    .color-bar-segment {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      text-shadow: 0 0 2px #000;
      font-size: 12px;
    }
  </style>
</head>
<body>
  <h1>图片颜色分析报告</h1>
  
  <div class="image-container">
    <div class="image-box">
      <h2>原始图片</h2>
      <img src="参考图.png" alt="原始图片">
    </div>
    <div class="image-box">
      <h2>马赛克图片</h2>
      <img src="mosaic.png" alt="马赛克图片">
    </div>
  </div>
  
  <h2>颜色分布</h2>
  <p>从马赛克图中提取的主要颜色（按出现频率排序）：</p>
  
  <div class="color-cards">
    ${colorData.slice(0, 20).map((item, index) => `
      <div class="color-card" style="background-color: ${item.color}">
        <div class="color-info">
          ${item.color}<br>
          频率: ${((item.count / colorData.reduce((sum, c) => sum + c.count, 0)) * 100).toFixed(1)}%
        </div>
      </div>
    `).join('')}
  </div>
  
  <div class="color-distribution">
    <h2>颜色频率分布图</h2>
    <div class="color-bar">
      ${colorData.slice(0, 10).map(item => {
        const percentage = (item.count / colorData.reduce((sum, c) => sum + c.count, 0)) * 100;
        return `<div class="color-bar-segment" style="background-color: ${item.color}; width: ${percentage}%;">${percentage.toFixed(1)}%</div>`;
      }).join('')}
    </div>
  </div>
</body>
</html>
  `;
  
  // 写入HTML文件
  await fs.promises.writeFile(CONFIG.outputReport, htmlContent);
}

// 运行主函数
main();