Package org.encog.util.downsample

Source Code of org.encog.util.downsample.RGBDownsample

/*
* Encog(tm) Core v3.3 - Java Version
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-core
* Copyright 2008-2014 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*  
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.util.downsample;

import java.awt.Image;
import java.awt.image.PixelGrabber;

import org.encog.EncogError;
import org.encog.util.ImageSize;

/**
* Downsample an image keeping the RGB colors.
*
*/
public class RGBDownsample implements Downsample {
  /**
   * The pixel map from the image.
   */
  private int[] pixelMap;

  /**
   * The downsample x-ratio.
   */
  private double ratioX;

  /**
   * The downsample y-ratio.
   */
  private double ratioY;

  /**
   * The image height.
   */
  private int imageHeight;

  /**
   * The image width.
   */
  private int imageWidth;

  /**
   * The left boundary of the downsample.
   */
  private int downSampleLeft;

  /**
   * The right boundary of the downsample.
   */
  private int downSampleRight;

  /**
   * The top boundary of the downsample.
   */
  private int downSampleTop;

  /**
   * The bottom boundary of the downsample.
   */
  private int downSampleBottom;

  /**
   * The current red average.
   */
  private int currentRed;

  /**
   * The current blue average.
   */
  private int currentBlue;

  /**
   * The current green average.
   */
  private int currentGreen;

