Mapping color representations

exercise No. 269

Q:

A developer requires RGB based colors represented by its red, green and blue components each ranging from -128 to 127 inclusive. As an example (127, -128, 0) denotes a full red intensity, zero green and medium blue.

Our developer wants to map triples like the former (127, -128, 0) back and forth into a single attribute of type int:

/**
 * Pack color components (r, g, b) ranging from -128 to 127 into
 * an <code>int</code>.
 *
 * Inverse operation to {@link #int2rgb(int)}.
 *
 * @param r Red component ranging from -128 to 127
 * @param g Green component ranging from -128 to 127
 * @param b Blue component ranging from -128 to 127
 * @return A value corresponding to the color in question.
 */
static public int rgb2int(final byte r, final byte g, final byte b) {
    ...
  return ...;
}

/**
 * Convert an <code>int</code> color specification back into its three (r, g, b) components.
 *
 * Inverse operation to {@link #rgb2int(byte, byte, byte)}.
 *
 * @param color A color value combining an (r, g, b) triple.
 * @return An array of length 3 representing (r, g, b) values.
 */
static public byte[] int2rgb(final int color) {
   ...
  return new byte[]{..., ..., ...};
}
  1. Is this possible? Explain your statement.

    Tip

    Consider the underlying data types.

  2. Provide at least an implementation sketch of rgb2int(...) and int2rgb(...) if the aforementioned mapping is possible.

A:

  1. An int consisting of four bytes could accommodate four such byte values rather than just three.

  2. Omitting Javadoc we may use:

    static public int rgb2int(final byte r, final byte g, final byte b) {
       // Transforming ranges from [-128, 127] to [0, 255]
       // Multiplying by 256 shifts 8 positions to the left within the returned int value.
       return r + 128  + 256 * ((g + 128) + (b + 128) * 256);
    }
    
    static public byte[] int2rgb(int color) {
       final byte[] rgb = new byte[3];
    
       // Transforming ranges back from [0, 255] to [-128, 127]
       rgb[0] = (byte) (color % 256 - 128);
    
       // Dividing by 256 shifts 8 positions to the right.
       color /=  256;
       rgb[1] = (byte) (color % 256 - 128);
    
       color /=  256;
       rgb[2] = (byte) (color % 256 - 128);
    
       return rgb;
    }

    Alternatively using bit-shift operations:

    static public int rgb2int(final byte r, final byte g, final byte b) {
       return ((128 + b) << 16) | ((128 + g) << 8) | (128 + r);
    }
    
    static public byte[] int2rgb(int color) {
       final byte[] rgb = new byte[3];
    
       rgb[0] = (byte) ((color & 255) - 128);
    
       color >>= 8;
       rgb[1] = (byte) ((color & 255) - 128);
    
       color >>= 8;
       rgb[2] = (byte) ((color & 255) - 128);
    
        return rgb;
    }