之前实现了tif文件的融合,现在实现图片的融合,效果如下
第一张是融合右边两张图的结果
我的思路是:
这是index.html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
h1 {
position: absolute;
top: 0;
z-index: 99;
color: red;
}
</style>
</head>
<body>
<input id="checkSVGLabel" type="checkbox" name=""> 显隐标注
<br>
<!-- <img id="defaultImg" src="" alt=""> -->
<canvas id="canvas"></canvas>
<script type="text/javascript">
// const terrainImageUrl = 'http://192.168.10.159:5502/images/orz.png'; // 替换为你的地形图URL
const terrainImageUrl = 'http://192.168.10.159:5502/images/orz5.png'; // 替换为你的地形图URL
const maskImageUrl = 'http://192.168.10.159:5502/images/mask1.png'; // 替换为你的黑底白框图URL
// const terrainImageUrl = 'http://192.168.10.159:5502/images/orz3.jpg'; // 替换为你的地形图URL
// const maskImageUrl = 'http://192.168.10.159:5502/images/mask4.jpg'; // 替换为你的黑底白框图URL
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const checkSVGLabel = document.getElementById('checkSVGLabel');
// const defaultImg = document.getElementById('defaultImg');
let changeImgUrl = terrainImageUrl
let imageWorker = null
function handleMaskImg (e)
{
if (e.target.checked && imageWorker) {
mergeMaskImg(terrainImageUrl, maskImageUrl, 'mergeMask')
} else {
mergeMaskImg(terrainImageUrl, maskImageUrl)
}
}
// 融合色块
function mergeMaskImg (orz, mask, type)
{
if (type === 'mergeMask') {
imageWorker.postMessage({
orz,
mask,
type: 'creatMaskImg'
})
} else {
const image = new Image();
image.src = orz;
image.onload = function ()
{
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
}
}
}
function clearWorker ()
{
if (worker) {
worker.terminate()
}
worker = null
}
window.onload = function ()
{
mergeMaskImg(terrainImageUrl, maskImageUrl)
imageWorker = new Worker("../js/imageWorker.js")
imageWorker.onmessage = (e) =>
{
const { type } = e.data;
if (type === 'putMaskImg') {
// 读取影像
// defaultImg.src = e.data.dataUrl
// 使用画布
console.log(e)
const { imageBitmap, canvasWidth, canvasHeight } = e.data;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx.drawImage(imageBitmap, 0, 0, canvasWidth, canvasHeight);
}
}
}
checkSVGLabel.addEventListener('change', handleMaskImg);
</script>
</body>
</html>
这是worker代码
self.addEventListener('message', async ({ data }) => {
if (data.type === 'creatMaskImg') {
let { orz, mask } = data
// 加载地形图和蒙版图像
const [terrainImage, maskImage] = await Promise.all([
loadImageBitmap(orz),
loadImageBitmap(mask)
])
const canvasWidth = terrainImage.width
const canvasHeight = terrainImage.height
const offscreenCanvas = new OffscreenCanvas(canvasWidth, canvasHeight)
const ctx = offscreenCanvas.getContext('2d')
// 绘制地形图
ctx.drawImage(terrainImage, 0, 0, canvasWidth, canvasHeight)
// 创建一个临时canvas来处理蒙版
const tempCanvas = new OffscreenCanvas(
maskImage.width,
maskImage.height
)
const tempCtx = tempCanvas.getContext('2d')
// 将黑底白框图绘制到临时canvas
tempCtx.drawImage(maskImage, 0, 0)
// 获取图像数据
const maskImageData = tempCtx.getImageData(
0,
0,
tempCanvas.width,
tempCanvas.height
)
const imgData = maskImageData.data
for (let i = 0; i < imgData.length; i += 4) {
// 获取当前像素的RGB值
const red = imgData[i]
const green = imgData[i + 1]
const blue = imgData[i + 2]
if (red === 0 && green === 0 && blue === 0) {
imgData[i + 3] = 0 // 透明度设置为0
} else {
if (red === 255 && green === 255 && blue === 255) {
// 黑色
// imgData[i] = 0
// imgData[i + 1] = 0
// imgData[i + 2] = 0
// 紫色
imgData[i] = 254
imgData[i + 1] = 0
imgData[i + 2] = 255
imgData[i + 3] = imgData[i + 3] * 0.5
// 透明图
// imgData[i] = null
// imgData[i + 1] = null
// imgData[i + 2] = null
}
}
}
// 将处理后的蒙版图像数据放回临时canvas
tempCtx.putImageData(maskImageData, 0, 0)
// 将临时canvas上的蒙版绘制到地形图上
ctx.drawImage(tempCanvas, 0, 0, canvasWidth, canvasHeight)
// ----------------- 传blob图像数据
// 将处理后的 offscreenCanvas 转换为 Blob
// const blob = await offscreenCanvas.convertToBlob()
// const dataUrl = await blobToDataURL(blob)
// self.postMessage({
// dataUrl,
// canvasWidth,
// canvasHeight,
// type: 'putMaskImg'
// })
// ----------------- 传canvas数据
// 将处理后的 offscreenCanvas 转换为 ImageBitmap 并返回到主线程
const imageBitmap = offscreenCanvas.transferToImageBitmap()
self.postMessage(
{ imageBitmap, canvasWidth, canvasHeight, type: 'putMaskImg' },
[imageBitmap]
)
}
})
async function loadImageBitmap(url) {
const response = await fetch(url)
const blob = await response.blob()
return createImageBitmap(blob)
}
function blobToDataURL(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(blob)
})
}
在worker中其实还可以将mask图片的黑色区域进行转换,也可以设置透明值,非常方便,如果不需要复杂的颜色处理,在处理后还可以结合mask-image去实现蒙版效果。