I created a applet using threads. When i run it and change the size of the window I see a few copies of "Applet started" string. I wonder why is that and how to fix that?
When exactly does this strin starts?
here is my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
import javax.swing.JApplet;
public class app extends javax.swing.JApplet {
/**
*
*/
Random generator = new Random();
public int n = 15;
public int m = 15;
public int k = 200;
public int size = 25;
public kwadrat[][] watki;
public double p = 0.98;
public boolean sth = true ;
/**
* Function initializes threads by given data
* #exception NumberFormatException when there is no data from html code
*
*/
public void init(){
try{n = Integer.parseInt(getParameter("n"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: n");
}
catch( NullPointerException e){}
try{m = Integer.parseInt(getParameter("m"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: m");
}
catch( NullPointerException e){}
try{k = Integer.parseInt(getParameter("k"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: k");
}
catch( NullPointerException e){}
try{ p = Double.parseDouble(getParameter("p"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: k");
}
catch( NullPointerException e){}
watki = new kwadrat[n][m];
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j){
watki[i][j] = new kwadrat(10+i*size,
10+j*size,
i,
j,
size,
(int)(k*(generator.nextDouble()+0.5)),
new java.awt.Color(generator.nextInt(255),
generator.nextInt(255),
generator.nextInt(255)
)
);
}
}
/**
* start method start the threads
*/
public void start(){
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j){
Thread t;
t = new Thread( new MovingRunnable(watki[i][j]));
t.start();
}
}
/**
* Paint method is responsible for drawing the rectangles(threads)
*/
public void paint(Graphics g){
//super.paint(g);
//g.fillRect(0, 0, 1000, 1000);
repaint();
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j){
g.setColor(watki[i][j].kwadratColor);
g.fillRect(watki[i][j].x, watki[i][j].y, size, size);
}
}
/**
*
* #author Seba
* Class MovingRunnable implements Runnable includes rectangles as threads
* #param b it is object of kwadrat class
* #param run() main method of the class. Changes color of rectangles
* #exception InterruptedException when something is wrong with sleeping thread
*/
private class MovingRunnable implements Runnable{
private final kwadrat b;
private MovingRunnable(kwadrat b){this.b=b;}
public void run(){
for(;;){
if(generator.nextDouble()<p){
int c1 = 0,c2 = 0,c3 = 0;
if(b.nrx>0){
c1 += watki[b.nrx-1][b.nry].kwadratColor.getRed();
c2 += watki[b.nrx-1][b.nry].kwadratColor.getGreen();
c3 += watki[b.nrx-1][b.nry].kwadratColor.getBlue();
}
if(b.nrx<n-1) {
c1 += watki[b.nrx+1][b.nry].kwadratColor.getRed();
c2 += watki[b.nrx+1][b.nry].kwadratColor.getGreen();
c3 += watki[b.nrx+1][b.nry].kwadratColor.getBlue();
}
if(b.nry>0) {
c1 += watki[b.nrx][b.nry-1].kwadratColor.getRed();
c2 += watki[b.nrx][b.nry-1].kwadratColor.getGreen();
c3 += watki[b.nrx][b.nry-1].kwadratColor.getBlue();
}
if(b.nry<m-1) {
c1 += watki[b.nrx][b.nry+1].kwadratColor.getRed();
c2 += watki[b.nrx][b.nry+1].kwadratColor.getGreen();
c3 += watki[b.nrx][b.nry+1].kwadratColor.getBlue();
}
b.changeColor(new java.awt.Color(c1/4,c2/4,c3/4));
}
else
//b.changeColor(Color.GRAY);
b.changeColor(generator);
repaint();
try {
Thread.sleep(b.wait);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
/**
*
* #author Seba
* #param x position in x
* #param y position in y
* #param nrx x position in watki[][] array
* #param nry y position in watki[][] array
* #param wait time of sleeping thread
* #param size size of side
* #param kwadratColor - color of the ractangle
* #param kwadrat(int,int,int,int,int,int,Color) main constructor
* #param changeColor(Random) changing color by generating Random
* #param changeColor(Color) changing color to given color
*/
class kwadrat{
public int x;
public int y;
public int nrx;
public int nry;
public int wait;
public int size;
Color kwadratColor;
public kwadrat( int x, int y, int nrx, int nry, int size , int wait, Color kwadratColor){
this.x = x;
this.y = y;
this.nrx = nrx;
this.nry = nry;
this.size = size;
this.kwadratColor = kwadratColor;
this.wait = wait;
}
public void changeColor(Random gen){
kwadratColor = new java.awt.Color(gen.nextInt(255),
gen.nextInt(255),
gen.nextInt(255)
);
}
public void changeColor(Color x){
kwadratColor = x;
}
}
Related
In the game that I am making called Flood It I am having trouble printing the objects that I am making which have a constructor that is:
Dot(int x, int y, int color)
I have three classes one class is DotInfo.java:
public class DotInfo {
private int x;
private int y;
private int color;
private boolean captured;
public DotInfo(int x, int y, int color){
this.x = x;
this.y = y;
this.color = color;
captured = false;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setCaptured(boolean captured) {
this.captured = captured;
}
public boolean isCaptured(){
return captured;
}
public int getColor() {
return color;
}
}
My second class is GameModel.java:
import java.util.Random;
public class GameModel {
/**
* predefined values to capture the color of a DotInfo
*/
public static final int COLOR_0 = 0;
public static final int COLOR_1 = 1;
public static final int COLOR_2 = 2;
public static final int COLOR_3 = 3;
public static final int COLOR_4 = 4;
public static final int COLOR_5 = 5;
public static final int NUMBER_OF_COLORS = 6;
public static DotInfo[][] dots;
private DotInfo dot;
private int size;
private int currentColor;
private Random generator;
private int steps;
private String rep;
/**
* Constructor to initialize the model to a given size of board.
*
* #param size
* the size of the board
*/
public GameModel(int size) {
this.size = size;
}
/**
* Resets the model to (re)start a game. The previous game (if there is one)
* is cleared up .
*/
public void reset(){
int color = 0;
dots = new DotInfo[size][size];
for (int i=0;i<size;i++) {
for (int j=0;j<size;j++) {
new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
System.out.println(dots[i][j]);
}
}
}
/**
* Getter method for the size of the game
*
* #return the value of the attribute sizeOfGame
*/
public int getSize(){
return size;
}
/**
* returns the current color of a given dot in the game
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
* #return the status of the dot at location (i,j)
*/
public int getColor(int i, int j){
int color=0;
for (int x=0;x<size;x++) {
for (int y=0;y<size;y++) {
if (dots[x][y].getX()==i && dots[x][y].getY()==j) {
color=dots[x][y].getColor();
}
}
}
return color;
}
/**
* returns true is the dot is captured, false otherwise
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
* #return the status of the dot at location (i,j)
*/
public boolean isCaptured(int i, int j){
boolean capture = true;
for (int x=0;x<size;x++) {
for (int y=0;y<size;y++) {
if (dots[x][y].getX()==i && dots[x][y].getY()==j) {
capture=dots[x][y].isCaptured();
}
}
}
return capture;
}
/**
* Sets the status of the dot at coordinate (i,j) to captured
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
*/
public void capture(int i, int j){
for (int x=0;x<size;x++) {
for (int y=0;y<size;y++) {
if (dots[x][y].getX()==i && dots[x][y].getY()==j) {
dots[x][y].setCaptured(true);
}
}
}
}
/**
* Getter method for the current number of steps
*
* #return the current number of steps
*/
public int getNumberOfSteps(){
return steps;
}
/**
* Setter method for currentSelectedColor
*
* #param val
* the new value for currentSelectedColor
*/
public void setCurrentSelectedColor(int val) {
currentColor = val;
}
/**
* Getter method for currentSelectedColor
*
* #return currentSelectedColor
*/
public int getCurrentSelectedColor() {
return currentColor;
}
/**
* Getter method for the model's dotInfo reference
* at location (i,j)
*
* #param i
* the x coordinate of the dot
* #param j
* the y coordinate of the dot
*
* #return model[i][j]
*/
public DotInfo get(int i, int j) {
for (int x=0;x<size;x++) {
for (int y=0;y<size;y++) {
if (dots[x][y].getX()==i && dots[x][y].getY()==j) {
dot = dots[x][y];
}
}
}
return dot;
}
/**
* The metod <b>step</b> updates the number of steps. It must be called
* once the model has been updated after the payer selected a new color.
*/
public void step(){
steps++;
}
/**
* The metod <b>isFinished</b> returns true iff the game is finished, that
* is, all the dats are captured.
*
* #return true if the game is finished, false otherwise
*/
public boolean isFinished(){
boolean flag=true;
for (int x=0;x<size;x++) {
for (int y=0;y<size;y++) {
if (dots[x][y].isCaptured()==false) {
flag=false;
}
}
}
return flag;
}
/**
* Builds a String representation of the model
*
* #return String representation of the model
*/
public String toString(){
for (int x=0;x<size;x++) {
for (int y=0;y<size;y++) {
rep += "Dot("+dots[x][y].getX()+", "+ dots[x][y].getY()+", "+dots[x][y].getColor()+")";
}
}
return rep;
}
}
My main class that runs everything is Floodit.java
public class FloodIt {
/**
* <b>main</b> of the application. Creates the instance of GameController
* and starts the game. If a game size (<12) is passed as parameter, it is
* used as the board size. Otherwise, a default value is passed
*
* #param args
* command line parameters
*/
public static void main(String[] args) {
GameModel model = new GameModel(5);
model.reset();
System.out.println(model);
}
}
Can someone tell me why my array will not update when i call my reset() method?
You forgot to assign the new DotInfo() objects to every position of the array.
The line:
new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
should be:
dots[i][j] = new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
in the reset method you have a for loop doing:
dots = new DotInfo[size][size];
for (int i=0;i<size;i++) {
for (int j=0;j<size;j++) {
new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
System.out.println(dots[i][j]);
}
}
this line,
new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
is doing NOTHING....
You are creating an object, yes, but not assigning it to nothing, so that object is getting lost....
You have to assign that new object to the element in the 2D array...
dots[i][j] = new DotInfo(i, j, generator.nextInt(NUMBER_OF_COLORS)+1);
Edit:
on the other hand, you need to init the generator object:
public GameModel(int size) {
this.size = size;
generator = new Random();
}
I am looking to solve the N-Queens problem, and I have pinpointed the issue that I am having. There is a JButton that is pressed to tell the user textually in the frame if their solution is correct or not. This button only seems to work when Queens have not been placed on the board. The problem seems to be the setText() method for my JLabel "ifNotSafe" is not working properly. If I put print statements under that method call, the correct message is sent to the console but the label is not changed. The label weirdly only works when Queens have not been placed on the board yet. There is also a Boxes object with an x value and a y value, and a getter method for each.
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
/*
* Overall class to make the whole ChessBoard and all the helper methods to
* tell the user whether their solution is correct or not
*/
public class ChessBoardGUI extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
//ImageIcon queenP = new //ImageIcon(getClass().getResource("/images/queen.png"));
//Image img = queenP.getImage();
//Image newImg = img.getScaledInstance(40, 40, java.awt.Image.SCALE_SMOOTH);
ImageIcon queenPic = new ImageIcon(newImg);
private static JButton tip;
private static JButton safe;
private static JLabel ifNotSafe;
private JButton[][] chessBoxes = new JButton[8][8];
public static JPanel chessBoard;
public static ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>();
/*
* Makes the whole frame for the ChessBoard
*/
public ChessBoardGUI() {
createBoard();
createOtherThings();
setSize(500, 500);
}
/*
* Creates the Tip and Safe buttons And Label to display when the solution
* is incorrect
*/
public void createOtherThings() {
safe = new JButton("Safe?");
tip = new JButton("Tip");
ifNotSafe = new JLabel("Status of Board is displayed here...");
ButtonListen1 safeListener = new ButtonListen1();
ButtonListen2 tipListener = new ButtonListen2();
safe.addActionListener(safeListener);
tip.addActionListener(tipListener);
}
/*
* ActionListener for the safe button
*/
class ButtonListen1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Tells user which queens are not safe
if (checkSolution(queensOnBoard) == true) {
//****THIS IS WHERE THE PROBLEM IS *******
ifNotSafe.setText("This Solution is correct so far");
System.out.println("Solution is correct");
} else{
ifNotSafe.setText("This Solution is incorrect so far");
// *********Also highlight the queens that are not safe******
System.out.println("Solution is incorrect");
}
}
}
/*
* ActionListener for the tip button
*/
class ButtonListen2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// ********Tells the user other places to put queens********
}
}
/*
* Creates the overall ChessBoard
*/
public void createBoard() {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(8);
gridLayout.setColumns(8);
chessBoard = new JPanel(gridLayout);
chessBoard.setSize(400, 400);
chessBoard.setBorder(new LineBorder(Color.BLACK));
chessBoard.setVisible(true);
/*
* Loops through to add each chessBox to the chessBoard
*/
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
/*
* Assigns a color to every other box
*/
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
chessBoxes[x][y].setOpaque(true);
chessBoard.add(chessBoxes[x][y]);
// Adds the ActionListener to each chessBox
BoxListener boxListen = new BoxListener();
chessBoxes[x][y].addActionListener(boxListen);
}
}
}
/*
* Action Listener for if the individual boxes on the ChessBoard are clicked
*/
class BoxListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = ((JButton) e.getSource());
// Runs through a loop to find the X and Y coordinate of the
// JButton(Box) that was clicked
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
if (chessBoxes[x][y] == button) {
/*
* If there is No Queen at that JButton
*/
if ((isOnBoard(queensOnBoard, x, y) == false)) {
// Makes sure the user can not place more than
// 8 Queens on the board
if (queensOnBoard.size() < 8) {
// Sets Picture of Queen on box
//button.setIcon(queenPic);
button.setText("Occupied");
// Adds box to the ArrayList of occupied boxes
queensOnBoard.add(new Boxes(x, y));
}
}
/*
* If there is a Queen at that JButton
*/
else {
removeQueen(queensOnBoard, x, y);
//button.setIcon(null);
button.setText("");
}
}
}
}
}
}
/*
* Checks if a certain Box has a Queen in it or not
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) {
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
return true;
}
}
return false;
}
/*
* Removes a Queen from the GUI at the specified Box (JButton)
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public void removeQueen(ArrayList<Boxes> a, int x, int y) {
/*
* Removes the box from the overall ArrayList of Boxes Occupied by
* queens according to the x and y location
*/
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
queensOnBoard.remove(i);
}
}
}
/*
* Return to the user which queens need to be highlighted
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public void conflictingQueens(ArrayList<Boxes> queensOnBoard) {
// *******Call the highlightBoxes method using the ArrayList
// Of Boxes you get from this method
}
/*
* Checks to see if solution is correct thusfar
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public boolean checkSolution(ArrayList<Boxes> queensOnBoard) {
int size = queensOnBoard.size();
if (size < 1) {
return true;
}
if (size == 1) {
return true;
}
for (int x = 0; x < size - 1; x++) {
for (int y = 1; y < size; y++) {
// Checks if Queen is safe from horizontal attacks
if (queensOnBoard.get(x).getX() == queensOnBoard.get(y).getX()) {
return false;
// Checks if Queen is safe from vertical attacks
} else if (queensOnBoard.get(x).getY() == queensOnBoard.get(y).getY()) {
return false;
// Checks if Queen is safe from diagonal attacks
// Uses diagonalAttack(queensOnBoard) as a helper method
} // else if(){
// return false;
// }
}
}
return true;
}
/*
* Checks to see if the queen is safe from diagonal attacks
*
*
*/
// public boolean diagonalAttack(ArrayList<Boxes> queensOnBoard){
//********
// }
/*
* Highlights boxes that are conflicting with one another
*
* #param highlight Is the ArrayList of Boxes that are occupied by Queens
* currently on the ChessBoard
*/
public void highlightBoxes(ArrayList<Boxes> highlight) {
int size1 = highlight.size();
int size2 = queensOnBoard.size();
// When there aren't any queens at risk, this block
// changes the background colors of the boxes back to
// Their respective color
if ((size1 == 0) && size1 == 1) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
/*
* Assigns a color to every other box
*/
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
}
}
}
// Runs through both the highlight and queensOnBoard ArrayLists and
// changes the background for the Queens at risk
for (int b = 0; b < size2; b++) {
for (int a = 0; a < size1; a++) {
if ((highlight.get(a).getX() == queensOnBoard.get(b).getX())
&& (highlight.get(a).getY() == queensOnBoard.get(b).getY())) {
int x = queensOnBoard.get(b).getX();
int y = queensOnBoard.get(b).getY();
chessBoxes[x][y].setBackground(Color.RED);
}
}
}
}
/*
* Main method to run the program
*
* #param args Is the String of args given to the console to run the
* operations of the program
*/
public static void main(String[] args) {
JFrame frame = new ChessBoardGUI();
frame.add(chessBoard);
chessBoard.setLocation(50, 50);
JPanel panel1 = new JPanel();
panel1.add(ifNotSafe);
panel1.add(safe);
panel1.add(tip);
frame.add(panel1);
frame.setTitle("ChessBoard");
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
You may have a layout problem in that your JLabel doesn't show well because the JPanel that holds it has been added incorrectly to the GUI. Understand that a JFrame's contentPane uses BorderLayout by default, and so when adding components to it, you should specify the BorderLayout location that the component should be placed in. The grid will be placed BorderLayout.CENTER, and panel1 should be placed BorderLayout.PAGE_START. Also, the grid's preferred size should be set, and you should call pack() on your JFrame after adding all components but before making it visible or setting its location.
Other minor quibbles:
None of your current fields should be public or static.
You should be adding components to your JFrame within the non-static code and not in the main method.
If you need to expose any properties to the outside static world, give your class public getter methods which will allow you to expose only what is necessary and in a controlled manner.
Test code is below. Note that I don't have your queen images available so I created a method that you won't need, private Icon createQueenIcon(). This way your code will run on my system. Also to make the code run and compile, I created and included the necessary Boxes class. In the future, be sure that you include all that is needed for us to be able to compile and run your code!
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.*;
public class ChessBoardGUI extends JFrame {
private static final long serialVersionUID = 1L;
// !! code changes below only to allow me to run your code without
// your images. !!
// ImageIcon queenP = new ImageIcon(getClass().getResource("/images/queen.png"));
// Image img = queenP.getImage();
// Image newImg = img.getScaledInstance(40, 40,
// java.awt.Image.SCALE_SMOOTH);
private ImageIcon queenPic = createQueenIcon(); //!! delete this
// all fields should be private and non-static
private JButton tip;
private JButton safe;
private JLabel ifNotSafe;
private JButton[][] chessBoxes = new JButton[8][8];
private JPanel chessBoard;
private ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>();
public ChessBoardGUI() {
createBoard();
add(chessBoard, BorderLayout.CENTER); // Do this here
// !! createOtherThings(); // get rid of -- put in constructor
safe = new JButton("Safe?");
tip = new JButton("Tip");
ifNotSafe = new JLabel("Status of Board is displayed here...");
ButtonListen1 safeListener = new ButtonListen1();
ButtonListen2 tipListener = new ButtonListen2();
safe.addActionListener(safeListener);
tip.addActionListener(tipListener);
// !! add the panel1 here!
JPanel panel1 = new JPanel();
panel1.add(ifNotSafe);
panel1.add(safe);
panel1.add(tip);
add(panel1, BorderLayout.PAGE_START); // using BorderLayout constants
// !! setSize(500, 500);
}
// !! so I can use images without having an image
// !! you won't need this
private Icon createQueenIcon() {
int w = 40;
BufferedImage img2 = new BufferedImage(w, w, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img2.createGraphics();
g2.setColor(new Color(183, 65, 14));
g2.fillRect(0, 0, w, w);
g2.setColor(new Color(255, 215, 0));
Font font = new Font(Font.SANS_SERIF, Font.BOLD, 30);
g2.setFont(font);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
FontMetrics fontMetrics = g2.getFontMetrics();
int textX = (w - fontMetrics.charWidth('Q')) / 2;
int textY = (w - fontMetrics.getHeight()) / 2 + fontMetrics.getAscent();
g2.drawString("Q", textX, textY);
g2.dispose();
return new ImageIcon(img2);
}
class ButtonListen1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (checkSolution(queensOnBoard) == true) {
// ****THIS IS WHERE THE PROBLEM IS ******* !!
ifNotSafe.setText("This Solution is correct so far");
System.out.println("Solution is correct");
} else {
ifNotSafe.setText("This Solution is incorrect so far");
// *********Also highlight the queens that are not safe******
System.out.println("Solution is incorrect");
}
}
}
/*
* ActionListener for the tip button
*/
class ButtonListen2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
}
}
/*
* Creates the overall ChessBoard
*/
public void createBoard() {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(8);
gridLayout.setColumns(8);
chessBoard = new JPanel(gridLayout);
chessBoard.setPreferredSize(new Dimension(640, 640));
chessBoard.setBorder(new LineBorder(Color.BLACK));
chessBoard.setVisible(true);
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
chessBoxes[x][y].setOpaque(true);
chessBoard.add(chessBoxes[x][y]);
BoxListener boxListen = new BoxListener();
chessBoxes[x][y].addActionListener(boxListen);
}
}
}
class BoxListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = ((JButton) e.getSource());
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
if (chessBoxes[x][y] == button) {
if ((isOnBoard(queensOnBoard, x, y) == false)) {
if (queensOnBoard.size() < 8) {
button.setIcon(queenPic);
queensOnBoard.add(new Boxes(x, y));
}
}
/*
* If there is a Queen at that JButton
*/
else {
removeQueen(queensOnBoard, x, y);
button.setIcon(null);
}
}
}
}
}
}
/*
* Checks if a certain Box has a Queen in it or not
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) {
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
return true;
}
}
return false;
}
/*
* Removes a Queen from the GUI at the specified Box (JButton)
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public void removeQueen(ArrayList<Boxes> a, int x, int y) {
/*
* Removes the box from the overall ArrayList of Boxes Occupied by
* queens according to the x and y location
*/
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
queensOnBoard.remove(i);
}
}
}
/*
* Return to the user which queens need to be highlighted
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public void conflictingQueens(ArrayList<Boxes> queensOnBoard2) {
}
/*
* Checks to see if solution is correct thusfar
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public boolean checkSolution(ArrayList<Boxes> queensOnBoard2) {
int size = queensOnBoard2.size();
if (size < 1) {
return true;
}
if (size == 1) {
return true;
}
for (int x = 0; x < size - 1; x++) {
for (int y = 1; y < size; y++) {
if (queensOnBoard2.get(x).getX() == queensOnBoard2.get(y).getX()) {
return false;
} else if (queensOnBoard2.get(x).getY() == queensOnBoard2.get(y).getY()) {
return false;
}
}
}
return true;
}
/*
* Checks to see if the queen is safe from diagonal attacks
*/
/*
* Highlights boxes that are conflicting with one another
*
* #param highlight Is the ArrayList of Boxes that are occupied by Queens
* currently on the ChessBoard
*/
public void highlightBoxes(ArrayList<Boxes> highlight) {
int size1 = highlight.size();
int size2 = queensOnBoard.size();
if ((size1 == 0) && size1 == 1) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
/*
* Assigns a color to every other box
*/
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
}
}
}
for (int b = 0; b < size2; b++) {
for (int a = 0; a < size1; a++) {
if ((highlight.get(a).getX() == queensOnBoard.get(b).getX())
&& (highlight.get(a).getY() == queensOnBoard.get(b).getY())) {
int x = queensOnBoard.get(b).getX();
int y = queensOnBoard.get(b).getY();
chessBoxes[x][y].setBackground(Color.RED);
}
}
}
}
public static void main(String[] args) {
// !! create the GUI in a Swing thread-safe manner
SwingUtilities.invokeLater(() -> createGui());
}
public static void createGui() {
JFrame frame = new ChessBoardGUI();
// !! frame.add(chessBoard); // not here
// !! chessBoard.setLocation(50, 50);
// !! this does not belong within main
// !! JPanel panel1 = new JPanel();
// panel1.add(ifNotSafe);
// panel1.add(safe);
// panel1.add(tip);
// frame.add(panel1);
frame.setTitle("ChessBoard");
frame.pack(); // !! call this to have your GUI size itself
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private static class Boxes {
private int x;
private int y;
public Boxes(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return x;
}
public int getX() {
return y;
}
}
}
I have found Haralick's algorithm already implemented. It is used to get some feature with the help of Gray-Level Co-occurence matrices.
Now i have problems getting it to work. There are no exceptions. The code is fine. I'm not sure where to begin. Can someone help me with the first steps?How to i get a texture feature?
Below you can find the complete Haralick source code:
package de.lmu.dbs.jfeaturelib.features;
import Jama.Matrix;
import de.lmu.dbs.jfeaturelib.Progress;
import de.lmu.ifi.dbs.utilities.Arrays2;
import ij.plugin.filter.PlugInFilter;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;
import java.util.Arrays;
import java.util.EnumSet;
/**
* Haralick texture features
*
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
* <pre>
* #article{haralick1973textural,
* title={Textural features for image classification},
* author={Haralick, R.M. and Shanmugam, K. and Dinstein, I.},
* journal={Systems, Man and Cybernetics, IEEE Transactions on},
* volume={3},
* number={6},
* pages={610--621},
* year={1973},
* publisher={IEEE}
* }
* </pre>
*
* #author graf
*/
public class Haralick extends AbstractFeatureDescriptor {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES = 32;
/**
* p_(x+y) statistics
*/
private double[] p_x_plus_y = new double[2 * NUM_GRAY_VALUES - 1];
/**
* p_(x-y) statistics
*/
private double[] p_x_minus_y = new double[NUM_GRAY_VALUES];
/**
* row mean value
*/
private double mu_x = 0;
/**
* column mean value
*/
private double mu_y = 0;
/**
* row variance
*/
private double var_x = 0;
/**
* column variance
*/
private double var_y = 0;
/**
* HXY1 statistics
*/
private double hx = 0;
/**
* HXY2 statistics
*/
private double hy = 0;
/**
* HXY1 statistics
*/
private double hxy1 = 0;
/**
* HXY2 statistics
*/
private double hxy2 = 0;
/**
* p_x statistics
*/
private double[] p_x = new double[NUM_GRAY_VALUES];
/**
* p_y statistics
*/
private double[] p_y = new double[NUM_GRAY_VALUES];
// -
private int haralickDist;
double[] features = null;
/**
* Constructs a haralick detector with default parameters.
*/
public Haralick() {
this.haralickDist = 1;
}
/**
* Constructs a haralick detector.
*
* #param haralickDist Integer for haralick distribution
*/
public Haralick(int haralickDist) {
this.haralickDist = haralickDist;
}
/**
* Defines the capability of the algorithm.
*
* #see PlugInFilter
* #see #supports()
*/
#Override
public EnumSet<Supports> supports() {
EnumSet set = EnumSet.of(
Supports.NoChanges,
Supports.DOES_8C,
Supports.DOES_8G,
Supports.DOES_RGB);
return set;
}
/**
* Starts the haralick detection.
*
* #param ip ImageProcessor of the source image
*/
#Override
public void run(ImageProcessor ip) {
if (!ByteProcessor.class.isAssignableFrom(ip.getClass())) {
ip = ip.convertToByte(true);
}
firePropertyChange(Progress.START);
process((ByteProcessor) ip);
addData(features);
firePropertyChange(Progress.END);
}
/**
* Returns information about the getFeature
*/
#Override
public String getDescription() {
StringBuilder sb = new StringBuilder();
sb.append("Haralick features: ");
sb.append("Angular 2nd moment, ");
sb.append("Contrast, ");
sb.append("Correlation, ");
sb.append("variance, ");
sb.append("Inverse Difference Moment, ");
sb.append("Sum Average, ");
sb.append("Sum Variance, ");
sb.append("Sum Entropy, ");
sb.append("Entropy, ");
sb.append("Difference Variance, ");
sb.append("Difference Entropy, ");
sb.append("Information Measures of Correlation, ");
sb.append("Information Measures of Correlation, ");
sb.append("Maximum Correlation COefficient");
return sb.toString();
}
private void process(ByteProcessor image) {
features = new double[14];
firePropertyChange(new Progress(1, "creating coocurrence matrix"));
Coocurrence coocurrence = new Coocurrence(image, NUM_GRAY_VALUES, this.haralickDist);
double[][] cooccurrenceMatrix = coocurrence.getCooccurrenceMatrix();
double meanGrayValue = coocurrence.getMeanGrayValue();
firePropertyChange(new Progress(25, "normalizing"));
normalize(cooccurrenceMatrix, coocurrence.getCooccurenceSums());
firePropertyChange(new Progress(50, "computing statistics"));
calculateStatistics(cooccurrenceMatrix);
firePropertyChange(new Progress(75, "computing features"));
double[][] p = cooccurrenceMatrix;
double[][] Q = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
double sum_j_p_x_minus_y = 0;
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = p[i][j];
sum_j_p_x_minus_y += j * p_x_minus_y[j];
features[0] += p_ij * p_ij;
features[2] += i * j * p_ij - mu_x * mu_y;
features[3] += (i - meanGrayValue) * (i - meanGrayValue) * p_ij;
features[4] += p_ij / (1 + (i - j) * (i - j));
features[8] += p_ij * log(p_ij);
// feature 13
if (p_ij != 0 && p_x[i] != 0) { // would result in 0
for (int k = 0; k < NUM_GRAY_VALUES; k++) {
if (p_y[k] != 0 && p[j][k] != 0) { // would result in NaN
Q[i][j] += (p_ij * p[j][k]) / (p_x[i] * p_y[k]);
}
}
}
}
features[1] += i * i * p_x_minus_y[i];
features[9] += (i - sum_j_p_x_minus_y) * (i - sum_j_p_x_minus_y) * p_x_minus_y[i];
features[10] += p_x_minus_y[i] * log(p_x_minus_y[i]);
}
// feature 13: Max Correlation Coefficient
double[] realEigenvaluesOfQ = new Matrix(Q).eig().getRealEigenvalues();
Arrays2.abs(realEigenvaluesOfQ);
Arrays.sort(realEigenvaluesOfQ);
features[13] = Math.sqrt(realEigenvaluesOfQ[realEigenvaluesOfQ.length - 2]);
features[2] /= Math.sqrt(var_x * var_y);
features[8] *= -1;
features[10] *= -1;
double maxhxhy = Math.max(hx, hy);
if (Math.signum(maxhxhy) == 0) {
features[11] = 0;
} else {
features[11] = (features[8] - hxy1) / maxhxhy;
}
features[12] = Math.sqrt(1 - Math.exp(-2 * (hxy2 - features[8])));
for (int i = 0; i < 2 * NUM_GRAY_VALUES - 1; i++) {
features[5] += i * p_x_plus_y[i];
features[7] += p_x_plus_y[i] * log(p_x_plus_y[i]);
double sum_j_p_x_plus_y = 0;
for (int j = 0; j < 2 * NUM_GRAY_VALUES - 1; j++) {
sum_j_p_x_plus_y += j * p_x_plus_y[j];
}
features[6] += (i - sum_j_p_x_plus_y) * (i - sum_j_p_x_plus_y) * p_x_plus_y[i];
}
features[7] *= -1;
}
/**
* Calculates the statistical properties.
*/
private void calculateStatistics(double[][] cooccurrenceMatrix) {
// p_x, p_y, p_x+y, p_x-y
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
p_x[i] += p_ij;
p_y[j] += p_ij;
p_x_plus_y[i + j] += p_ij;
p_x_minus_y[Math.abs(i - j)] += p_ij;
}
}
// mean and variance values
double[] meanVar;
meanVar = meanVar(p_x);
mu_x = meanVar[0];
var_x = meanVar[1];
meanVar = meanVar(p_y);
mu_y = meanVar[0];
var_y = meanVar[1];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
// hx and hy
hx += p_x[i] * log(p_x[i]);
hy += p_y[i] * log(p_y[i]);
// hxy1 and hxy2
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
hxy1 += p_ij * log(p_x[i] * p_y[j]);
hxy2 += p_x[i] * p_y[j] * log(p_x[i] * p_y[j]);
}
}
hx *= -1;
hy *= -1;
hxy1 *= -1;
hxy2 *= -1;
}
/**
* Compute mean and variance of the given array
*
* #param a inut values
* #return array{mean, variance}
*/
private double[] meanVar(double[] a) {
// VAR(X) = E(X^2) - E(X)^2
double ex = 0, ex2 = 0; // E(X), E(X^2)
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
ex += a[i];
ex2 += a[i] * a[i];
}
ex /= a.length;
ex2 /= a.length;
double var = ex2 - ex * ex;
return new double[]{ex, var};
}
/**
* Returns the logarithm of the specified value.
*
* #param value the value for which the logarithm should be returned
* #return the logarithm of the specified value
*/
private double log(double value) {
double log = Math.log(value);
if (log == Double.NEGATIVE_INFINITY) {
log = 0;
}
return log;
}
private void normalize(double[][] A, double sum) {
for (int i = 0; i < A.length; i++) {
Arrays2.div(A[i], sum);
}
}
//<editor-fold defaultstate="collapsed" desc="getter/Setter">
/**
* Getter for haralick distributions
*
* #return haralick distributions
*/
public int getHaralickDist() {
return haralickDist;
}
/**
* Setter for haralick distributions
*
* #param haralickDist int for haralick distributions
*/
public void setHaralickDist(int haralickDist) {
this.haralickDist = haralickDist;
}
//</editor-fold>
}
//<editor-fold defaultstate="collapsed" desc="Coocurrence Matrix">
/**
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
*/
class Coocurrence {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES;
/**
* The number of gray levels in an image
*/
private final int GRAY_RANGES = 256;
/**
* The scale for the gray values for conversion rgb to gray values.
*/
private final double GRAY_SCALE;
/**
* gray histogram of the image.
*/
private final double[] grayHistogram;
/**
* quantized gray values of each pixel of the image.
*/
private final byte[] grayValue;
/**
* mean gray value
*/
private double meanGrayValue = 0;
/**
* The cooccurrence matrix
*/
private final double[][] cooccurrenceMatrices;
/**
* The value for one increment in the gray/color histograms.
*/
private final int HARALICK_DIST;
private final ByteProcessor image;
public Coocurrence(ByteProcessor b, int numGrayValues, int haralickDist) {
this.NUM_GRAY_VALUES = numGrayValues;
this.image = b;
this.GRAY_SCALE = (double) GRAY_RANGES / (double) NUM_GRAY_VALUES;
this.cooccurrenceMatrices = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
this.grayValue = new byte[image.getPixelCount()];
this.grayHistogram = new double[GRAY_RANGES];
this.HARALICK_DIST = haralickDist;
calculate();
}
public double getMeanGrayValue() {
return this.meanGrayValue;
}
public double[][] getCooccurrenceMatrix() {
return this.cooccurrenceMatrices;
}
public double getCooccurenceSums() {
return image.getPixelCount() * 8;
}
private void calculate() {
calculateGreyValues();
final int imageWidth = image.getWidth();
final int imageHeight = image.getHeight();
final int d = HARALICK_DIST;
int i, j, pos;
// image is not empty per default
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
pos = imageWidth * y + x;
// horizontal neighbor: 0 degrees
i = x - d;
// j = y;
if (!(i < 0)) {
increment(grayValue[pos], grayValue[pos - d]);
}
// vertical neighbor: 90 degree
// i = x;
j = y - d;
if (!(j < 0)) {
increment(grayValue[pos], grayValue[pos - d * imageWidth]);
}
// 45 degree diagonal neigbor
i = x + d;
j = y - d;
if (i < imageWidth && !(j < 0)) {
increment(grayValue[pos], grayValue[pos + d - d * imageWidth]);
}
// 135 vertical neighbor
i = x - d;
j = y - d;
if (!(i < 0) && !(j < 0)) {
increment(grayValue[pos], grayValue[pos - d - d * imageWidth]);
}
}
}
meanGrayValue = Arrays2.sum(grayValue);
}
private void calculateGreyValues() {
int size = image.getPixelCount();
int gray;
for (int pos = 0; pos < size; pos++) {
gray = image.get(pos);
grayValue[pos] = (byte) (gray / GRAY_SCALE); // quantized for texture analysis
grayHistogram[gray]++;
}
Arrays2.div(grayHistogram, size);
}
/**
* Incremets the coocurrence matrix at the specified positions (g1,g2) and
* (g2,g1).
*
* #param g1 the gray value of the first pixel
* #param g2 the gray value of the second pixel
*/
private void increment(int g1, int g2) {
cooccurrenceMatrices[g1][g2]++;
cooccurrenceMatrices[g2][g1]++;
}
}
//</editor-fold>
Here you have the source.
Thanks in advance=)
My task is to create an OpenGL Java program which will load a dataset, and then display an orthogonal slice of said data on the X, Y and Z axis. I'm new to OpenGL and I've been having trouble with plotting the data. The class to load the dataset has been provided for me:
public class VolumetricDataSet {
private final int[] dimensions;
private int maxValue;
private int minValue;
private final int[][][] volumeData;
/**
* Construct a new dataset from a File.
*
* #param in
* the file to read the data from.
* #param xSize
* the maximal x dimension to use.
* #param ySize
* the maximal y dimension to use.
* #param zSize
* the maximal z dimension to use.
* #throws IOException
* if the underlying reader encounters an error.
* #throws FileNotFoundException
* if the file cannot be found.
*/
public VolumetricDataSet(final File in, final int xSize, final int ySize,
final int zSize) throws IOException, FileNotFoundException {
this(new FileInputStream(in), xSize, ySize, zSize);
}
/**
* Construct a new dataset.
*
* #param in
* the stream to read the data from.
* #param xSize
* the maximal x dimension to use.
* #param ySize
* the maximal y dimension to use.
* #param zSize
* the maximal z dimension to use.
* #throws IOException
* if the underlying reader encounters an error.
*/
public VolumetricDataSet(final InputStream in, final int xSize,
final int ySize, final int zSize) throws IOException {
int value = 0, xCur = 0, yCur = 0, zCur = 0;
volumeData = new int[xSize][ySize][zSize];
while ((value = in.read()) != -1) {
volumeData[xCur][yCur][zCur] = value;
if (value > maxValue)
maxValue = value;
if (value < minValue)
minValue = value;
if (++xCur == xSize) {
xCur = 0;
if (++yCur == ySize) {
yCur = 0;
zCur++;
}
}
}
dimensions = new int[] { xSize, ySize, zSize };
}
/**
* Retrieve the length of the x y z dimensions of the data set. 3 element array
*
* #return the dimensions.
*/
public int[] getDimensions()
{
return dimensions;
}
/**
* #return the maximal value
*/
public int getMaxValue()
{
return maxValue;
}
/**
* #return the minimal value.
*/
public int getMinValue()
{
return minValue;
}
/**
* #return the entire data set as a 3-D array. x is the 1st dimension, y the
* 2nd and z the 3rd.
*/
public int[][][] getVolumeData()
{
return volumeData;
}
}
My code to display the data:
VolumetricDataSet ds = new VolumetricDataSet(new File("C:\\Users\\Me\\Desktop\\Work\\Comp Graphics\\marschnerlobb.raw.gz"), 41, 41, 41);
int[][][] volumeData = ds.getVolumeData();
int[] dimensions = ds.getDimensions();
for(int i = 0; i < dimensions[0]; i++)
{
for(int j = 0; j < dimensions[1]; j++)
{
if(volumeData[i][j][0] < 1)
{
gl.glColor3f(0.0f,0.0f,0.0f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 40)
{
gl.glColor3f(0.0f,0.0f,0.1f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 80)
{
gl.glColor3f(0.0f,0.0f,0.2f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 120)
{
gl.glColor3f(0.0f,0.0f,0.3f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 160)
{
gl.glColor3f(0.0f,0.0f,0.4f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 200)
{
gl.glColor3f(0.0f,0.0f,0.5f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 240)
{
gl.glColor3f(0.0f,0.0f,0.6f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 280)
{
gl.glColor3f(0.0f,0.0f,0.7f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
}
}
marschnerlobb.raw.gz is the dataset that I am currently using to test my program which can be found at http://www.volvis.org/
When I run the program at first I thought it was correct as it looked like it may be a a slice from the dataset I used (which resembles a square). But when I tried it with a different dataset (a skull) the result being displayed was still a square image.
I am newbie to the java....working on a piece of applet code...............as I am still going through the OOPs concepts and java understanding and need to develop below mentioned functionality.
The piece of code I have works like this :
First it reads all parameters from HTML tags and stores in global variables. Then it sends query to CGI to read graph data. Then it converts data for plotting and draws graph. There is a option for user to select 1-24 hours. Based on the selection graph will be plotted by plotting only selected data. Every 30 sec it sends query to CGI for collecting data.
The code uses following library and uses java 1.5 environment and i cannot change it due to embeded requirements :
I need to enchance it by implementing zoom in zoom out feature with x-y axis granuality changing with zoom in .
My worry is how to do that?I know its Frustrating question ...but i am here to get suggestion from the java experts so that I can quickly learn and implement this stuff.
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
/******************************************************************************
*
* Class - Graph
*
* This is the entry point.
* This class extends Applet class and implements Runnable.
*
*****************************************************************************/
public class GraphPerf extends Applet implements Runnable,ItemListener,MouseMotionListener
{
//Global variables
int MAX_DATA_X ;
int SIZE_X= 480;
int SIZE_Y= 250;
int SIZE_Y1= 240;
int MIN_ERROR = -1;
int MAX_LOG10_ERROR_COUNT = 1001;
int MAX_ERROR_COUNT = 101;
int SIZE_Y_EXTENDED_BOTTOM = 20;
int MAX_DISP_PARMS = 16;
int MAX_NUM_INTERVELL_PER_DAY = 96;
int MAX_DISP_PARMS_STD = 7;
int refreshTime;
String serverAddress,hostAddr;
Color plotColor1,plotColor8;
float graphData[][];
float graph_data_rf_east,graph_data_rf_west;
int xOffset = 50;
int yOffset = 40;
int Y1_MAX_VALUE = 100;
int Y2_MAX_VALUE = 3;
float RANGE2;
Thread graphThread;
Image Buffer;
Graphics plot;
Choice timeChoice, modeChoice, seloptChoice;
int duration=1, viewMode=1, line_type = 0,viewOpt = 1;
Label valueLabel1, valueLabel2,valueLabel3,valueLabel4,valueLabel5;
boolean GraphBottomExtendFlag=true;
/******************************************************************************
*
* method - init
*
* This is the method called first after applet loaded in to browser.
* This function reads configurable parameters from HTML tag and updates
* global variables.
*****************************************************************************/
public void init()
{
MAX_DATA_X = 672;//Integer.parseInt(getParameter("max_data_x"));
//refreshTime = 30;//Integer.parseInt(getParameter("refresh_sec"));
/*URL url = getDocumentBase();
String host = url.getHost();
try
{
InetAddress addr = InetAddress.getByName(host);
hostAddr=addr.getHostAddress();
}catch (UnknownHostException ex) {
ex.printStackTrace();
}
*/
//serverAddress = new String ( getParameter("access_str")+ hostAddr + getParameter("data_server"));
graphData = new float[MAX_DISP_PARMS][MAX_DATA_X+1];
/*initialize the array with -1 not with 0(0 also valid for graph data) */
int i =0,j = 0;
for( j=0; j<MAX_DISP_PARMS; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
graphData[j][i] = -1;
}
}
graph_data_rf_east = -1;
graph_data_rf_west = -1;
plotColor1 = Color.orange;
plotColor2 = Color.black;
plotColor8 = Color.red;
plotColor9 = Color.green;
setBackground(Color.white);
setLayout(null);
timeChoice = new Choice();
timeChoice.add("1");
timeChoice.add("2");
timeChoice.add("3");
timeChoice.add("4");
timeChoice.add("5");
timeChoice.add("6");
timeChoice.add("7");
add(timeChoice);
timeChoice.setBounds(190,340,40,23);
timeChoice.addItemListener(this);
Label timeLabel1 = new Label("View graph for last");
Label timeLabel2 = new Label("day(s)");
add(timeLabel1);
timeLabel1.setBounds(xOffset+30,340,160,23);
add(timeLabel2);
timeLabel2.setBounds(240,340,50,23);
valueLabel1 = new Label();
add(valueLabel1);
valueLabel1.setBounds(300,340,50,23);
valueLabel2 = new Label();
add(valueLabel2);
valueLabel2.setBounds(370,340,70,23);
valueLabel3 = new Label();
add(valueLabel3);
valueLabel3.setBounds(440,340,70,23);
valueLabel4 = new Label();
add(valueLabel4);
valueLabel4.setBounds(500,340,70,23);
valueLabel5 = new Label();
add(valueLabel5);
valueLabel5.setBounds(370,370,80,25);
modeChoice = new Choice();
modeChoice.add("East");
modeChoice.add("West");
/* Display this only for Protected and East-West Mode */
if(2/*Integer.parseInt(getParameter("mode"))*/ == 2)
{
add(modeChoice);
}
else
{
viewOpt = 1;
}
modeChoice.setBounds(xOffset+SIZE_X-55, 0, 60, 25);
modeChoice.addItemListener(this);
addMouseMotionListener(this);
}
public void start()
{
graphThread = new Thread(this);
graphThread.start();
}
public void stop()
{
graphThread = null;
}
/******************************************************************************
*
* This method will be called after starting the thread. This is a
* infinite loop which will call query method for every 30 sec to read data
* from CGI. Then it plots graph by calling plotGraph method
* the thread.
*****************************************************************************/
public void run()
{
/*while (false)
{
try
{//getData(serverAddress);
int sizeY = SIZE_Y;
if(GraphBottomExtendFlag)
{
sizeY += SIZE_Y_EXTENDED_BOTTOM;
}
repaint(xOffset+1,yOffset+1,SIZE_X-1,sizeY-1);
//graphThread.sleep(refreshTime*1000);
}catch (Exception e) { System.out.println(e); }
}*/
}
/******************************************************************************
*
* method - paint
*
* This method displays the graph plotted by plotGraph method
* in the screen. Then it draws axis for the graph
*
*****************************************************************************/
public void paint(Graphics g1)
{
int sizeY = SIZE_Y;
/*If Graph Bottom is to be Etended
*soo that zero is displayed properly
*/
if(GraphBottomExtendFlag)
{
sizeY += SIZE_Y_EXTENDED_BOTTOM;
}
if( duration <= 5 )
{
Buffer = createImage(SIZE_X, sizeY);
plot = Buffer.getGraphics();
plotGraph(plot);
g1.drawImage (Buffer,xOffset,yOffset,this);
}
else
{
Buffer = createImage(MAX_DATA_X*duration/7,sizeY);
plot = Buffer.getGraphics();
plotGraph(plot);
g1.drawImage (Buffer,xOffset,yOffset,SIZE_X,sizeY,this);
}
g1.setColor(Color.black);
g1.drawRect(70,150,270,80);
/*Dram Graph boarder */
g1.drawRect(xOffset,yOffset,SIZE_X,sizeY);
g1.drawRect(xOffset-1,yOffset-1,SIZE_X+2,sizeY+2);
/*Plot X axis*/
int max_x_marks = 8;
int temp = 1,cnt_graph = 0;
int float_temp,float_temp2;
/*max 8 plots on x axis*/
for(int x=max_x_marks; x>0; x--)
{
float_temp = (int)((MAX_NUM_INTERVELL_PER_DAY*duration)/max_x_marks)*((max_x_marks+1)-x);
float_temp2 = SIZE_X-(60*cnt_graph);
g1.drawString(String.valueOf(float_temp),(float_temp2-20) ,SIZE_Y+yOffset+35);
cnt_graph++;
}
/*Plot Y1 AXIS*/
temp = Y1_MAX_VALUE;
for(int x = 0; x <= SIZE_Y; x+= 25)
{
g1.drawString(String.valueOf(temp), 25, x + yOffset+10);
temp -= (Y1_MAX_VALUE - 0)/10;
}
temp = 1000;
/*Plot Y2 AXIS*/
int index_log = 1;
for(int x = 0; x <= SIZE_Y1; x+= 80)
{
if(x== 240)
index_log--;
if(temp>=1)
{
g1.drawString(String.valueOf(temp), 550, x+yOffset+8-index_log);
g1.drawLine(530,x+yOffset+5-index_log, 540, x+yOffset+5-index_log);
}
temp = temp/10;
}
Font thisFont = new Font("Times New Roman", Font.BOLD, 14);
g1.setFont(thisFont);
g1.drawString("Y2", 550, 160);
g1.drawString("Y1",5, 160);
}
/******************************************************************************
*
* method - plotGraph
*
* Depending on the mode, "East", "West" or "Combined", it plots
* single or two graphs in the same applet.
*
* Inputs :
* g - Graphics object
*****************************************************************************/
public void plotGraph(Graphics g)
{
g.setColor(new Color(255,255,220));
/*If Error-Sec-Count Graph
*Then extend the lower portion
*soo that zero is displayed properly
*/
if(GraphBottomExtendFlag)
{
g.fillRect(0,0,MAX_DATA_X,SIZE_Y + SIZE_Y_EXTENDED_BOTTOM);
}
else
{
g.fillRect(0,0,MAX_DATA_X,SIZE_Y);
}
switch(viewMode)
{
case 1 :
plot1(g);
plot_timeelapsed_east(g);
break;
case 2 :
plot8(g);
plot_timeelapsed_west(g);
break;
}
}
/******************************************************************************
*
* method - plot1
*
* This method uses graphData[0][] global variable and plots series of lines
* in the applet
*
* Inputs :
* g - Graphics object
*****************************************************************************/
void plot1(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
localPlotBuffer = new int[2];
g.setColor(plotColor1);
if(duration > 5)
{
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY); x > 0 ; x--)
{
/*if data is valid data then plot else ignore*/
if((graphData[0][end]>MIN_ERROR)&&(graphData[0][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[0][end-1]>MIN_ERROR)&&(graphData[0][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end-1] == 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine(x-1,(localPlotBuffer[0]+5), x-2,(localPlotBuffer[1]+5));
g.drawLine(x,(localPlotBuffer[0]+5), x-1,(localPlotBuffer[1]+5));
}
end--;
}
}
else
{
float temp = SIZE_X;
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY) ; x > 0 ; x--)
{
float LocalTemp1 = temp;
float LocalTemp2 = (int)(temp-(double)5/(double)duration);
/*Normalise the pixcel positions */
/*Normalise the pixcel positions */
if(duration == 1)
{
if(LocalTemp1>(SIZE_X-3))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-3))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 2)
{
if(LocalTemp1>(SIZE_X-2))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-2))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 3)
{
if(LocalTemp1>(SIZE_X-1))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-1))
LocalTemp2 = SIZE_X;
}
/*if data is valid data then plot else ignore*/
if((graphData[0][end]>MIN_ERROR)&&(graphData[0][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[0][end-1]>MIN_ERROR)&&(graphData[0][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end-1] == 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine((int)LocalTemp1,(localPlotBuffer[0]+5), (int)LocalTemp2,(localPlotBuffer[1]+5));
}
temp-=(double)5/(double)duration;
end--;
}
}
}
/******************************************************************************
*
* method - plot8
*
* This method uses graphData[7][] global variable and plots series of lines
* in the applet
*
* Inputs :
* g - Graphics object
*****************************************************************************/
void plot8(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
localPlotBuffer = new int[2];
g.setColor(plotColor1);
if(duration > 5)
{
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY); x > 0 ;x-- )
{
/*if data is valid data then plot else ignore*/
if((graphData[8][end]>MIN_ERROR)&&(graphData[8][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[8][end-1]>MIN_ERROR)&&(graphData[8][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end-1]== 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine(x-1,(localPlotBuffer[0]+5), x-2,(localPlotBuffer[1]+5));
g.drawLine(x,(localPlotBuffer[0]+5), x-1,(localPlotBuffer[1]+5));
}
end--;
}
}
else
{
float temp = SIZE_X;
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY) ; x > 0 ; x--)
{
float LocalTemp1 = temp;
float LocalTemp2 = (int)(temp-(double)5/(double)duration);
/*Normalise the pixcel positions */
if(duration == 1)
{
if(LocalTemp1>(SIZE_X-3))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-3))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 2)
{
if(LocalTemp1>(SIZE_X-2))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-2))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 3)
{
if(LocalTemp1>(SIZE_X-1))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-1))
LocalTemp2 = SIZE_X;
}
/*if data is valid data then plot else ignore*/
if((graphData[8][end]>MIN_ERROR)&&(graphData[8][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[8][end-1]>MIN_ERROR)&&(graphData[8][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end-1]== 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine((int)LocalTemp1,(localPlotBuffer[0]+5), (int)LocalTemp2,(localPlotBuffer[1]+5));
}
temp-=(double)5/(double)duration;
end--;
}
}
}
/******************************************************************************
*
* method - plot_timeelapsed_east
*
* This method uses graph_data_rf_east global variable and plots series of lines
* in the applet
*****************************************************************************/
void plot_timeelapsed_east(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
int x= 0;
localPlotBuffer = new int[2];
x= (duration*MAX_NUM_INTERVELL_PER_DAY);
g.setColor(plotColor9);
/*if data is valid data then plot else ignore*/
if((graph_data_rf_east>0)&&(graph_data_rf_east<MAX_LOG10_ERROR_COUNT))
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graph_data_rf_east)/(float)Y2_MAX_VALUE));
if(duration>5)
g.drawLine(x-1,SIZE_Y+5, x-2,(localPlotBuffer[0]+5));
else
g.drawLine(SIZE_X,SIZE_Y+5, 474+duration,(localPlotBuffer[0]+5));
}
}/*End for plot_timeelapsed_east() */
/******************************************************************************
*
* method - plot_timeelapsed_west
*
* This method uses graph_data_rf_east global variable and plots series of lines
* in the applet
*****************************************************************************/
void plot_timeelapsed_west(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
int x= 0;
localPlotBuffer = new int[2];
x= (duration*MAX_NUM_INTERVELL_PER_DAY);
g.setColor(plotColor9);
/*if data is valid data then plot else ignore*/
if((graph_data_rf_east>MIN_ERROR)&&(graph_data_rf_east<MAX_LOG10_ERROR_COUNT))
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graph_data_rf_west)/(float)Y2_MAX_VALUE));
if(duration>5)
g.drawLine(x-1,SIZE_Y+5, x-2,(localPlotBuffer[0]+5));
else
g.drawLine(SIZE_X,SIZE_Y+5, 474+duration,(localPlotBuffer[0]+5));
}
}
/******************************************************************************
*
* method - getData
*
* This method sends query to CGI to collect data. Then it converts the
* data for applet area then updates global variable.
*
* Inputs :
* serverAddress - server CGI path
*****************************************************************************/
public void getData(String serverAddress)
{
URL addr;
BufferedReader in;
String inputLine;
int count = 0;
int i=0,j = 0;
try
{
addr = new URL(serverAddress);
URLConnection connection = addr.openConnection();
in = new BufferedReader(new InputStreamReader(addr.openStream()));
/*Read data for first link */
for( j=0; j<MAX_DISP_PARMS_STD; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
inputLine = in.readLine();
graphData[j][i] = Integer.parseInt(inputLine);
}
}
for( i=0; i<MAX_DATA_X; i++)
{
inputLine = in.readLine();
graphData[7][i] = Integer.parseInt(inputLine);
if(graphData[7][i] == 1)
graphData[7][i] = 10;
}
inputLine = in.readLine();
graph_data_rf_east = Integer.parseInt(inputLine);
/*Reading data for second link */
if(Integer.parseInt(getParameter("mode")) == 2)
{
for( j=8; j<15; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
inputLine = in.readLine();
graphData[j][i] = Integer.parseInt(inputLine);
}
}
for( i=0; i<MAX_DATA_X; i++)
{
inputLine = in.readLine();
graphData[15][i] = Integer.parseInt(inputLine);
if(graphData[15][i] == 1)
graphData[15][i] = 10;
}
inputLine = in.readLine();
graph_data_rf_west = Integer.parseInt(inputLine);
}
in.close();
}catch (Exception e) { System.out.println("Server Data Read Error:"+e); }
}
/******************************************************************************
*
* method - itemStateChanged
*
* This method will be called whenever event occured on this choice.
* it read the current status and changes scale accordingly.
* *****************************************************************************/
public void itemStateChanged(ItemEvent evt)
{
if( evt.getSource() == timeChoice )
duration = Integer.parseInt(timeChoice.getSelectedItem());
else
viewMode = modeChoice.getSelectedIndex()+1;
repaint();
}
/******************************************************************************
*
* method - mouseMoved
*
* This method will be called whenever mouse cursor is moved over the
* applet. Depending on the cursor position, it will display Actual
* X and Y values of the graph.
*****************************************************************************/
public void mouseMoved(MouseEvent evt)
{
int x = evt.getX()-xOffset;
int y = evt.getY()-yOffset-5;
int a = evt.getX();
int b = evt.getY();
int duration = Integer.parseInt(timeChoice.getSelectedItem());
if( (x>=0) && (x<=SIZE_X) && (y>=0) && (y<=SIZE_Y) )
{
valueLabel1.setText("X ");
valueLabel2.setText("Y1 ");
valueLabel3.setText("Y2 ");
try
{
int x_max_value = ((SIZE_X*duration)/5);
int x1 = (int)((float)((float)((float)(SIZE_X*duration))/5) * ((float)((float)(SIZE_X - x))/((float)SIZE_X)));
/*For Durations less than 16 scale starts with 1*/
int y1 = (int)((float)Y1_MAX_VALUE * (((float)SIZE_Y - (float)y)/((float)SIZE_Y)));
int y2 = (int) Math.pow(10,((float)(3 * ((float)(1 - (float)y/((float)SIZE_Y1))))));
valueLabel1.setText("X="+x1);
valueLabel2.setText("X pix="+a);
valueLabel3.setText("Y="+y1);
valueLabel4.setText("Y pix="+b);
valueLabel5.setText("Y2="+y2);
}
catch(Exception e) {System.out.println("Mouse Moved Error" + e);}
}
else
{
valueLabel1.setText(" ");
valueLabel2.setText(" ");
valueLabel3.setText(" ");
}
}
public void mouseDragged(MouseEvent evt) { }
}
There are many ways to do this. Here are two:
You can simply scale the values: Multiply every coordinate with the zoom factor.
Use Java2D and AffineTransform:
AffineTransform transformer = new AffineTransform();
transformer.scale(zoom, zoom);
Graphics2D g2d = (Graphics2D)g;
g2d.setTransform(transformer);
// draw to g2d.
[EDIT] If you want to do everything yourself, see this page for a refresh of basic linear algebra: 2D Transformations
Don't mind the 3D example at the top; the rest of the page is about 2D.
I used JCC kit for my target platform and it's less than 100kb library. You need to understand the library and after that you can play without worrying about size. :)
Good library to use in embedded systems whether size is always the issue. it has inbuilt function o transform coordinates into screen coordinates and vice-verse.