You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

图片马赛克工具技术咨询:尺寸调整、错误排查及缩放设置

问题与解决方案

用户问题

  1. 若上传的图片尺寸过大,请问应在何处插入标签进行调整?是否可使用style标签修改?此外,点击create按钮后生成的图片出现错误,烦请排查代码问题。
  2. 插入图片并点击“Create”后,希望缩小生成图片的比例,请问需修改代码的哪部分?是否还有其他需调整的内容?

相关代码

JavaScript

var TILE_WIDTH = 5;
var TILE_HEIGHT = 5;

document.getElementById("input").onchange = function() {
  var reader = new FileReader();
  reader.onload = function(e) {
    // get loaded data and render thumbnail.
    document.getElementById("image").src = e.target.result;
  };
  // read the image file as a data URL.
  reader.readAsDataURL(this.files[0]);
};

// first function call to create photomosaic 
function photomosaic(image) {

  // Dimensions of each tile
  var tileWidth = TILE_WIDTH;
  var tileHeight = TILE_HEIGHT;

  //creating the canvas for photomosaic
  var canvas = document.createElement('canvas');
  var context = canvas.getContext("2d");
  canvas.height = image.height;
  canvas.width = image.width;

  var imageData = context.getImageData(0, 0, image.width, image.height);
  var pixels = imageData.data;

  // Number of mosaic tiles
  var numTileRows = image.width / tileWidth;
  var numTileCols = image.height / tileHeight;


  //canvas copy of image
  var imageCanvas = document.createElement('canvas');
  var imageCanvasContext = canvas.getContext('2d');
  imageCanvas.height = image.height;
  imageCanvas.width = image.width;
  imageCanvasContext.drawImage(image, 0, 0);


  //function for finding the average color
  function averageColor(row, column) {
    var blockSize = 1, // we can set how many pixels to skip

      data, width, height,
      i = -4,
      length,
      rgb = {
        r: 0,
        g: 0,
        b: 0
      },
      count = 0;

    try {
      data = imageCanvasContext.getImageData(column * TILE_WIDTH, row * TILE_HEIGHT, TILE_HEIGHT, TILE_WIDTH);
    } catch (e) {
      alert('Not happening this time!');
      return rgb;
    }

    length = data.data.length;

    while ((i += blockSize * 4) < length) {
      ++count;
      rgb.r += data.data[i];
      rgb.g += data.data[i + 1];
      rgb.b += data.data[i + 2];
    }

    // ~~ used to floor values
    rgb.r = ~~(rgb.r / count);
    rgb.g = ~~(rgb.g / count);
    rgb.b = ~~(rgb.b / count);

    return rgb;

  }

  // Loop through each tile
  for (var r = 0; r < numTileRows; r++) {
    for (var c = 0; c < numTileCols; c++) {
      // Set the pixel values for each tile
      var rgb = averageColor(r, c)
      var red = rgb.r;
      var green = rgb.g;
      var blue = rgb.b;

      // Loop through each tile pixel
      for (var tr = 0; tr < tileHeight; tr++) {
        for (var tc = 0; tc < tileWidth; tc++) {

          // Calculate the true position of the tile pixel
          var trueRow = (r * tileHeight) + tr;
          var trueCol = (c * tileWidth) + tc;

          // Calculate the position of the current pixel in the array
          var pos = (trueRow * (imageData.width * 4)) + (trueCol * 4);

          // Assign the colour to each pixel
          pixels[pos + 0] = red;
          pixels[pos + 1] = green;
          pixels[pos + 2] = blue;
          pixels[pos + 3] = 255;
        };
      };
    };
  };

  // Draw image data to the canvas
  context.putImageData(imageData, 0, 0);
  return canvas;
}

function create() {
  var image = document.getElementById('image');
  var canvas = photomosaic(image);
  document.getElementById("output").appendChild(canvas);
};

CSS

#output,
.container {
  text-align: center;
}

.inputDiv {
  margin: 20px 0px;
}

HTML

<div class="container">
  <img id="image" src="https://via.placeholder.com/100" />
  
  <div class="inputDiv">
    <input id="input" type="file" accept="image/*">
    <button onclick="create()">create</button>
  </div>
  <div id='output'></div>
</div>

解决方案

问题1解答

图片尺寸调整

  • 可以直接通过style标签修改上传预览图的显示尺寸,比如给<img id="image">添加内联样式:
    <img id="image" src="https://via.placeholder.com/100" style="max-width: 500px; max-height: 500px;" />
    
  • 或者在CSS中统一控制:
    #image {
      max-width: 100%;
      max-height: 500px;
      object-fit: contain;
    }
    
  • 生成的马赛克画布也可以通过CSS限制显示大小,避免页面溢出:
    #output canvas {
      max-width: 100%;
      height: auto;
    }
    

代码错误排查

原代码存在3处关键错误:

  1. imageCanvas上下文指向错误:
    原代码中var imageCanvasContext = canvas.getContext('2d');应该改为var imageCanvasContext = imageCanvas.getContext('2d');,否则会复用主画布的上下文,导致获取不到上传图片的像素数据。
  2. 行列计算颠倒:
    numTileRows(行数)应该基于图片高度计算,numTileCols(列数)基于宽度计算,原代码写反了,修正后:
    var numTileRows = image.height / tileHeight;
    var numTileCols = image.width / tileWidth;
    
  3. getImageData参数顺序错误:
    getImageData的参数是x, y, width, height,原代码中把宽高顺序写反了,修正后:
    data = imageCanvasContext.getImageData(column * tileWidth, row * tileHeight, tileWidth, tileHeight);
    

问题2解答

缩小生成图片比例

可以通过添加缩放因子来调整生成画布的尺寸,修改步骤如下:

  1. 定义缩放因子:在photomosaic函数开头添加缩放比例,比如var scaleFactor = 0.5;(表示缩小到原尺寸的50%)。
  2. 调整画布尺寸:
    var canvas = document.createElement('canvas');
    var context = canvas.getContext("2d");
    canvas.height = image.height * scaleFactor;
    canvas.width = image.width * scaleFactor;
    
  3. 调整图片副本画布的尺寸与绘制:
    var imageCanvas = document.createElement('canvas');
    var imageCanvasContext = imageCanvas.getContext('2d');
    imageCanvas.height = image.height * scaleFactor;
    imageCanvas.width = image.width * scaleFactor;
    imageCanvasContext.drawImage(image, 0, 0, imageCanvas.width, imageCanvas.height);
    
  4. 调整像素数据与循环计算:
    由于画布尺寸缩放,getImageData和循环中的行列计算要基于缩放后的尺寸,修正imageData和行列数:
    var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
    var numTileRows = canvas.height / tileHeight;
    var numTileCols = canvas.width / tileWidth;
    
  5. 可选:同步调整预览图尺寸:如果需要让预览图和生成图尺寸匹配,也可以给<img id="image">添加对应缩放样式。

内容的提问来源于stack exchange,提问作者semi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:30:51