Package net.sourceforge.jiu.color.analysis

Source Code of net.sourceforge.jiu.color.analysis.MeanDifference

/*
* MeanDifference
*
* Copyright (c) 2003, 2004, 2005, 2006, 2007 Marco Schmidt.
* All rights reserved.
*/

package net.sourceforge.jiu.color.analysis;

import net.sourceforge.jiu.data.GrayIntegerImage;
import net.sourceforge.jiu.data.Palette;
import net.sourceforge.jiu.data.Paletted8Image;
import net.sourceforge.jiu.data.PixelImage;
import net.sourceforge.jiu.data.RGB24Image;
import net.sourceforge.jiu.data.RGBIndex;
import net.sourceforge.jiu.data.RGBIntegerImage;
import net.sourceforge.jiu.ops.MissingParameterException;
import net.sourceforge.jiu.ops.Operation;
import net.sourceforge.jiu.ops.WrongParameterException;

/**
* This operation determines the mean difference between two images.
* It requires two images of the same resolution and adds the absolute difference
* of all samples.
* Then it divides by the number of samples in the image (width times height times
* number of channels).
* <h3>Supported combinations of image types</h3>
* <ul>
* <li>One of the two images is of type {@link net.sourceforge.jiu.data.RGB24Image},
* the other of type {@link net.sourceforge.jiu.data.Paletted8Image}.</li>
* <li>Both images are of the same type and that type implements {@link net.sourceforge.jiu.data.RGBIntegerImage}.</li>
* <li>Both images are of the same type and that type implements {@link net.sourceforge.jiu.data.GrayIntegerImage}.</li>
* </ul>
* <h3>Usage example</h3>
* <pre>Double meanDifference = MeanDifference.compute(image1, image2);</pre>
* @author Marco Schmidt
* @since 0.11.0
*/
public class MeanDifference extends Operation
{
  private double diff;
  private PixelImage image1;
  private PixelImage image2;

  /**
   * Compute the mean difference between two images.
   * @param image1 first image to be examined
   * @param image2 second image to be examined
   * @return sum of all differences divided by number of pixels
   *  as Double or <code>null</code> on failure (image types
   *  are incompatible)
   * @since 0.15.0
   */
  public static Double compute(PixelImage image1, PixelImage image2)
  {
    MeanDifference diff = new MeanDifference();
    diff.setImages(image1, image2);
    try
    {
      diff.process();
      return new Double(diff.getDifference());
    }
    catch (Exception e)
    {
      return null;
    }
  }

  /**
   * Returns abs(a - b).
   * @param a first number
   * @param b second number
   * @return abs(a - b)
   */
  private static int computeDiff(int a, int b)
  {
    // code is equal to Math.abs(a - b);
    int diff = a - b;
    if (diff < 0)
    {
      return -diff;
    }
    else
    {
      return diff;
    }
  }

  /**
   * After a call to process, returns the determined mean difference value.
   * @return difference value, 0.0 or larger
   */
  public double getDifference()
  {
    return diff;
  }

  public void process() throws MissingParameterException, WrongParameterException
  {
    if (image1 == null)
    {
      throw new MissingParameterException("You must specify images using setImages.");
    }
    boolean sameType = image1.getImageType() == image2.getImageType();
    if (image1 instanceof RGB24Image && image2 instanceof Paletted8Image)
    {
      process((RGB24Image)image1, (Paletted8Image)image2);
    }
    else
    if (image2 instanceof RGB24Image && image1 instanceof Paletted8Image)
    {
      process((RGB24Image)image2, (Paletted8Image)image1);
    }
    else
    if (sameType && image1 instanceof RGBIntegerImage)
    {
      process((RGBIntegerImage)image1, (RGBIntegerImage)image2);
    }
    else
    if (sameType && image1 instanceof GrayIntegerImage)
    {
      process((GrayIntegerImage)image1, (GrayIntegerImage)image2);
    }
    else
    {
      throw new WrongParameterException("Not a supported image type combination.");
    }
  }

  private void process(GrayIntegerImage image1, GrayIntegerImage image2)
  {
    final int HEIGHT = image1.getHeight();
    final int WIDTH = image1.getWidth();
    long sum = 0;
    for (int y = 0; y < HEIGHT; y++)
    {
      for (int x = 0; x < WIDTH; x++)
      {
        sum += computeDiff(image1.getSample(x, y), image2.getSample(x, y));
      }
      setProgress(y, HEIGHT);
    }
    setDifference((double)sum / (WIDTH * HEIGHT));
  }

  private void process(RGB24Image image1, Paletted8Image image2)
  {
    final int HEIGHT = image1.getHeight();
    final int WIDTH = image1.getWidth();
    long sum = 0;
    Palette pal = image2.getPalette();
    int[] red = pal.getSamples(RGBIndex.INDEX_RED);
    int[] green = pal.getSamples(RGBIndex.INDEX_GREEN);
    int[] blue = pal.getSamples(RGBIndex.INDEX_BLUE);
    for (int y = 0; y < HEIGHT; y++)
    {
      for (int x = 0; x < WIDTH; x++)
      {
        int palSample = image2.getSample(x, y);
        sum += computeDiff(image1.getSample(RGBIndex.INDEX_RED, x, y), red[palSample]);
        sum += computeDiff(image1.getSample(RGBIndex.INDEX_GREEN, x, y), green[palSample]);
        sum += computeDiff(image1.getSample(RGBIndex.INDEX_BLUE, x, y), blue[palSample]);
      }
      setProgress(y, HEIGHT);
    }
    setDifference((double)sum / (WIDTH * HEIGHT * 3));
  }

  private void process(RGBIntegerImage image1, RGBIntegerImage image2)
  {
    final int HEIGHT = image1.getHeight();
    final int WIDTH = image1.getWidth();
    long sum = 0;
    for (int y = 0; y < HEIGHT; y++)
    {
      for (int x = 0; x < WIDTH; x++)
      {
        sum += computeDiff(image1.getSample(RGBIndex.INDEX_RED, x, y), image2.getSample(RGBIndex.INDEX_RED, x, y));
        sum += computeDiff(image1.getSample(RGBIndex.INDEX_GREEN, x, y), image2.getSample(RGBIndex.INDEX_GREEN, x, y));
        sum += computeDiff(image1.getSample(RGBIndex.INDEX_BLUE, x, y), image2.getSample(RGBIndex.INDEX_BLUE, x, y));
      }
      setProgress(y, HEIGHT);
    }
    setDifference((double)sum / (WIDTH * HEIGHT * 3));
  }

  private void setDifference(double newValue)
  {
    diff = newValue;
  }

  /**
   * Sets the two images for which the mean difference is to be
   * determined.
   * @param firstImage first image
   * @param secondImage second image
   * @throws IllegalArgumentException if either of the images is null,
   *  if their resolution is different or if their types are not supported
   *  by this operation
   */
  public void setImages(PixelImage firstImage, PixelImage secondImage)
  {
    if (firstImage == null || secondImage == null)
    {
      throw new IllegalArgumentException("Both image arguments must be non-null.");
    }
    if (firstImage.getWidth() != secondImage.getWidth())
    {
      throw new IllegalArgumentException("The images must have the same width.");
    }
    if (firstImage.getHeight() != secondImage.getHeight())
    {
      throw new IllegalArgumentException("The images must have the same height.");
    }
    image1 = firstImage;
    image2 = secondImage;
  }
}
TOP

Related Classes of net.sourceforge.jiu.color.analysis.MeanDifference

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.