繁体   English   中英

如何使用浏览器端 javascript 将具有编码高度值的 32 位 RGB png 转换为 16 位 png?

[英]How do you convert a 32bit RGB png with encoded height values to 16 bit png using browser side javascript?

我正在尝试从 32 位 Rgb 编码高度值 png 创建一个 16 位高度图 png。

根据mapbox ,我可以使用此公式将其 png 像素值解码为以米为单位的高度值。 height = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1)

我不熟悉此类信息,并试图自己弄清楚,但我需要一些帮助。

我发现这个程序叫做image-js ,这个程序的文档在这里 注意我在浏览器中使用它而不是节点。

我认为它具有我需要的能力。 但是,我真的不确定如何从原始图像中获取数据并使用根据上述公式计算出的新高度值创建一个新的 16 位 png。

如果您查看图像下的文档,我可以设置许多属性,例如

bitDepth 并将其设置为 16

getPixelsArray() 这个 function 将以 r,g,b 的形式给我一个像素值数组。 我想我可以通过上面的公式运行每个像素来获得高度。 之后如何将此高度数据转回 16 位灰度高度图 png?

谢谢!

示例图像。 32bit Rgb编码高度值png 在此处输入图像描述

16 位高度图 png. 您必须放大才能看到图像变化在此处输入图像描述

更新:

感谢拖拉机的建议。 我想在我的问题中添加一些信息。

我不一定需要使用 image-js。 我的主要目标是从 32 位 RGB 获得 16 位高度图。 所以任何其他浏览器端的 javscript 方法都可以。 我也在使用浏览器端 createWritable(); stream 将文件写入磁盘。

我有一个从这个不错的模块https://github.com/colkassad/terrain-rgb-height使用的方法但是我无法让 pngjs 的浏览器端版本正常工作。 我认为浏览器端 stream 读取器/写入器和节点读取器/写入器之间存在差异,因此无法正常工作。

谢谢!

查看 GitHub 上Image-js package 的源代码,发现在调用库时使用的options object 在源文件kind.js中得到验证,该文件在赋值语句中列举了支持的选项属性:

const { components, alpha, bitDepth, colorModel } = definition;

但是,许多选项默认使用kind选项属性,它本身默认为“RGBA”。

了解更多关于选项属性的信息可以使用它们(我找不到代码之外的选项文档)。

我会建议

  1. 从 32 位编码高度 png 创建一个 Image-js 图像。 省略kind属性以使用默认的 32 位 PNG 像素 model 的 3 个颜色通道和一个 alpha 通道。

  2. 使用 MapBox 转换算法将图像数据(作为图像对象的data属性中的类型数组保存)转换为高度值的一维数组 ( image.data ) 类型数组的布局似乎与用于ImageData的布局相同

  3. 使用创建一个新的 image-js 图像

    new Image(width, height, decodedHeightArray, {kind="GREY", bitDepth:16})

    其中decodedHeightArray是上一步准备的数组。

只需将我的代码添加到 tracktor 提供的答案中,非常感谢 traktor

这非常有效。 对于任何想要代码的人

我正在使用image-js对图像进行编码和解码

 let file_handleSixteen = await dir_handle.getFileHandle(sixteen_file_name, {create: true})

 let writableSixteen = await file_handleSixteen.createWritable();


async function convert16(arrayBuff) {

  let image = await Image.load(arrayBuff);

  let width = image.width
  let height = image.height

  let decodedHeightArray = []
  let pixelsArray = image.getPixelsArray()
  for (const pixel of pixelsArray) {
    let r = pixel[0]
    let g = pixel[1]
    let b = pixel[2]
    let height = getHeightFromRgb(r, g, b);
    decodedHeightArray.push(height)
  }
  let newImage = new Image(width, height, decodedHeightArray, {kind: "GREY", bitDepth: 16})
  return newImage.toBlob()
}

function getHeightFromRgb(r, g, b) {
  return -10000 + ((r * 256 * 256 + g * 256 + b) * 0.1);
}


  const file = await file_handleRgb.getFile();
  let imageBuffer = await file.arrayBuffer()
  let convertedArray = await convert16(imageBuffer)

 await writableSixteen.write(convertedArray)
 await writableSixteen.close();

我还使用浏览器流 api 将文件写入磁盘。 请注意,文件流 writable.write 只接受某些值,其中之一是 Blob,这就是为什么在将其传递给 write 方法之前将其转换为 Blob 的原因


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM