Discussion:
How to .setPixel(int,int) ?
Wayne M Barnes
2004-12-27 18:41:14 UTC
Permalink
Dear ImageJ,

I am writing a plugin to search all around an image, and I need
to be able to mark where I have been, already, one pixel at a time.
( I only want to sprinkle a few pixels, without disturbing the whole
picture too much.)

So far, I have been doing a slow, kludgy method summarizable as:

IJ.setForegroundColor(1, 255, 3);
img2.setRoi(x, y, 1, 1);
IJ.run("Fill", "slice");

I spend a lot of time watching "Fill: ... " with no picture
update until the program really comes to a long pause, after
which my pixels finally show up.

What I really need is a fast-acting method such as:

int [] colors = new int[4];

IJ.setForegroundColor(1, 255, 3);

img2.setPixel(x,y);
// or
img2.setPixel(x,y,colors);

But I don't see any .setPixel option. (Basically I want the opposite
of ImagePlus.getPixel(int,int). I have seen something like
putPixel, but I can't figure out how to use it, and it seems
to be only black & white, anyway.

Can someone tell me where and if my imagined method might be? Or
suggest some other way to change a single pixel to a specified RGB color?
I started with the plugin Cell_counter, and I want to change the
pixels on img2.

Thank you,
--
Wayne M Barnes
***@etaq.com fax: (314) 754-9556
Duane and Julie
2004-12-27 19:19:41 UTC
Permalink
Wayne,

I don't know the 'right' way to do this, but I just get the pixels as an array using getPixels() and process them from there. When I'm all done, I use setPixels() to put them back.

It seems to be the fastest way to modify an image.

duane
Post by Wayne M Barnes
Dear ImageJ,
I am writing a plugin to search all around an image, and I need
to be able to mark where I have been, already, one pixel at a time.
( I only want to sprinkle a few pixels, without disturbing the whole
picture too much.)
IJ.setForegroundColor(1, 255, 3);
img2.setRoi(x, y, 1, 1);
IJ.run("Fill", "slice");
I spend a lot of time watching "Fill: ... " with no picture
update until the program really comes to a long pause, after
which my pixels finally show up.
int [] colors = new int[4];
IJ.setForegroundColor(1, 255, 3);
img2.setPixel(x,y);
// or
img2.setPixel(x,y,colors);
But I don't see any .setPixel option. (Basically I want the opposite
of ImagePlus.getPixel(int,int). I have seen something like
putPixel, but I can't figure out how to use it, and it seems
to be only black & white, anyway.
Can someone tell me where and if my imagined method might be? Or
suggest some other way to change a single pixel to a specified RGB color?
I started with the plugin Cell_counter, and I want to change the
pixels on img2.
Thank you,
--
Wayne M Barnes
Wayne M Barnes
2004-12-28 03:25:42 UTC
Permalink
Dear Duane,

Your suggestion sounds good in English. I am only learning to use Java;
Can you please show me some code that will work in a plugin?

Here is my guess, but I know it's not right, yet:

ImagePlus img2;
ColorProcessor image2;
int[] arrayOfPixels = new int [3000200];
arrayOfPixels = image2.getPixels();

arrayOfPixels[1223] = 0; // Did I just create a white pixel?

// This doesn't look very close. How to I refer to my img2 ?
// How do I put the modified array back to img2 ?


Can you maybe send me some code that works?

Thank you,

- Wayne Barnes
Post by Duane and Julie
Wayne,
I don't know the 'right' way to do this, but I just get the pixels as an array using getPixels() and process
them from there. When I'm all done, I use setPixels() to put them back.
Post by Duane and Julie
It seems to be the fastest way to modify an image.
duane
Post by Wayne M Barnes
Dear ImageJ,
I am writing a plugin to search all around an image, and I need
to be able to mark where I have been, already, one pixel at a time.
( I only want to sprinkle a few pixels, without disturbing the whole
picture too much.)
IJ.setForegroundColor(1, 255, 3);
img2.setRoi(x, y, 1, 1);
IJ.run("Fill", "slice");
I spend a lot of time watching "Fill: ... " with no picture
update until the program really comes to a long pause, after
which my pixels finally show up.
int [] colors = new int[4];
IJ.setForegroundColor(1, 255, 3);
img2.setPixel(x,y);
// or
img2.setPixel(x,y,colors);
But I don't see any .setPixel option. (Basically I want the opposite
of ImagePlus.getPixel(int,int). I have seen something like
putPixel, but I can't figure out how to use it, and it seems
to be only black & white, anyway.
Can someone tell me where and if my imagined method might be? Or
suggest some other way to change a single pixel to a specified RGB color?
I started with the plugin Cell_counter, and I want to change the
pixels on img2.
Thank you,
--
Wayne M Barnes
--
Wayne M Barnes
***@etaq.com fax: (314) 754-9556
Duane and Julie
2004-12-28 16:06:19 UTC
Permalink
Wayne,

