云计算百科
云计算领域专业知识百科平台

Python上传图片后自动将其处理成像素方块风格

这是一个HTML代码,上传图片后自动将其处理成像素方块风格,并支持调整方块大小和下载结果。

 

```html

<!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>

  * { box-sizing: border-box; }

  body {

    margin: 0; min-height: 100vh; padding: 24px;

    font-family: system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;

    background: #14161a; color: #e8eaed;

    display: flex; flex-direction: column; align-items: center; gap: 18px;

  }

  .panel {

    display: flex; flex-wrap: wrap; gap: 16px; align-items: center; justify-content: center;

    background: #1e2128; padding: 14px 18px; border-radius: 14px;

    box-shadow: 0 6px 24px rgba(0,0,0,.35);

  }

  label { display: flex; align-items: center; gap: 8px; font-size: 14px; }

  input[type="range"] { width: 160px; accent-color: #4f9cff; }

  button, .file-btn {

    border: none; border-radius: 9px; padding: 9px 16px; font-size: 14px;

    background: #4f9cff; color: #fff; cursor: pointer; transition: .2s;

  }

  button:hover, .file-btn:hover { background: #3a86e8; }

  button:disabled { opacity: .4; cursor: not-allowed; }

  #file { display: none; }

  #stage {

    max-width: 100%; display: flex; align-items: center; justify-content: center;

    border: 2px dashed #333842; border-radius: 16px; padding: 16px; min-height: 220px;

    width: min(1000px, 100%);

  }

  #stage.dragover { border-color: #4f9cff; background: rgba(79,156,255,.08); }

  canvas { max-width: 100%; height: auto; display: block; image-rendering: pixelated; }

  .hint { color: #7c8493; font-size: 13px; }

  .value { width: 34px; text-align: right; color: #4f9cff; font-variant-numeric: tabular-nums; }

</style>

</head>

<body>

 

  <div class="panel">

    <label class="file-btn">

      选择图片

      <input type="file" id="file" accept="image/*">

    </label>

 

    <label>

      方块大小

      <input type="range" id="size" min="2" max="64" value="12">

      <span class="value" id="sizeVal">12</span>

    </label>

 

    <button id="download" disabled>下载 PNG</button>

  </div>

 

  <div id="stage">

    <p class="hint">点击「选择图片」,或把图片拖到这里 / 直接 Ctrl+V 粘贴</p>

  </div>

 

<script>

/* ========== 元素引用 ========== */

const fileInput = document.getElementById('file');

const sizeInput = document.getElementById('size');

const sizeVal = document.getElementById('sizeVal');

const stage = document.getElementById('stage');

const downloadBtn= document.getElementById('download');

 

let canvas = null; // 输出画布

let ctx = null;

let sourceImg = null; // 原始图片对象

 

/* ========== 读取文件 ========== */

function loadFile(file) {

  if (!file || !file.type.startsWith('image/')) return;

  const url = URL.createObjectURL(file);

  const img = new Image();

  img.onload = () => {

    sourceImg = img;

    URL.revokeObjectURL(url);

    render();

    downloadBtn.disabled = false;

  };

  img.onerror = () => alert('图片读取失败,请换一张试试');

  img.src = url;

}

 

/* ========== 高质量缩小(逐级减半,保证取到准确的平均色) ========== */

function downscale(src, srcW, srcH, dstW, dstH) {

  // 先把原图画到临时画布

  let cur = document.createElement('canvas');

  cur.width = srcW; cur.height = srcH;

  cur.getContext('2d').drawImage(src, 0, 0);

 

  let cw = srcW, ch = srcH;

 

  // 每次缩小一半,直到接近目标尺寸,避免一次性大幅缩放产生锯齿/偏色

  while (cw / 2 >= dstW && ch / 2 >= dstH && cw > 2 && ch > 2) {

    const nw = Math.max(1, Math.floor(cw / 2));

    const nh = Math.max(1, Math.floor(ch / 2));

    const next = document.createElement('canvas');

    next.width = nw; next.height = nh;

    const nctx = next.getContext('2d');

    nctx.imageSmoothingEnabled = true;

    nctx.imageSmoothingQuality = 'high';

    nctx.drawImage(cur, 0, 0, cw, ch, 0, 0, nw, nh);

    cur = next; cw = nw; ch = nh;

  }

 

  // 最后一步缩到目标尺寸

  const out = document.createElement('canvas');

  out.width = dstW; out.height = dstH;

  const octx = out.getContext('2d');

  octx.imageSmoothingEnabled = true;

  octx.imageSmoothingQuality = 'high';

  octx.drawImage(cur, 0, 0, cw, ch, 0, 0, dstW, dstH);

  return out;

}

 

/* ========== 核心:渲染像素方块图 ========== */

function render() {

  if (!sourceImg) return;

 

  const block = Number(sizeInput.value); // 每个方块边长(像素)

  const W = sourceImg.naturalWidth;

  const H = sourceImg.naturalHeight;

 

  // 1. 计算缩略图尺寸:原图被切成多少个小格子

  const cols = Math.max(1, Math.round(W / block));

  const rows = Math.max(1, Math.round(H / block));

 

  // 2. 缩小成 cols × rows 的小图,每个像素 = 一个方块的平均色

  const small = downscale(sourceImg, W, H, cols, rows);

  const smallData = small.getContext('2d').getImageData(0, 0, cols, rows).data;

 

  // 3. 准备输出画布

  if (!canvas) {

    canvas = document.createElement('canvas');

    ctx = canvas.getContext('2d');

    stage.innerHTML = '';

    stage.appendChild(canvas);

  }

 

  const outW = cols * block;

  const outH = rows * block;

  canvas.width = outW;

  canvas.height = outH;

  ctx.imageSmoothingEnabled = false; // 关掉平滑,保证方块边缘硬朗

  ctx.clearRect(0, 0, outW, outH);

 

  // 4. 逐格铺纯色方块(比直接放大更锐利,不会有插值杂色)

  for (let y = 0; y < rows; y++) {

    for (let x = 0; x < cols; x++) {

      const i = (y * cols + x) * 4;

      const a = smallData[i + 3];

      if (a === 0) continue; // 全透明格子跳过

      ctx.fillStyle = `rgba(${smallData[i]},${smallData[i+1]},${smallData[i+2]},${a / 255})`;

      ctx.fillRect(x * block, y * block, block, block);

    }

  }

}

 

/* ========== 交互事件 ========== */

fileInput.addEventListener('change', e => loadFile(e.target.files[0]));

 

sizeInput.addEventListener('input', () => {

  sizeVal.textContent = sizeInput.value;

  render();

});

 

downloadBtn.addEventListener('click', () => {

  if (!canvas) return;

  const a = document.createElement('a');

  a.download = `pixel-${sizeInput.value}px.png`;

  a.href = canvas.toDataURL('image/png');

  a.click();

});

 

/* 拖拽上传 */

['dragenter', 'dragover'].forEach(ev =>

  stage.addEventListener(ev, e => { e.preventDefault(); stage.classList.add('dragover'); })

);

['dragleave', 'drop'].forEach(ev =>

  stage.addEventListener(ev, e => { e.preventDefault(); stage.classList.remove('dragover'); })

);

stage.addEventListener('drop', e => loadFile(e.dataTransfer.files[0]));

 

/* 粘贴上传 */

document.addEventListener('paste', e => {

  const item = […(e.clipboardData?.items || [])].find(i => i.type.startsWith('image/'));

  if (item) loadFile(item.getAsFile());

});

</script>

</body>

</html>

```

 

像素方块化工具的功能拆解

 

· 图片上传入口:页面提供“选择图片”按钮,同时支持拖拽图片到虚线区域,或直接使用 Ctrl+V 粘贴图片。

· 方块大小调节:通过滑块控制每个像素方块的边长(2~64像素),拖动时右侧数值会同步变化,并即时重新渲染预览。

· 像素化渲染逻辑:先算出原图会被切成多少行、多少列,再将原图高质量缩小到对应的小尺寸,最后逐个方块填充纯色,保证边缘硬朗清晰。

· 结果导出:点击“下载 PNG”按钮,会将当前画布内容保存为 pixel-xxpx.png,方便直接使用。

 

—

 

优化建议: 若想改变默认方块大小,可调整滑块初始值(当前为12);最大、最小值由 min="2" 和 max="64" 控制,您可按需修改。

 

 

 

 

文章仅供参考学习用。

赞(0)
未经允许不得转载:网硕互联帮助中心 » Python上传图片后自动将其处理成像素方块风格
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!