All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.mistral.example.histogramviewer.XYPlotter Maven / Gradle / Ivy

/***********************************************************************************************************************
 *
 * Mistral - open source imaging engine
 * Copyright (C) 2003-2012 by Tidalwave s.a.s.
 *
 ***********************************************************************************************************************
 *
 * 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.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://mistral.tidalwave.it
 * SCM: https://bitbucket.org/tidalwave/mistral-src
 *
 **********************************************************************************************************************/
package it.tidalwave.mistral.example.histogramviewer;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JComponent;
import it.tidalwave.image.render.Overlay;

/*******************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 ******************************************************************************/
public class XYPlotter extends JComponent
  {
    class DataBundle
      {
        private int[] data;

        private Color color;

        public DataBundle (int[] data, Color color)
          {
            this.data = data;
            this.color = color;
          }

        public int[] getData ()
          {
            return data;
          }

        public Color getColor ()
          {
            return color;
          }
      }

    private Map dataMap = new HashMap();

    private List dataList = new ArrayList(); // needed to keep the order

    private int max;

    private int min;

    private BufferedImage buffer;

    private Overlay overlay;

    public final static int LINEAR = 0;

    public final static int LOG = 1;

    private int xMode = LINEAR;

    private int logXBands = 2;

    private boolean area = false;

    public XYPlotter()
      {
        setOpaque(false);
      }
    
    /*******************************************************************************
     * 
     * 
     * 
     *******************************************************************************/
    public void setXAxisLinear ()
      {
        this.xMode = LINEAR;
      }

    /*******************************************************************************
     * 
     * @param logXBands
     * 
     *******************************************************************************/
    public void setXAxisLogarithmic (int logXBands)
      {
        this.logXBands = logXBands;
        this.xMode = LOG;
      }

    /*******************************************************************************
     * 
     * 
     * 
     *******************************************************************************/
    public void setAreaPlot ()
      {
        area = true;
      }

    /*******************************************************************************
     * 
     * @return
     * 
     *******************************************************************************/
    public boolean isXAxisLogarithmic ()
      {
        return xMode == LOG;
      }

    /*******************************************************************************
     * 
     * 
     * 
     *******************************************************************************/
    public void clearData ()
      {
        dataList.clear();
        dataMap.clear();
        min = Integer.MAX_VALUE;
        max = Integer.MIN_VALUE;
        buffer = null;
      }

    /*******************************************************************************
     * 
     * @param key
     * @param data
     * @param color
     * 
     *******************************************************************************/
    public void addUnsignedData (Object key, short[] data, Color color)
      {
        int[] data2 = new int[data.length];

        for (int i = 0; i < data.length; i++)
          {
            data2[i] = data[i] & 0xffff;
          }

        addData(key, data2, color);
      }

    /*******************************************************************************
     * 
     * @param key
     * @param data
     * @param color
     * 
     *******************************************************************************/
    public void addData (Object key, int[] data, Color color)
      {
        buffer = null;
        int[] myData = new int[data.length];
        System.arraycopy(data, 0, myData, 0, data.length);

        for (int i = 0; i < myData.length; i++)
          {
            int d = myData[i];
            max = Math.max(max, d);
            min = Math.min(min, d);
          }

        dataMap.put(key, new DataBundle(myData, color));
        dataList.add(key);

        if (isVisible())
          repaint();

        //        System.err.println("Data: " + data.length + " max: " + max + " min: " + min);
      }

    /*******************************************************************************
     * 
     * @inheritDoc
     * 
     *******************************************************************************/
    public void paint (Graphics g)
      {
        if ((buffer == null) || (buffer.getWidth() != getWidth()) || (buffer.getHeight() != getHeight()))
          {
            buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = null;

            try
              {
                g2 = (Graphics2D)buffer.getGraphics();

                if (!area)
                  {
                    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                  }

                else
                  {
                    //g2.setComposite(AlphaComposite.Xor);
                  }

                plot(g2);
              }

            finally
              {
                g2.dispose();
              }
          }

        if (buffer != null)
          {
            g.drawImage(buffer, 0, 0, null);
          }

        else
          plot(g);
      }

    /*******************************************************************************
     *
     * Sets an overlay to overimpose to the image.
     *
     * @param  overlay  the overlay
     *
     ******************************************************************************/
    public void setOverlay (Overlay overlay)
      {
        this.overlay = overlay;
      }

    /*******************************************************************************
     * 
     * @param g
     * 
     *******************************************************************************/
    private void plot (Graphics g)
      {
        Graphics2D g2 = (Graphics2D)g.create();

        try
          {
            int width = getSize().width;
            int height = getSize().height;

            g.setColor(new Color(0, 0, 0, 0));
            g.fillRect(0, 0, width, height);

            if (overlay != null)
              {
//                overlay.paint(g, getBounds());
              }

            int xMin = 0;
            double f = 0;

            if (xMode == LOG)
              {
                double xMinNorm = 1 / Math.pow(2, logXBands);
                f = 1.0 / (logXBands * Math.log(2));
                xMin = (int)Math.round(xMinNorm * width);
              }

            else if (xMode == LINEAR)
              {
                xMin = 0;
              }

            int yMax = Integer.MIN_VALUE;

            for (Iterator j = dataList.iterator(); j.hasNext();)
              {
                Object key = j.next();
                DataBundle dataBundle = (DataBundle)dataMap.get(key);
                int[] data = dataBundle.getData();

                for (int i = xMin; i < data.length; i++)
                  {
                    yMax = Math.max(yMax, data[i]);
                  }
              }

            double yScale = (double)height / (double)yMax;

            for (Iterator j = dataMap.values().iterator(); j.hasNext();)
              {
                DataBundle dataBundle = (DataBundle)j.next();
                g.setColor(dataBundle.getColor());
                int[] data = dataBundle.getData();
                int mask = dataBundle.getColor().getRGB();

                boolean first = true;
                int length = data.length;
                double xScale = (double)width / (double)length;
                int prevX = 0, prevY = 0;

                for (int i = xMin; i < length; i++)
                  {
                    int x = 0;

                    if (xMode == LINEAR)
                      {
                        x = (int)Math.round(i * xScale);
                      }

                    else if (xMode == LOG)
                      {
                        double xNorm = (double)i / (double)length;
                        xNorm = 1 + Math.log(xNorm) * f;
                        x = (int)Math.round(xNorm * width);
                      }

                    int y = height - (int)Math.round(data[i] * yScale);

                    if (!first)
                      {
                        if (!area)
                          {
                            g.drawLine(prevX, prevY, x, y);
                          }

                        else
                          {
                            for (int xx = prevX; xx < x; xx++)
                              {
                                for (int yy = y; yy < height; yy++)
                                  {
                                    int rgb = buffer.getRGB(xx, yy);
                                    buffer.setRGB(xx, yy, rgb | mask);
                                  }

                                //g.drawLine(x, height, x, y);
                              }
                          }
                      }

                    prevX = x;
                    prevY = y;
                    first = false;
                  }
              }
          }

        finally
          {
            g2.dispose();
          }
      }
  }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy