0

I have a float numbers between 0 and 16 581 375, I need to split this number into 3 between 0 and 255 that is equal to the result after multiplying them together.

Examples:

  • 255 becomes => 1 * 1 * 255
  • 1275 becomes => 1 * 5 * 255
  • 7152750 becomes => 110 * 255 * 255

Here is how I get my 3 numbers:

var MAX = 255*255*255;

function getNumbersFromValue( v ){

  v = Math.max(0, Math.min(MAX, v)) || 0;

  if( v <= 255 ){

    return {
      r: 1,
      g: 1,
      b: v
    };

  }
  else if( v <= (255 * 255) ){

      return {
        r: 1,
        g: (v / 255),
        b: 255
      };

  }
  else {

    return {
      r: (v / 255 / 255),
      g: 255,
      b: 255
    };

  };

};

My problem is that I need the three numbers to be integers without losing precision (or something insignificant) and the starting value (variable v in the example) can be a float between 0 and 16 581 375 (255*255*255).

Jordan
  • 3,776
  • 3
  • 22
  • 28

2 Answers2

0

You could use carmickr's answer for converting a integer number to rgb values.

function go(rgb) {
    return {
       r: (rgb >> 16) & 0xFF,
       g: (rgb >> 8) & 0xFF,
       b: rgb & 0xFF
    };
}

console.log(go(255));
console.log(go(257));
console.log(go(1275));
console.log(go(4711));
console.log(go(7152750));
console.log(go(7152751));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Community
  • 1
  • 1
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Updated answer—encoding data as RGB values

You can encode and decode integers with 24 bits of data in RGB values like this:

function numToRGB(num){ //num is integer in range 0 through 16777215
  return {
    r: (num >> 16) & 0xff,
    g: (num >> 8) & 0xff,
    b: num & 0xff
  }
}

function RGBtoNum(rgb){
  return rgb.r << 16 ^ rgb.g << 8 ^ rgb.b;
}

console.log(numToRGB(0xffffff));

console.log(RGBtoNum({
  r: 255,
  g: 255,
  b: 255
}));

You could theoretically use RGBA to encode 32 bits in each pixel, but this is not stable.

Answer to the original question

From the constraints you describe,

  • starting value as a float in the range 0 through 16 581 375,
  • split into three components that each can range from 0 through 255,
  • the product of the components should correspond to the starting value,
  • components can only be integers,

there are just 764 possible combinations that uniquely map to a value in the starting value range (0 through 16 581 375):

  • 0 × 0 × 0
  • 1 × 1 × (1 through 255)
  • 1 × (2 through 255) × 255
  • (2 through 255) × 255 × 255

It is not possible to extract components without loss of precision from any possible starting value (given that any float in the range is a valid start value). The best we can do, is to round to the closest match. For example, the number 185 694 does not have an integer solution according to the constraints. But, it is closer to 195 075 (3 × 255 × 255) than 130 050 (2 × 255 × 255).

Here is one way to do this in code:

function extract(v) {
  if (v === 0) return {
    r: 0,
    g: 0,
    b: 0
  };
  for (var rgb = [], i = 3; i--; v /= 255)
    rgb[i] = Math.max(1, Math.min(Math.round(v), 255));
  return {
    r: rgb[0],
    g: rgb[1],
    b: rgb[2]
  };
}

/* test 185 694 */
console.log(extract(185694));

As your code example seems to indicate that you work with 24-bit rgb colors, it would be helpful to know more about the context of the problem. How come that the starting value is a float? Why the range 0 through 16 581 375?

For encoding the 764 possible combinations, the range of integers from 0 through 763 would suffice. For encoding any 24-bit rgb value, the constraints do not fit—they allow only a very limited subset of possible rgb values (< 0.01 %).

Community
  • 1
  • 1
Tomas Langkaas
  • 4,551
  • 2
  • 19
  • 34