我有一张大约8000x4000像素的图像.这张照片被分解成几个彩色斑点.

以下是部分图像的示例,以显示其外观:

an example of a section of image

我可以非常简单地使用传单来绘制图像:

var map = L.map('map', {
    crs: L.CRS.Simple,
    minZoom: -2
});

var bounds = [[0,0], [3616,8192]];

var provinces = L.imageOverlay(
    'myimage.png', 
    bounds, 
    {opacity: 0.7}
).addTo(map);

我有一个为图像重新着色的翻译,我想使用它来将特定 colored颜色 的所有像素转换为不同的特定 colored颜色 的像素.这就是我需要帮助解决的问题.

var colour_mapping = {'#4287f5':'#42f5ef', '#a3911c':'#de3510', ...}

我看过关于堆栈溢出的答案,详细说明了如何更改画布的特定像素,但我不知道如何在宣传单中实现最佳效果.

How would I replace all pixels of a specific RGB in a PNG with another RGB in javascript?

推荐答案

因为您已经认为自己能够‘在运行中’操作图像,所以您必须首先将其绘制到html <canvas>元素上.另一方面,Leaflet的imageOverlay()方法需要一个指向实际图像的URL--因此,仅靠操纵画布不会给您带来太大帮助.

但还是有希望的.canvas对象提供了一个名为toDataURL()的方法,它返回一些可以输入到imageOverlay()中的内容.

让我们分解一下你必须做的事情:

  1. 创建一个空Image并使用它加载 map
  2. 如果图像加载完成,则创建一个图像大小的画布
  3. 将图像绘制到画布上
  4. 循环通过ctx.getImageData()获得的画布的图像数据.这将为画布中的每个像素返回一个由红色、绿色、蓝色和Alpha值组成的大型array.由于您的colour_mapping对象由十六进制值组成,例如#4dc8c8,我们首先需要将RGB值转换为十六进制,以便能够在对象中查找匹配项.如果找到匹配项,则获取替换 colored颜色 并将十六进制值转换为RGB以最终更改 colored颜色 .
  5. 将处理后的图像数据绘制到画布上.
  6. 使用toDataURL()获取数据URL,最后呼叫imageOverlay().

下面是一个用白色替换两种 colored颜色 的示例:

var map = L.map('map').setView([0.5, 0.5], 9);


var imageUrl = './js/UAZyt.png';
imageUrl = "https://corsproxy.io/?https://i.stack.imgur.com/UAZyt.png"
let image = new Image();
image.crossOrigin = "anonymous"
image.onload = (e) => {
  imageBounds = [
    [0, 0],
    [1, 1]
  ];

  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  canvas.width = e.target.naturalWidth;
  canvas.height = e.target.naturalHeight;
  ctx.drawImage(e.target, 0, 0);
  let colour_mapping = {
    '#4dc8c8': '#ffffff',
    '#be8eff': '#ffffff'
  };

  let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  let r, g, b, hex, hex2;
  for (let a = 0; a < imageData.data.length; a += 4) {
    r = imageData.data[a];
    g = imageData.data[a + 1];
    b = imageData.data[a + 2];
    hex = "#" + ((r << 16) | (g << 8) | b).toString(16);
    if (colour_mapping[hex]) {
      hex2 = colour_mapping[hex].match(/[0-9a-f]{2}/g);
      imageData.data[a] = parseInt(hex2[0], 16);
      imageData.data[a + 1] = parseInt(hex2[1], 16);
      imageData.data[a + 2] = parseInt(hex2[2], 16);
    }
  }
  ctx.putImageData(imageData, 0, 0);
  L.imageOverlay(canvas.toDataURL(), imageBounds).addTo(map);
}
image.src = imageUrl;
#map {
  height: 360px;
}
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<div id="map"></div>

Javascript相关问答推荐

我应该在redux reducer中调用其他reducer函数吗?

警告!合同执行期间遇到错误[执行已恢复](Base Layer 2)

没有输出到带有chrome.Devtools扩展的控制台

IMDB使用 puppeteer 加载更多按钮(nodejs)

字节数组通过echo框架传输到JS blob

调用removeEvents不起作用

仅针对RTK查询中的未经授权的错误取消maxRetries

在拖放时阻止文件打开

无法读取未定义错误的属性路径名''

从包含数百行的表中获取更改后的值(以表单形式发送到后端)的正确方法是什么?

我在Django中的视图中遇到多值键错误

material UI按钮组样式props 不反射

JavaScript不重定向配置的PATH

邮箱密码重置链接不适用于已部署的React应用程序

Vaadin定制组件-保持对javascrip变量的访问

自定义确认组件未在vue.js的v菜单内打开

ComponentWillReceiveProps仍在React 18.2.0中工作

扩散运算符未按预期工作,引发语法错误

MAT-TREE更多文本边框对齐问题

:host::ng-Deep不将样式应用于material 复选框