Part 1: Write an image viewer using JAI Your JAI image viewer must have the foll
ID: 3749134 • Letter: P
Question
Part 1: Write an image viewer using JAI
Your JAI image viewer must have the following components and functionalities:
A menu bar with a File option that opens a file from a file dialog, and an Exit option to quit the application.
Zoom-in, Zoom-out and Normal buttons. You should enable and disable the buttons whenever appropriate.
A scrollable pane to view the image.
The viewer must support JPEG and BMP. You may add other file formats if you wish.
Part 2: Write a media player using JMF
Your MMF media player should have the following components and functionalities:
It should play video files in MPEG, AVI and MOV formats, and audio files in MIDI format. Feel free to add other supported formats.
A menu bar with an Open option to open a media file, a Close option to close the currently opened file, and an Exit option to quit the application.
A control that consists of the following buttons:
Playbutton – plays the current video or audio file.
Stopbutton – stops the current video or audio file.
Pausebutton – stop playing the current video or audio file. When the play button is pressed, it continues to play the file from the paused position.
Position bar – display the current position of the media file.
Explanation / Answer
package it.geosolutions.rendered.viewer;
import static java.awt.image.DataBuffer.TYPE_DOUBLE;
import static java.awt.image.DataBuffer.TYPE_FLOAT;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.media.jai.iterator.RandomIter;
import javax.media.jai.iterator.RandomIterFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
//import com.digitalglobe.util.security.SecurityValidator;
/**
* Simple rendered image browser, allows to zoom in, out, display tile grid and
* view pixel values on mouse over
*
* @author Andrea Aime
* @author Daniele Romagnoli, GeoSolutions SAS
* @author Simone Giannecchini, GeoSolutions SAS
*
*/
public class ImageViewer extends JPanel
{
private ZoomableImageDisplay display;
private ImageViewer relatedViewer;
private JLabel status;
private RandomIter pixelIter;
private int[] ipixel;
private double[] dpixel;
private StringBuffer sb = new StringBuffer();
private RenderedImage image;
protected File lastDirectory;
public ImageViewer(ImageViewer relatedViewer)
{
this();
this.relatedViewer = relatedViewer;
}
public ImageViewer()
{
setLayout(new BorderLayout());
// build the button bar
JButton zoomIn = new JButton("Zoom in");
JButton zoomOut = new JButton("Zoom out");
final JToggleButton tileGrid = new JToggleButton("Tile grid");
JButton save = new JButton("Save...");
final JButton showChain = new JButton("Show chain in separate window");
JPanel buttonBar = new JPanel();
buttonBar.setLayout(new FlowLayout(FlowLayout.LEFT));
buttonBar.add(zoomIn);
buttonBar.add(zoomOut);
buttonBar.add(tileGrid);
buttonBar.add(save);
buttonBar.add(showChain);
// actual image viewer
display = new ZoomableImageDisplay();
// display.setBackground(Color.BLACK);
tileGrid.setSelected(display.isTileGridVisible());
// the "status bar"
status = new JLabel("Move on the image to display pixel values... ");
// compose
add(buttonBar, BorderLayout.NORTH);
add(new JScrollPane(display), BorderLayout.CENTER);
add(status, BorderLayout.SOUTH);
// events
zoomIn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
display.setScale(display.getScale() * 2.0);
if (relatedViewer != null)
{
relatedViewer.display.setScale(relatedViewer.display.getScale() * 2.0);
}
}
});
zoomOut.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
display.setScale(display.getScale() / 2.0);
if (relatedViewer != null)
{
relatedViewer.display.setScale(relatedViewer.display.getScale() / 2.0);
}
}
});
tileGrid.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
display.setTileGridVisible(tileGrid.isSelected());
if (relatedViewer != null)
{
relatedViewer.display.setTileGridVisible(tileGrid.isSelected());
}
}
});
save.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
// File location = getStartupLocation();
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new FileFilter()
{
@Override
public String getDescription()
{
return "*.png";
}
@Override
public boolean accept(File file)
{
return file.isDirectory() || file.getName().toLowerCase().endsWith(".png");
}
});
int result = chooser.showSaveDialog(ImageViewer.this);
if (result == JFileChooser.APPROVE_OPTION)
{
File selected = chooser.getSelectedFile();
if (!selected.getName().toLowerCase().endsWith(".png"))
{
selected = new File(selected.getParentFile(), selected.getName() + ".png");
}
lastDirectory = selected.getParentFile();
try
{
ImageIO.write(image, "PNG", selected);
status.setText("File successfully saved");
}
catch (IOException e)
{
status.setText("Failed to save file: " + e.getMessage());
}
}
}
});
showChain.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
RenderedImageBrowser.showChain(image);
}
});
display.addMouseMotionListener(new MouseMotionAdapter()
{
@Override
public void mouseMoved(MouseEvent e)
{
if (pixelIter != null)
{
int x = (int) Math.round(e.getX() / display.getScale());
int y = (int) Math.round(e.getY() / display.getScale());
sb.setLength(0);
if ((x < image.getMinX()) || (x >= (image.getMinX() + image.getWidth())) ||
(y < image.getMinY()) || (y >= (image.getMinY() + image.getHeight())))
{
sb.append("Outside of image bounds");
}
else
{
sb.append("Value at ");
sb.append(x).append(", ").append(y).append(": [");
int dataType = image.getSampleModel().getDataType();
if ((dataType == TYPE_DOUBLE) || (dataType == TYPE_FLOAT))
{
pixelIter.getPixel(x, y, dpixel);
for (int i = 0; i < dpixel.length; i++)
{
sb.append(dpixel[i]);
if (i < (dpixel.length - 1))
{
sb.append(", ");
}
}
}
else
{ // integer samples
pixelIter.getPixel(x, y, ipixel);
for (int i = 0; i < ipixel.length; i++)
{
sb.append(ipixel[i]);
if (i < (ipixel.length - 1))
{
sb.append(", ");
}
}
}
sb.append(']');
}
status.setText(sb.toString());
}
}
});
}
// protected File getStartupLocation()
// {
// if (lastDirectory != null)
// {
// // REMEDIATION:Path Manipulation:Critical:STIGCAT1
// SecurityValidator.getDirectoryPathValidator().validate(
// "PropertyUtil.getFileFromClasspath", lastDirectory.getAbsolutePath(), false);
//
// return lastDirectory;
// }
// else
// {
// // REMEDIATION:Path Manipulation:Critical:STIGCAT1
// return new File(SecurityValidator.getFileNameValidator().validate(
// "ImageViewer.getStartupLocation", "/tmp", false));
// }
// }
public void setImage(RenderedImage image)
{
this.image = image;
if(image == null) {
display.setVisible(false);
pixelIter = null;
} else {
display.setImage(image);
display.setVisible(true);
pixelIter = RandomIterFactory.create(image, null);
ipixel = new int[image.getSampleModel().getNumBands()];
dpixel = new double[image.getSampleModel().getNumBands()];
}
}
public ImageViewer getRelatedViewer()
{
return relatedViewer;
}
public void setRelatedViewer(ImageViewer relatedViewer)
{
this.relatedViewer = relatedViewer;
}
public void setStatusMessage(String message) {
status.setText(message);
}
}