paint program

C

C Williams

Hi,

I am quite new to Java and thought that making a simple painting program
would be a good way to get familiar with how to deal with its graphical
features. I'm using Swing and can see how to draw solid rectangles,
circles, lines, etc. But what I would like to do is implement an
airbrush, which I would like to work as fast as possible. Basically, I
would like to work with pixels directly: take all of the ones within a
radius of a mouse click, blend them with a mask the represents the
brush, and then update just those pixels back on the canvas.

I'm not sure what sort of component I can draw upon that lets me just
loop through its pixels. I've done something fairly similar to this a
few years ago (in C++), so I am okay with the concept but just
struggling with the implementation in Java.

Any help you have would be most appreciated!

Thanks,

-Casey
 
P

Paul Lutus

C said:
Hi,

I am quite new to Java and thought that making a simple painting program
would be a good way to get familiar with how to deal with its graphical
features. I'm using Swing and can see how to draw solid rectangles,
circles, lines, etc. But what I would like to do is implement an
airbrush, which I would like to work as fast as possible. Basically, I
would like to work with pixels directly: take all of the ones within a
radius of a mouse click, blend them with a mask the represents the
brush, and then update just those pixels back on the canvas.

I'm not sure what sort of component I can draw upon that lets me just
loop through its pixels.

For this purpose, you cannot use a preexisting component, you need to so
some programming.

One approach would be to create a short-period repeating timer that, when it
timed out, would find the current mouse cursor position, discover whether
the mouse button was down, then if these conditions were true, would:

1. Generate a set of signed random numbers to represent Cartesian
coordinates in x and y.

2. Mathematically process the random numbers so they lie in a circle, rather
than the square that would naturally be true.

3. Draw points on the drawing surface at the position of the random x,y
coordinates offset by the mouse position.

The reason for the timer is that, if you hold the mouse over a specific
location on the drawing surface, you would want the number of painted dots
to increase over time, just as would be true if you held a spray can over a
spot on a wall in the real world.
 
C

C Williams

Paul said:
C Williams wrote:




For this purpose, you cannot use a preexisting component, you need to so
some programming.

One approach would be to create a short-period repeating timer that, when it
timed out, would find the current mouse cursor position, discover whether
the mouse button was down, then if these conditions were true, would:

1. Generate a set of signed random numbers to represent Cartesian
coordinates in x and y.

2. Mathematically process the random numbers so they lie in a circle, rather
than the square that would naturally be true.

3. Draw points on the drawing surface at the position of the random x,y
coordinates offset by the mouse position.

The reason for the timer is that, if you hold the mouse over a specific
location on the drawing surface, you would want the number of painted dots
to increase over time, just as would be true if you held a spray can over a
spot on a wall in the real world.

Thanks, Paul. Yes, I was planning to incorporate a timer to model an
actual spray can. I guess my question is, what is the best way to go
about actually manipulating a java application's display on a
pixel-by-pixel basis? i.e. how do i do this in *java*?

Specifically, how can I get the information for each pixel in a given
region, come up with a new calculation for each pixel in that region,
and then update it to my new calculation?

Thanks for anyone who can help!
 
J

John Davison

C said:
Hi,

I am quite new to Java and thought that making a simple painting program
would be a good way to get familiar with how to deal with its graphical
features. I'm using Swing and can see how to draw solid rectangles,
circles, lines, etc. But what I would like to do is implement an
airbrush, which I would like to work as fast as possible. Basically, I
would like to work with pixels directly: take all of the ones within a
radius of a mouse click, blend them with a mask the represents the
brush, and then update just those pixels back on the canvas.

I'm not sure what sort of component I can draw upon that lets me just
loop through its pixels. I've done something fairly similar to this a
few years ago (in C++), so I am okay with the concept but just
struggling with the implementation in Java.

Any help you have would be most appreciated!

Thanks,

-Casey

My guess is that you'll have to use an image.

I'm guessing that Java probably doesn't keep track of the color of each
pixel of each component. It probably just says "draw whatever" and then
the underlying OS takes care of the pixels. (Someone correct me if I am
wrong here.)