  /**
   * Called to downsample the image and store it in the down sample component.
   *
   * @param image
   *            The image to downsample.
   * @param height
   *            The height to downsample to.
   * @param width
   *            THe width to downsample to.
   * @return The downsampled image.
   */
  public double[] downSample(final Image image, final int height,
      final int width) {

    processImage(image);

    final double[] result = new double[height * width * 3];

    final PixelGrabber grabber = new PixelGrabber(image, 0, 0,
        this.imageWidth, this.imageHeight, true);

    try {
      grabber.grabPixels();
    } catch (final InterruptedException e) {
      throw new EncogError(e);
    }

    this.pixelMap = (int[]) grabber.getPixels();

    // now downsample

    this.ratioX = (double) (this.downSampleRight - this.downSampleLeft)
        / (double) width;
    this.ratioY = (double) (this.downSampleBottom - this.downSampleTop)
        / (double) height;

    int index = 0;
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        downSampleRegion(x, y);
        result[index++] = this.currentRed;
        result[index++] = this.currentGreen;
        result[index++] = this.currentBlue;
      }
    }

    return result;
  }

  /**
   * Called to downsample a region of the image.
   *
   * @param x
   *            The x coordinate of the resulting downsample.
   * @param y
   *            The y coordinate of the resulting downsample.
   */
  public void downSampleRegion(final int x, final int y) {
    final int startX = (int) (this.downSampleLeft + x * this.ratioX);
    final int startY = (int) (this.downSampleTop + y * this.ratioY);
    int endX = (int) (startX + this.ratioX);
    int endY = (int) (startY + this.ratioY);

    endX = Math.min(this.imageWidth, endX);
    endY = Math.min(this.imageHeight, endY);
   
    // sample at least one pixel (for instance if down-sample size is the same as regular size)
    endX = Math.max(startX+1, endX);
    endY = Math.max(startY+1, endY);

    int redTotal = 0;
    int greenTotal = 0;
    int blueTotal = 0;

    int total = 0;

    for (int yy = startY; yy < endY; yy++) {
      for (int xx = startX; xx < endX; xx++) {
        final int loc = xx + yy * this.imageWidth;
        final int pixel = this.pixelMap[loc];
        final int red = pixel >> 16 & 0xff;
        final int green = pixel >> 8 & 0xff;
        final int blue = pixel & 0xff;

        redTotal += red;
        greenTotal += green;
        blueTotal += blue;
        total++;
      }
    }

    this.currentRed = redTotal / total;
    this.currentGreen = greenTotal / total;
    this.currentBlue = blueTotal / total;
  }

  /**
   * This method is called to automatically crop the image so that whitespace
   * is removed.
   */
  public void findBounds() {
    // top line
    for (int y = 0; y < this.imageHeight; y++) {
      if (!hLineClear(y)) {
        this.downSampleTop = y;
        break;
      }

    }
    // bottom line
    for (int y = this.imageHeight - 1; y >= 0; y--) {
      if (!hLineClear(y)) {
        this.downSampleBottom = y;
        break;
      }
    }
    // left line
    for (int x = 0; x < this.imageWidth; x++) {
      if (!vLineClear(x)) {
        this.downSampleLeft = x;
        break;
      }
    }

    // right line
    for (int x = this.imageWidth - 1; x >= 0; x--) {
      if (!vLineClear(x)) {
        this.downSampleRight = x;
        break;
      }
    }
  }

  public int getCurrentBlue() {
    return this.currentBlue;
  }

  public int getCurrentGreen() {
    return this.currentGreen;
  }

  public int getCurrentRed() {
    return this.currentRed;
  }

  /**
   * @return the downSampleBottom
   */
  public int getDownSampleBottom() {
    return this.downSampleBottom;
  }

  /**
   * @return the downSampleLeft
   */
  public int getDownSampleLeft() {
    return this.downSampleLeft;
  }

  /**
   * @return the downSampleRight
   */
  public int getDownSampleRight() {
    return this.downSampleRight;
  }

  /**
   * @return the downSampleTop
   */
  public int getDownSampleTop() {
    return this.downSampleTop;
  }

  /**
   * @return the imageHeight
   */
  public int getImageHeight() {
    return this.imageHeight;
  }

  /**
   * @return the imageWidth
   */
  public int getImageWidth() {
    return this.imageWidth;
  }

  /**
   * @return the pixelMap
   */
  public int[] getPixelMap() {
    return this.pixelMap;
  }

  /**
   * @return the ratioX
   */
  public double getRatioX() {
    return this.ratioX;
  }

  /**
   * @return the ratioY
   */
  public double getRatioY() {
    return this.ratioY;
  }

  /**
   * This method is called internally to see if there are any pixels in the
   * given scan line. This method is used to perform autocropping.
   *
   * @param y
   *            The horizontal line to scan.
   * @return True if there were any pixels in this horizontal line.
   */
  private boolean hLineClear(final int y) {
    for (int i = 0; i < this.imageWidth; i++) {
      if (this.pixelMap[y * this.imageWidth + i] != -1) {
        return false;
      }
    }
    return true;
  }

  /**
   * Process the image and prepare it to be downsampled.
   *
   * @param image
   *            The image to downsample.
   */
  public void processImage(final Image image) {
    final ImageSize size = new ImageSize(image);
    this.imageHeight = size.getHeight();
    this.imageWidth = size.getWidth();
    this.downSampleLeft = 0;
    this.downSampleTop = 0;
    this.downSampleRight = this.imageWidth;
    this.downSampleBottom = this.imageHeight;

    this.ratioX = (double) (this.downSampleRight - this.downSampleLeft)
        / (double) getImageWidth();
    this.ratioY = (double) (this.downSampleBottom - this.downSampleTop)
        / (double) getImageHeight();
  }

  /**
   * Set the current blue average.
   * @param currentBlue The current blue average.
   */
  public void setCurrentBlue(final int currentBlue) {
    this.currentBlue = currentBlue;
  }
 
  /**
   * Set the current green average.
   * @param currentGreen The current green average.
   */
  public void setCurrentGreen(final int currentGreen) {
    this.currentGreen = currentGreen;
  }

  /**
   * Set the current red average.
   * @param currentRed The current red average.
   */
  public void setCurrentRed(final int currentRed) {
    this.currentRed = currentRed;
  }

  /**
   * Set the pixel map.
   * @param pixelMap The pixel map.
   */
  public void setPixelMap(final int[] pixelMap) {
    this.pixelMap = pixelMap;
  }

  /**
   * This method is called to determine ....
   *
   * @param x
   *            The vertical line to scan.
   * @return True if there are any pixels in the specified vertical line.
   */
  private boolean vLineClear(final int x) {
    for (int i = 0; i < this.imageHeight; i++) {
      if (this.pixelMap[i * this.imageWidth + x] != -1) {
        return false;
      }
    }
    return true;
  }

}
TOP

Related Classes of org.encog.util.downsample.RGBDownsample

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.