Javascript:PNG 解码后的 pixel 转 BMP 问题 时间: 2022-06-24 17:38 分类: 修仙日记 `PNG`文件格式在这里不做赘述,`Javascript`解码`PNG`无非就是按照`PNG`文件格式依次读取`PNG buffer`,关键图像信息都在`IDAT chunk`中。 读取完`IDAT`后,因为它是压缩的,所以需要解压缩(即使是压缩,它也是无损的,因为解压缩是无损的,有兴趣的可以去了解一下它的压缩算法),由于我是在`Javascript`中解码`PNG`图像,可以直接使用`pako.js`的`inflate`方法来解码。 按格式读取`PNG`图像自己懒得写,这里找了一个现成的比较轻量的工具:https://github.com/photopea/UPNG.js 由于我只用到里面的解码相关,所以只抽取里面的`decode`相关代码即可。 利用上面工具类读取到`pixel`后,有个需求就是将其转为`BMP`,搜索了半天,没找到现成方便使用的,于是想着自己来撸一个。 但是,知识有限,不知道它们之间的转换规则,百度一搜`png 转 bmp`,全是`xxx转换工具`或者那傻逼`JAVA现成的类`在调用,虽然可以查看其源码实现,但我仅仅只是想要`png 转 bmp`而已,源码就懒得去研究了。 对于这种底层的实现我发现搜索到的答案真的太少了,就和前段时间研究的那个`.SUP`字幕文件格式解析一样,可能大多数人的开发都是基于现有库进行实现,所以搜索到的结果才少之又少。 废话不多说,皇天不负有心人,终于看到一个比较有用的文章:https://blog.csdn.net/pow8368684/article/details/78891081 关键: > 因为BMP图片是从下往上,从左往右存储的,所以RGB数据写入BMP数据里要倒过来取。 代码: ``` var a = 0 ; for(var i = 0 ; i < height ; i ++){ for(var j = 0 ; j < width * 3 ; j ++ ){ nBytes[54 + a] = bytes[bytes.length - (width * 3 * i) - (width * 3 - j)]; a ++ ; } } ``` 但是,经过多番调试,上面代码对于我的`PNG`图片还是有问题的,发现`PNG`解码后的`pixel`比`BMP`的图像数据正好多`PNG图片高`的个数。 上面`PNG`工具获取到的位深为`8位`应该是有问题的,实际上我的图片是`24`位的,讲到这里,那就说下我为什么有这个需求吧:去年写了篇将数据无损存储到`BMP`的文章,大致就是白嫖大厂的图床。 白嫖被发现后,服务端将`BMP`转成了`PNG`输出,但是经过转换发现,竟然是无损转换,也就是说`PNG`再转回`BMP`依旧是我们隐藏的数据,于是就有了今天这个需求:在网页中将`PNG`转回`BMP`。 由于`BMP`是我自己生成的,所以知道它就是`24位深`的,并且生成的时候做了对齐处理:也就是`宽*3`是4的倍数,本来按道理`PNG`解码后的图像数据大小应该跟`BMP`是一致的,因为`BMP`的宽生成的时候已经做了对齐处理。 哪知道,图床服务端`BMP`转`PNG`的时候又对齐了一次,即:`(宽*3+1)*高`,这也就解释了为什么`PNG`解码后的`pixel`大小比`BMP`的多了一个高的长度。 问题不止于此,还有就是大小端的问题,因为是`24`位,所以每个像素占三个字,也就是每三个字节做大小端处理,节具体修改后的代码如下: ``` var img = UPNG.decode(rsp); var a = 0 ; newResponse = new Uint8Array(img.width * 3*img.height); for(var i = 0 ; i < img.height ; i ++){ for(var j = 0 ; j < img.width * 3 ; j+=3 ){ newResponse[a+2] = img.data[img.data.length - (img.width * 3 * i) - (img.width * 3 - j) - img.height]; newResponse[a+1] = img.data[img.data.length - (img.width * 3 * i) - (img.width * 3 - (j+1)) - img.height]; newResponse[a] = img.data[img.data.length - (img.width * 3 * i) - (img.width * 3 - (j+2)) - img.height]; a += 3; } } ``` 至此,问题顺利解决。 标签: 无