首页 > 代码库 > Javascript TypedArray 解惑:Uint8Array 与 Uint8ClampedArray 的区别
Javascript TypedArray 解惑:Uint8Array 与 Uint8ClampedArray 的区别
JS的类型数组大体可分为3类:无符号整数、有符号整数、浮点数。
Int8Array; Uint8Array; Uint8ClampedArray; Int16Array; Uint16Array; Int32Array; Uint32Array; Float32Array; Float64Array;
基本上都可以望文生义,看名字就知道怎么回事。
但是有一个例外 Uint8ClampedArray ,它与 Uint8Array 颇为相似,但又有所区别。
因为颜色数据刚好都是符合8位二进制的无符号整数,所以这两个类型在处理Canvas绘图数据时常常用到。
Uint8ClampedArray主要用于某些特殊场景,典型的就是 ImageData.
clamped这个词的字面意思是“紧固的,夹紧的”。
如果输入的值已经是0~255之间的整数,那么Uint8Array 与 Uint8ClampedArray的最终结果是一致的。
Uint8Array 与 Uint8ClampedArray 的区别,就在于处理不在该范围(0~255之间的整数)的输入数值的转换逻辑的差异。
Uint8Array采用的转换逻辑是ToUint8 .
其中一个关键点是,它将输入数与256取模,将8个比特位转化为正整数,它也不会进行四舍五入。
所以 new Uint8Array([33.999]) 等价于 new Uint8Array([33.111])
特别注意,对于负数来说,由于负数的二进制存储形式是补码形式的,其转换后得到的值与输入值的联系就不直观了。
例如 -23,二进制是11101001即得233 (23的二进制是00010111,它的补码就是11101001),
所以new Uint8Array([-23]) 等价于 new Uint8Array([233])
详细规则如下:
- Let number be ToNumber(argument).
- ReturnIfAbrupt(number).
- If number is NaN, +0, ?0, +∞, or ?∞, return +0.
- Let int be sign(number) × floor(abs(number)).
- Let int8bit be int modulo 28.
- Return int8bit.
Uint8ClampedArray 采用的转换逻辑是ToUint8Clamp
它会将负数归入0,大于255的数归入255,所以取模就不用了。
所以new Uint8ClampedArray([-23]) 等价于 new Uint8ClampedArray([ 0 ])
上面说到 new Uint8Array([-23]) 等价于 new Uint8Array([ 233 ]) ,这样就看出差别了吧。
另外,它不是直接取整,而是会处理舍入,但并不是像Math.round()那样的四舍五入,而是采用一种叫做银行家舍入的方法。
详细规则如下:
- Let number be ToNumber(argument).
- ReturnIfAbrupt(number).
- If number is NaN, return +0.
- If number ≤ 0, return +0.
- If number ≥ 255, return 255.
- Let f be floor(number).
- If f + 0.5 < number, then return f + 1.
- If number < f + 0.5, then return f.
- If f is odd, then return f + 1.
- Return f.
参考
- TypedArray (MDN)
- Uint8ClampedArray 对象(MSDN)
- Type Conversion (ECMA-262)
Javascript TypedArray 解惑:Uint8Array 与 Uint8ClampedArray 的区别