将 imageData 渲染到新的 canvas

Rendering imageData to new canvas

我正在学习 George Francis 在教程中的一些初始示例之后的教程,他展示了如何使用图像数据创建随机布局。

我正在尝试找出如何从使用 paper.js 创建的 canvas 获取图像数据,因为我需要从 canvas 上的每个单独像素获取 rgb 值=]

Link to codepen

未知数:

目前我正在尝试以下操作:

// create a white rectangle the size of the view (not sure I need this but doing it so that there are both white and black pixels)
const bg = new paper.Path.Rectangle({
  position: [0,0],
  size: view.viewSize.multiply(2),
  fillColor: 'white'
})

// create a black rectangle smaller than the view size
const shape = new paper.Path.RegularPolygon({
  radius: view.viewSize.width * 0.4,
  fillColor: 'black',
  strokeColor: 'black',
  sides: 4,
  position: view.center
})

// So far so good shapes render as expected. Next put the shapes in a group
const group = new paper.Group([bg,shape])
// rasterise the group (thinking it needs to be rasterized to get the pixel data, but again , not sure?)
group.rasterize()
// iterate over each pixel on the canvas and get the image data
for(let x = 0; x < width; x++){
  for(let y = 0; y < height; y++){
    const { data } = view.context.getImageData(x,y,1,1)
    console.log(data)
  }
}

预期:要获得一个缓冲区数组,如果像素是白色,它将给我

Uint8ClampedArray(4) [0, 0, 0, 0, buffer: ArrayBuffer(4),
byteLength: 4, byteOffset: 0, length: 4]
0: 255
1: 255
2: 255
//(not sure if the fourth index represents (rgb'a')?
3: 255
buffer: 
ArrayBuffer(4)
byteLength: 4
byteOffset: 0
length: 4
Symbol(Symbol.toStringTag): (...)
[[Prototype]]: TypedArray

如果像素是黑色我应该得到

Uint8ClampedArray(4) [0, 0, 0, 0, buffer: ArrayBuffer(4),
    byteLength: 4, byteOffset: 0, length: 4]
    0: 0
    1: 0
    2: 0
    3: 0
    buffer: 
    ArrayBuffer(4)
    byteLength: 4
    byteOffset: 0
    length: 4
    Symbol(Symbol.toStringTag): (...)
    [[Prototype]]: TypedArray

即 255,255,255(白色)或 0,0,0(黑色)

相反,所有值都是 0,0,0?

我认为您的问题是在您获取图像数据时,您的场景尚未绘制到 canvas。
为了确保它被绘制,你只需要调用 view.update().

这是一个简单的 sketch 演示如何使用它。
请注意,如果您直接使用 Canvas API 来操作图像数据,则无需光栅化场景。但您也可以将其光栅化并利用 Paper.js 辅助方法,例如 raster.getPixel().

// Draw a white background (you effectively need it otherwise your default
// pixels will be black).
new Path.Rectangle({
    rectangle: view.bounds,
    fillColor: 'white'
});

// Draw a black rectangle covering most of the canvas.
new Path.Rectangle({
    rectangle: view.bounds.scale(0.9),
    fillColor: 'black'
});

// Make sure that the scene is drawn into the canvas.
view.update();

// Get the canvas image data.
const { width, height } = view.element;
const imageData = view.context.getImageData(0, 0, width, height);

// Loop over each pixel and store all the different colors to check that this works.
const colors = new Set();
const length = imageData.data.length;
for (let i = 0; i < length; i += 4) {
    const [r, g, b, a] = imageData.data.slice(i, i + 4);
    const color = JSON.stringify({ r, g, b, a });
    colors.add(color);
}
console.log('colors', [...colors]);