[英]Fast way to resize ImageData in browser?
我有一個 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
經過一番擺弄之后,我找到了一個使用此答案作為起點的解決方案。 基本上,您可以將較大的畫布繪制到較小的畫布中,然后從中獲取 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);
這是一個代碼筆,它證明檢索到的圖像數據是原始畫布的縮小版本,而不僅僅是從中裁剪出來的。
如果要循環調整大小,請在調用 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);
});
試試這個,但它很慢......
/**
*
* @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;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.