Uint8ClampedArrayに小数を代入すると詰まる
先に結論だけ
Uint8ClampedArrayに小数を代入すると、0.5以下が切り捨てられます。複合代入演算子を利用しても同様です。
この記事の想定する環境
この記事は以下の環境で動作することを想定しています。
- Google Chrome 78.0.3904.108
記事を読む前に、お手元の環境をご確認ください。
Uint8ClampedArrayとは
Uint8ClampedArrayは、8ビット符号なし整数値の配列です。JavaScriptのNumberは、浮動小数点を扱いますがこの配列は0 ~ 255の整数値に値が制限されます。Uint8ClampedArrayなどのTypedArrayは型付きの要素の配列です。
どのような操作で必要となるのか
Canvas要素のImageDataオブジェクトが、ピクセルデータをUint8ClampedArrayで格納しています。TypedArrayは一般的に、バイナリデータをJavaScriptで操作する際のインターフェイスです。
小数を代入してみる
このUint8ClampedArrayに、小数を代入するとどのような振る舞いをするでしょう?情報がなかったため、Codepenでテストコードを書いてみました。
const array = new Uint8ClampedArray(1);
for( let i = 1; i < 101; i++){
const val = 1.0 - (i / 100)
array[0] = val;
console.log( val , array[0] )
}
このコードの出力は以下の通りです。
0.99 1
pen.js:7 0.98 1
pen.js:7 0.97 1
...(中略)...
pen.js:7 0.51 1
pen.js:7 0.5 0
pen.js:7 0.49 0
...(中略)...
pen.js:7 0.020000000000000018 0
pen.js:7 0.010000000000000009 0
pen.js:7 0 0
0.5以下が切り捨て、それ以上では1に丸め込みが行われていました。四捨五入ではなく0.5で切り捨てが行われているのは意外でした。
どんなときに困るのか
JavaScriptのNumber型は浮動小数点なので、うっかり以下のようなコードを書いてしまうとバグを生みます。
array[0] *= 0.8;
このコードではarray[0]が2以下になると、数値がそれ以上減りません。丸め込み処理が行われるためです。例としてCanvasのピクセルを徐々に暗くしたいのに、いつまでもわずかな灰色が残ります。
array[0] = ( array[0] * 0.8 ) | 0;
Math.floorやビット演算で明示的に小数を切り捨てると、この問題は解決します。
参考記事 : HTML5 canvas のパフォーマンスの改善 / 浮動小数点座標の使用を控える
整数型を持った言語では当然問題になるコードですが、JavaScriptでも同様の注意が必要となる場合があります。
とくにCanvasを操作する場合はご注意ください。
以上、ありがとうございました。
Author And Source
この問題について(Uint8ClampedArrayに小数を代入すると詰まる), 我々は、より多くの情報をここで見つけました https://qiita.com/masato_makino/items/97828a5820dcb3d4ba87著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .