RGBと整数の相互変換

点群PNGではRGBから整数、整数からRGB、それぞれ2ピクセル分まで考慮しての変換ルーチンが必要になる。スクリプトを適当に作って間違えないよう関数をまとめておく。

//1ピクセル分rgbを符号なし整数に変換[0, 2^24-1]
/*
	@param	typed	: Uint8ClampedArray with 3 elements
	@return	number	: number
*/
const rgbToUnsigned	= ( value ) => {
	return value[0] * 256 ** 2
			+ value[1] * 256 ** 1
			+ value[2] * 256 ** 0;
};

//1ピクセル分rgbを符号付き整数に変換[-2^23, 2^23-1]
/*
	@param	typed	: Uint8ClampedArray with 3 elements
	@return	number	: number
*/
const rgbToSigned	= ( value ) => {
	return rgbToUnsigned( value )
			- ( value[0] < 128 ? 0 : 256 ** 3 );
};

//2ピクセル分rgbを符号なし整数に変換[0, 2^48-1]
/*
	@param	typed	: Uint8ClampedArray with 6 elements
	@return	number	: number
*/
const rgb2pxToUnsigned = ( value ) => {
	return value[0] * 256 ** 5
			+ value[1] * 256 ** 4
			+ value[2] * 256 ** 3
			+ value[3] * 256 ** 2
			+ value[4] * 256 ** 1
			+ value[5] * 256 ** 0;
};

//2ピクセル分rgbを符号付き整数に変換[-2^47, 2^47-1]
/*
	@param	typed	: Uint8ClampedArray with 6 elements
	@return	number	: number
*/
const rgb2pxToSigned	= ( value ) => {
	return rgb2pxToUnsigned( value )
			- ( value[0] < 128 ? 0 : 256 ** 6 );
};

//整数を1ピクセル分rgbに変換
/*
	@param	number	: number
	@return	array	: array uint8clamped with 3 elements
*/
const numberToRgb = ( value ) => {
	return [
		value >> 16 & 0xff,
		value >> 8 & 0xff,
		value & 0xff,
	];
};

//整数を2ピクセル分rgbに変換
/*
	@param	number	: number
	@return	array	: array uint8clamped with 3 elements
*/
const numberToRgb2px	= ( value ) => {
	const number24	= 256 ** 3;
	const upper		= ( value - (value % number24) ) / number24
		- ( value < 0 ? 1 : 0 );
	return [].concat( numberToRgb(upper), numberToRgb(value) );
};

JavaScriptのビット演算は数値を32ビットとして扱うので、2ピクセル分RGB(48ビット)を正しく扱えず、一工夫が必要だった。