Skip to content

Instantly share code, notes, and snippets.

@Cellane
Created November 10, 2010 21:54
Show Gist options
  • Save Cellane/671603 to your computer and use it in GitHub Desktop.
Save Cellane/671603 to your computer and use it in GitHub Desktop.
public class Cviceni1 {
public static void main (String[] args) {
new Form ().setVisible (true);
}
}
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public final class Form extends javax.swing.JFrame implements G_Controls {
public static int leftX, topY, rightX, bottomY;
public static G_Color foregroundColor = new G_Color ();
public static G_Color backgroundColor = new G_Color ();
public static G_Point start = new G_Point ();
public static G_Point end = new G_Point ();
public static int activeTaskId = 0;
public static boolean firstLocationSet = false;
private static final long serialVersionUID = 1L;
private G_Graphics graphic;
private G_Canvas canvas;
private JMenuBar menuBar = new JMenuBar ();
private JMenu fileMenu = new JMenu ("File");
private JToolBar toolBar = new JToolBar ();
private JButton pixelButton = new JButton ("Pixel");
private JButton lineButton = new JButton ("Line");
private JButton rectangleButton = new JButton ("Rectangle");
private JButton foregroundColorChooserButton = new JButton ("Foreground");
private JButton backgroundColorChooserButton = new JButton ("Background");
private int[][] kernel;// = {{0, -1, 0}, {-1, 5, -1}, {0, -1, 0}};
public Form () {
super ();
init ();
leftX = 0;
topY = 0;
rightX = canvas.getWidth () - 1;
bottomY = canvas.getHeight () - 1;
G_draw ();
}
public void G_draw () {
graphic.clear ();
G_repaint ();
}
public void G_mousePressed (G_Button button, int x, int y) {
G_ButtonPressed.buttonPressed (x, y);
G_repaint ();
}
public void G_mouseReleased (G_Button button, int x, int y) {
G_ButtonReleased.buttonReleased (x, y, graphic);
G_repaint ();
}
public void G_repaint () {
canvas.repaint ();
}
private void init () {
Action openMenuItem, closeMenuItem;
BufferedImage image;
int shortcutKeyMask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMask ();
// JFrame
setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE);
this.setTitle ("Mion Painting Tool");
this.setSize (800, 600);
this.setLocationRelativeTo (null);
// JMenu
openMenuItem = new openActionClass ("Open",
KeyStroke.getKeyStroke (KeyEvent.VK_O, shortcutKeyMask));
closeMenuItem = new closeActionClass ("Close",
KeyStroke.getKeyStroke (KeyEvent.VK_W, shortcutKeyMask));
fileMenu.add (new JMenuItem (openMenuItem));
fileMenu.add (new JMenuItem (closeMenuItem));
menuBar.add (fileMenu);
this.setJMenuBar (menuBar);
// JToolBar
pixelButton.putClientProperty ("JButton.segmentPosition", "first");
pixelButton.putClientProperty ("JButton.buttonType", "segmented");
pixelButton.addActionListener (new pixelActionClass ());
lineButton.putClientProperty ("JButton.segmentPosition", "middle");
lineButton.putClientProperty ("JButton.buttonType", "segmented");
lineButton.addActionListener (new lineActionClass ());
rectangleButton.putClientProperty ("JButton.segmentPosition", "last");
rectangleButton.putClientProperty ("JButton.buttonType", "segmented");
rectangleButton.addActionListener (new rectangleActionClass ());
foregroundColorChooserButton.putClientProperty ("JButton.segmentPosition", "first");
foregroundColorChooserButton.putClientProperty ("JButton.buttonType", "segmented");
foregroundColorChooserButton.addActionListener (new foregroundColorChooserActionClass ());
backgroundColorChooserButton.putClientProperty ("JButton.segmentPosition", "last");
backgroundColorChooserButton.putClientProperty ("JButton.buttonType", "segmented");
backgroundColorChooserButton.addActionListener (new backgroundColorChooserActionClass ());
toolBar.add (pixelButton);
toolBar.add (lineButton);
toolBar.add (rectangleButton);
toolBar.add (Box.createHorizontalGlue ());
toolBar.add (foregroundColorChooserButton);
toolBar.add (backgroundColorChooserButton);
toolBar.setFloatable (false);
getContentPane ().add (toolBar, BorderLayout.NORTH);
// BufferedImage
image = new BufferedImage (this.getSize ().width, this.getSize ().height, BufferedImage.TYPE_INT_RGB);
// graphic
graphic = new G_Graphics (image);
// canvas
canvas = new G_Canvas (image);
canvas.setPreferredSize (new Dimension (this.getSize ().width, this.getSize ().height));
// content
getContentPane ().add (canvas, java.awt.BorderLayout.CENTER);
// mouse listener
canvas.addMouseListener (new MouseAdapter() {
public void mousePressed (MouseEvent evt) {
G_Button button = G_Button.B_NONE;
if (evt.getButton () == MouseEvent.BUTTON1) button = G_Button.B_LEFT;
if (evt.getButton () == MouseEvent.BUTTON2) button = G_Button.B_RIGHT;
G_mousePressed (button, evt.getX (), evt.getY ());
}
public void mouseReleased (MouseEvent evt) {
G_Button button = G_Button.B_NONE;
if (evt.getButton () == MouseEvent.BUTTON1) button = G_Button.B_LEFT;
if (evt.getButton () == MouseEvent.BUTTON2) button = G_Button.B_RIGHT;
G_mouseReleased (button, evt.getX (), evt.getY ());
}
});
pack ();
}
/**
* Abstract class that's performed when user clicks the File -> Open option
*/
private class openActionClass extends AbstractAction {
public openActionClass (String text, KeyStroke shortcut) {
super (text);
putValue (ACCELERATOR_KEY, shortcut);
}
public void actionPerformed (ActionEvent e) {
FileDialog fileDialog = new FileDialog (new Frame (), "Open File",
FileDialog.LOAD);
String file;
fileDialog.setVisible (true);
if (fileDialog.getFile () != null) {
file = fileDialog.getDirectory () + fileDialog.getFile ();
graphic.showImage (file);
G_repaint ();
}
}
}
/**
* Abstract class that's performed when user clicks the File -> Close option
*/
private class closeActionClass extends AbstractAction {
public closeActionClass (String text, KeyStroke shortcut) {
super (text);
putValue (ACCELERATOR_KEY, shortcut);
}
public void actionPerformed (ActionEvent e) {
System.exit (0);
}
}
/**
* Abstract class that's performed when user clicks the Pixel button
*/
private class pixelActionClass implements ActionListener {
public void actionPerformed (ActionEvent e) {
activeTaskId = 0;
}
}
/**
* Abstract class that's performed when user clicks the Line button
*/
private class lineActionClass implements ActionListener {
public void actionPerformed (ActionEvent e) {
activeTaskId = 1;
}
}
/**
* Abstract class that's performed when user clicks the Rectangle button
*/
private class rectangleActionClass implements ActionListener {
public void actionPerformed (ActionEvent e) {
activeTaskId = 2;
}
}
/**
* Abstract class that's performed when user clicks the Foreground Color button
*/
private class foregroundColorChooserActionClass implements ActionListener {
public void actionPerformed (ActionEvent e) {
Color color = JColorChooser.showDialog (getContentPane (), "Choose foreground color",
getForeground ());
if (color != null) {
foregroundColor.setR (color.getRed ());
foregroundColor.setG (color.getGreen ());
foregroundColor.setB (color.getBlue ());
}
}
}
/**
* Abstract class that's performed when user clicks the Background Color button
*/
private class backgroundColorChooserActionClass implements ActionListener {
public void actionPerformed (ActionEvent e) {
Color color = JColorChooser.showDialog (getContentPane (), "Choose background color",
getBackground ());
if (color != null) {
backgroundColor.setR (color.getRed ());
backgroundColor.setG (color.getGreen ());
backgroundColor.setB (color.getBlue ());
}
}
}
}
public enum G_Button {
B_RIGHT, B_LEFT, B_NONE
}
public class G_ButtonPressed {
public static void buttonPressed (int x, int y) {
switch (Form.activeTaskId) {
case 1:
if (!Form.firstLocationSet) {
Form.start.setX (x);
Form.start.setY (y);
Form.firstLocationSet = true;
}
break;
case 2:
if (!Form.firstLocationSet) {
Form.start.setX (x);
Form.start.setY (y);
Form.firstLocationSet = true;
}
}
}
}
public class G_ButtonReleased {
public static void buttonReleased (int x, int y, G_Graphics graphic) {
switch (Form.activeTaskId) {
case 0:
graphic.putPixel (x, y, Form.foregroundColor);
break;
case 1:
if (Form.firstLocationSet) {
Form.end.setX (x);
Form.end.setY (y);
if ((Form.start.getX () != Form.end.getX ()) && (Form.start.getY () != Form.end.getY ())) {
graphic.drawLine (Form.start.getX (), Form.start.getY (), Form.end.getX (),
Form.end.getY (), Form.foregroundColor);
}
Form.firstLocationSet = false;
}
break;
case 2:
if (Form.firstLocationSet) {
Form.end.setX (x);
Form.end.setY (y);
if ((Form.start.getX () != Form.end.getX ()) && (Form.start.getY () != Form.end.getY ())) {
graphic.drawRectangle (Form.start.getX (), Form.start.getY (), Form.end.getX (),
Form.end.getY (), Form.foregroundColor);
}
Form.firstLocationSet = false;
}
break;
}
}
}
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class G_Canvas extends java.awt.Canvas {
private static final long serialVersionUID = 1L;
private BufferedImage bitmap;
G_Canvas (BufferedImage b) {
bitmap = b;
}
public void paint (Graphics g) {
bitmap.flush ();
g.drawImage (bitmap, 0, 0, this);
}
}
public class G_Color {
public static G_Color G_cBlack = new G_Color (0, 0, 0);
public static G_Color G_cRed = new G_Color (255, 0, 0);
public static G_Color G_cGreen = new G_Color (0, 255, 0);
public static G_Color G_cBlue = new G_Color (0, 0, 255);
public static G_Color G_cYellow = new G_Color (255, 255, 0);
public static G_Color G_cWhite = new G_Color (255, 255, 255);
public int r;
public int g;
public int b;
public G_Color () {
}
public G_Color (int rc, int gc, int bc) {
r = rc;
g = gc;
b = bc;
}
public void setR (int r) {
this.r = r;
}
public void setG (int g) {
this.g = g;
}
public void setB (int b) {
this.b = b;
}
}
public interface G_Controls {
public void G_mousePressed (G_Button button, int x, int y);
public void G_mouseReleased (G_Button button, int x, int y);
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class G_Graphics {
private BufferedImage bitmap;
private Graphics2D g;
public G_Graphics (BufferedImage b) {
bitmap = b;
g = bitmap.createGraphics ();
}
public void putPixel (int x, int y, G_Color color) {
Color colorHelp = new Color (color.r, color.g, color.b);
bitmap.setRGB (x, y, colorHelp.getRGB ());
}
/**
* Public overloaded method that accepts raw color channel values as arguments,
* and stores result into specified bitmap
*
* @param x x-position of pixel
* @param y y-position of pixel
* @param r red channel value
* @param g green channel value
* @param b blue channel value
* @param image bitmap to store the pixel
*/
public void putPixel (int x, int y, int r, int g, int b, BufferedImage image) {
Color color = new Color (r, g, b);
image.setRGB (x, y, color.getRGB ());
}
/**
* Public method that grabs everything that's on canvas at the moment of method call
* and applies convolution edit on canvas using specified kernel; result is stored
* temporarily in new raster, and when the convolution is done, that raster is
* displayed to user
*
* @param kernel kernel used for convolution
*/
public void convolution (int[][] kernel) {
BufferedImage bitmapHelp = new BufferedImage (bitmap.getWidth (), bitmap.getHeight (),
BufferedImage.TYPE_INT_RGB);
G_Color originalColor;
float finalRed, finalGreen, finalBlue;
int kernelCount;
kernelCount = kernelCount (kernel);
// We don't know how to deal with borders yet
for (int helpY = 1; helpY < (bitmap.getHeight () - 1); helpY++) {
for (int helpX = 1; helpX < (bitmap.getWidth () - 1); helpX++) {
finalRed = 0;
finalGreen = 0;
finalBlue = 0;
for (int y = -1, i = 0; y < 2; y++, i++) {
for (int x = -1, j = 0; x < 2; x++, j++) {
float temporary;
originalColor = getPixel (helpX + x, helpY + y);
temporary = kernel[i][j] / (float) kernelCount;
finalRed += (float) originalColor.r * temporary;
finalGreen += (float) originalColor.g * temporary;
finalBlue += (float) originalColor.b * temporary;
}
}
finalRed = fixColor (finalRed);
finalGreen = fixColor (finalGreen);
finalBlue = fixColor (finalBlue);
putPixel (helpX, helpY, (int) finalRed, (int) finalGreen, (int) finalBlue, bitmapHelp);
}
}
// Replace current canvas
g.drawImage (bitmapHelp, 0, 0, null);
}
/**
* Private method that calculates sum of values stored in kernel or matrix
*
* @param kernel kernel to count with
* @return sum of values stored in kernel
*/
private int kernelCount (int[][] kernel) {
int kernelCount = 0;
for (int[] row : kernel) {
for (int element : row) {
kernelCount += element;
}
}
return (kernelCount);
}
/**
* Private method that does last-time correction of color channel values
*
* @param color color to fix
* @return fixed value
*/
private float fixColor (float color) {
if (color > 255) {
color = 255;
} else if (color < 0) {
color = 0;
}
return (color);
}
/**
* Public method that fixes coordinates of a line using Cohen-Sutherland algorithm,
* then calls drawLineBresenham () method to draw the line with corrected coordinates
* TODO write an overloaded method that allows the user to create own clipping mask,
* TODO then move this algorithm into that overloaded method
*
* @param startX x coordinate of start point
* @param startY y coordinate of start point
* @param endX x coordinate of end point
* @param endY y coordinate of end point
* @param color color of painted line
*/
public void drawLine (int startX, int startY, int endX, int endY, G_Color color) {
int codeStart, codeEnd;
boolean accept;
codeStart = generateCode (startX, startY);
codeEnd = generateCode (endX, endY);
accept = false;
while (true) {
if ((codeStart == 0) && (codeEnd == 0)) {
accept = true;
break;
} else if ((codeStart & codeEnd) != 0) {
break;
} else {
boolean codeWhich;
int workX, workY, codeWork;
// if start code isn't 0 –> true, we're working with start point
// if start code is 0 –> false, we're working with end point
codeWhich = (codeStart != 0);
if (codeWhich) {
codeWork = codeStart;
workX = startX;
workY = startY;
} else {
codeWork = codeEnd;
workX = endX;
workY = endY;
}
if ((codeWork & 1) != 0) {
workY = ((endY - startY) / (endX - startX)) * (Form.leftX - workX) + workY;
workX = Form.leftX;
} else if ((codeWork & 2) != 0) {
workY = ((endY - startY) / (endX - startX)) * (Form.rightX - workX) + workY;
workX = Form.rightX;
} else if ((codeWork & 4) != 0) {
workX = ((endX - startX) / (endY - startX)) * (Form.bottomY - workY) + workX;
workY = Form.bottomY;
} else if ((codeWork & 8) != 0) {
workX = ((endX - startX) / (endY - startX)) * (Form.topY - workY) + workX;
workY = Form.topY;
}
if (codeWork == codeStart) {
startX = workX;
startY = workY;
codeStart = generateCode (startX, startY);
} else {
endX = workX;
endY = workY;
codeEnd = generateCode (endX, endY);
}
}
}
if (accept) {
drawLineBresenham (startX, startY, endX, endY, color);
}
}
/**
* Generates code required for clipping for given point
* 1 = left
* 2 = right
* 4 = bottom
* 8 = top
*
* @param x x coordinate of given point
* @param y y coordinate of given point
* @return calculated code
*/
private int generateCode (int x, int y) {
int code = 0;
if (x < Form.leftX) {
code += 1;
} else if (x > Form.rightX) {
code += 2;
}
if (y > Form.bottomY) {
code += 4;
} else if (y < Form.topY) {
code += 8;
}
return (code);
}
/**
* Private method that draws a line with given start & end coordinates,
* using Bresenham algorithm
* This method should be never called directly; call drawLine () instead!
*
* @param startX x coordinate of start point
* @param startY y coordinate of start point
* @param endX x coordinate of end point
* @param endY y coordinate of end point
* @param color color of painted line
*/
private void drawLineBresenham (int startX, int startY, int endX, int endY, G_Color color) {
int dY = endY - startY;
int dX = endX - startX;
int fraction, stepX, stepY;
if (dY < 0) {
dY = -dY;
stepY = -1;
} else {
stepY = 1;
}
if (dX < 0) {
dX = -dX;
stepX = -1;
} else {
stepX = 1;
}
dY = 2 * dY;
dX = 2 * dX;
putPixel (startX, startY, color);
if (dX > dY) {
fraction = (2 * dY) - dX;
while (startX != endX) {
if (fraction >= 0) {
startY += stepY;
fraction -= dX;
}
startX += stepX;
fraction += dY;
putPixel (startX, startY, color);
}
} else {
fraction = (2 * dX) - dY;
while (startY != endY) {
if (fraction >= 0) {
startX += stepX;
fraction -= dY;
}
startY += stepY;
fraction += dX;
putPixel (startX, startY, color);
}
}
}
/**
* Public method that draws a rectangle using drawLine () method
* @param startX top left X-coordinate
* @param startY top left Y-coordinate
* @param endX bottom right X-coordinate
* @param endY bottom right Y-coordinate
* @param color color of the line
*/
public void drawRectangle (int startX, int startY, int endX, int endY, G_Color color) {
drawLine (startX, startY, startX, endY, color);
drawLine (startX, startY, endX, startY, color);
drawLine (endX, endY, startX, endY, color);
drawLine (endX, endY, endX, startY, color);
}
/**
* Public method that draws a triangle using drawLine () method
* @param aX X-coordinate of the first point
* @param aY Y-coordinate of the first point
* @param bX X-coordinate of the second point
* @param bY Y-coordinate of the second point
* @param cX X-coordinate of the third point
* @param cY Y-coordinate of the third point
* @param color color of the line
*/
public void drawTriangle (int aX, int aY, int bX, int bY, int cX, int cY, G_Color color) {
drawLine (aX, aY, bX, bY, color);
drawLine (bX, bY, cX, cY, color);
drawLine (cX, cY, aX, aY, color);
}
public void drawPolygon (G_Point[] coordinates, G_Color color) {
for (int i = 0; i < coordinates.length - 1; i++) {
drawLine (coordinates[i].x, coordinates[i].y, coordinates[i + 1].x, coordinates[i + 1].y, color);
}
drawLine (coordinates[coordinates.length - 1].x, coordinates[coordinates.length - 1].y, coordinates[0].x,
coordinates[0].y, color);
}
public void drawPolygon (G_Point3[] coordinates, G_Color color) {
}
public void movePolygon (G_Point[] coordinates, G_Color color, int moveX, int moveY) {
for (G_Point coordinate : coordinates) {
coordinate.x += moveX;
coordinate.y += moveY;
}
drawPolygon (coordinates, color);
}
public void scalePolygon (G_Point[] coordinates, G_Color color, float factor) {
for (G_Point coordinate : coordinates) {
coordinate.x *= factor;
coordinate.y *= factor;
}
drawPolygon (coordinates, color);
}
public void geometryFill (int startX, int startY, int endX, int endY, G_Color color) {
for (int i = startY; i <= endY; i++) {
drawLine (startX, i, endX, i, color);
}
}
public void fill (int x, int y, G_Color targetColor, G_Color borderColor) {
int r, g, b;
r = getPixel (x, y).r;
g = getPixel (x, y).g;
b = getPixel (x, y).b;
if (((r != targetColor.r) && (r != borderColor.r)) ||
((g != targetColor.g) && (g != borderColor.g)) ||
((b != targetColor.b) && (b != borderColor.b))) {
putPixel (x, y, targetColor);
fill (x + 1, y, targetColor, borderColor);
fill (x - 1, y, targetColor, borderColor);
fill (x, y + 1, targetColor, borderColor);
fill (x, y - 1, targetColor, borderColor);
}
}
public int move (int coordination, int movement) {
return (coordination + movement);
}
public G_Color getPixel (int x, int y) {
Color colorHelp = new Color (bitmap.getRGB (x, y));
G_Color color = new G_Color ();
color.r = colorHelp.getRed ();
color.g = colorHelp.getGreen ();
color.b = colorHelp.getBlue ();
return (color);
}
public void clear () {
g.setBackground (new Color (255, 255, 255));
g.clearRect (0, 0, bitmap.getWidth (), bitmap.getHeight ());
}
public void showImage (String path) {
try {
BufferedImage bitmapHelp = (BufferedImage) ImageIO.read (new File (path));
g.drawImage (bitmapHelp, 0, 0, null);
} catch (IOException e) {
e.printStackTrace ();
}
}
}
public class G_Point {
protected int x, y;
public G_Point () {
this (0, 0);
}
public G_Point (int x, int y) {
this.x = x;
this.y = y;
}
public int getX () {
return (x);
}
public void setX (int x) {
this.x = x;
}
public int getY () {
return (y);
}
public void setY (int y) {
this.y = y;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment