MIASDBViewer.java
package ac.essex.ooechs.imaging.commons.apps;
import ac.essex.ooechs.imaging.commons.util.panels.ImagePanel;
import ac.essex.ooechs.imaging.commons.PixelLoader;
import javax.swing.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.File;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Vector;
import java.util.StringTokenizer;
/**
* <p/>
* This program 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 2
* of the License, or (at your option) any later version,
* provided that any use properly credits the author.
* This program 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 at http://www.gnu.org
* </p>
*
* @author Olly Oechsle, University of Essex, Date: 29-Jan-2007
* @version 1.0
*/
public class MIASDBViewer extends JFrame {
public static final String APP_NAME = "MIAS Viewer";
final File directory = new File("/home/ooechs/Desktop/mias/");
private ImagePanel imagePanel;
private JLabel abnormality;
private JLabel backgroundTissueType;
private JLabel severity;
Vector<MIASImage> images;
int cursor = 0;
public static void main(String[] args) {
new MIASDBViewer();
}
public MIASDBViewer() {
super(APP_NAME);
JMenu file = new JMenu("File");
JMenuItem open = new JMenuItem("Open");
open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
read(new File(directory, "Info.txt"));
}
});
JMenuItem exit = new JMenuItem("Exit");
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
file.add(open);
file.add(exit);
JMenuBar bar = new JMenuBar();
bar.add(file);
setJMenuBar(bar);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton btnNext = new JButton("Next");
JButton btnPrev = new JButton("Prev");
btnNext.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
next();
}
});
btnPrev.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
prev();
}
});
panel.add(btnPrev);
panel.add(btnNext);
JPanel status = new JPanel(new GridLayout(1, 3));
abnormality = new JLabel("");
severity = new JLabel("");
backgroundTissueType = new JLabel("");
status.add(backgroundTissueType);
status.add(abnormality);
status.add(severity);
Container c = getContentPane();
imagePanel = new ImagePanel();
c.add(panel, BorderLayout.NORTH);
c.add(imagePanel, BorderLayout.CENTER);
c.add(status, BorderLayout.SOUTH);
setSize(1024, 1024);
setVisible(true);
}
public void next() {
if (images == null) {
alert("Load images first");
return;
}
if (cursor < images.size()) {
MIASImage image = images.elementAt(cursor);
cursor++;
displayImage(image);
} else {
alert("No more images");
}
}
public void prev() {
if (images == null) {
alert("Load images first");
return;
}
if (cursor > 0) {
MIASImage image = images.elementAt(cursor - 1);
cursor--;
displayImage(image);
} else {
alert("Can't go back");
}
}
public void displayImage(MIASImage image) {
try {
PixelLoader loader = new PixelLoader(new File(directory, image.getFilename() + ".pgm.bmp"));
BufferedImage img = loader.getBufferedImage();
if (image.getX() != -1) {
Graphics g = img.getGraphics();
if (image.getSeverity() == MIASImage.BENIGN) {
g.setColor(Color.WHITE);
} else {
g.setColor(Color.RED);
}
int halfRadius = image.getRadius() / 2;
int x = image.getX() - halfRadius;
int y = img.getHeight() - image.getY() - halfRadius;
g.drawOval(x, y, image.getRadius(), image.getRadius());
}
imagePanel.setImage(img);
abnormality.setText("Abnormality: " + image.abnormalityToString());
severity.setText("Severity: " + image.severityToString());
backgroundTissueType.setText("Background: " + image.backgroundTypeToString());
setTitle(APP_NAME + " - " + image.getFilename());
} catch (Exception e) {
alert("Can't load next image: " + e);
}
}
public void read(File f) {
cursor = 0;
images = new Vector<MIASImage>(100);
try {
BufferedReader in = new BufferedReader(new FileReader(f));
if (!in.ready()) throw new IOException();
String line;
while ((line = in.readLine()) != null) {
if (line.startsWith("mdb")) {
int x = -1;
int y = -1;
int radius = 0;
StringTokenizer tokenizer = new StringTokenizer(line);
String filename = tokenizer.nextToken();
String backgroundTissue = tokenizer.nextToken();
String abnormality = tokenizer.nextToken();
String severity = "";
if (tokenizer.hasMoreTokens()) {
severity = tokenizer.nextToken();
try {
if (tokenizer.hasMoreTokens()) {
x = Integer.parseInt(tokenizer.nextToken());
y = Integer.parseInt(tokenizer.nextToken());
radius = Integer.parseInt(tokenizer.nextToken());
}
} catch (NumberFormatException nfe) {
// do nothing.
}
}
images.add(new MIASImage(filename, backgroundTissue, abnormality, severity, x, y, radius));
}
}
System.out.println("Loaded: " + images.size() + " images.");
next();
} catch (IOException e) {
alert("Error Reading file: " + e);
}
}
public void alert(String message) {
JOptionPane.showMessageDialog(this, message);
}
class MIASImage {
/*
1st column: MIAS database reference number.
2nd column: Character of background tissue:
F - Fatty
G - Fatty-glandular
D - Dense-glandular
3rd column: Class of abnormality present:
CALC - Calcification
CIRC - Well-defined/circumscribed masses
SPIC - Spiculated masses
MISC - Other, ill-defined masses
ARCH - Architectural distortion
ASYM - Asymmetry
NORMAL - Normal
4th column: Severity of abnormality;
B - Benign
M - Malignant
*/
public static final int FATTY = 0;
public static final int FATTY_GLANDULAR = 1;
public static final int DENSE_GLANDULAR = 2;
public static final int CALCIFICATION = 0;
public static final int WELL_DEFINED_OR_CIRCUMSCRIBED_MASSES = 1;
public static final int SPICULATED_MASSES = 2;
public static final int OTHER_ILL_DEFINED_MASSES = 3;
public static final int ARCHITECTURAL_DISTORTION = 4;
public static final int ASYMMETRY = 5;
public static final int NORMAL = 6;
public static final int NOT_APPLICABLE = 0;
public static final int BENIGN = 1;
public static final int MALIGNANT = 2;
protected String filename;
protected int backgroundTissueType;
protected int abnormality;
protected int severity;
protected int x, y, radius;
public MIASImage(String filename, String backgroundTissueType, String abnormality, String severity, int x, int y, int radius) {
this.filename = filename;
if (backgroundTissueType.equals("F")) this.backgroundTissueType = FATTY;
if (backgroundTissueType.equals("G")) this.backgroundTissueType = FATTY_GLANDULAR;
if (backgroundTissueType.equals("D")) this.backgroundTissueType = DENSE_GLANDULAR;
/*
CALC - Calcification
CIRC - Well-defined/circumscribed masses
SPIC - Spiculated masses
MISC - Other, ill-defined masses
ARCH - Architectural distortion
ASYM - Asymmetry
NORMAL - Normal
*/
if (abnormality.equals("CALC")) this.abnormality = CALCIFICATION;
if (abnormality.equals("CIRC")) this.abnormality = WELL_DEFINED_OR_CIRCUMSCRIBED_MASSES;
if (abnormality.equals("MISC")) this.abnormality = OTHER_ILL_DEFINED_MASSES;
if (abnormality.equals("ARCH")) this.abnormality = ARCHITECTURAL_DISTORTION;
if (abnormality.equals("ASYN")) this.abnormality = ASYMMETRY;
if (abnormality.equals("NORM")) this.abnormality = NORMAL;
this.severity = NOT_APPLICABLE;
if (severity.equals("B")) this.severity = BENIGN;
if (severity.equals("M")) this.severity = MALIGNANT;
this.x = x;
this.y = y;
this.radius = radius;
}
public String getFilename() {
return filename;
}
public int getBackgroundTissueType() {
return backgroundTissueType;
}
public int getAbnormality() {
return abnormality;
}
public int getSeverity() {
return severity;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getRadius() {
return radius;
}
public String backgroundTypeToString() {
String[] types = new String[]{"Fatty", "Fatty Glandular", "Dense Glandular"};
return types[backgroundTissueType];
}
public String abnormalityToString() {
String[] abnormalities = new String[]{"Calcification", "Well defined / Circumscribed masses", "Spiculated Masses", "Other ill defined masses", "Architectural distortion", "Asymmetry", "Normal"};
return abnormalities[abnormality];
}
public String severityToString() {
String[] severities = new String[]{"Not Applicable", "Benign", "Malignant"};
return severities[severity];
}
}
}