Hello. I am a beginner at this Java stuff, so bear with me.
I have been writing an imaging application as a way of learning Java. I
have got little bits working and tied them together in an application. But
now I am looking to tune, or correctly model, the application use threads to
improve performance.
What I am looking for is if I have structured my application in a logical
way and if I have where would it be useful to apply threads. Below is the
code of the application if someone could take a quick look and see if I have
made any major blunders with my structure and where they would apply
threads. Thanks for taking the time to read.
import java.awt.*;
import java.io.*;
import java.awt.event. *;
import java.awt.geom.* ;
import java.awt.image. *;
import java.awt.event. ActionEvent;
import java.awt.event. ActionListener;
import javax.swing.*;
import javax.swing.UIM anager;
import java.util.Linke dList;
import java.awt.image. BufferedImage;
import javax.imageio.* ;
//start of new image processor class
class newImgProc2 extends JComponent{
private BufferedImage source, destination;
public JComboBox options;
public int startX, startY, endX, endY, ix, iy, rectH, rectW;
public LinkedList lLsUndo = new LinkedList();
public int undoFlag = 0;
public JScrollPane iScroll;
public boolean swap = false;
public newImgProc2( BufferedImage image ) {//extend buffered image
to include undo handler
source = destination = image;
setBackground(C olor.white);
setLayout(new BorderLayout()) ;
// create a panel to hold the combo box
JPanel controls = new JPanel();
JPanel nuCont = new JPanel();
//use my button creator class to create a button
ButtCreator butt1 = new
ButtCreator("my Bright","graphi cs/bright.gif","gr aphics/roll.gif","Make
Brighter");
ButtCreator butt2 = new
ButtCreator("my Scale","graphic s/scale.gif","gra phics/roll.gif","Scal e
Down");
ButtCreator bLoad = new
ButtCreator("my Load","graphics/load.gif","grap hics/roll.gif","Load a File");
ButtCreator bSave = new
ButtCreator("my Save","graphics/save.gif","grap hics/roll.gif","Save a File");
ButtCreator bDark = new
ButtCreator("my Dark","graphics/dark.gif","grap hics/roll.gif","Make Darker");
ButtCreator bRot = new
ButtCreator("my Rotate","graphi cs/rotate.gif","gr aphics/roll.gif","Rota te the
image");
ButtCreator bUndo = new
ButtCreator("my Undo","graphics/undo.gif","grap hics/roll.gif","Undo ");
ButtCreator bRedo = new
ButtCreator("my Redo","graphics/redo.gif","grap hics/roll.gif","Redo ");
controls.add(bu tt1);
controls.add(bD ark);
controls.add(bu tt2);
controls.add(bL oad);
controls.add(bS ave);
controls.add(bR ot);
nuCont.add(bUnd o);
nuCont.add(bRed o);
add(controls, BorderLayout.NO RTH);
add(nuCont, BorderLayout.SO UTH);
//------
//add an event handler
//add the event listener to the object
ProcButt pB = new ProcButt();
butt1.addAction Listener(pB);
butt2.addAction Listener(pB);
bLoad.addAction Listener(pB);
bSave.addAction Listener(pB);
bDark.addAction Listener(pB);
bUndo.addAction Listener(pB);
bRedo.addAction Listener(pB);
bRot.addActionL istener(pB);
}
//undo method
public void updateUndoAr(Bu fferedImage img){
lLsUndo.add(und oFlag,img);
undoFlag = undoFlag+1;
if(lLsUndo.size ()>undoFlag){
for (int i=undoFlag;i<=l LsUndo.size();i ++){
lLsUndo.remove( i);
}
}
}
public void undoUndoAr(){
try{
System.out.prin tln("before undo "+undoFlag) ;
if(undoFlag-1>=0){
undoFlag = undoFlag-1;
}
BufferedImage last =
(BufferedImage) lLsUndo.get(und oFlag);
setTheImage(las t);
System.out.prin tln("after undo "+undoFlag) ;
}
catch( IndexOutOfBound sException e){
Toolkit.getDefa ultToolkit().be ep();
JPanel warn = new JPanel();
JOptionPane.sho wMessageDialog( warn, "ERROR: Undo
Error!\n\t\tNot hing left to undo!\n"+e);
}
}
public void redoUndoAr(){
try{
System.out.prin tln("f before redo "+undoFlag) ;
undoFlag = undoFlag+1;
System.out.prin tln("f after redo "+undoFlag) ;
BufferedImage last = (BufferedImage) lLsUndo.get(und oFlag);
setTheImage(las t);
}
catch( IndexOutOfBound sException e){
Toolkit.getDefa ultToolkit().be ep();
JPanel warn = new JPanel();
JOptionPane.sho wMessageDialog( warn, "ERROR: Redo
Error!\n\t\tNot hing more to redo!\n"+e);
}
}
//class procButt implements ActionListener, UndoableEditLis tener{
class ProcButt implements ActionListener{
public void actionPerformed (ActionEvent e){
String b = e.getActionComm and();//teh name of the
button
BufferedImageOp op = null;
if(b.equals("my Bright")){
op = new RescaleOp(1.5f, 0, null);
}
else if(b.equals("my Undo")){
undoUndoAr();
}
else if(b.equals("my Redo")){
redoUndoAr();
}
else if(b.equals("my Scale")){
op = new
AffineTransform Op(AffineTransf orm.getScaleIns tance(.75, .75), null);
}
else if(b.equals("my Load")){
getImage();
}
else if(b.equals("my Rotate")){
op = new
AffineTransform Op(AffineTransf orm.getRotateIn stance(Math.PI / 6), null);
}
else if(b.equals("my Dark")){
op = new RescaleOp(.5f, 0, null);
}
else if(b.equals("my Save")){
try{
outputFile();
}
catch(Exception exp){
System.out.prin tln(exp);
}
}
if (op != null){
updateUndoAr(de stination);
destination = op.filter(sourc e, null);
source = destination;
}
repaint();
}
}
//class to deal with painting the thing
public void paintComponent( Graphics g) {
int imageWidth = destination.get Width();
int imageHeight = destination.get Height();
int width = getSize().width ;
int height = getSize().heigh t;
g.drawImage(des tination,0, 0, null);
//start listeners
addMouseListene r(new MouseAdapter(){
public void mousePressed(Mo useEvent e){
startX = e.getX();
startY = e.getY();
}
public void mouseReleased(M ouseEvent e){
updateUndoAr(de stination);
BufferedImage my;
if(swap == true){
my = source.getSubim age(ix,iy,rectW ,rectH);
swap = false;
}
else{
my =
source.getSubim age(startX,star tY,rectW,rectH) ;
swap = false;
}
source = my;
destination = source;
repaint();
}
});
addMouseMotionL istener(new MouseMotionAdap ter(){
public void mouseDragged(Mo useEvent e){
repaint();
ix = e.getX();
iy = e.getY();
if(ix>startX){
rectW = ix - startX;
}
else{
rectW = startX - ix;
swap = true;
}
if(iy>startY){
rectH = iy - startY;
}
else{
rectH = startY - iy;
swap = true;
}
Graphics g2 = getGraphics();
if(swap == true){
g2.drawRect(ix, iy,rectW,rectH) ;
}
else{
g2.drawRect(sta rtX,startY,rect W,rectH);
}
}
});
//end list
}
// temp output file bit
public void outputFile() throws Exception{
//start of the output stuff
FileOutputStrea m fo = new FileOutputStrea m("graphics/myImg.jpg");
BufferedOutputS tream bo = new BufferedOutputS tream(fo);
ImageIO.write(d estination, "jpeg", bo);
bo.close();
//finding the size of teh image in memory
ByteArrayOutput Stream baos = new ByteArrayOutput Stream();
ImageIO.write(d estination, "jpeg", baos);
System.out.prin tln("data in mem = "+baos.size ());
baos.close();
}
// EOF temp outupt file bit
// load file from users HD method
public void getImage(){
JFileChooser dlg = new JFileChooser();
//disable the file dialog from showing all
dlg.setAcceptAl lFileFilterUsed (false);
dlg.addChoosabl eFileFilter(new DialogFilter()) ;
int r = dlg.showDialog( this, "Load Image");
if( r == JFileChooser.CA NCEL_OPTION){
return;
}
try{
File f = dlg.getSelected File();
java.net.URL url = f.toURL();
ImageIcon icn = new ImageIcon(url);
System.out.prin tln(icn.getImag eLoadStatus());
//gets the size of the local file
long sizeLocal = f.length();
System.out.prin tln("local size of file from dialog
"+sizeLocal );
Image fi = icn.getImage();
// draw the Image into a BufferedImage
int w = fi.getWidth(nul l), h = fi.getHeight(nu ll);
//buffImage is being passed to the image processor class
BufferedImage fBuff = new BufferedImage(w , h,
BufferedImage.T YPE_INT_RGB);
Graphics2D imageGraphics = fBuff.createGra phics();
setTheImage(fBu ff);
scaleTheImage(f Buff);
//end paste from main
}
catch(Exception e){
System.out.prin tln("could not load file");
}
}
//end of load file method
private Rectangle getAffectedArea (int oldX, int oldY, int newx, int newy,
int width, int height)
{
int x = Math.min(oldX, newx);
int y = Math.min(oldY, newy);
int w = (Math.max(oldX, newx) + width) - x;
int h = (Math.max(oldY, newy) + height) - y;
return new Rectangle(x, y, w, h);
}
//if the image is being sent in from an extended class, then reset
it here
public void setTheImage(Buf feredImage iImg){
source = iImg;
destination = source;
repaint();
}
public void scaleTheImage(B ufferedImage iImg){
BufferedImageOp op;
int w = iImg.getWidth() ;
int h = iImg.getHeight( );
op = new
AffineTransform Op(AffineTransf orm.getScaleIns tance(.5, .5), null);
destination = op.filter(sourc e, null);
source = destination;
}
//so an external class can get the image
public BufferedImage retTheImage(){
return source;
}
}
//end of new image processor class
//*************** *******
class outTheImage2 extends newImgProc2{
private BufferedImage theImage;
public outTheImage2(Bu fferedImage theImage){
super(theImage) ;
scaleTheImage() ;
}
public void scaleTheImage() {
//get the current image from the parent
BufferedImage thisImg = super.retTheIma ge(), destImg;
int w = thisImg.getWidt h();
int h = thisImg.getHeig ht();
BufferedImageOp op;
//transform the image
op = new AffineTransform Op(AffineTransf orm.getScaleIns tance(.5,
..5), null);
destImg = op.filter(thisI mg, null);
//set the image back to the parent
super.setTheIma ge(destImg);
}
}
//creates the frame of the whole application
class ImageProcCanvas 2 extends JFrame{
public ImageProcCanvas 2(outTheImage2 thisImage, int w, int h){
JFrame.setDefau ltLookAndFeelDe corated(true);
try{
UIManager.setLo okAndFeel("com. sun.java.swing. plaf.windows.Wi ndowsLookAndFee l
" );
}
catch(Exception e){
System.out.prin tln(e);
}
JFrame frame = new JFrame("OGRe Image Processor");
frame.getConten tPane().add(thi sImage);
int myH = h +200;
frame.setSize(w , myH);
frame.setDefaul tCloseOperation ( JFrame.EXIT_ON_ CLOSE );
frame.setVisibl e(true);
}
}
//*************** *******
public class BufferedImage00 2 {
public static void main(String args[]){
String filename = "graphics/desk001.jpg";
String outFileName = "outImg.jpg ";
// get the image from hd or could be url
ImageIcon icon = new ImageIcon(filen ame);
Image i = icon.getImage() ;
// draw the Image into a BufferedImage
int w = i.getWidth(null ), h = i.getHeight(nul l);
//buffImage is being passed to the image processor class
BufferedImage buffImage = new BufferedImage(w , h,
BufferedImage.T YPE_INT_RGB);
//create the image
Graphics2D imageGraphics = buffImage.creat eGraphics();
imageGraphics.d rawImage(i, 0, 0, null);
//get the height of the buffered image
int width = buffImage.getWi dth()+40;
int height = buffImage.getHe ight()+80;
//scale the buffered image
outTheImage2 i1 = new outTheImage2(bu ffImage);
//set up a new frame to deal with the whole app
ImageProcCanvas 2 newOgre = new ImageProcCanvas 2(i1, width, height);
}
}
//*************** *******
There are two other objects too. One for creating the buttons and one for
filtering the dialog to show only images on the users HD. I think this
maybe too much to take in in one go.. but thanks for taking the time to read
this far.
cheers
Martin
--
---------------
http://www.nonstoploop.co.uk/ - dynamic websites
http://www.rossanobacchin.be/ - fine art
http://www.weycameras.co.uk/ - photographic supplies
---------------