Here is the source code for a game or we can say a small utility "Crayon" wherein one can color gif images. A great delightful program for old and the kids!
Shape.javaimport java.awt.*;
// Shape class
//
// The Shape class is an extension of the Polygon class that adds
// a method for moving the Polygon to a different location. It makes
// a copy of the original coordinates, then when you move it to a new
// location, it just adds the new position to each coordinate. In other words,
// if you moved the shape to (100,100), moveShape would add 100 to each x
// coordinate and each y coordinate. You should give the coordinates relative
// to 0, 0.
public class Shape extends Polygon
{
private int[] originalXpoints;
private int[] originalYpoints;
public int x;
public int y;
public Shape(int x[], int y[], int n)
{
super(x, y, n);
// Make a copy of the x coordinates
originalXpoints = new int[n];
System.arraycopy(x, 0, originalXpoints, 0, n);
// Make a copy of the x coordinates
originalYpoints = new int[n];
System.arraycopy(y, 0, originalYpoints, 0, n);
}
public void moveShape(int newX, int newY)
{
int i;
// Add the new X and new Y values to the original coordinates, and make that
// the new position of this shape.
for (i=0; i < npoints; i++)
{
xpoints[i] = originalXpoints[i] + newX;
ypoints[i] = originalYpoints[i] + newY;
}
}
}
_____________________________________________________________________________
Crayon.javaimport java.applet.*;
import java.awt.*;
import java.awt.image.*;
// Crayon Applet
//
// The Crayon applet uses the PixelGrabber to create an array of pixel
// values from an image. It then allows you to paint the image using
// a set of crayons, and then redisplays the image using the
// MemoryImageSource.
// If you want to use other images with this applet, make sure that
// the lines are done in black, since it specifically looks for black
// as the boundary for an area.
// Also, beware, this applet runs very slowly on a 486/100
public class Crayon extends Applet
{
private Image coloringBook; // the original image
private Image displayImage; // the image to be displayed
private int imageWidth, imageHeight; // the dimensions of the image
// the following two arrays set up the shape of the crayons
int crayonShapeX[] = { 0, 2, 10, 15, 23, 25, 25, 0 };
int crayonShapeY[] = { 15, 15, 0, 0, 15, 15, 45, 45 };
// We use the Shape class defined earlier so we can move the crayons
// to a new location easily.
private Shape crayons[];
// The color class doesn't provide a default value for brown, so we add one.
private Color brown = new Color(130, 100, 0);
// crayonColors is an array of all the colors the crayons can be. You can
// add new crayons just by adding to this array.
private Color crayonColors[] = {
Color.blue, Color.cyan, Color.darkGray,
Color.gray, Color.green, Color.magenta,
Color.orange, Color.pink, Color.red,
Color.white, Color.yellow, brown };
private Color currentDrawingColor; // the color we are coloring with
private int imagePixels[]; // the memory image of the picture
boolean imageValid = false; // did we read the image in o.k.?
// blackRGB is just used as a shortcut to get to the black pixel value
private int blackRGB = Color.black.getRGB();
Thread appletThread;
public void init()
{
int i;
String pictureName = getParameter("picture");
if (pictureName == null)
{
pictureName = "smileman.gif";
}
MediaTracker tracker = new MediaTracker(this);
// Get the image we will color
coloringBook = getImage(getDocumentBase(), pictureName);
// tell the media tracker about the image
tracker.addImage(coloringBook, 0);
// Wait for the image, if we get an error, flag the image as invalud
try {
tracker.waitForAll();
if (tracker.checkAll()) {
imageValid = true;
} else {
Object errors[] = tracker.getErrorsAny();
for (i=0; i < errors.length; i++) {
}
imageValid = false;
}
} catch (Exception oops) {
oops.printStackTrace();
imageValid = false;
}
// Get the image dimensions
imageWidth = coloringBook.getWidth(this);
imageHeight = coloringBook.getHeight(this);
// Copy the image to the array of pixels
resetMemoryImage();
// Create a new display image from the array of pixels
remakeDisplayImage();
// Create a set of crayons. We determine how many crayons to create
// based on the size of the crayonColors array
crayons = new Shape[crayonColors.length];
for (i=0; i < crayons.length; i++)
{
// Create a new crayon shape for each color
crayons[i] = new Shape(crayonShapeX,
crayonShapeY, crayonShapeX.length);
// The crayons are lined up in a row below the image
crayons[i].moveShape(i * 30,
imageHeight + 10);
}
// Start coloring with the first crayon
currentDrawingColor = crayonColors[0];
}
// resetMemoryImage copies the coloringBook image into the
// imagePixels array.
private void resetMemoryImage()
{
int offset = 0;
int incr = imageHeight / 4;
System.out.println("Image size = "+(imageWidth*imageHeight));
imagePixels = new int[imageWidth * imageHeight];
grabPixels(0, 0, imageWidth, imageHeight);
}
private void grabPixels(int fromx, int fromy, int width, int height)
{
while (true) {
// Set up a pixel grabber to get the pixels
PixelGrabber grabber = new PixelGrabber(
coloringBook,
fromx, fromy, width, height, imagePixels,
fromy * imageWidth + fromx, imageWidth);
// Ask the image grabber to go get the pixels
try {
grabber.grabPixels();
} catch (Exception e) {
// Ignore for now
continue;
}
// Make sure that the image copied correctly, although we don't
// do anything if it doesn't.
if ((grabber.status() & ImageObserver.ABORT) != 0)
{
// uh oh, it aborted
continue;
}
break;
}
}
// getPixel returns the pixel value for a particular x and y
private int getPixel(int x, int y)
{
return imagePixels[y * imageWidth + x];
}
// setPixel sets the pixel value for a particular x and y
private void setPixel(int x, int y, int color)
{
imagePixels[y*imageWidth + x] = color;
}
// floodFill starts at a particular x and y coordinate and fills it, and all
// the surrounding pixels with a color. The doesn't paint over black pixels,
// so they represent the borders of the fill.
// The easiest way to code a flood fill is by doing it recursively - you
// call flood fill on a pixel, color that pixel, then it calls flood fill
// on each surrounding pixel and so on. Unfortunately, that usually causes
// stack overflows since recursion is pretty expensive.
// This routine uses an alternate method. It makes a queue of pixels that
// it still has to fill. It takes a pixel off the head of the queue and
// colors the pixels around it, then adds those pixels to the queue. In other
// words, a pixel is really added to the queue after it has been colored.
// If a pixel has already been colored, it is not added, so eventually, it
// works the queue down until it is empty.
private void floodFill(int x, int y, int color)
{
// If the pixel we are starting with is already black, we won't paint
if (getPixel(x, y) == blackRGB)
{
return;
}
// Create the pixel queue. Assume the worst case where every pixel in the
// image may be in the queue.
int pixelQueue[] = new int[imageWidth * imageHeight];
int pixelQueueSize = 0;
// Add the start pixel to the queue (we created a single array of ints,
// even though we are enqueuing two numbers. We put the y value in the
// upper 16 bits of the integer, and the x in the lower 16. This gives
// a limit of 65536x65536 pixels, that should be enough.)
pixelQueue[0] = (y << 16) + x;
pixelQueueSize = 1;
// Color the start pixel
setPixel(x, y, color);
// Keep going while there are pixels in the queue
while (pixelQueueSize > 0)
{
// Get the x and y values of the next pixel in the queue
x = pixelQueue[0] & 0xffff;
y = (pixelQueue[0] >> 16) & 0xffff;
// Remove the first pixel from the queue. Rather than move all the
// pixels in the queue, which would take forever, just take the one
// off the end and move it to the beginning (order doesn't matter here).
pixelQueueSize--;
pixelQueue[0] = pixelQueue[pixelQueueSize];
// If we aren't on the left side of the image, see if the pixel to the
// left has been painted. If not, paint it and add it to the queue
if (x > 0) {
if ((getPixel(x-1, y) != blackRGB) &&
(getPixel(x-1, y) != color))
{
setPixel(x-1, y, color);
pixelQueue[pixelQueueSize] =
(y << 16) + x-1;
pixelQueueSize++;
}
}
// If we aren't on the top of the image, see if the pixel above
// this one has been painted. If not, paint it and add it to the queue
if (y > 0) {
if ((getPixel(x, y-1) != blackRGB) &&
(getPixel(x, y-1) != color))
{
setPixel(x, y-1, color);
pixelQueue[pixelQueueSize] =
((y-1) << 16) + x;
pixelQueueSize++;
}
}
// If we aren't on the right side of the image, see if the pixel to the
// right has been painted. If not, paint it and add it to the queue
if (x < imageWidth-1) {
if ((getPixel(x+1, y) != blackRGB) &&
(getPixel(x+1, y) != color))
{
setPixel(x+1, y, color);
pixelQueue[pixelQueueSize] =
(y << 16) + x+1;
pixelQueueSize++;
}
}
// If we aren't on the bottom of the image, see if the pixel below
// this one has been painted. If not, paint it and add it to the queue
if (y < imageHeight-1) {
if ((getPixel(x, y+1) != blackRGB) &&
(getPixel(x, y+1) != color))
{
setPixel(x, y+1, color);
pixelQueue[pixelQueueSize] =
((y+1) << 16) + x;
pixelQueueSize++;
}
}
}
}
// remakeDisplayImage takes the array of pixels and turns it into an
// image for us to display
private void remakeDisplayImage()
{
displayImage = createImage(new MemoryImageSource(
imageWidth, imageHeight, imagePixels, 0, imageWidth));
}
// The paint method is written with the assumption that the screen has
// not been cleared ahead of time, that way we can create an update
// method that doesn't clear the screen, but doesn't need an off-screen
// image.
public void paint(Graphics g)
{
int i;
// If we got the image successfully, draw it, otherwise, print a message
// saying we couldn't get it
if (imageValid)
{
g.drawImage(displayImage, 0, 0, this);
}
else
{
g.drawString("Unable to load coloring image.", 0, 50);
}
// Draw the crayons
for (i=0; i < crayons.length; i++)
{
// Draw each crayon in the color it represents
g.setColor(crayonColors[i]);
g.fillPolygon(crayons[i]);
// Get the box that would enclose the crayon
Rectangle box = crayons[i].getBoundingBox();
// If the crayon is the current one, draw a black box around it, if not,
// draw a box the color of the background around it (in case the current
// crayon has changed, we want to make sure the old box is erased).
if (crayonColors[i] == currentDrawingColor)
{
g.setColor(Color.black);
}
else
{
g.setColor(getBackground());
}
// Draw the box around the crayon
g.drawRect(box.x, box.y, box.width, box.height);
}
}
// Override the update method to call paint without clearing the screen
public void update(Graphics g)
{
paint(g);
}
public boolean mouseDown(Event event, int x, int y)
{
int i;
// Check each crayon to see of the mouse was clicked inside of it. If so,
// change the current color to that crayon's color. We use the "inside"
// method to see if the mouse x,y is within the crayon shape. Pretty handy!
for (i=0; i < crayons.length; i++)
{
if (crayons[i].inside(x, y))
{
currentDrawingColor = crayonColors[i];
repaint();
return true;
}
}
// If the mouse wasn't clicked on a crayon, see if it was clicked within
// the image. This assumes that the image starts at 0, 0.
if ((x < imageWidth) && (y < imageHeight))
{
// If the image was clicked, fill that section of the image with the
// current crayon color
floodFill(x, y, currentDrawingColor.getRGB());
// Now re-create the display image since we just changed the pixels
remakeDisplayImage();
repaint();
return true;
}
return true;
}
}
Please find the class files attached! :)\
Enjoy!
Any problems, PM me!