Package com.lightcrafts.media.jai.opimage

Source Code of com.lightcrafts.media.jai.opimage.MedianFilterOpImage

/*
* $RCSfile: MedianFilterOpImage.java,v $
*
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* Use is subject to license terms.
*
* $Revision: 1.1 $
* $Date: 2005/02/11 04:56:33 $
* $State: Exp $
*/
package com.lightcrafts.media.jai.opimage;
import java.awt.Rectangle;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import com.lightcrafts.mediax.jai.AreaOpImage;
import com.lightcrafts.mediax.jai.BorderExtender;
import com.lightcrafts.mediax.jai.ImageLayout;
import com.lightcrafts.mediax.jai.RasterAccessor;
import com.lightcrafts.mediax.jai.RasterFormatTag;
import java.util.Map;
import com.lightcrafts.mediax.jai.operator.MedianFilterShape;
// import com.lightcrafts.media.jai.test.OpImageTester;

/**
* An abstract OpImage class that subclasses will use to perform
* MedianFiltering with specific masks.
*
*
*/
abstract class MedianFilterOpImage extends AreaOpImage {

    protected MedianFilterShape maskType;
    protected int maskSize;

    /**
     * Creates a MedianFilterOpImage given an image source, an
     * optional BorderExtender, a maskType and maskSize.  The image
     * dimensions are derived the source image.  The tile grid layout,
     * SampleModel, and ColorModel may optionally be specified by an
     * ImageLayout object.
     *
     * @param source a RenderedImage.
     * @param extender a BorderExtender, or null.
     * @param layout an ImageLayout optionally containing the tile grid layout,
     *        SampleModel, and ColorModel, or null.
     * @param maskType the filter mask type.
     * @param maskSize the filter mask size.
     */
    public MedianFilterOpImage(RenderedImage source,
                               BorderExtender extender,
                               Map config,
                               ImageLayout layout,
                               MedianFilterShape maskType,
                               int maskSize) {
  super(source,
              layout,
              config,
              true,
              extender,
              (maskSize-1)/2,
              (maskSize-1)/2,
              (maskSize/2),
              (maskSize/2));
        this.maskType = maskType;
        this.maskSize = maskSize;
    }

    /**
     * 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) {
        // Retrieve format tags.
        RasterFormatTag[] formatTags = getFormatTags();

        Raster source = sources[0];
        Rectangle srcRect = mapDestRect(destRect, 0);
        RasterAccessor srcAccessor =
            new RasterAccessor(source, srcRect,
                               formatTags[0],
                               getSource(0).getColorModel());
        RasterAccessor dstAccessor =
            new RasterAccessor(dest, destRect, 
                               formatTags[1], getColorModel());
        switch (dstAccessor.getDataType()) {
        case DataBuffer.TYPE_BYTE:
            byteLoop(srcAccessor, dstAccessor, maskSize);
            break;
        case DataBuffer.TYPE_SHORT:
            shortLoop(srcAccessor, dstAccessor, maskSize);
            break;
        case DataBuffer.TYPE_USHORT:
            ushortLoop(srcAccessor, dstAccessor, maskSize);
            break;
        case DataBuffer.TYPE_INT:
            intLoop(srcAccessor, dstAccessor, maskSize);
            break;
        case DataBuffer.TYPE_FLOAT:
            floatLoop(srcAccessor, dstAccessor, maskSize);
            break;
        case DataBuffer.TYPE_DOUBLE:
            doubleLoop(srcAccessor, dstAccessor, maskSize);
            break;
        }
        // If the RasterAccessor object set up a temporary buffer for the
        // op to write to, tell the RasterAccessor to write that data
        // to the raster no that we're done with it.
        if (dstAccessor.isDataCopy()) {
            dstAccessor.clampDataArrays();
            dstAccessor.copyDataToRaster();
        }
    }

    /** Performs median filtering using the subclass's mask on byte data */
    protected abstract void byteLoop(RasterAccessor src,
                                     RasterAccessor dst,
                                     int filterSize);

    /** Performs median filtering using the subclass's mask on short data */
    protected abstract void shortLoop(RasterAccessor src,
                                      RasterAccessor dst,
                                      int filterSize);

    /** Performs median filtering using the subclass's mask on ushort data */
    protected abstract void ushortLoop(RasterAccessor src,
                                       RasterAccessor dst,
                                       int filterSize);
         
    /** Performs median filtering using the subclass's mask on int data */
    protected abstract void intLoop(RasterAccessor src,
                                    RasterAccessor dst,
                                    int filterSize);

    /** Performs median filtering using the subclass's mask on float data */
    protected abstract void floatLoop(RasterAccessor src,
                                      RasterAccessor dst,
                                      int filterSize);

