@Override
  public int hashCode() {
    int hash = 0;
    int tmp;

    if (hasAlpha) {
      hash ^= 1;
      hash <<= 8;
    }
    if (isAlphaPremultiplied) {
      hash ^= 1;
      hash <<= 8;
    }

    tmp = hash >>> 24;
    hash ^= numColorComponents;
    hash <<= 8;
    hash |= tmp;

    tmp = hash >>> 24;
    hash ^= transparency;
    hash <<= 8;
    hash |= tmp;

    tmp = hash >>> 24;
    hash ^= cs.getType();
    hash <<= 8;
    hash |= tmp;

    tmp = hash >>> 24;
    hash ^= pixel_bits;
    hash <<= 8;
    hash |= tmp;

    tmp = hash >>> 24;
    hash ^= transferType;
    hash <<= 8;
    hash |= tmp;

    if (bits != null) {

      for (int element : bits) {
        tmp = hash >>> 24;
        hash ^= element;
        hash <<= 8;
        hash |= tmp;
      }
    }

    return hash;
  }
  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof ColorModel)) {
      return false;
    }
    ColorModel cm = (ColorModel) obj;

    return (pixel_bits == cm.getPixelSize()
        && transferType == cm.getTransferType()
        && cs.getType() == cm.getColorSpace().getType()
        && hasAlpha == cm.hasAlpha()
        && isAlphaPremultiplied == cm.isAlphaPremultiplied()
        && transparency == cm.getTransparency()
        && numColorComponents == cm.getNumColorComponents()
        && numComponents == cm.getNumComponents()
        && Arrays.equals(bits, cm.getComponentSize()));
  }
  /**
   * Instantiates a new color model with the specified pixel bit depth. The transferType is chosen
   * based on the pixel bits, and the other data fields are given default values.
   *
   * @param bits the array of component masks.
   */
  public ColorModel(int bits) {

    if (bits < 1) {
      // awt.271=The number of bits in bits is less than 1
      throw new IllegalArgumentException(Messages.getString("awt.271")); // $NON-NLS-1$
    }

    pixel_bits = bits;
    transferType = getTransferType(bits);
    cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    hasAlpha = true;
    isAlphaPremultiplied = false;
    transparency = Transparency.TRANSLUCENT;

    numColorComponents = 3;
    numComponents = 4;

    this.bits = null;
  }
 @Override
 public String toString() {
   // The output format based on 1.5 release behavior.
   // It could be reveled such way:
   // ColorModel cm = new
   // ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB,
   // false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
   // System.out.println(cm.toString());
   return "ColorModel: Color Space = "
       + cs.toString()
       + "; has alpha = " //$NON-NLS-1$ //$NON-NLS-2$
       + hasAlpha
       + "; is alpha premultipied = " //$NON-NLS-1$
       + isAlphaPremultiplied
       + "; transparency = "
       + transparency //$NON-NLS-1$
       + "; number color components = "
       + numColorComponents //$NON-NLS-1$
       + "; pixel bits = "
       + pixel_bits
       + "; transfer type = " //$NON-NLS-1$ //$NON-NLS-2$
       + transferType;
 }
  /**
   * Instantiates a new color model with the specified values.
   *
   * @param pixel_bits the pixel length in bits.
   * @param bits the array of component masks.
   * @param cspace the color space.
   * @param hasAlpha whether the color model has alpha.
   * @param isAlphaPremultiplied whether the alpha is pre-multiplied.
   * @param transparency the transparency strategy, @see java.awt.Transparency.
   * @param transferType the transfer type (primitive java type to use for the components).
   */
  protected ColorModel(
      int pixel_bits,
      int[] bits,
      ColorSpace cspace,
      boolean hasAlpha,
      boolean isAlphaPremultiplied,
      int transparency,
      int transferType) {

    if (pixel_bits < 1) {
      // awt.26B=The number of bits in the pixel values is less than 1
      throw new IllegalArgumentException(Messages.getString("awt.26B")); // $NON-NLS-1$
    }

    if (bits == null) {
      // awt.26C=bits is null
      throw new NullPointerException(Messages.getString("awt.26C")); // $NON-NLS-1$
    }

    int sum = 0;
    for (int element : bits) {
      if (element < 0) {
        // awt.26D=The elements in bits is less than 0
        throw new IllegalArgumentException(Messages.getString("awt.26D")); // $NON-NLS-1$
      }
      sum += element;
    }

    if (sum < 1) {
      // awt.26E=The sum of the number of bits in bits is less than 1
      throw new NullPointerException(Messages.getString("awt.26E")); // $NON-NLS-1$
    }

    if (cspace == null) {
      // awt.26F=The cspace is null
      throw new IllegalArgumentException(Messages.getString("awt.26F")); // $NON-NLS-1$
    }

    if (transparency < Transparency.OPAQUE || transparency > Transparency.TRANSLUCENT) {
      // awt.270=The transparency is not a valid value
      throw new IllegalArgumentException(Messages.getString("awt.270")); // $NON-NLS-1$
    }

    this.pixel_bits = pixel_bits;
    this.bits = bits.clone();

    maxValues = new int[bits.length];
    maxBitLength = 0;
    for (int i = 0; i < maxValues.length; i++) {
      maxValues[i] = (1 << bits[i]) - 1;
      if (bits[i] > maxBitLength) {
        maxBitLength = bits[i];
      }
    }

    cs = cspace;
    this.hasAlpha = hasAlpha;
    this.isAlphaPremultiplied = isAlphaPremultiplied;
    numColorComponents = cs.getNumComponents();

    if (hasAlpha) {
      numComponents = numColorComponents + 1;
    } else {
      numComponents = numColorComponents;
    }

    this.transparency = transparency;
    this.transferType = transferType;
  }