【问题标题】:Fast way to resize ImageData in browser?在浏览器中调整 ImageData 大小的快速方法?
【发布时间】:2019-03-25 15:09:38
【问题描述】:

我有一个 600 x 400 像素的画布,它返回一个数据长度为 960,000 (600*400*4) 的 ImageData。有没有办法将宽度和高度缩小 10 倍,我想得到一个数据长度为 9600 (60*40*4) 的 ImageData。

const canvas = document.getElementsByTagName("canvas")[0]
var ctx = canvas.getContext("2d");
const origImageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
origImageData
// => ImageData {data: Uint8ClampedArray(960000), width: 600, height: 400}
const smallImageData = downscale(origImageData, 60, 40);
smallImageData
// => ImageData {data: Uint8ClampedArray(9600), width: 60, height: 40}

我需要生成的 ImageData.data 数组以进行进一步操作。 这个方法会在循环中被调用,所以如果速度快就好了。

编辑 这是建议的方法,我不确定它是否正确:

var canvas2 = document.createElement('canvas');
canvas2.width = canvas.width/10;
canvas2.height = canvas.height/10;
var ctx2 = canvas2.getContext('2d');
// Step that I found confusing
// Is the new image data being created?
ctx2.putImageData(origImageData, 0, 0);
// Which image data I'm getting here resized or part of original ?
ctx2.getImageData(0,0,  canvas2.width, canvas2.height)

编辑 2 它似乎不起作用,小画布没有调整大小,但只是裁剪 https://codepen.io/bobiblazeski/full/drrQoB

【问题讨论】:

  • 你有没有做过任何研究试图自己找到解决方案?
  • 只使用生成的图像数据并将其绘制在较小的画布上? developer.mozilla.org/en-US/docs/Web/API/…
  • 不创建额外元素就不能直接转换吗?
  • @sean 该解决方案通常建议使用离屏画布,我不确定我得到的是新的 ImageData 还是旧图像数据的一部分。

标签: javascript html5-canvas


【解决方案1】:

经过一番折腾,我找到了一个以this 答案为起点的解决方案。基本上你可以将更大的画布绘制成更小的画布,然后从中获取 ImageData。

const bigCanvas = document.getElementById("big");
const bigContext = bigCanvas.getContext("2d");        
const smallContext = document.getElementById("small").getContext("2d");         
smallContext.scale(0.5, 0.5);
smallContext.drawImage(bigCanvas, 0, 0);        
const smallImageData = smallContext.getImageData(0, 0, bigCanvas.width, bigCanvas.height);

这是一个codepen,作为检索到的图像数据是缩小版本的证据 原始画布,而不仅仅是从中裁剪出来的。

如果要循环调整大小,请在调用 drawImage codepen 之前清除目标画布。

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const bigCanvas = document.getElementById("big");
const bigContext = bigCanvas.getContext("2d");
const smallCanvas = document.getElementById("small");
const smallContext = smallCanvas.getContext("2d"); 
const otherCanvas = document.getElementById("other");
const otherContext = otherCanvas.getContext("2d");

function getImage(i) {
    bigContext.clearRect(0, 0, bigCanvas.width, bigCanvas.height);
    bigContext.fillRect(((i+0)%5)*100,   0, 100, 100);
    bigContext.fillRect(((i+1)%5)*100, 100, 100, 100);
    bigContext.fillRect(((i+2)%5)*100, 200, 100, 100);    
    bigContext.fillRect(((i+3)%5)*100, 100, 100, 100);
    bigContext.fillRect(((i+4)%5)*100,   0, 100, 100);
    bigContext.fillRect(((i+0)%5)*100, 200, 100, 100);    

    smallContext.clearRect(0, 0, smallCanvas.width, smallCanvas.height);
    smallContext.drawImage(bigCanvas, 0, 0, smallCanvas.width, smallCanvas.height);
    const smallImageData = smallContext.getImageData(0,0, 
        bigCanvas.width, bigCanvas.height);

    otherContext.putImageData(smallImageData, 0, 0);
};

window.addEventListener("DOMContentLoaded", function() {
    var i = 0;
    setInterval(() => {
        console.log(i);
        getImage(i++);
    }, 3000);
});

【讨论】:

    【解决方案2】:

    试试这个 但它很慢......

    /**
     * 
     * @param {ImageData} originalImageData 
     * @param {Int32} targetWidth 
     * @param {Int32} targetHeight 
     */
    function scaleImageData(originalImageData, targetWidth, targetHeight) {
        const targetImageData = new ImageData(targetWidth, targetHeight);
        const h1 = originalImageData.height;
        const w1 = originalImageData.width;
        const h2 = targetImageData.height;
        const w2 = targetImageData.width;
        const kh = h1 / h2;
        const kw = w1 / w2;
        const cur_img1pixel_sum = new Int32Array(4);
        for (let i2 = 0; i2 < h2; i2 += 1) {
            for (let j2 = 0; j2 < w2; j2 += 1) {
                for (let i in cur_img1pixel_sum) cur_img1pixel_sum[i] = 0;
                let cur_img1pixel_n = 0;
                for (let i1 = Math.ceil(i2 * kh); i1 < (i2 + 1) * kh; i1 += 1) {
                    for (let j1 = Math.ceil(j2 * kw); j1 < (j2 + 1) * kw; j1 += 1) {
                        const cur_p1 = (i1 * w1 + j1) * 4;
                        for (let k = 0; k < 4; k += 1) {
                            cur_img1pixel_sum[k] += originalImageData.data[cur_p1 + k];
                        };
                        cur_img1pixel_n += 1;
                    };
                };
                const cur_p2 = (i2 * w2 + j2) * 4;
                for (let k = 0; k < 4; k += 1) {
                    targetImageData.data[cur_p2 + k] = cur_img1pixel_sum[k] / cur_img1pixel_n;
                };
            };
        };
        return targetImageData;
    };
    

    【讨论】:

      猜你喜欢
      • 2017-08-08
      • 2010-10-26
      • 2012-03-31
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多