Of course. I would have given you Java the first time, but I was away from the programming environment at the time. :-)

--------------------------------

import ij.*;
import ij.io.*;
import ij.process.*;

public class Process {

public static void main(String[] args) {

String imageName = "";

// get input image
if (args.length != 0) {
imageName = args[0];
}
else {
OpenDialog od = new OpenDialog("Select an image", "");
if (od.getFileName().length() != 0) {
imageName = od.getDirectory() + od.getFileName();
}
else {
System.err.println("no image selected");
return;
}
}

// open image
ImagePlus imp = new ImagePlus(imageName);
ImageProcessor ip = imp.getProcessor();

// create a float processor
FloatProcessor nip = (FloatProcessor) ip.convertToFloat();

// create a Process
Process process = new Process();

// do the process
FloatProcessor oip = process.doProcess(nip);

// new ImagePlus for display
ImagePlus omp = new ImagePlus("Processed", oip);

// display images
imp.show();
omp.show();

}

public FloatProcessor doProcess(FloatProcessor ip) {

// get info and pixels
int cols = ip.getWidth();
int rows = ip.getHeight();
float[] in = (float[]) ip.getPixels();

// create output image
FloatProcessor out_ip = new FloatProcessor(cols, rows);
float[] out = (float[]) out_ip.getPixels();

// for each pixel in image
float pixel;
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
pixel = in[x + y * cols];

// do something
if (pixel > 128) {
pixel = 255;
}
else {
pixel = 0;
}

// put result in output
out[x + y * cols] = pixel;

}
}

return out_ip;

}

}

--------------------------------

Since you are new to Java, the above code runs and actually does something. It no doubt doesn't do what you want, but it is a complete standalone program that uses ImageJ. Note that there should be a little more error checking.

If you wanted a plugin for ImageJ, you will need to create a run method.

I hope this helps,

duane
Post by Wayne M Barnes
Dear Duane,
Your suggestion sounds good in English. I am only learning to use Java;
Can you please show me some code that will work in a plugin?
ImagePlus img2;
ColorProcessor image2;
int[] arrayOfPixels = new int [3000200];
arrayOfPixels = image2.getPixels();
arrayOfPixels[1223] = 0; // Did I just create a white pixel?
// This doesn't look very close. How to I refer to my img2 ?
// How do I put the modified array back to img2 ?
Can you maybe send me some code that works?
Thank you,
- Wayne Barnes
Post by Duane and Julie
Wayne,
I don't know the 'right' way to do this, but I just get the pixels as an array using getPixels() and process
them from there. When I'm all done, I use setPixels() to put them back.
Post by Duane and Julie
It seems to be the fastest way to modify an image.
duane
Post by Wayne M Barnes
Dear ImageJ,
I am writing a plugin to search all around an image, and I need
to be able to mark where I have been, already, one pixel at a time.
( I only want to sprinkle a few pixels, without disturbing the whole
picture too much.)
IJ.setForegroundColor(1, 255, 3);
img2.setRoi(x, y, 1, 1);
IJ.run("Fill", "slice");
I spend a lot of time watching "Fill: ... " with no picture
update until the program really comes to a long pause, after
which my pixels finally show up.
int [] colors = new int[4];
IJ.setForegroundColor(1, 255, 3);
img2.setPixel(x,y);
// or
img2.setPixel(x,y,colors);
But I don't see any .setPixel option. (Basically I want the opposite
of ImagePlus.getPixel(int,int). I have seen something like
putPixel, but I can't figure out how to use it, and it seems
to be only black & white, anyway.
Can someone tell me where and if my imagined method might be? Or
suggest some other way to change a single pixel to a specified RGB color?
I started with the plugin Cell_counter, and I want to change the
pixels on img2.
Thank you,
--
Wayne M Barnes
--
Wayne M Barnes
Duane and Julie
2004-12-28 17:40:14 UTC
Permalink
Wayne,

