/**
   * Performs median filtering on a specified rectangle. The sources are cobbled.
   *
   * @param sources an array of source Rasters, guaranteed to provide all necessary source data for
   *     computing the output.
   * @param dest a WritableRaster tile containing the area to be computed.
   * @param destRect the rectangle within dest to be processed.
   */
  protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) {
    Raster source = sources[0];
    Rectangle srcRect = mapDestRect(destRect, 0);

    int formatTag = MediaLibAccessor.findCompatibleTag(sources, dest);

    MediaLibAccessor srcAccessor = new MediaLibAccessor(source, srcRect, formatTag);
    MediaLibAccessor dstAccessor = new MediaLibAccessor(dest, destRect, formatTag);
    int numBands = getSampleModel().getNumBands();

    int cmask = (1 << numBands) - 1;
    mediaLibImage[] srcML = srcAccessor.getMediaLibImages();
    mediaLibImage[] dstML = dstAccessor.getMediaLibImages();
    for (int i = 0; i < dstML.length; i++) {
      switch (dstAccessor.getDataType()) {
        case DataBuffer.TYPE_BYTE:
        case DataBuffer.TYPE_USHORT:
        case DataBuffer.TYPE_SHORT:
        case DataBuffer.TYPE_INT:
          if (maskSize == 3) {
            // Call appropriate Medialib accelerated function
            Image.MinFilter3x3(dstML[i], srcML[i]);
          } else if (maskSize == 5) {
            // Call appropriate Medialib accelerated function
            Image.MinFilter5x5(dstML[i], srcML[i]);
          } else if (maskSize == 7) {
            // Call appropriate Medialib accelerated function
            Image.MinFilter7x7(dstML[i], srcML[i]);
          }

          break;
        case DataBuffer.TYPE_FLOAT:
        case DataBuffer.TYPE_DOUBLE:
          if (maskSize == 3) {
            // Call appropriate Medialib accelerated function
            Image.MinFilter3x3_Fp(dstML[i], srcML[i]);
          } else if (maskSize == 5) {
            // Call appropriate Medialib accelerated function
            Image.MinFilter5x5_Fp(dstML[i], srcML[i]);
          } else if (maskSize == 7) {
            // Call appropriate Medialib accelerated function
            Image.MinFilter7x7_Fp(dstML[i], srcML[i]);
          }
          break;
        default:
          String className = this.getClass().getName();
          throw new RuntimeException(JaiI18N.getString("Generic2"));
      }
    }

    if (dstAccessor.isDataCopy()) {
      dstAccessor.copyDataToRaster();
    }
  }