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 and their sizes in particular.

  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;
    }