Monday, November 19, 2012

Drawing a chessboard in JavaScript


Programming with ImageJ is really easy with the built-in macro language. However, for some more sophisticated scripts, it is - sometimes - interesting to access low-level functions only available in the ImageJ programming interface (I mean only available for Java programmers). For fast prototyping, a good alternative is the use of the JavaScript language.


1- Refresher of the 'chessboard' algorithm


Fig.1: Chessboard

The algorithm is based on the fact that when the sum of the X- and Y-coordinates of a cell is even, the drawing color is white otherwise black.

2- Implementation with squares

2-1- First try
Start with the Recorder (choose in the combo list, the 'JavaScript' mode) and create a 256x256 8-bit image with black background, then draw a square anywhere and fill it with white.
Click on the 'Create' button and a new window entitled 'Script.js' is created. Locate the following lines to start coding the script...

imp = IJ.createImage("chessboard", "8-bit Black", 256, 256, 1);
imp.setRoi(38, 18, 32, 32);

IJ.setForegroundColor(255, 255, 255);
IJ.run(imp, "Fill", "slice");


From our previous version of IJ Macro script [Link], complete your code by adding the loops and conditional statement. They follow the same syntax as in the IJ macro language. The only difference is the variable declaration that must be preceded by the keyword 'var'. There is not much more work to do to get the final script.

Here is the result ...

+++ IJ JavaScript Snippet: chess.js +++ +++ End of IJ JavaScript Snippet +++

Note: Don't forget the last line of code 'imp.show()' which allows the display of the created window. Indeed, in JavaScript, when a window is created, it is - by default - not visible.
2-2- Improving our script
If we look at the Application Programming Interface (API) of ImageJ located here [Link] and focus on ImagePlus and ImageProcessor classes (left panel).
There are plenty of utility methods for drawing, filling areas, setting color(s),etc.

In ImageProcessor class, there is a method fill(Roi roi)  filling an area delimited by a rectangle selection (ROI means 'Region Of Interest' aka the yellow rectangular selection) as shown below.


fill

public void fill(Roi roi)
Fills the ROI with the current fill/draw value.
See Also:
setColor(Color), setValue(double), fill(Roi)


Moreover, as mentioned in the fill(...) method above in the 'See Also' section, setting the gray level can be done with the setValue(double) method.

Thus, drawing a white square can be done in three steps:
(i) Sets the color value with setValue(...) method
(ii) Create a square ROI 
(iii) Draw with the fill() function

The drawing code becomes ...

    var new_roi = new Roi(x*scale,y*scale,cellsize,cellsize);
    imp.getProcessor().fill(new_roi );

 or in one single line...

imp.getProcessor().fill(new Roi(x*scale,y*scale,cellsize,cellsize) );

3- Implementation with a 8x8 image

In this implementation, we start with a 8x8 image, set the pixel values to white and then scale this image to 256x256.
The recorder displays the following command using the plugin Size... (available in Image > Adjust > Size...)

IJ.run(imp, "Size...", "width=256 height=256 interpolation=None");

However, by exploring ImageJ API, we can find out something similar ...

var resized_ip = ip.resize(256);
imp.setProcessor(resized_ip);

Thus, the code is now...

+++ IJ JavaScript Snippet: chess88.js +++ +++ End of IJ JavaScript Snippet +++



Hope that helps.

No comments:

Post a Comment