Skip to content

Instantly share code, notes, and snippets.

@onsummer
Last active September 19, 2023 13:43
Show Gist options
  • Save onsummer/f744612359f82ecd90ca12fc20e281e8 to your computer and use it in GitHub Desktop.
Save onsummer/f744612359f82ecd90ca12fc20e281e8 to your computer and use it in GitHub Desktop.
Canvas2D RGBA-TypeArray ImageBitmap ImageData
function appendTextureViewCanvas(id) {
const root = viewer.container.parentNode;
const cesiumCanvas = viewer.canvas;
const canvas = document.createElement('canvas');
canvas.id = id;
canvas.setAttribute('width', cesiumCanvas.clientWidth);
canvas.setAttribute('height', cesiumCanvas.clientHeight);
canvas.style.width = `${Math.floor(cesiumCanvas.clientWidth / 4)}px`;
canvas.style.height = `${Math.floor(cesiumCanvas.clientHeight / 4)}px`;
canvas.style.border = "1px solid red";
canvas.style.position = "absolute";
canvas.style.bottom = "80px";
canvas.style.right = "40px";
canvas.style.transform = "scaleY(-1)";
root.appendChild(canvas);
}
appendTextureViewCanvas('depth-board');
const scene = viewer.scene;
const cesiumContext = scene.context;
const picker = scene.picking;
const depthMapCanvas = document.getElementById('depth-board');
const ctx = depthMapCanvas.getContext('2d');
const scratchPackedDepth = new Cesium.Cartesian4();
const packedDepthScale = new Cesium.Cartesian4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0);
function decodeFloat32Value(r, g, b, a) {
const pixel = [r, g, b, a];
const packedDepth = Cesium.Cartesian4.unpack(pixel, 0, scratchPackedDepth);
Cesium.Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth);
return Cesium.Cartesian4.dot(packedDepth, packedDepthScale);
}
function decodeDepthPixels(pixels, w, h) {
const depthValues = [];
for (let i = 0; i < pixels.length; i+=4) {
const r = pixels[i];
const g = pixels[i + 1];
const b = pixels[i + 2];
const a = pixels[i + 3];
depthValues.push(decodeFloat32Value(r, g, b, a));
}
return depthValues;
}
// 进来的是单波段灰度值
async function drawPixels(pixels, w, h) {
ctx.clearRect(0, 0, w, h);
const grayMappingColor = [255, 255, 255];
const grayPixels = pixels.map((p) => {
const depthValue = Math.floor(255 * p);
return [...grayMappingColor, depthValue];
});
const grayPixelsFlat = new Uint8ClampedArray(grayPixels.flat());
const imageData = new window.ImageData(grayPixelsFlat, w, h);
const imageBitmap = await createImageBitmap(imageData, 0, 0, w, h);
ctx.drawImage(imageBitmap, 0, 0);
}
const drawDepthMapToCanvas = () => {
if (!scene.useDepthPicking) {
return undefined;
}
picker.update();
const pickDepth = picker.getPickDepth(scene, 0);
const drawHeight = scene.drawingBufferHeight;
const drawWidth = scene.drawingBufferWidth;
const fbo = pickDepth.framebuffer;
const start = performance.now();
const pixels = cesiumContext.readPixels({
x: 0,
y: 0,
width: drawWidth,
height: drawHeight,
framebuffer: fbo,
});
const depthValues = decodeDepthPixels(pixels, drawWidth, drawHeight);
drawPixels(depthValues, drawWidth, drawHeight).then(() => {
const end = performance.now();
console.log(((end - start) / 1000).toFixed(2) + 's');
});
};
Sandcastle.addToolbarButton("TestGetDepthMap", drawDepthMapToCanvas);
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RGBA Array DrawImage</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
div.container {
width: calc(100vw - 32px);
height: calc(100vh - 32px);
padding: 16px;
#board {
width: 400;
height: 300;
border: 2px solid rgb(158, 2, 255);
}
}
</style>
</head>
<body>
<div class="container">
<canvas id="board"></canvas>
</div>
<script>
const cvs = document.getElementById('board')
const ctx = cvs.getContext('2d')
const main = async () => {
const width = 400
const height = 300
const imageDataArray = new Uint8ClampedArray(4 * width * height)
for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {
imageDataArray[i * width * 4 + j * 4] = 240
imageDataArray[i * width * 4 + j * 4 + 1] = 182
imageDataArray[i * width * 4 + j * 4 + 2] = 49
imageDataArray[i * width * 4 + j * 4 + 3] = Math.floor(j * 255 / width)
}
}
const imageData = new ImageData(imageDataArray, width, height)
const imageBitmap = await createImageBitmap(imageData, 0, 0, width, height)
console.log(imageBitmap)
ctx.drawImage(imageBitmap, 0, 0)
}
main()
</script>
</body>
</html>
@onsummer
Copy link
Author

onsummer commented Sep 6, 2023

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment