/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* This file is part of CATS.
*
* CATS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CATS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CATS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.comcast.cats.vision.panel.imagecompare;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.List;
import javax.swing.GroupLayout;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
import com.comcast.cats.event.CatsEvent;
import com.comcast.cats.event.CatsEventHandler;
import com.comcast.cats.event.VideoEvent;
import com.comcast.cats.image.RegionInfo;
public class FreezeVideoPanel extends JPanel implements MouseListener, MouseMotionListener, CatsEventHandler
{
private static final long serialVersionUID = -758016315574347047L;
private static final Logger logger = Logger.getLogger( FreezeVideoPanel.class );
private Point start = new Point();
private Point end = start;
private BufferedImage image = null;
private BufferedImage backUpSnapshot = null;
private final BasicStroke dashed = new BasicStroke( 1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
10.0f, new float[]
{ 10.0f }, 0.0f );
private int rectX;
private int rectY;
private int rectWidth;
private int rectHeight;
private Rectangle2D.Double selectionRect = new Rectangle2D.Double( 0, 0, 0, 0 );
private RegionDetailsPanel regionDetailsPanel;
private boolean videoMode = false;
private List< RegionInfo > regionsList;
public FreezeVideoPanel( BufferedImage image )
{
this.image = image;
initImageScreen();
addMouseListener( this );
addMouseMotionListener( this );
setMinimumSize( getSize() );
}
/**
* Initialize the panel screen dimension/size. This call is needed in order
* to display the initial image screen at 720x480.
*/
public void initImageScreen()
{
logger.info( "Initializing Image panel" );
GroupLayout layout = new GroupLayout( this );
this.setLayout( layout );
refreshSize();
}
/**
* Initiate painting of a region.
*
* @param region
* The region details.
*/
public void paintRegion( RegionInfo region )
{
if ( region != null )
{
start = new Point( region.getX(), region.getY() );
end = new Point( region.getX() + region.getWidth(), region.getY() + region.getHeight() );
repaint();
}
}
/**
* Clear all regions from the snapshot.
*/
public void clearRegion()
{
start.setLocation( 0, 0 );
end = start;
regionsList = null;
repaint();
}
/**
* Paints all regions on the snapshot.
*
* @param regionsList
* List of regions
*/
public void paintRegions( List< RegionInfo > regionsList )
{
if ( regionsList != null )
{
this.regionsList = regionsList;
}
}
/**
* Paint method
*/
public void paint( Graphics g )
{
Graphics2D g2 = ( Graphics2D ) g;
g2.clearRect( 0, 0, this.getWidth(), this.getHeight() );
g2.setStroke( dashed );
g2.setColor( Color.WHITE );
if ( !videoMode )
{
if ( image != null )
{
// Calculate the rectangle.
rectX = ( int ) start.getX();
rectY = ( int ) start.getY();
rectWidth = ( int ) ( end.getX() - start.getX() );
rectHeight = ( int ) ( end.getY() - start.getY() );
if ( rectWidth < 0 )
{
rectX += rectWidth;
rectWidth *= -1;
}
if ( rectHeight < 0 )
{
rectY += rectHeight;
rectHeight *= -1;
}
if ( start != end )
{
// User is selecting a region, draw image translucent.
BufferedImage translucentSnapShot = ImageFunctions.maskImageTranslucent( image, 0.7f );
g2.drawImage( translucentSnapShot, 0, 0, ( int ) ( translucentSnapShot.getWidth() ),
( int ) ( translucentSnapShot.getHeight() ), this );
}
else
{
// No region is being selected, draw the actual image.
rectWidth = 0;
rectHeight = 0;
g2.drawImage( image, 0, 0, ( int ) ( image.getWidth() ), ( int ) ( image.getHeight() ), this );
}
// Draw the non transparent subimage in the selected area.
if ( rectWidth > 0 && rectHeight > 0 )
{
// Make sure we don't draw outside of the raster.
if ( ( rectX + rectWidth ) >= image.getWidth() )
{
rectWidth = image.getWidth() - rectX;
}
else if ( rectX < 0 )
{
rectX = 0;
}
if ( ( rectY + rectHeight ) >= image.getHeight() )
{
rectHeight = image.getHeight() - rectY;
}
else if ( rectY < 0 )
{
rectY = 0;
}
g2.drawImage( image.getSubimage( rectX, rectY, rectWidth, rectHeight ), rectX, rectY, this );
selectionRect.setFrame( rectX, rectY, rectWidth, rectHeight );
g2.draw( selectionRect );
}
// Update the panel with coordinates.
if ( regionDetailsPanel != null )
{
regionDetailsPanel.setRegionInfo( rectX, rectY, rectWidth, rectHeight );
}
}
}
else
{
g2.drawImage( image, 0, 0, ( int ) ( image.getWidth() ), ( int ) ( image.getHeight() ), this );
if ( regionsList != null )
{
for ( RegionInfo region : regionsList )
{
g2.drawRect( region.getX(), region.getY(), region.getWidth(), region.getHeight() );
}
}
}
}
@Override
public void mousePressed( MouseEvent e )
{
start = e.getPoint();
}
@Override
public void mouseDragged( MouseEvent e )
{
end = e.getPoint();
// Don't let the end point go off screen.
if ( end.getX() < 0 )
{
end.setLocation( 0, end.getY() );
}
if ( end.getY() < 0 )
{
end.setLocation( end.getX(), 0 );
}
repaint();
}
@Override
public void mouseClicked( MouseEvent e )
{
start = end = e.getPoint();
repaint();
}
@Override
public void mouseEntered( MouseEvent e )
{
}
@Override
public void mouseExited( MouseEvent e )
{
}
@Override
public void mouseReleased( MouseEvent e )
{
}
@Override
public void mouseMoved( MouseEvent e )
{
}
/**
* Registers the RegionDetailsPanel that will maintain the region
* information of this snapshot.
*
* @param regionDetailsPanel
* The region details panel.
*/
public void registerDetailsPanel( RegionDetailsPanel regionDetailsPanel )
{
if ( null != regionDetailsPanel )
{
this.regionDetailsPanel = regionDetailsPanel;
}
}
/**
* Sets a snapshot to this panel as the current frozen image.
*
* @param image
* The snapshot to be set.
*/
public void setSnapshot( final BufferedImage image )
{
this.image = image;
refreshSize();
repaint();
}
private void refreshSize()
{
GroupLayout layout = ( GroupLayout ) getLayout();
layout.setHorizontalGroup( layout.createParallelGroup( GroupLayout.Alignment.LEADING ).addGap( 0,
image.getWidth(), Short.MAX_VALUE ) );
layout.setVerticalGroup( layout.createParallelGroup( GroupLayout.Alignment.LEADING ).addGap( 0,
image.getHeight(), Short.MAX_VALUE ) );
}
/**
* Get the current frozen image.
*
* @return
*/
public BufferedImage getSnapshot()
{
return image;
}
/**
* Start video mode; The panel will run the current video.
*/
public void startVideoMode()
{
videoMode = true;
backUpSnapshot = image; // back up the frozen image.
}
/**
* Stop video.
*/
public void stopVideoMode()
{
image = backUpSnapshot; // revert back to the snapshot.
repaint();
videoMode = false;
}
@Override
public void catsEventPerformed( CatsEvent evt )
{
if ( evt instanceof VideoEvent )
{
VideoEvent vEvent = ( VideoEvent ) evt;
image = vEvent.getImage(); // update the current frame and reapint.
repaint();
}
}
public boolean isVideoMode()
{
return videoMode;
}
public void setVideoMode( boolean videoMode )
{
this.videoMode = videoMode;
}
public BufferedImage getImage()
{
return image;
}
public void setImage( BufferedImage image )
{
this.image = image;
repaint();
}
}