I just noticed that you specifically asked about a plugin. Sorry about that. I've included a run method that should work, but it's untested.

--------------------------------

/**
* @see ij.plugin.PlugIn#run(java.lang.String)
*/
public void run(String arg) {

// check for an open image or stack
if (IJ.getImage() == null) {
IJ.noImage();
IJ.showStatus("Process: no image open");
return;
}

// show text in status bar
IJ.showStatus("Process started");

// create a Process
Process process = new Process();

// get input
ImagePlus imp = IJ.getImage();

// get processor
ImageProcessor ip = imp.getProcessor();

// process the image
FloatProcessor oip = process.doProcess((FloatProcessor) in_ip.convertToFloat());

// put results back
imp.setProcessor(imp.getShortTitle() + " (Processed)", oip);

}

--------------------------------

duane
Post by Duane and Julie
Wayne,
Of course. I would have given you Java the first time, but I was away from the programming environment at the time. :-)
--------------------------------
import ij.*;
import ij.io.*;
import ij.process.*;
public class Process {
public static void main(String[] args) {
String imageName = "";
// get input image
if (args.length != 0) {
imageName = args[0];
}
else {
OpenDialog od = new OpenDialog("Select an image", "");
if (od.getFileName().length() != 0) {
imageName = od.getDirectory() + od.getFileName();
}
else {
System.err.println("no image selected");
return;
}
}
// open image
ImagePlus imp = new ImagePlus(imageName);
ImageProcessor ip = imp.getProcessor();
// create a float processor
FloatProcessor nip = (FloatProcessor) ip.convertToFloat();
// create a Process
Process process = new Process();
// do the process
FloatProcessor oip = process.doProcess(nip);
// new ImagePlus for display
ImagePlus omp = new ImagePlus("Processed", oip);
// display images
imp.show();
omp.show();
}
public FloatProcessor doProcess(FloatProcessor ip) {
// get info and pixels
int cols = ip.getWidth();
int rows = ip.getHeight();
float[] in = (float[]) ip.getPixels();
// create output image
FloatProcessor out_ip = new FloatProcessor(cols, rows);
float[] out = (float[]) out_ip.getPixels();
// for each pixel in image
float pixel;
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
pixel = in[x + y * cols];
// do something
if (pixel > 128) {
pixel = 255;
}
else {
pixel = 0;
}
// put result in output
out[x + y * cols] = pixel;
}
}
return out_ip;
}
}
--------------------------------
Since you are new to Java, the above code runs and actually does something. It no doubt doesn't do what you want, but it is a complete standalone program that uses ImageJ. Note that there should be a little more error checking.
If you wanted a plugin for ImageJ, you will need to create a run method.
I hope this helps,
duane
Post by Wayne M Barnes
Dear Duane,
Your suggestion sounds good in English. I am only learning to use Java;
Can you please show me some code that will work in a plugin?
ImagePlus img2;
ColorProcessor image2;
int[] arrayOfPixels = new int [3000200];
arrayOfPixels = image2.getPixels();
arrayOfPixels[1223] = 0; // Did I just create a white pixel?
// This doesn't look very close. How to I refer to my img2 ?
// How do I put the modified array back to img2 ?
Can you maybe send me some code that works?
Thank you,
- Wayne Barnes
Post by Duane and Julie
Wayne,
I don't know the 'right' way to do this, but I just get the pixels as an array using getPixels() and process
them from there. When I'm all done, I use setPixels() to put them back.
Post by Duane and Julie
It seems to be the fastest way to modify an image.
duane
Post by Wayne M Barnes
Dear ImageJ,
I am writing a plugin to search all around an image, and I need
to be able to mark where I have been, already, one pixel at a time.
( I only want to sprinkle a few pixels, without disturbing the whole
picture too much.)
IJ.setForegroundColor(1, 255, 3);
img2.setRoi(x, y, 1, 1);
IJ.run("Fill", "slice");
I spend a lot of time watching "Fill: ... " with no picture
update until the program really comes to a long pause, after
which my pixels finally show up.
int [] colors = new int[4];
IJ.setForegroundColor(1, 255, 3);
img2.setPixel(x,y);
// or
img2.setPixel(x,y,colors);
But I don't see any .setPixel option. (Basically I want the opposite
of ImagePlus.getPixel(int,int). I have seen something like
putPixel, but I can't figure out how to use it, and it seems
to be only black & white, anyway.
Can someone tell me where and if my imagined method might be? Or
suggest some other way to change a single pixel to a specified RGB color?
I started with the plugin Cell_counter, and I want to change the
pixels on img2.
Thank you,
--
Wayne M Barnes
--
Wayne M Barnes
Wayne M Barnes
2005-01-01 20:22:19 UTC
Permalink
Dear Duane,

