001/*
002 * Copyright 2010, 2011 Institut Pasteur.
003 * 
004 * This file is part of ICY.
005 * 
006 * ICY is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * ICY is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with ICY. If not, see <http://www.gnu.org/licenses/>.
018 */
019package plugins.tutorial.roi;
020
021import icy.canvas.IcyCanvas;
022import icy.canvas.IcyCanvas2D;
023import icy.image.IcyBufferedImage;
024import icy.painter.Overlay;
025import icy.roi.ROI2D;
026import icy.sequence.Sequence;
027import icy.type.collection.array.Array1DUtil;
028import icy.util.ShapeUtil;
029import icy.util.ShapeUtil.ShapeConsumer;
030
031import java.awt.Color;
032import java.awt.Graphics2D;
033import java.awt.Polygon;
034import java.awt.Shape;
035import java.awt.geom.Line2D;
036
037import plugins.kernel.roi.roi2d.ROI2DShape;
038
039/**
040 * This painter draws an intensity profile of the image over a polyline
041 * 
042 * @author Fabrice de Chaumont
043 * @author Stephane Dallongeville
044 */
045public class IntensityOverRoiPainter extends Overlay
046{
047    public IntensityOverRoiPainter()
048    {
049        super("Intensity test overlay");
050    }
051
052    @Override
053    public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas)
054    {
055        // check if we are dealing with a canvas 2D and we have a valid Graphics object
056        if ((canvas instanceof IcyCanvas2D) && (g != null))
057        {
058            // create a graphics object so that we can then dispose it at the end of the paint to
059            // clean all change performed in the paint, like transform, color change, stroke (...).
060            Graphics2D g2 = (Graphics2D) g.create();
061
062            for (ROI2D roi : sequence.getROI2Ds())
063            {
064                if (roi instanceof ROI2DShape)
065                    computeIntensityROI((ROI2DShape) roi, g2, sequence, canvas);
066            }
067
068            g2.dispose();
069        }
070    }
071
072    private static void computeIntensityROI(ROI2DShape roi, final Graphics2D g, final Sequence sequence, final IcyCanvas canvas)
073    {
074        ShapeUtil.consumeShapeFromPath(roi.getPathIterator(null), new ShapeConsumer()
075        {
076            @Override
077            public boolean consume(Shape shape)
078            {
079                if (shape instanceof Line2D)
080                    drawHisto((Line2D) shape, g, sequence, canvas);
081
082                return true; // continue
083            }
084        });
085    }
086
087    static void drawHisto(Line2D line, Graphics2D g, Sequence sequence, final IcyCanvas canvas)
088    {
089        for (int component = 0; component < sequence.getSizeC(); component++)
090        {
091            // create histo data
092            int distance = (int) line.getP1().distance(line.getP2());
093
094            double vx = (line.getP2().getX() - line.getP1().getX()) / distance;
095            double vy = (line.getP2().getY() - line.getP1().getY()) / distance;
096
097            double[] data = new double[distance];
098
099            double x = line.getP1().getX();
100            double y = line.getP1().getY();
101
102            for (int i = 0; i < distance; i++)
103            {
104                IcyBufferedImage image = canvas.getCurrentImage();
105                if (image.isInside((int) x, (int) y))
106                {
107                    data[i] = Array1DUtil.getValue(image.getDataXY(component), image.getOffset((int) x, (int) y),
108                            image.isSignedDataType());
109                }
110                else
111                {
112                    data[i] = 0;
113                }
114
115                x += vx;
116                y += vy;
117            }
118
119            final Graphics2D g2 = (Graphics2D) g.create();
120
121            Polygon polygon = new Polygon();
122            polygon.addPoint(0, 0);
123            for (int i = 0; i < distance; i++)
124                // pity polygon does not support this with double...
125                polygon.addPoint(i, (int) data[i]);
126            polygon.addPoint(distance, 0);
127
128            g2.setColor(Color.white);
129            if (sequence.getSizeC() != 1)
130            {
131                if (component == 0)
132                    g2.setColor(Color.red);
133                if (component == 1)
134                    g2.setColor(Color.green);
135                if (component == 2)
136                    g2.setColor(Color.blue);
137            }
138
139            // transform to put the painter at the right place
140            g2.translate(line.getX1(), line.getY1());
141            g2.rotate(Math.atan2(vy, vx), 0, 0);
142
143            g2.draw(polygon);
144
145            g2.dispose();
146        }
147    }
148}