使用 DataView 和 ArrayBuffer 转换 32BitPackedARGB 数组以解决 Endiness
Converting 32BitPackedARGB array with DataView and ArrayBuffer to solve Endiness
我这里有这段代码:
var can = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
can.width = '16';
can.height = '16';
var ctx = can.getContext('2d');
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillRect(0, 0, 16, 16);
var ARGBpixmap = [16, 16];
var image_data = ctx.getImageData(0, 0, can.width, can.height);
for (var x = 0; x < image_data.width; x++) {
for (var y = 0; y < image_data.height; y++) {
var i = x * 4 + y * 4 * image_data.width;
var r = image_data.data[i];
var g = image_data.data[i + 1];
var b = image_data.data[i + 2];
ARGBpixmap.push(r + g + b);
}
}
console.log(ARGBpixmap);
然而,这是恩典。所以我听说我必须使用DataView和ArrayBuffer。这是我的尝试:
var can = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
can.width = '16';
can.height = '16';
var ctx = can.getContext('2d');
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillRect(0, 0, 16, 16);
// Getting pixels as a byte (uint8) array
var imageData = ctx.getImageData(0, 0, can.width, can.height);
var pixels8BitsRGBA = imageData.data;
console.log(pixels8BitsRGBA.length)
var sizeOfEachStoredNumber = 4; //bytes
var numberOfStoresPerPixel = 4; //we have a r g and b
var numberOfPixels = can.width * can.height;
var buffer = new ArrayBuffer((numberOfPixels * (sizeOfEachStoredNumber * numberOfStoresPerPixel)) + 8); // +8 bytes for the two leading 32 bytes integers
console.log((numberOfPixels * (sizeOfEachStoredNumber * numberOfStoresPerPixel)) + 8);
//buffer size is: 256 repetitions of 4 numbers. each number is 4bytes. so 16 bytes per repetition. 256 reps. so 4096 total bytes is size
// Reverting bytes from RGBA to ARGB
//var pixels8BitsARGB =
var view = new DataView(buffer, 0);
view.setUint8(0, can.width, true);
view.setUint8(4, can.height, true);
for(var i = 0 ; i < pixels8BitsRGBA.length ; i += 4) {
var bytePos = i/4*16+8; //starting byte position of this group of 4 numbers // +8 bytes for the two leading 32 bytes integers
//console.log(bytePos, h)
var r = pixels8BitsRGBA[i ];
var g = pixels8BitsRGBA[i+1];
var b = pixels8BitsRGBA[i+2];
var a = pixels8BitsRGBA[i+3];
view.setUint8(bytePos, a, true);
view.setUint8(bytePos+4, r, true);
view.setUint8(bytePos+8, g, true);
view.setUint8(bytePos+12, b, true);
}
// Converting array buffer to a uint32 one, and adding leading width and height
var pixelsAs32Bits = new Uint32Array(buffer);
console.log(pixelsAs32Bits);
两者都是可复制粘贴的代码,第一个获得非常不同的数字。如何修复我的代码?我对DataView和ArrayBuffer不是很好。
你真的不需要类型化数组,但我想使用它们并没有什么坏处。
如果没有类型化数组,在第一个代码段中,
ARGBpixmap.push(r + g + b);
只需要
ARGBpixmap.push((r << 16) + (g << 8) + b);
这会将 3 个字节转换为表单的单个 32 位整数
00000000 RRRRRRRR GGGGGGGG BBBBBBBBB
您可能需要 1 或 alpha 值而不是 0,具体取决于您要如何处理数据。若要获取 alpha 值,请使用
var r = image_data.data[i];
var g = image_data.data[i + 1];
var b = image_data.data[i + 2];
var a = image_data.data[i + 3];
ARGBpixmap.push((a << 24) + (r << 16) + (g << 8) + b);
您可以使用此行获得无符号数字,但这并不重要,因为低 32 位完全相同,请参阅 http://www.codeonastick.com/2013/06/javascript-convert-signed-integer-to.html
ARGBpixmap.push(((a << 24) + (r << 16) + (g << 8) + b) >>> 0);
在第二个代码段中
view.setUint8(bytePos, a, true);
view.setUint8(bytePos+4, r, true);
view.setUint8(bytePos+8, g, true);
view.setUint8(bytePos+12, b, true);
应该是
view.setUint8(i + 3, a, true);
view.setUint8(i + 2, r, true);
view.setUint8(i + 1, g, true);
view.setUint8(i + 0, b, true);
原因是现在您正在源和目标处逐字节处理 ARGB 数据。 我已经是一个字节位置,你不需要计算另一个。相关差异仅在每个 4 字节组中。
编辑:考虑恩迪亚内斯。
相关文章:
- 根据某些条件验证用户输入,而不是将输入输入到数组中,需要最基本的解决方案
- Coderbyte数组添加解决方案--For循环与For循环
- 将对象完全转换为键和值的数组:更好的解决方案
- 在数组中查找重复项的最佳解决方案
- 使用 DataView 和 ArrayBuffer 转换 32BitPackedARGB 数组以解决 Endiness
- 创建包含正则表达式匹配中所有组的数组的有效解决方案
- 我正在尝试遍历所有字母表的数组并将所有其他字母大写.任何解决方案
- 数组中的字符串“”被解释,是否有解决方法
- 如何使用 Json 和 Javascript 解决 PHP 数组
- 在数组中查找单元格的更好解决方案
- Chrome:如何解决Math.max.apply(Math,数组)上的“超出最大调用堆栈大小”错误
- 你能解决它吗?使用数组实现JavaScript转盘
- each()在IE8上不起作用,并给了我一个“;期望应用数组或参数对象”;.如何解决
- 用JavaScript解决这个看似简单的数组循环难题
- 长数组的对象销毁解决方案
- 将Javascript用户数组与“解决方案”匹配数组中
- 对于数组有没有更简单的解决方案
- 数组组合以解决遍历问题
- 数组的数组或使用相同var返回不同值的另一种解决方案
- 数组中的第一个唯一数字.需要优雅的解决方案