    /** Performs median filtering using the subclass's mask on double data */
    protected abstract void doubleLoop(RasterAccessor src,
                                       RasterAccessor dst,
                                       int filterSize);

    /** Returns the median of the input integer array */
    protected int medianFilter(int data[]) {
        if (data.length == 3) {
           int a = data[0];
           int b = data[1];
           int c = data[2];
           if (a < b) {
              if (b < c) {
                  return b;
              } else {
                  if (c > a) {
                      return c;
                  } else {
                      return a;
                  }
              }
           } else {
              if (a < c) {
                  return a;
              } else {
                  if (b < c) {
                     return c;
                  } else {
                     return b;
                  }
              }
           }
        }
        int left=0;
        int right=data.length-1;
        int target = data.length/2;
        while (true) {
            int oleft = left;
            int oright = right;
            int mid = data[(left+right)/2];
            do {
              while(data[left]<mid) {
                left++;
              }
              while (mid<data[right]) {
                right--;
              }
              if (left<=right) {
                int tmp=data[left];
                data[left]=data[right];
                data[right]=tmp;
                left++;
                right--;
              }
            } while (left<=right);
            if (oleft<right && right >= target) {
                left = oleft;
            } else if (left<oright && left <= target) {
                right = oright;
            } else {
                return data[target];
            }
        }
    }

    /** Returns the median of the input float array */
    protected float medianFilterFloat(float data[]) {
        if (data.length == 3) {
           float a = data[0];
           float b = data[1];
           float c = data[2];
           if (a < b) {
              if (b < c) {
                  return b;
              } else {
                  if (c > a) {
                      return c;
                  } else {
                      return a;
                  }
              }
           } else {
              if (a < c) {
                  return a;
              } else {
                  if (b < c) {
                     return c;
                  } else {
                     return b;
                  }
              }
           }
        }
        int left=0;
        int right=data.length-1;
        int target = data.length/2;
        while (true) {
            int oleft = left;
            int oright = right;
            float mid = data[(left+right)/2];
            do {
              while(data[left]<mid) {
                left++;
              }
              while (mid<data[right]) {
                right--;
              }
              if (left<=right) {
                float tmp=data[left];
                data[left]=data[right];
                data[right]=tmp;
                left++;
                right--;
              }
            } while (left<=right);
            if (oleft<right && right >= target) {
                left = oleft;
            } else if (left<oright && left <= target) {
                right = oright;
            } else {
                return data[target];
            }
        }
    }

    /** Returns the median of the input double array */
    protected double medianFilterDouble(double data[]) {
        if (data.length == 3) {
           double a = data[0];
           double b = data[1];
           double c = data[2];
           if (a < b) {
              if (b < c) {
                  return b;
              } else {
                  if (c > a) {
                      return c;
                  } else {
                      return a;
                  }
              }
           } else {
              if (a < c) {
                  return a;
              } else {
                  if (b < c) {
                     return c;
                  } else {
                     return b;
                  }
              }
           }
        }
        int left=0;
        int right=data.length-1;
        int target = data.length/2;
        while (true) {
            int oleft = left;
            int oright = right;
            double mid = data[(left+right)/2];
            do {
              while(data[left]<mid) {
                left++;
              }
              while (mid<data[right]) {
                right--;
              }
              if (left<=right) {
                double tmp=data[left];
                data[left]=data[right];
                data[right]=tmp;
                left++;
                right--;
              }
            } while (left<=right);
            if (oleft<right && right >= target) {
                left = oleft;
            } else if (left<oright && left <= target) {
                right = oright;
            } else {
                return data[target];
            }
        }
    }

//     // Calls a method on OpImage that uses introspection, to make this
//     // class, discover it's createTestImage() call, call it and then
//     // benchmark the performance of the created OpImage chain.
//     public static void main(String args[]) {
//         String classname =
//                "com.lightcrafts.media.jai.opimage.MedianFilterSquareOpImage";
//         OpImageTester.performDiagnostics(classname,args);
//         classname =
//                "com.lightcrafts.media.jai.opimage.MedianFilterXOpImage";
//         OpImageTester.performDiagnostics(classname,args);
//         classname =
//                "com.lightcrafts.media.jai.opimage.MedianFilterPlusOpImage";
//         OpImageTester.performDiagnostics(classname,args);
//         classname =
//                "com.lightcrafts.media.jai.opimage.MedianFilterSeparableOpImage";
//         OpImageTester.performDiagnostics(classname,args);
//     }
}
TOP

Related Classes of com.lightcrafts.media.jai.opimage.MedianFilterOpImage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.