Package magick4j.effects

Source Code of magick4j.effects.ContrastStretchEffect

package magick4j.effects;

import java.awt.image.WritableRaster;
import magick4j.Constants;
import magick4j.MagickImage;
import magick4j.PixelPacket;
import magick4j.exceptions.OptionException;

import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.round;
import static magick4j.Quantum.scaleQuantumToMap;
import static magick4j.Quantum.roundToQuantum;

/**
*
* @author serabe
*/
public class ContrastStretchEffect extends BasicEffect{
  protected double blackPoint;
  protected double currentWhitePoint;
  protected double whitePoint;

  public ContrastStretchEffect(double blackPoint, double whitePoint){
    this.blackPoint = blackPoint;
    this.whitePoint = whitePoint;
  }

  @Override
  protected MagickImage effect(MagickImage image) throws OptionException {
   
    MagickImage norm = image.createCompatible();

    int h = image.getHeight(), w = image.getWidth();
    int x, y, intensity, base;

    this.currentWhitePoint = w*h-this.whitePoint;

    double[] histogram  = new double[(int) (Constants.MaxMap+1)*4];
    double[] stretchMap = new double[(int) (Constants.MaxMap+1)*4];
    double[] p = new double[w*4];
    double[] q = new double[w*4];
    double[] black = new double[4];
    double[] white = new double[4];

    WritableRaster o = image.getImage().getRaster();
    WritableRaster d = norm.getImage().getRaster();

    /*
     * Calculate histogram.
     */
    for(y = 0; y < h; y++){

      p = o.getPixels(0, y, w, 1, p);

      // TODO Include Channels

      for(x = 0; x < w; x++){
        intensity = 4*((int) round(scaleQuantumToMap(PixelPacket.calculateIntensity(p, x*4))));
        histogram[intensity+0]++;
        histogram[intensity+1]++;
        histogram[intensity+2]++;
      }
    }

    /*
     * Find boundaries.
     */

    // TODO Include Channels.
    black[0] = black[1] = black[2] = black[3] = 0;
    white[0] = white[1] = white[2] = white[3] = (int) Constants.QuantumRange;

    black[0] = minLimit(histogram, 0);
    white[0] = maxLimit(histogram, 0);

    black[1] = minLimit(histogram, 1);
    white[1] = maxLimit(histogram, 1);

    black[2] = minLimit(histogram, 2);
    white[2] = maxLimit(histogram, 2);

    //black[3] = minLimit(histogram, 0);
    //white[3] = maxLimit(histogram, 0);

    histogram = null;

    /*
     * Calculate the strecht map
     */

    for(int i = 0; i<= Constants.MaxMap; i++){
      base = 4*i;
      // TODO Include Channels
      stretchMap[base+0] = stretch(i, black[0], white[0]);
      stretchMap[base+1] = stretch(i, black[1], white[1]);
      stretchMap[base+2] = stretch(i, black[2], white[2]);
      stretchMap[base+3] = 255;
    }

    /*
     * Modify the image.
     */

    for(y = 0; y < h; y++){

      p = o.getPixels(0, y, w, 1, p);
      System.arraycopy(p, 0, q, 0, w*4);

      for(x = 0; x < w; x++){
        base = x*4;

        // TODO Include Channels.
        q[base+0] = roundToQuantum(stretchMap[(int) (scaleQuantumToMap(p[base+0])*4+0)]);
        q[base+1] = roundToQuantum(stretchMap[(int) (scaleQuantumToMap(p[base+1])*4+1)]);
        q[base+2] = roundToQuantum(stretchMap[(int) (scaleQuantumToMap(p[base+2])*4+2)]);
        q[base+3] = 255.0;
      }

      d.setPixels(0, y, w, 1, q);
    }

    return norm;

  }

  private int maxLimit(double[] histogram, int offSet) {
    double intensity = 0.0;
    int x = 0;

    for(x = (int) Constants.MaxMap; x != 0 ; x--){
      intensity += histogram[x*4 + offSet];
      if(intensity > this.currentWhitePoint)
        break;
    }

    return x;
  }

  private int minLimit(double[] histogram, int offSet) {
    double intensity = 0.0;
    int x = 0;

    for(x = 0; x <= Constants.MaxMap; x++){
      intensity += histogram[x*4 + offSet];
      if(intensity > this.blackPoint)
        break;
    }

    return x;
  }

  private double stretch(int i, double min, double max) {
    if(i <= min){
      return 0.0;
    }else if(i >= max){
      return Constants.QuantumRange;
    }else if(min != max){
      return scaleQuantumToMap(Constants.MaxMap*(i-min)/(max-min));
    }else{
      return 0.0;
    }
  }

}
TOP

Related Classes of magick4j.effects.ContrastStretchEffect

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.