Day '1' plotting that pixel!
by
Ben Kenwright
We'll start simple, really simple! Code doesn't necessarily have to be
complex to create amazing effects - and even today, with P4's and super powerful
graphics cards, even the sloppiest and most inefficient code can run fast.
WHAT is important though, is that your code works and that it does what its
suppose to. As we can start of by creating simple but effective drawing
routines....then if we need to we can just rewrite those routines without
effecting our code :)
You may ask at this early stage, why where messing around with pixels, and
java 1.1 and not jumping in at the deep end with Java3D and the Java VM 1.4 or
later. Well by teaching you the basics of 3D...and I mean the underlying
basics...how to actually create 3D from nothing more than pixels and
maths...you'll be able to take those Java3D library's and do much more with
them, as you know what is really happening.
I also dislike visiting web pages, where it constantly asks you to add a new
plug-in or on some occasions just shows a grey box where the applet should be
:-/ Nearly all browsers support java 1.1, and even windows xp default is
with java 1.1 enabled. So you won't have to worry about people coming to
you and saying that your cool demo you created isn't working :)
By accessing the pixels directly we can do so much more:
- Create dynamic images and patterns on the fly instead of loading images
from file
- Dynamic images can contain a lot more details
- Create our own 3D render ware and not have to rely on other API's
So lets create a very simple applet:
import java.applet.*;
public class setpixels extends
Applet
{
}// End of our Applet |
And we compile it like this:
C:>javac -target 1.1 setpixels.java
Don't forget that we must name the file the same name as the entry
class....so for example if we'd called our applet "aba" we'd have to name our
file "aba.java". Else you'll get a compile error.
Now you compile this above...wooosh...it compiles no errors...nothing...but
it creates a "setpixels.class" file, which is what the browser uses.
There is two main ways to run the applet - the most common way is through
your browser alternatively you can use the java binary called 'appletviewer.exe'
which you call and pass the name of the name of the html file.
You need a html file to show off your applet, and this is all a html file has
to contain:
<html> <head>
<title>xbdev applet demo</title>
</head>
<body>
<applet code="setpixels.class"
width="320" height="320">
</applet>
</body>
</html> |
A warning to the new here - if you use your browser to view your applet
changes, you'll find that you have to close all your browser windows and I mean
all...and re-open the applet in the browser again. As your browser caches
the '.class' file. That's why I always find it better to test the applets
out in the 'appletviewer.exe' program...just call it like this at the command
prompt:
C:>appletviewer.exe setpixels.html
Of course you can name your html file anything you want! And make sure
your in the same directory as your .html and .class file.
*Drinks some coffee*...hehe...well when you start out in java, all this seems
pretty straight forwards...but don't worry...thats about it, we can start
getting down to some code now. You run the above applet and guess what
happens? You get a grey applet box in your browser about 320x320 in size
:)
import java.awt.*;
// We need this so we can use 'Graphics' class
import java.applet.*;
// So we can make an applet :)
public class setpixels extends
Applet
{
public void init(){}
// Called when the applet is about to start
public void start(){}
// When the applet starts or gains focus again
public void stop(){}
// When the applet window looses focus
public void destroy(){}
// Called when applet dies and is gone forever
public void update(){}
// When its time to repaint - if we don't override this
// this function it clears the screen for us
public void paint(Graphics g) {}
// The function that does the painting
}// End of our Applet |
Well what we have here, is what all applets have! I've put a small
description of what each one basically does....I usually find that you only use
init() and paint() on most occassions....but then you also find you need to do
an update() on as well or you get this flicker due to it always clearing your
screen.
Main ways to set a pixel are:
drawLine (x,y,x,y)
fillRect (x,y,1,1)
MemoryImageSource(..) which
is inherited from ImageProducer
Speed is the biggest factor here! Depending on how many pixels you want
t plot is one factor...as if your going to do a complete screen render of your
own pixels, it faster to have direct access to the image pixels through 'MemoryImageSource(..)'
but then to plot a few pixels on another image you might just use fillRect(..).
Method A - Plot Pixel
import java.awt.*;
import java.applet.*;
public class setpixels extends
Applet
{
int x=10, y=10;
public void paint(Graphics g)
{ g.setColor( Color.red );
g.fillRect( x, y, 1, 1 );
}
}// End of our Applet |
Method B - Plot Pixel
import java.awt.*;
import java.awt.image.*;
// Need for MemoryImageSource(..)
import java.applet.*;
public class setpixels extends
Applet
{
Image c;
int pixels[] =
new int[320 * 320];
public void init ()
{
int n = 0;
ImageProducer p;
for (int
i = 0; i < 320 ; i++)
// Clears the screen to green
for (
int j = 0; j < 320 ; j++)
pixels[n++]=0xff00ff00;
pixels[30 + 35*320] = 0xff0000ff;
// Set pixel at x=30, y=35 to blue
pixels[30 + 36*320] = 0xff0000ff;
// Set pixel at x=30, y=36 to blue
pixels[30 + 37*320] = 0xff0000ff;
// Set pixel at x=30, y=37 to blue
p = new
MemoryImageSource(320,320,pixels,0,320);
c = createImage(p);
}
public void paint(Graphics g)
{
g.drawImage(c,0,0,this);
}
}// End of our Applet |
Method C - Dynamic method B
import java.awt.*;
import java.awt.image.*;
// Need for MemoryImageSource(..)
import java.applet.*;
public class setpixels extends
Applet
{
Image c;
MemoryImageSource p;
int pixels[] =
new int[320 * 320];
public void init ()
{
int n = 0;
for (int
i = 0; i < 320 ; i++)
// Clears the screen to green
for ( int j = 0; j < 320 ;
j++)
pixels[n++]=0xff00ff00;
p = new
MemoryImageSource(320,320,pixels,0,320);
p.setAnimated(true);
p.setFullBufferUpdates(true);
c = createImage(p);
}
public void paint(Graphics g)
{
pixels[30 + 35*320] = 0xff0000ff;
// Set pixel at x=30, y=35 to blue
pixels[30 + 36*320] = 0xff0000ff;
// Set pixel at x=30, y=36 to blue
pixels[30 + 37*320] = 0xff0000ff;
// Set pixel at x=30, y=37 to blue
p.newPixels(0,0,/*width*/320,/*height*/320);
// Update the images pixels
g.drawImage(c,0,0,this);
}
public void update(Graphics g){}
// So it doesn't flicker white/green
}// End of our Applet |
Method C is possibly the most preferred way, but then again I've seen people
who write there own class inherited from 'ImageProducer' because the 'MemoryImageSource'
class is inherited from it...so there is nothing stopping us from inheriting and
doing our own.
Might want to look at Method C, and instead of calling p.newPixels(..) you
could use p.flush(). And then if you think further, possibly use 'ImageProducer'
instead of 'MemoryImageSource'...like this:
import java.awt.*;
import java.awt.image.*;
// Need for MemoryImageSource(..)
import java.applet.*;
public class setpixels extends
Applet
{
Image c;
int pixels[] =
new int[320 * 320];
public void init ()
{
int n = 0;
ImageProducer p;
for (int
i = 0; i < 320 ; i++)
// Clears the screen to green
for ( int
j = 0; j < 320 ; j++)
pixels[n++]=0xff00ff00;
p = new
MemoryImageSource(320,320,pixels,0,320);
c = createImage(p);
}
public void paint(Graphics g)
{
pixels[30 + 35*320] = 0xff0000ff;
// Set pixel at x=30, y=35 to blue
c.flush();
g.drawImage(c,0,0,this);
}
public void update(Graphics g){}
// So it doesn't flicker white/green
}// End of our Applet |
It looks hard! Yup, having to learn all those new API's...but the
beauty of them is that they've been around since the beginning of java and are
still around with java 1.4 which means we can create applets that will work even
on my best friend 'kl0wn' pentium-2 350 Mhz pc...which is running windows 98 and
java 1.1 :)
Lets add a small function to catch mouse input so we can in effect draw lots
of pixels on the screen
import java.awt.*;
import java.applet.*;
public class setpixels extends
Applet
{
Image c;
public void init ()
{
c = createImage(320,320);
}
public void paint(Graphics g)
{
g.drawImage(c,0,0,this);
}
public void update(Graphics g){
paint(g); }
// Is called when we call repaint()
public void setPixel(Image image,
int x, int
y, Color color )
{
Graphics g = c.getGraphics( );
g.setColor( color );
g.fillRect( x, y, 1, 1 );
g.dispose( );
}// End of setPixel(..)
/*********************************************************************************************/
/* */
/*
Capture mouse drags */
/*
Parameters: */
/*
evt is The event... */
/*
x is the x mouse position */
/*
y is the y mouse position */
/*
return whether or not we handled the event */
/*
*/
/*********************************************************************************************/
public boolean mouseMove(Event
evt, int x, int
y)
{
setPixel(c, x, y, Color.red );
repaint();
return true;
}// End of mouseDrag(..)
}// End of our Applet |
All we've done in the above applet, is take our 'fillRect' and create a
function that we can call to draw pixels :) Then I've tapped into the
applet mouseMove function to capture mouse events...and plot the pixels on the
screen. Simple but effective.
This is one of those cool applets that you put on your web page so you can
make pretty patterns...lol.... if you move the mouse really really slowly when
you run the code, you'll be able to make some notes :)
Well have the power of the PIXEL now! Today applet doodle
101...tomorrow...LINES...then onto 3D WORLDS :-D
|