I changed your "standalone" code to have Duane and duane instead of Process and
process. (Just trying to reduce my confusion a little.)

It compiles and produces Duane.class.

But when I try to run it with
java -cp ij.jar Duane

I get only the error:

Exception in thread "main" java.lang.NoClassDefFoundError: Duane

So how am I supposed to run this?

In case you can see a typo, I reposted it at

http://etaq.com/wayne/duane/

Thank you,
--
Wayne M Barnes
***@etaq.com fax: (314) 754-9556
Wayne M Barnes
2005-01-02 23:21:39 UTC
Permalink
Dear Duane, Wayne R., Mike and Jason,

I got it. Here is the answer to my problem, how
to make Cell_counter.java work faster than "Fill" "Slice".
It uses some respelled and relocated advice frome Wayne R.

1. Put the line
ImageProcessor ip;
// at the beginning of the plugin, before
//any methods (like right after "ImagePlus img2;", to make it global.

2. In the 'run' section, remove "ImageProcessor" from the line
ImageProcessor ip = imp1.getProcessor;
// so 'ip' is the global one.

3. To put a pixel during some method, use a line like:
ip.putPixel(ix,iy,red<<16 | green <<8 | blue);
// This works very fast, even in a loop that does 10,000 pixels.

4. To see the new pixel(s)
img2.updateAndDraw();

I'll submit the complete faster version soon.

- Wayne M. Barnes
At "the beginning of the plugin" I already have a line in my 'run'
ImageProcessor ip = imp1.getProcessor();
Down in a method in my code, my IDE won't allow me to use
ip.putPixel(bx,by,1<<16 | 255<<8 | 3);
// The 'ip' remains red = 'Cannot resolve symbol ip'.
The ip variable must be defined in the method it is used in or it must
be an instance variable.
I have not touched the 'run' part of the plugin Cell_counter which I
started with. I reproduce it below. How would you modify this? Where
exactly should I put your suggested ImageProcessor declaration? Do I
really need it?
You need an ImageProcessor (ip) object to process an image. The run()
method is passed an ImageProcessor for the current image. You can pass
this ImageProcessor to the method that does the processing.
After I solve the above problems, shouldn't your last suggested
line be
ip2.updateAndDraw();
instead of
imp2.updateAndDraw(); // ?
updateAndDraw() is a method of the ImagePlus class so you need to call
it using an ImagePlus object such as imp2. You might want to spend some
time with the ImageJ API at
"http://rsb.info.nih.gov/ij/developer/api/index.html" to get some idea
which methods belong to the ImagePlus class and which belong to the
ImageProcessor class.

-wayne

--
Wayne M Barnes
***@etaq.com fax: (314) 754-9556

Wayne Rasband
2004-12-29 14:49:14 UTC
Permalink
Post by Wayne M Barnes
I am writing a plugin to search all around an image, and
I need to be able to mark where I have been, already, one
pixel at a time. ( I only want to sprinkle a few pixels, without
disturbing the whole picture too much.)
IJ.setForegroundColor(1, 255, 3);
img2.setRoi(x, y, 1, 1);
IJ.run("Fill", "slice");
Change this to:

ip2.putPixel(x, y, red<<16 | green<<8 | blue);

and the code should run at least 1000 times faster.

At the beginning of the plugin, add

ImageProcessor ip2 = imp.getProcessor();

to get an ImageProcessor and, at the end, add

imp2.updateAndDraw()

to update the display.

-wayne
Loading...