But you *can* draw to an image, then draw the image onto a component.

To access the pixels of an image, you have to go through a Raster, which
"encapsulates a DataBuffer that stores the sample values and a
SampleModel that describes how to locate a given sample value in a
DataBuffer."

Check out java.awt.image.Raster and the getPixel() functions.

Hope that helps.

- john
 
P

Paul Lutus

John Davison wrote:

/ ...
I'm guessing that Java probably doesn't keep track of the color of each
pixel of each component. It probably just says "draw whatever" and then
the underlying OS takes care of the pixels. (Someone correct me if I am
wrong here.)

You're wrong here.
But you *can* draw to an image, then draw the image onto a component.

And you can "draw" directly onto a component, using that component's paint()
method. This is the most efficient way to address the original problem.
 
S

Skip

I am quite new to Java and thought that making a simple painting program
would be a good way to get familiar with how to deal with its graphical
features. I'm using Swing and can see how to draw solid rectangles,
circles, lines, etc. But what I would like to do is implement an
airbrush, which I would like to work as fast as possible. Basically, I
would like to work with pixels directly: take all of the ones within a
radius of a mouse click, blend them with a mask the represents the
brush, and then update just those pixels back on the canvas.

Take a look at:
java.awt.image.MemoryImageSource

use setAnimated(true) to make it dynamic.
it's all you ever wanted ;-)
 
C

C Williams

Alex said:
It's not efficient at all - as the user builds up pixels with their
paintbrush, would you redraw every pixel at each paint?
Much more efficient/easier to draw to a buffer, then draw the buffer (or
part thereof) to the screen when needed.
Swing *does* have double buffering built in, but it is per-paint time
and not a persistent image, which is what the OP needs from the sound of
it.

Also, it's a good idea to override paintComponent rather than paint -
paint calls paintComponent amongst other things (like paintChildren and
paintBorders).

alex

Thank you all for your input--I shall look into what you have said when
I next get a chance to work on it (I can't now as I am at work!).

I DO need to know the current state because i want my brush to have more
capability than just "add paint." For instance, I might want to blend
colors or blur or change to greyscale, etc. Though, as some have
pointed out, it's probably best to store this information in a buffer
and write to the screen as necessary.

Thanks, and please continue to give advice!
 
A

Aaron J Gage

C Williams said:
Hi, Basically, I
would like to work with pixels directly: take all of the ones within a
radius of a mouse click, blend them with a mask the represents the
brush, and then update just those pixels back on the canvas.

I'm not sure what sort of component I can draw upon that lets me just
loop through its pixels. I've done something fairly similar to this a
few years ago (in C++), so I am okay with the concept but just
struggling with the implementation in Java.

You could create your own Component (subclass) and keep track of the pixels
yourself (maybe using a 2D array of Color objects?). Java has no method in
the Graphics class or subclasses such as setPixel(x, y, col) but you get the
same effect with drawLine(x, y, x, y, col),
and of course you can getPixel(x, y) by indexing into your array!


maybe something like:

public class PaintComponent extends JComponent {

private int W = 200, H = 200;
Color pixels[][]; // = new Color[W][H];

public PaintComponent() {
super();
addMouseListener( new MouseHandler() );
}

public void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D)g;

for (int x = 0; x < W ; ++x)
for (int y = 0 ; y < H ; ++y)
g.drawLine(x, y, x, y, pixels[x][y]);

// and whatever else (border etc)
}

class MouseHandler extends MouseAdapter() {
//override the handler methods you need
}
}

This code isn;t complete, but gives you an idea of what I mean.
You could even implement get/setPixel in this class.

You can use the repaint() and repaint(x, y, w, h) to invoke a repaint of
your component internally. The 2nd clips the region to redraw. You can (and
should) get this in the paintComponent method by calling:
g.getClipBounds() // I think, without checking the API.
should return Rectangle
end only repaint that portion of the component.

Hope this helps you.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top