Efficient way to set every other row/column to 0?

Hi everyone,

I’m looking for an efficient (quick…) way to set the pixel values of every second row and column to 0 in a 32bit image (size up to 4k x 4k).
I’m using Jython, and the best way I found to date was the math macro with a formula like this: v=v*((x+1)%2)*((y+1)%2)

Any ideas?

Hi @Flobert, welcome to the forum!

If you value speed above all else, for per-pixel operations, the consensus recommendation is to code in Java rather than Jython. See:

Best regards and good luck,
John

2 Likes

The Nashorn JavaScript engine, included with Java 8, is good at per-pixel operations, almost as fast as Java. It generates Java byte code, which is then JIT-compiled. The following code runs 10 times faster than Process>Math>Macro. The Help>Examples>JavaScrip>Plasma Cloud script, available in the latest ImageJ daily build, is an impressive example of the speed of JavaScript. On a fast computer, it generates a 1000x700 plasma cloud frame in 16 ms.

``````  w = h = 4096;
var img = IJ.createImage("Untitled", "32-bit ramp", w, h, 1);
var ip = img.getProcessor();
var t0 = System.currentTimeMillis();
for (var y=0; y<h; y+=2)
for (var x=0; x<w; x+=2)
ip.setf(x, y, 0);
IJ.log((System.currentTimeMillis()-t0)+" ms");
img.show();``````
3 Likes

Hi,
thanks for your suggestions! The js approach doesn’t give me any speedup on my machine, unfortunately.
I’d like to try the java one, but that will require a bit of research on my part^^

I did some test yesterday and found that I can do the operation quite fast by generating a 4k, 8 bit image template of 1’s and 0’s, which takes a few seconds, but needs to run only once, and multiplying that with any image that needs to be processed (which only takes an instant).
The question is, can I replicate that behavior in my program in a way that it doesn’t end up as a series of weird hacks and work-arounds, held together by duct tape and voodoo?

Have a great day,
Florian

PS: A little background might be helpful. I wrote a bit of jython code for a Gaussian / Laplace Pyramid decomposition and synthesis, and one of the operations I need to do is to double the image size by interleaving rows an columns of zeros. For that, I used Image>Scale without interpolation and set all the odd rows and columns to 0.

What version of Java are you using? The JavaScript code I posted should run in less than a second if you are using Java 8. Java 6 is about eight times slower.

Thanks for the hint. Apparently, my Fiji install is running on the bundled Java 6 (64 bit). I’ll try to get an admin to install java 8…

Here is an updated version of my JavaScript example that is about four times faster, making it 40 times faster than using Process>Math>Macro. I had forgotten that the Nashorn JavaScript optimizer works best on code that is in a function.

``````  w = h = 4096;
img = IJ.createImage("Untitled", "32-bit ramp", w, h, 1);
ip = img.getProcessor();
t0 = System.currentTimeMillis();
process(ip, w, h);
img.setTitle((System.currentTimeMillis()-t0)+" ms");
img.show();

function process(ip, w, h) {
for (var y=0; y<h; y+=2)
for (var x=0; x<w; x+=2)
ip.setf(x, y, 0);
}``````
1 Like

Hi Wayne,

I’ve tested the script in Java 8 and it works much faster. I had to modify the function a bit to do exactly what I need, and now the processing time is consistently below 300 ms. Perfect!

Now I just need an easy way to use in my jython project (rewriting would be a pain, I guess…), but I’ll manage somehow.

Thanks a lot!

Final script:

``````importClass(Packages.ij.IJ);
importPackage(java.lang)

img = IJ.createImage("Untitled", "32-bit ramp", w, h, 1);
ip = img.getProcessor();
t0 = System.currentTimeMillis();
decimate(ip, w, h);
img.setTitle((System.currentTimeMillis()-t0)+" ms - DEC");
img.show();

function decimate(ip,w,h) {
for (var y=0; y<h; y+=1)
if (y%2==0)
for (var x=1; x<w; x+=2)
ip.setf(x, y, 0);
else
for (var x=0; x<w; x+=1)
ip.setf(x, y, 0);
}``````