/**
  * Highlights an area in a RgbImage by turning the non-masked areas gray and dimming them.
  *
  * @return the masked color image.
  * @param imRgb the input RgbImage.
  * @param imMask The input mask. Pixels with the value Byte.MIN_VALUE are unmasked. Everything
  *     else is considered to be masked.
  * @throws Error if the input sizes do not match
  */
 public RgbImage push(RgbImage imRgb, Gray8Image imMask) throws Error {
   if (imRgb.getWidth() != imMask.getWidth() || imRgb.getHeight() != imMask.getHeight()) {
     throw new Error(
         Error.PACKAGE.CORE,
         jjil.core.ErrorCodes.IMAGE_MASK_SIZE_MISMATCH,
         imRgb.toString(),
         imMask.toString(),
         null);
   }
   int[] rgbData = imRgb.getData();
   byte[] maskData = imMask.getData();
   for (int i = 0; i < imRgb.getWidth() * imRgb.getHeight(); i++) {
     if (maskData[i] == Byte.MIN_VALUE) {
       /* get individual r, g, and b values, unmasking them from the
        * ARGB word and converting to an unsigned byte.
        */
       int r = RgbVal.getR(rgbData[i]) - Byte.MIN_VALUE;
       int g = RgbVal.getG(rgbData[i]) - Byte.MIN_VALUE;
       int b = RgbVal.getB(rgbData[i]) - Byte.MIN_VALUE;
       // also darken unmasked pixels
       int gray = (r + g + b) / 5;
       /* average the values to get the grayvalue
        */
       /* Create ARGB word */
       rgbData[i] = ((gray) << 16) | ((gray) << 8) | gray;
     }
   }
   return imRgb;
 }
 /**
  * Assigns a constant rectangle to the input Gray8Image, replacing values in the image.
  *
  * @param image the input image (output replaces input).
  * @throws Error if the input is not a Gray8Image.
  */
 public void push(Image image) throws Error {
   if (!(image instanceof Gray8Image)) {
     throw new Error(
         Error.PACKAGE.ALGORITHM, ErrorCodes.IMAGE_NOT_GRAY8IMAGE, image.toString(), null, null);
   }
   Gray8Image input = (Gray8Image) image;
   byte[] data = input.getData();
   int nLimitY = Math.min(input.getHeight(), this.cY + this.nHeight);
   int nLimitX = Math.min(input.getWidth(), this.cX + this.nWidth);
   for (int i = this.cY; i < nLimitY; i++) {
     int nStart = i * image.getWidth();
     for (int j = this.cX; j < nLimitX; j++) {
       data[nStart + j] = this.bValue;
     }
   }
   super.setOutput(input);
 }