I need to convert RGB-16 color values to RGB-8. The question is twofold.
First, what is a recommended way of doing this?
In RGB-8, the topmost value is 255, and in RGB-16 it is 65535, so it seems I can simply divide RGB-16 values to 257, and this will be enough?
But then why is the following solution for MatLab exists?
To convert an RGB image from double to uint8, first multiply by 255.
RGB8 = uint8(round(RGB64*255));http://matlab.izmiran.ru/help/techdoc/creating_plots/chimag12.html
And the second part of the question, how to do it with JavaScript? I have tried
const RGB16 = ...
const RGB8 = new Uint8Array(Math.round(RGB16*255));
but it seems it simply returns an array of zeroes.
>Solution :
Converting RGB-16 color values to RGB-8 involves scaling down the values appropriately to fit within the range of 0-255. Your intuition is correct; you can divide RGB-16 values by 257 (not 255) to get the equivalent RGB-8 values.
The reason for dividing by 257 instead of 255 is that 65535 (maximum value of RGB-16) divided by 255 results in 257. This division will ensure that the full range of RGB-16 values (0-65535) is mapped to the full range of RGB-8 values (0-255).
Regarding the MATLAB solution you found, there’s a slight difference. In MATLAB, the RGB image is first scaled to the range [0, 1] (since MATLAB’s double representation uses values between 0 and 1) by multiplying by 255. Then, it is converted to an unsigned 8-bit integer (uint8) using the round function to round the values to the nearest integers. This step ensures that fractional values are not truncated, which could happen if a simple cast was performed.
For example, if you directly converted RGB-16 values to RGB-8 using a simple cast, like this:
RGB8 = uint8(RGB16/257); % Incorrect
Some information could be lost because casting would truncate the fractional parts.
Now, let’s address the JavaScript part of the question. The approach you used in JavaScript is not entirely correct. To convert RGB-16 values to RGB-8 in JavaScript, you need to scale the values and ensure they fit within the valid range (0-255).
Here’s a corrected way to do it:
// Assuming RGB16 is an array of RGB-16 values (e.g., [r, g, b])
const RGB16 = [65535, 32768, 49152]; // Example RGB-16 values
// Convert RGB-16 to RGB-8
const RGB8 = RGB16.map(value => Math.round(value / 257));
console.log(RGB8); // Output: [ 255, 128, 192 ]