/// Evolver Copyright 2000, Morgan McGuire
/// matrix@alum.mit.edu   http://graphics3d.com/matrix
import java.awt.*;

public class FrequencyStars extends ZeroArgumentOperator implements ELOperator 
{
  /**
   * Underlying image
   */
  static protected ELMatrix image = null;

  static private synchronized void loadImage() {
    if (image == null) {
      // Initialize the underlying image
      System.out.println("(Loading flare.jpg)");

      // Single 32x32 flare
      ELMatrix flare = new ELMatrix("flare.jpg");
      
      image = ELMatrix.alloc(256, 256);
      
      for(int c = 0; c < 3; c++) {
        float imageC[] = image.channel[c];
        float flareC[] = flare.channel[c];
        
        for(int y = 255; y >= 0; y--) {
          for(int x = 255; x >= 0; x--) {
            int offset = x + y * 256;
            imageC[offset] = flareC[(x % 32) + (y % 32) * 32];
          }
        }
      }
    }
  }

  public void apply(ELMatrix argument[], ELMatrix out, ELEnvironment environment)
  {
    loadImage();

    checkArguments(argument);
    
    // For extra performance, pull the arrays into locals so we avoid
    // excess dereferences.
    float red[] = out.red;
    float grn[] = out.grn;
    float blu[] = out.blu;

    int width = out.getWidth();
    int height = out.getHeight();
    float xspan = width;
    float yspan = height;

    // Image dimensions (cache for performance)
    int w = image.getWidth();
    int h = image.getHeight();

    double filteredFrequency[] = environment.filteredFrequency;

    int i = width * height - 1;
    for(int y = height - 1; y >= 0; y--) {

      int ny = (int)((y * h) / yspan);
      int fy = ny / 32;

      for(int x = width - 1; x >= 0; x--) {
        int nx = (int)((x * w) / xspan);
        int fx = nx / 32;
        int n = nx + w * ny;
        int f = fx + 8 * fy;

        float s = (float)filteredFrequency[f];

        red[i] = image.red[n] * s;
        grn[i] = image.grn[n] * s;
        blu[i] = image.blu[n] * s;
        i--;
      }      
    }
  }

  public void paintIcon(Graphics2D graphics, int x, int y, int width, int height)
  {
    image.drawImage(graphics, x, y, width, height);
  }

  public String name()
  {
    return "FrequencyStars";
  }

  public String description()
  {
    return "Grid of stars with intensity based on input frequencies.";
  }

  public boolean hasExternalInfluences() {
    return true;
  }
}
