N
news.skynet.be
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.UIManager;
import java.util.LinkedList;
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(Color.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("myBright","graphics/bright.gif","graphics/roll.gif","Make
Brighter");
ButtCreator butt2 = new
ButtCreator("myScale","graphics/scale.gif","graphics/roll.gif","Scale
Down");
ButtCreator bLoad = new
ButtCreator("myLoad","graphics/load.gif","graphics/roll.gif","Load a File");
ButtCreator bSave = new
ButtCreator("mySave","graphics/save.gif","graphics/roll.gif","Save a File");
ButtCreator bDark = new
ButtCreator("myDark","graphics/dark.gif","graphics/roll.gif","Make Darker");
ButtCreator bRot = new
ButtCreator("myRotate","graphics/rotate.gif","graphics/roll.gif","Rotate the
image");
ButtCreator bUndo = new
ButtCreator("myUndo","graphics/undo.gif","graphics/roll.gif","Undo");
ButtCreator bRedo = new
ButtCreator("myRedo","graphics/redo.gif","graphics/roll.gif","Redo");
controls.add(butt1);
controls.add(bDark);
controls.add(butt2);
controls.add(bLoad);
controls.add(bSave);
controls.add(bRot);
nuCont.add(bUndo);
nuCont.add(bRedo);
add(controls, BorderLayout.NORTH);
add(nuCont, BorderLayout.SOUTH);
//------
//add an event handler
//add the event listener to the object
ProcButt pB = new ProcButt();
butt1.addActionListener(pB);
butt2.addActionListener(pB);
bLoad.addActionListener(pB);
bSave.addActionListener(pB);
bDark.addActionListener(pB);
bUndo.addActionListener(pB);
bRedo.addActionListener(pB);
bRot.addActionListener(pB);
}
//undo method
public void updateUndoAr(BufferedImage img){
lLsUndo.add(undoFlag,img);
undoFlag = undoFlag+1;
if(lLsUndo.size()>undoFlag){
for (int i=undoFlag;i<=lLsUndo.size();i++){
lLsUndo.remove(i);
}
}
}
public void undoUndoAr(){
try{
System.out.println("before undo "+undoFlag);
if(undoFlag-1>=0){
undoFlag = undoFlag-1;
}
BufferedImage last =
(BufferedImage)lLsUndo.get(undoFlag);
setTheImage(last);
System.out.println("after undo "+undoFlag);
}
catch( IndexOutOfBoundsException e){
Toolkit.getDefaultToolkit().beep();
JPanel warn = new JPanel();
JOptionPane.showMessageDialog(warn, "ERROR: Undo
Error!\n\t\tNothing left to undo!\n"+e);
}
}
public void redoUndoAr(){
try{
System.out.println("f before redo "+undoFlag);
undoFlag = undoFlag+1;
System.out.println("f after redo "+undoFlag);
BufferedImage last = (BufferedImage)lLsUndo.get(undoFlag);
setTheImage(last);
}
catch( IndexOutOfBoundsException e){
Toolkit.getDefaultToolkit().beep();
JPanel warn = new JPanel();
JOptionPane.showMessageDialog(warn, "ERROR: Redo
Error!\n\t\tNothing more to redo!\n"+e);
}
}
//class procButt implements ActionListener, UndoableEditListener{
class ProcButt implements ActionListener{
public void actionPerformed(ActionEvent e){
String b = e.getActionCommand();//teh name of the
button
BufferedImageOp op = null;
if(b.equals("myBright")){
op = new RescaleOp(1.5f, 0, null);
}
else if(b.equals("myUndo")){
undoUndoAr();
}
else if(b.equals("myRedo")){
redoUndoAr();
}
else if(b.equals("myScale")){
op = new
AffineTransformOp(AffineTransform.getScaleInstance(.75, .75), null);
}
else if(b.equals("myLoad")){
getImage();
}
else if(b.equals("myRotate")){
op = new
AffineTransformOp(AffineTransform.getRotateInstance(Math.PI / 6), null);
}
else if(b.equals("myDark")){
op = new RescaleOp(.5f, 0, null);
}
else if(b.equals("mySave")){
try{
outputFile();
}
catch(Exception exp){
System.out.println(exp);
}
}
if (op != null){
updateUndoAr(destination);
destination = op.filter(source, null);
source = destination;
}
repaint();
}
}
//class to deal with painting the thing
public void paintComponent(Graphics g) {
int imageWidth = destination.getWidth();
int imageHeight = destination.getHeight();
int width = getSize().width;
int height = getSize().height;
g.drawImage(destination,0, 0, null);
//start listeners
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
startX = e.getX();
startY = e.getY();
}
public void mouseReleased(MouseEvent e){
updateUndoAr(destination);
BufferedImage my;
if(swap == true){
my = source.getSubimage(ix,iy,rectW,rectH);
swap = false;
}
else{
my =
source.getSubimage(startX,startY,rectW,rectH);
swap = false;
}
source = my;
destination = source;
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent 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(startX,startY,rectW,rectH);
}
}
});
//end list
}
// temp output file bit
public void outputFile() throws Exception{
//start of the output stuff
FileOutputStream fo = new FileOutputStream("graphics/myImg.jpg");
BufferedOutputStream bo = new BufferedOutputStream(fo);
ImageIO.write(destination, "jpeg", bo);
bo.close();
//finding the size of teh image in memory
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(destination, "jpeg", baos);
System.out.println("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.setAcceptAllFileFilterUsed(false);
dlg.addChoosableFileFilter(new DialogFilter());
int r = dlg.showDialog(this, "Load Image");
if( r == JFileChooser.CANCEL_OPTION){
return;
}
try{
File f = dlg.getSelectedFile();
java.net.URL url = f.toURL();
ImageIcon icn = new ImageIcon(url);
System.out.println(icn.getImageLoadStatus());
//gets the size of the local file
long sizeLocal = f.length();
System.out.println("local size of file from dialog
"+sizeLocal);
Image fi = icn.getImage();
// draw the Image into a BufferedImage
int w = fi.getWidth(null), h = fi.getHeight(null);
//buffImage is being passed to the image processor class
BufferedImage fBuff = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D imageGraphics = fBuff.createGraphics();
setTheImage(fBuff);
scaleTheImage(fBuff);
//end paste from main
}
catch(Exception e){
System.out.println("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(BufferedImage iImg){
source = iImg;
destination = source;
repaint();
}
public void scaleTheImage(BufferedImage iImg){
BufferedImageOp op;
int w = iImg.getWidth();
int h = iImg.getHeight();
op = new
AffineTransformOp(AffineTransform.getScaleInstance(.5, .5), null);
destination = op.filter(source, 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(BufferedImage theImage){
super(theImage);
scaleTheImage();
}
public void scaleTheImage(){
//get the current image from the parent
BufferedImage thisImg = super.retTheImage(), destImg;
int w = thisImg.getWidth();
int h = thisImg.getHeight();
BufferedImageOp op;
//transform the image
op = new AffineTransformOp(AffineTransform.getScaleInstance(.5,
..5), null);
destImg = op.filter(thisImg, null);
//set the image back to the parent
super.setTheImage(destImg);
}
}
//creates the frame of the whole application
class ImageProcCanvas2 extends JFrame{
public ImageProcCanvas2(outTheImage2 thisImage, int w, int h){
JFrame.setDefaultLookAndFeelDecorated(true);
try{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel
" );
}
catch(Exception e){
System.out.println(e);
}
JFrame frame = new JFrame("OGRe Image Processor");
frame.getContentPane().add(thisImage);
int myH = h +200;
frame.setSize(w, myH);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible(true);
}
}
//**********************
public class BufferedImage002 {
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(filename);
Image i = icon.getImage();
// draw the Image into a BufferedImage
int w = i.getWidth(null), h = i.getHeight(null);
//buffImage is being passed to the image processor class
BufferedImage buffImage = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
//create the image
Graphics2D imageGraphics = buffImage.createGraphics();
imageGraphics.drawImage(i, 0, 0, null);
//get the height of the buffered image
int width = buffImage.getWidth()+40;
int height = buffImage.getHeight()+80;
//scale the buffered image
outTheImage2 i1 = new outTheImage2(buffImage);
//set up a new frame to deal with the whole app
ImageProcCanvas2 newOgre = new ImageProcCanvas2(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
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.UIManager;
import java.util.LinkedList;
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(Color.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("myBright","graphics/bright.gif","graphics/roll.gif","Make
Brighter");
ButtCreator butt2 = new
ButtCreator("myScale","graphics/scale.gif","graphics/roll.gif","Scale
Down");
ButtCreator bLoad = new
ButtCreator("myLoad","graphics/load.gif","graphics/roll.gif","Load a File");
ButtCreator bSave = new
ButtCreator("mySave","graphics/save.gif","graphics/roll.gif","Save a File");
ButtCreator bDark = new
ButtCreator("myDark","graphics/dark.gif","graphics/roll.gif","Make Darker");
ButtCreator bRot = new
ButtCreator("myRotate","graphics/rotate.gif","graphics/roll.gif","Rotate the
image");
ButtCreator bUndo = new
ButtCreator("myUndo","graphics/undo.gif","graphics/roll.gif","Undo");
ButtCreator bRedo = new
ButtCreator("myRedo","graphics/redo.gif","graphics/roll.gif","Redo");
controls.add(butt1);
controls.add(bDark);
controls.add(butt2);
controls.add(bLoad);
controls.add(bSave);
controls.add(bRot);
nuCont.add(bUndo);
nuCont.add(bRedo);
add(controls, BorderLayout.NORTH);
add(nuCont, BorderLayout.SOUTH);
//------
//add an event handler
//add the event listener to the object
ProcButt pB = new ProcButt();
butt1.addActionListener(pB);
butt2.addActionListener(pB);
bLoad.addActionListener(pB);
bSave.addActionListener(pB);
bDark.addActionListener(pB);
bUndo.addActionListener(pB);
bRedo.addActionListener(pB);
bRot.addActionListener(pB);
}
//undo method
public void updateUndoAr(BufferedImage img){
lLsUndo.add(undoFlag,img);
undoFlag = undoFlag+1;
if(lLsUndo.size()>undoFlag){
for (int i=undoFlag;i<=lLsUndo.size();i++){
lLsUndo.remove(i);
}
}
}
public void undoUndoAr(){
try{
System.out.println("before undo "+undoFlag);
if(undoFlag-1>=0){
undoFlag = undoFlag-1;
}
BufferedImage last =
(BufferedImage)lLsUndo.get(undoFlag);
setTheImage(last);
System.out.println("after undo "+undoFlag);
}
catch( IndexOutOfBoundsException e){
Toolkit.getDefaultToolkit().beep();
JPanel warn = new JPanel();
JOptionPane.showMessageDialog(warn, "ERROR: Undo
Error!\n\t\tNothing left to undo!\n"+e);
}
}
public void redoUndoAr(){
try{
System.out.println("f before redo "+undoFlag);
undoFlag = undoFlag+1;
System.out.println("f after redo "+undoFlag);
BufferedImage last = (BufferedImage)lLsUndo.get(undoFlag);
setTheImage(last);
}
catch( IndexOutOfBoundsException e){
Toolkit.getDefaultToolkit().beep();
JPanel warn = new JPanel();
JOptionPane.showMessageDialog(warn, "ERROR: Redo
Error!\n\t\tNothing more to redo!\n"+e);
}
}
//class procButt implements ActionListener, UndoableEditListener{
class ProcButt implements ActionListener{
public void actionPerformed(ActionEvent e){
String b = e.getActionCommand();//teh name of the
button
BufferedImageOp op = null;
if(b.equals("myBright")){
op = new RescaleOp(1.5f, 0, null);
}
else if(b.equals("myUndo")){
undoUndoAr();
}
else if(b.equals("myRedo")){
redoUndoAr();
}
else if(b.equals("myScale")){
op = new
AffineTransformOp(AffineTransform.getScaleInstance(.75, .75), null);
}
else if(b.equals("myLoad")){
getImage();
}
else if(b.equals("myRotate")){
op = new
AffineTransformOp(AffineTransform.getRotateInstance(Math.PI / 6), null);
}
else if(b.equals("myDark")){
op = new RescaleOp(.5f, 0, null);
}
else if(b.equals("mySave")){
try{
outputFile();
}
catch(Exception exp){
System.out.println(exp);
}
}
if (op != null){
updateUndoAr(destination);
destination = op.filter(source, null);
source = destination;
}
repaint();
}
}
//class to deal with painting the thing
public void paintComponent(Graphics g) {
int imageWidth = destination.getWidth();
int imageHeight = destination.getHeight();
int width = getSize().width;
int height = getSize().height;
g.drawImage(destination,0, 0, null);
//start listeners
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
startX = e.getX();
startY = e.getY();
}
public void mouseReleased(MouseEvent e){
updateUndoAr(destination);
BufferedImage my;
if(swap == true){
my = source.getSubimage(ix,iy,rectW,rectH);
swap = false;
}
else{
my =
source.getSubimage(startX,startY,rectW,rectH);
swap = false;
}
source = my;
destination = source;
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent 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(startX,startY,rectW,rectH);
}
}
});
//end list
}
// temp output file bit
public void outputFile() throws Exception{
//start of the output stuff
FileOutputStream fo = new FileOutputStream("graphics/myImg.jpg");
BufferedOutputStream bo = new BufferedOutputStream(fo);
ImageIO.write(destination, "jpeg", bo);
bo.close();
//finding the size of teh image in memory
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(destination, "jpeg", baos);
System.out.println("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.setAcceptAllFileFilterUsed(false);
dlg.addChoosableFileFilter(new DialogFilter());
int r = dlg.showDialog(this, "Load Image");
if( r == JFileChooser.CANCEL_OPTION){
return;
}
try{
File f = dlg.getSelectedFile();
java.net.URL url = f.toURL();
ImageIcon icn = new ImageIcon(url);
System.out.println(icn.getImageLoadStatus());
//gets the size of the local file
long sizeLocal = f.length();
System.out.println("local size of file from dialog
"+sizeLocal);
Image fi = icn.getImage();
// draw the Image into a BufferedImage
int w = fi.getWidth(null), h = fi.getHeight(null);
//buffImage is being passed to the image processor class
BufferedImage fBuff = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D imageGraphics = fBuff.createGraphics();
setTheImage(fBuff);
scaleTheImage(fBuff);
//end paste from main
}
catch(Exception e){
System.out.println("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(BufferedImage iImg){
source = iImg;
destination = source;
repaint();
}
public void scaleTheImage(BufferedImage iImg){
BufferedImageOp op;
int w = iImg.getWidth();
int h = iImg.getHeight();
op = new
AffineTransformOp(AffineTransform.getScaleInstance(.5, .5), null);
destination = op.filter(source, 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(BufferedImage theImage){
super(theImage);
scaleTheImage();
}
public void scaleTheImage(){
//get the current image from the parent
BufferedImage thisImg = super.retTheImage(), destImg;
int w = thisImg.getWidth();
int h = thisImg.getHeight();
BufferedImageOp op;
//transform the image
op = new AffineTransformOp(AffineTransform.getScaleInstance(.5,
..5), null);
destImg = op.filter(thisImg, null);
//set the image back to the parent
super.setTheImage(destImg);
}
}
//creates the frame of the whole application
class ImageProcCanvas2 extends JFrame{
public ImageProcCanvas2(outTheImage2 thisImage, int w, int h){
JFrame.setDefaultLookAndFeelDecorated(true);
try{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel
" );
}
catch(Exception e){
System.out.println(e);
}
JFrame frame = new JFrame("OGRe Image Processor");
frame.getContentPane().add(thisImage);
int myH = h +200;
frame.setSize(w, myH);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible(true);
}
}
//**********************
public class BufferedImage002 {
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(filename);
Image i = icon.getImage();
// draw the Image into a BufferedImage
int w = i.getWidth(null), h = i.getHeight(null);
//buffImage is being passed to the image processor class
BufferedImage buffImage = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
//create the image
Graphics2D imageGraphics = buffImage.createGraphics();
imageGraphics.drawImage(i, 0, 0, null);
//get the height of the buffered image
int width = buffImage.getWidth()+40;
int height = buffImage.getHeight()+80;
//scale the buffered image
outTheImage2 i1 = new outTheImage2(buffImage);
//set up a new frame to deal with the whole app
ImageProcCanvas2 newOgre = new ImageProcCanvas2(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