@Override
  public void applyInPlace(FastBitmap sourceImage) {
    int width = overlayImage.getWidth();
    int height = overlayImage.getHeight();

    int[] rgbO;
    for (int x = 0; x < height; x++) {
      for (int y = 0; y < width; y++) {
        rgbO = overlayImage.getRGB(x, y);

        if (rgbO[0] >= _replaceColor[0]
            && rgbO[1] >= _replaceColor[1]
            && rgbO[2] >= _replaceColor[2]) {
          // x and y is reverted
          sourceImage.setRGB(x + getyOffset(), y + getxOffset(), rgbO);
        }
      }
    }
  }
  @Override
  public void applyInPlace(FastBitmap fastBitmap) {

    if (fastBitmap.isRGB()) {
      int width = fastBitmap.getWidth();
      int height = fastBitmap.getHeight();
      LinkedList<IntPoint> examList = new LinkedList();

      Color old = new Color(fastBitmap.getRGB(startPoint));

      switch (algorithm) {
        case FourWay:
          if (!Color.isEqual(old, replace)) {
            examList.addFirst(new IntPoint(startPoint));

            while (examList.size() > 0) {
              IntPoint p = examList.removeLast();
              old = new Color(fastBitmap.getRGB(p));

              if (!Color.isEqual(old, replace)) {
                int x = p.x;
                int y = p.y;

                fastBitmap.setRGB(x, y, replace);

                if (y - 1 > 0) {
                  examList.addFirst(new IntPoint(x, y - 1)); // check west neighbor
                }
                if (y + 1 < width) {
                  examList.addFirst(new IntPoint(x, y + 1)); // check east neighbor
                }
                if (x + 1 < height) {
                  examList.addFirst(new IntPoint(x + 1, y)); // check south neighbor
                }
                if (x - 1 > 0) {
                  examList.addFirst(new IntPoint(x - 1, y)); // check north neighbor
                }
              }
            }
          }
          break;

        case EightWay:
          if (!Color.isEqual(old, replace)) {
            examList.addFirst(new IntPoint(startPoint));
            while (examList.size() > 0) {
              IntPoint p = examList.removeFirst();

              if (Color.isEqual(old, replace)) {
                int x = p.x;
                int y = p.y;

                fastBitmap.setRGB(x, y, replace);

                if ((x - 1 > 0) && (y - 1 > 0)) {
                  examList.addFirst(new IntPoint(x - 1, y - 1)); // check north-west neighbor
                }
                if (x - 1 > 0) {
                  examList.addFirst(new IntPoint(x - 1, y)); // check north neighbor
                }
                if ((x + 1 < height) && (y + 1 < width)) {
                  examList.addFirst(new IntPoint(x + 1, y + 1)); // check north-east neighbor
                }
                if (y - 1 > 0) {
                  examList.addFirst(new IntPoint(x, y - 1)); // check west neighbor
                }
                if (y + 1 < width) {
                  examList.addFirst(new IntPoint(x, y + 1)); // check east neighbor
                }
                if ((x + 1 < height) && (y - 1 > 0)) {
                  examList.addFirst(new IntPoint(x + 1, y - 1)); // check south-west neighbor
                }
                if (x + 1 < height) {
                  examList.addFirst(new IntPoint(x + 1, y)); // check south neighbor
                }
                if ((x + 1 < height) && (y + 1 < width)) {
                  examList.addFirst(new IntPoint(x + 1, y + 1)); // check south-east neighbor
                }
              }
            }
          }
          break;
      }
    } else if (fastBitmap.isGrayscale()) {
      int width = fastBitmap.getWidth();
      int height = fastBitmap.getHeight();
      LinkedList<IntPoint> examList = new LinkedList();

      int iGray = fastBitmap.getGray(startPoint);

      int _gray = gray;
      int _Gray = _gray;

      switch (algorithm) {
        case FourWay:
          if (iGray != _Gray) {
            examList.addFirst(new IntPoint(startPoint));
            while (examList.size() > 0) {
              IntPoint p = examList.removeLast();
              _gray = fastBitmap.getGray(p.x, p.y);
              _Gray = _gray;

              if (_Gray == iGray) {
                int x = p.x;
                int y = p.y;

                fastBitmap.setGray(x, y, gray);

                if (y - 1 > 0) {
                  examList.addFirst(new IntPoint(x, y - 1)); // check west neighbor
                }
                if (y + 1 < width) {
                  examList.addFirst(new IntPoint(x, y + 1)); // check east neighbor
                }
                if (x + 1 < height) {
                  examList.addFirst(new IntPoint(x + 1, y)); // check south neighbor
                }
                if (x - 1 > 0) {
                  examList.addFirst(new IntPoint(x - 1, y)); // check north neighbor
                }
              }
            }
          }
          break;

        case EightWay:
          if (iGray != _Gray) {
            examList.addFirst(new IntPoint(startPoint));
            while (examList.size() > 0) {
              IntPoint p = examList.removeFirst();
              _gray = fastBitmap.getGray(p.x, p.y);
              _Gray = _gray;

              if (_Gray == iGray) {
                int x = p.x;
                int y = p.y;

                fastBitmap.setGray(x, y, gray);

                if ((x - 1 > 0) && (y - 1 > 0)) {
                  examList.addFirst(new IntPoint(x - 1, y - 1)); // check north-west neighbor
                }
                if (x - 1 > 0) {
                  examList.addFirst(new IntPoint(x - 1, y)); // check north neighbor
                }
                if ((x + 1 < height) && (y + 1 < width)) {
                  examList.addFirst(new IntPoint(x + 1, y + 1)); // check north-east neighbor
                }
                if (y - 1 > 0) {
                  examList.addFirst(new IntPoint(x, y - 1)); // check west neighbor
                }
                if (y + 1 < width) {
                  examList.addFirst(new IntPoint(x, y + 1)); // check east neighbor
                }
                if ((x + 1 < height) && (y - 1 > 0)) {
                  examList.addFirst(new IntPoint(x + 1, y - 1)); // check south-west neighbor
                }
                if (x + 1 < height) {
                  examList.addFirst(new IntPoint(x + 1, y)); // check south neighbor
                }
                if ((x + 1 < height) && (y + 1 < width)) {
                  examList.addFirst(new IntPoint(x + 1, y + 1)); // check south-east neighbor
                }
              }
            }
          }
          break;
      }
    } else {
      throw new IllegalArgumentException("Flood fill only works in RGB and grayscale images.");
    }
  }