[JAVA] Plugin development with ImageJ

Talk about wanting to make a plugin with convenient and convenient ImageJ

There are too few Japanese documents, so the story doesn't go on. This is a record of a battle (with English literature) called a personal memo.

What is ImageJ?

It may be unnecessary explanation for those who look for such an article,

Open source and public domain image processing software Highly extensible with plugins and macros From the Wiki

So it's a waste not to use macros and plugins! That said, in order to master these, it is necessary to understand Imagej's developer information as well as programming knowledge.

For macros, if you google "Imagej macro function" etc., you can get the explanation of the original function and how to write If and For in Japanese, so if you have some programming knowledge and English knowledge (or Google Translate and Guts), you can manage it. Naruto (* ´ω ` *)

The problem is the plugin. I hope that the development of Japanese literature will progress, but since there are (small) and few (small) articles, this article aims to be a pioneer of Web information providers. (Although I say that there are already Japanese documents ... here ... ~~ In other words, it can no longer be a pioneer. ~~)

Well, with the expectation that there may be demand if there is little, this article is also a memorandum, deciphering the outline of the plug-in from the English document "Writing ImageJ Plugins–A Tutorial", and the important part (as much as possible) ) In addition to making it easy to understand

・ Hello Work pop-up ・ Creating an image with gradation ・ Black-and-white inversion of open 8-bit image ・ Divide RGB images into 3 colors, R, G, and B ・ Place two buttons and associate them with the message box.

I aim to create something like that. English references Writing ImageJ Plugins–A Tutorial Honke In Japanese Java # 1 for creating ImageJ Plugin Creating an ImageJ Plugin: Introduction

By the way, I'm a person in the C ++ and VB fields, and I'm not familiar with Java, so I'm sorry if I make a mistake ... I'm forced to write Java! ~~

0th step of development

Knowledge you need to know when developing plugins with Imagej.

Image type

type Definition Description
8bit grayscale 0 ( =ImagePlus.GRAY8) White~gray~Black image. Express each pixel in bytes
8bit color Look-up table(LUT)Expression using. Pixel value(0~255)An image of up to 256 colors is expressed based on the information on how many colors each corresponds to.
16bit grayscale 1 ( =ImagePlus.GRAY16) One pixel value is 0~It becomes 65535. A ridiculous image in which the amount of information in each pixel is 256 times that of an 8-bit image. Each pixel is represented by short.
RGB color 3 ( =ImagePlus.COLOR_RGB)※ ImagePlus.An image that expresses the three colors of red, green, and blue in 8 bits each. This is probably the image you see on the net. Each pixel is represented by an int
32bit grayscale 2 ( =ImagePlus.GRAY32) A super image with 32 bits allocated to one pixel. For example, 0 for each pixel~1.Can be 0(That is, a real number).. Each pixel is represented by a float.

First step of development

Select "Plugins"-> "New"-> "Plugin 〇〇" to display the plugin editor. It seems that you need to save it to execute it, so let's save it according to the dialog. It seems that an underscore is required in the file name, so save it like File_name. In the explanation, it was OK just to save it in the Plugin folder under the folder of Imagej itself, but since it was not displayed in Imagej, create a folder called MyPlugins in "ImageJ \ plugins " and My_Plugin there I saved it as.

Troubleshooting at this point

I can't find the compiler.jar → I solved it by installing the JDK and updating to the latest version of Imagej. ~~ I don't know which one worked. .. .. ~~

template

About templates created by "Plugins"-> "New"-> "Plugin 〇〇"

For busy people

PlugIn Those that do not necessarily require image input. For example, if you want to write the processing of the analysis result, it will be here. PlugInFilter Requests for image input. It may or may not be executed depending on the type of image. e.g. Input other than 16-bit images is not allowed, RGB images are absolutely useless, etc.

PluginFrame It seems to use this when you want to create a new window

PlugIn By standard

python


public void run(String arg)

The method is prepared. When I tried

PlugIn


import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;
import ij.plugin.frame.*;

public class My_Plugin implements PlugIn {

	public void run(String arg) {
		ImagePlus imp = IJ.getImage();
		IJ.run(imp, "Invert", "");
		IJ.wait(1000);
		IJ.run(imp, "Invert", "");
	}

}

The template was written. This means flipping the displayed image in black and white, waiting for 1 second, and then flipping it in black and white again (that is, restoring it). PlugInFilter This is

python


public int setup(String arg, ImagePlus imp)
public void run(ImageProcessor ip)

Is in the template.

PluginFrame


import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

public class Filter_Plugin implements PlugInFilter {
	ImagePlus imp;

	public int setup(String arg, ImagePlus imp) {
		this.imp = imp;
		return DOES_ALL;
	}

	public void run(ImageProcessor ip) {
		ip.invert();
	}
}

Setup is called when the plugin is instantiated (perhaps ready?). So, at that time, two arguments are passed. The arg of setup is the same as the arg of run of PlugIn, the imp of setup is handled by Imagej, and the currently active image is passed. The return value is a flag. It seems that you can set a flag for what type of image you can handle.

flag effect
DOES_ALL Accept any image
DOES_RGB Accept RGB images
DOES_16 Accept 16-bit grayscale images
DOES_32 Accepts 32-bit floating point grayscale images
DOES_8C Accept 8-bit color images
DOES_8G Accept 8-bit grayscale images

bonus

flag effect
DOES_STACKS Accept the stack
DONE Do not run run
NO_CHANGES Do not rewrite pixel data
NO_IMAGE_REQUIRED Does not require images
NO_UNDO Does not support "redo"
ROI_REQUIRED Need ROI
SUPPORTS_MASKING Plugin filters always work on the bounding rectangle of theROI. If this flag is set and there is a non-rectangular ROI, ImageJ will restore the pixelsthat are inside the bounding rectangle but outside the ROI

I'm not sure. ..

The Run method receives ʻImageProcessor and does the actual processing. For ʻip passed to run

Have a processor as an argument. You can modify the processor directly, or you can prevent the new processor and new image from changing the original image based on that data. The original image is locked while the plugin is running.

It seems that. (Corrected English literature by Google Translate)

PlugInFrame Since it is a subclass of AWT that implements the Plugin interface, it seems that you can create a window with buttons and text boxes using awt. You can declare your plugin as a subclass of PlugInFilter, he said.

PlugInFrame


import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.frame.*;

public class Plugin_Frame extends PlugInFrame {

	public Plugin_Frame() {
		super("Plugin_Frame");
		TextArea ta = new TextArea(15, 50);
		add(ta);
		pack();
		GUI.center(this);
		show();
	}
}

By the way, in the template between these three types, which of ʻij.pulugin. * , ʻij.plugin.filter. *, ʻij.pulugin.frame. * `Is imported is different.

Imagej classes

Once you know what the template is doing, it's time to actually use Imagej's API to write the actual program. At that time, what kind of class Imagej has and what you can do with it is important. What do ʻij.gui and ʻij.measure in the API Explanation Page package do? That's right. By the way, the UML class diagram is here.

ij ImageJ The basis of ImageJ. This class contains information about the program's main entry point and ImageJ's main window.

IJ There are various useful functions.

Convenient function


//Display error message
static void error(java.lang.String message);
//You can also display the error message on the log screen
static void redirectErrorMessages();
//Display message box
static void showMessage(java.lang.String message);
static void showMessage(java.lang.String title, java.lang.String message);
//Displaying a message box with a cancel button
static boolean showMessageWithCancel(java.lang.String title, java.lang.String message);
//Export text to Result window
//Seems to be deprecated
static void write(java.lang.String s);
//Items in the Result window(Area, Mean, etc.)write
//You can set multiple items by separating them with the tab character.
//Calling this method will reset what is displayed
static void setColumnHeadings(java.lang.String headings);
//Show in log window
static void log(java.lang.String s);
//Convert numbers to letters
//You can also select up to several decimal places
static java.lang.String d2s(double n);
static java.lang.String d2s(double n,int precison);

//Status bar(Main Imagej window)Write letters to
static void showStatus(java.lang.String s);
//Status bar(Main Imagej window)Operate the progress bar of
//0.0~1.Give a value up to 0 or the current value/Give a target value
static void showProgress(double val);
static void showProgress(int currentIndex, int finalIndex);

//You can also ask the user to enter a value
static double getNumber(java.lang.String prompt, double defaultValue)
static java.lang.String getString(java.lang.String prompt, java.lang.String defaultString)

//Use other plugins in the menu
//If you use Macro's Recorder function, you can use it as a reference for what to give as an argument.
static void run(java.lang.String command);
static void run(java.lang.String command,java.lang.String options);

//Get the currently active image
static ImagePlus getImage();

ImagePlus A class based on the ʻImageProcessor class. Images in ImageJ are represented based on this class. In other words, it may be said that it cannot be avoided when creating an image processing plug-in. ~~ By the way, the ʻImageWindow class is required for display. ~~ It seems that it can be displayed with the show () method. ~~ Maybe it's not basic to use the ImageWindow class ~~

constructor


ImagePlus ()
//For example https://imagej.nih.gov/ij/images/lena.If you specify jpg
//Download and display Lena's image from the nih page.
ImagePlus ( java.lang.String pathOrURL)
//The character specified in title becomes the title when displayed in the ImageWindow class.
ImagePlus ( java.lang.String title, java.awt.Image img)
ImagePlus ( java.lang.String title, ImageProcessor ip)
ImagePlus ( java.lang.String title, ImageStack stack)

Display related methods


//Create a window and display an image
void show();
//Status bar(The part below the main body of Imagej that displays the coordinates of the cursor and the color of that part)
//You can also display characters in
void show(java.lang.String statusMessage);
//After displaying the window with the show method
//After making changes to the image with the ImageProcessor class etc.
//Update the image by calling draw
void draw();
//You can also specify the range to update
void draw(int x, int y, int width, int height);
//Update and display
void updateAndDraw();
//Image information as well as images(Type, size, etc.)Also updated and displayed
//Calling updateAndDraw internally
void updateAndRepaintWindow();
//Close if displayed
void hide();

Main methods


//Returns an ID indicating RGB, 8bit, etc.
int getType ()
//Returns the width of the image.
int getWidth ()
//Returns the height of the image.
int getHeight ()
//Returns the title written in the window.
java.lang.String getTitle ()
//Returns information on various images.
ij.io.FileInfo getFileInfo ()
//java.awt.Returns an Image type image.
java.awt.Image getImage ()
//Set the title.
void setTitle ( java.lang.String title)
//Set the image.
void setImage ( java.awt.Image img)

It seems that ImagePlus can also set user-created properties.

python


java.util.Properties getProperties()
java.lang.Object getPropertiy ( java.lang.String key)
void setProperty ( java.lang.String key, java.lang.Object value)

ImageStack A class for arranging images.

WindowManager A class that manages open windows.

ij.gui ImageWindow ~~ I told you I didn't have a turn, that's a lie ~~ It seems to be a class related to windows when Imagej displays images etc. Inside ImageCanvas: Class related to the rendering area of information such as image rendering and size ImagePlus: A class with image data And so on. And this ImageWindow class. Since it is inherited from around java.awt.Frame, it is possible to arrange buttons etc. Therefore, if you want to create a window with parts such as buttons, you need to access not only the ImagePlus show but also the ImageWindow class. A detailed explanation of awt is ~~ C ++ It is a heavy load for humans in the field ~~ I will leave it to other excellent articles, but at the end of this article I will place two buttons and give a sample that makes each react differently I'll leave it.

By the way, you can also turn the While Loop only while the screen is displayed by doing the following.

python


ImagePlus ip = new ImagePlus(variable of type imageProcessor);
ImageWindow iw = new ImageWindow(ip);
iw.running = true;
double count =0;
while(iw.running){
	IJ.log(IJ.d2s(count));
	count++;
	IJ.wait(100);
}

ImageCanvas This is a class related to depiction of images and sizes mentioned above.

python


//Gets the coordinates of the current cursor
java.awt.Point getCursorLoc();

ProgressBar It shows progress when loading a large number of images. If you just use it

python


for (int n = 1;n<=10 ;n++ ) {
	IJ.showProgress(n / 10.0);
	IJ.wait(100);
}

I feel that it's okay just to do something like that.

NewImage A class that creates new images.

//Create and display nStack images in one stack of 200x100, 8bit with the title test
int nStack=3;
ij.gui.NewImage.open("test",200,100,nStack,ImagePlus.GRAY8,0);
//Show new image creation dialog
ij.gui.NewImage ni = new ij.gui.NewImage(); 

The NewImage class also has convenient static methods for creating images.

//8-bit grayscale image
static ImagePlus createByteImage(java.lang.String title, int width, int height,int slices, int option);
//32bit grayscale image
static ImagePlus createFloatImage(java.lang.String title, int width, int height,int slices, int option);
//RGB image
static ImagePlus createRGBImage(java.lang.String title, int width, int height,int slices, int option);
//16bit image
static ImagePlus createShortImage(java.lang.String title, int width, int height,int slices, int option);
//(For the time being)Image of any bit depth. When I tried to make it with 10bit, I got an error ...
static ImagePlus createImage(java.lang.String title, int width, int height,int nSlices, int bitDepth, int options);
Option name effect
FILL_BLACK Painted in black
FILL_WHITE Painted white
FILL_RAMP Horizontal gradation
FILL_NOISE Noisy state
FILL_RANDOM Noisy state

Since these options are defined in the NewImage class, they can be accessed by typing NewImage. (Option name).

Roi dialog window etc...

ij.io Read / save files, etc.

ij.macro It parses as a parser for macro languages and built-in macros.

//Write 5 to Log
ij.macro.MacroRunner mr= new ij.macro.MacroRunner("print(5)");

ij.measure Includes classes for measurement.

ij.plugin Many features of Imagej are implemented as plugins, so if you look for the plugin class or its subpackages, you can usually find it ~~, the references said ~~. ij.plugin.filter I can't understand (including whether it's necessary). ij.plugin.frame I can't understand.

ij.process A collection of classes that store and process the data of the image itself ImageProcessor The most basic class when processing images. You can make ImagePlus from here. When a plugin is created from PlugInFilter, it is passed as an argument of the run method. This class seems to be useful when you want to do image processing, including access to pixels.

Access to pixels

python


//Receive pixel data as an array.
//The type of array depends on the type of image, so match the type of image you want.
//You need to cast the return value.
//Also, the image is two-dimensional, but the return value is a one-dimensional array, so
//To access pixels through this array[x + y × "Image width"]And so on.
getPixels()
//Set the array according to the type and size of ImageProcessor.
void setPixels(java.lang.Object pixels)
//Get the value by accessing each pixel individually/Set
int getPixel(int x, int y)
void putPixel(int x, int y, int value)
float getPixelValue(int x, int y)
//Pixel-based access is possible. It will be useful for RGB images.
//I made a sample below.
int[] getPixel(int x, int y, int[] iArray)

// (x,y)Lines starting with/Access columns and get values/Set
void getRow(int x, int y, int[] data, int length)
void putRow(int x, int y, int[] data, int length)
void getColumn(int x, int y, int[] data, int length)
void putColumn(int x, int y, int[] data, int length)

//(x1, y1) → (x2, y2)Returns the pixel values up to
10. double[] getLine(int x1, int y1, int x2, int y2)

Example of accessing each pixel


//Example of receiving an RGB image
//Let myProcessor be the variable name of the ImageProcessor that contains the RGB image.
int[] pixels = (int[]) myProcessor.getPixels();
//(100, 50)Access pixels at coordinates
//Assume that the width of the image is assigned to a variable called imageWidth
int pixel = pixels[100 + 50*imageWidth];
int red   = (int)((pixel & 0xff0000) >> 16);
int green = (int)((pixel & 0x00ff00) >>  8);
int blue  = (int)((pixel & 0x0000ff)      );

Example of accessing pixels using getPixel and array


//This sample creates an RGB image with a gradient.
//`getPixel`I get the value with, but as a result"a0 b50 c100"It will be displayed.
//In this way, you can see that you can access each channel of a specific pixel without using the bit operator.
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;
import ij.plugin.frame.*;

public class My_Plugin implements PlugIn {

	public void run(String arg) {
 		int pxs[] = new int[256*256];
		for(int y = 0; y<256; y++){
			for(int x = 0; x<256; x++){
				pxs[x+y *256]=(int)(y + (y/2 <<8)) ;
			}
		}
		ColorProcessor bp = new ColorProcessor(256,256);
		bp.setPixels(pxs);
		ImagePlus ip = new ImagePlus("test",bp);
		ImageWindow iw = new ImageWindow(ip);
		ImageProcessor IP = ip.getProcessor();

		int Arr[] = new int[3];
		IJ.showMessage("a"+ IP.getPixel(0,100,Arr)[0] +
			" b"+ IP.getPixel(0,100,Arr)[1] +
			" c"+ IP.getPixel(0,100,Arr)[2]);
	}
}

copy

When you want to process an image, you may not want to make changes to the original image. In that case, a new image could be created by using the NewImage class or the createImagePlus method of the ImagePlus class. However, the images created in these classes were empty (= pure white, pure black, etc.). It may not be smart to access each pixel and copy the values one by one when you want to copy the original image to those images. In that case, it is recommended to use the following method.

python


//xloc the contents of ip,Overwrite yloc location
void insert(ImageProcessor ip, int xloc, int yloc);
//xloc the contents of ip,Write to yloc location according to mode
void copyBits(ImageProcessor ip, int xloc, int yloc, int mode);

The interface defined in Blitter of ij.process can be used for mode. dst shows the value of each pixel of the copy destination, and src shows the value of each pixel of the copy source.

Definition name effect
COPY dst=src
COPY_INVERTED dst=255-src (8-bits and RGB)
ADD dst=dst+src
SUBTRACT dst=dst-src
MULTIPLY dst=src*src
DIVIDE dst=dst/src
AVERAGE dst=(dst+src)/2
DIFFERENCE dst=abs(dst-src)
AND dst=dst AND src
OR dst=dst OR src
XOR dst=dst XOR src
MIN dst=min(dst,src)
MAX dst=max(dst,src)
COPY_TRANSPARENT Make white pixels transparent and copy
COPY_ZERO_TRANSPARENT Make black pixels transparent and copy

Image type conversion

You may also want to convert the image type. Is possible.

Type conversion


//The one after conversion is as the function name indicates.
//0 by doScaling-255、0-It seems that you can decide whether to scale to the range of 65535.
ImageProcessor convertToByte(boolean doScaling);
ImageProcessor convertToRGB()
ImageProcessor convertToShort(boolean doScaling)

//Conversion to float type
//If this function, a calibration table, is set
//It seems that it will also calibrate.
ImageProcessor convertToFloat()
//About calibration
//By setting a lookup table, conversion according to it is possible.
//Float when converting to byte type[256],
//Float when converting to Short type[65536]To
//Use as a look-up table.
//Example of use
//In this example, for an 8-bit grayscale image
//1 only when the pixel value is 100.To 0, otherwise 0.Convert to 0.
float[] calib = new float[256];
for (int k = 0; k <256 ; k++ ) {
	calib[k] = (float)0.0;
}
calib[100] = (float)1.0;
(srcImageProcessor).setCalibrationTable(calib);
ImageProcessor ip = (srcImageProcessor).convertToFloat();
ImagePlus IpF = new ImagePlus("float",ip);
IpF.show();

Binarization

Even binarization is defined here

threshold


//Binarization by setting a threshold
void threshold(int level);
//Binarization by automatically setting the threshold
void autoThreshold();
//Acquisition of automatically set threshold
int getAutoThreshold();

Use of roi (Regions of interest)

1. void setRoi(int x, int y, int width, int height) 2. void setRoi(java.awt.Rectangle r) 3. viod serRoi(java.awt.Polygon r) Set Roi. Roi's base class seems to be defined in ij.gui. ij.gui also has Roi classes other than rectangles, such as Line, ʻOverROI, PolygoneRoi, FreehandRoi, PointRoi, ShapeRoi, and TextRoi`.

There are many other useful functions

Histogram acquisition, filtering, maximum / minimum value acquisition, inversion, depiction, etc. in the image seem to be defined in the ImageProcessor class.

Mutual conversion with ImagePlus

Conversion direction Method Description
ImagePlus → ImageProcesosr (ImagePlus).getProcessor() Use ImagePlus getProcessor method
ImageProcesosr → ImagePlus ImagePlus(ImageProcessor ip) Pass as an argument to the ImagePlus constructor

Precautions when casting pixel values

In java, byte and short are signed, that is, they are defined in the range of -128 to 127 and -32768 to 32767, but when we process images, they are processed in the range of 0 to 255 and 0 to 65535. .. Therefore, when casting numerical values, it is necessary to pay attention to the sign.

Conversion direction Method
byte → int int pix = pix_byte & 0xff;
int → byte pix_byte = (byte) pix;
short → int int pix = pix_short & 0xffff;
int → short pix_short = (short) pix;

Must be.

Also, this class is an abstract class and cannot be instantiated. If it is not entered as an argument or generated from ImagePlus. .. For example, if you want to create an image from 0 via ImageProcessor, it seems to use the following subclass. (Int width, int height) is required as an argument when creating an instance.

python


1. ByteProcessor
Used for 8-bit images. A subclass of BinaryProcessor.
2. ShortProcessor
Used for 16-bit images.
3. ColorProcessor
Used for RGB images. 32 bits are allocated to one pixel, and each color is expressed in 8 bits.
4. FloatProcessor
Used for 32-bit images.

Troubleshooting at this point

I'm not sure even if I look at the specification table → I have to read the source ...

i.e. The converter class in ij.plugin in Resources. It seems that the image can be converted from RGB to 8bit etc., but in the specification table, only run and convert methods were implemented. Each argument is also a string, and when I wondered when to select the image, I found that I was running WindowManager.getCurrentImage () inside the run method. So

Converter cnv =new Converter ();
cnv.run("");//Select the currently open image
cnv.convert("8-bit");//conversion

It turned out that it can be used by.

Sample collection

Hello World

Is it the simplest to use PlugIn if you want to do Hello Work? Write this in the run.

helloWorld


IJ.showMessage("hello","world!");

Image with gradation

Set the value in the array showing each prepared pixel with a double for loop, and set it in the ImageProcessor class. Then convert it to the ImagePlus class and display it in the ImageWindow class.

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;
import ij.plugin.frame.*;

public class My_Plugin implements PlugIn {

	public void run(String arg) {
 		byte pxs[] = new byte[256*256];
		for(int y = 0; y < 256; y++){
			for(int x = 0; x < 256; x++){
				pxs[x + y * 256]=(byte) y;
			}
		}
		ByteProcessor bp = new ByteProcessor(256,256);
		bp.setPixels(pxs);
		ImagePlus ip = new ImagePlus("test",bp);
		ImageWindow iw = new ImageWindow(ip);
	}
}

Black and white inversion

The sample written in the bibliography is just like that.

python


import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

public class Filter_Plugin implements PlugInFilter {
	ImagePlus imp;

	public int setup(String arg, ImagePlus imp) {
		if (arg.equals("about")) 
		{
			showAbout();
			return DONE;
		}
		return DOES_8G+DOES_STACKS+SUPPORTS_MASKING;
	}

	public void run(ImageProcessor ip) {
		byte[] pixels = (byte[])ip.getPixels();
		int width = ip.getWidth();
		Rectangle r = ip.getRoi();

		int offset, i;
		for (int y=r.y; y<(r.y+r.height); y++)
		{
			offset = y*width;
			for (int x=r.x; x<(r.x+r.width); x++)
			{
				i = offset + x;
				pixels[i] = (byte)(255-pixels[i]);
			}
		}
	}
	void showAbout() {
		IJ.showMessage("About Inverter_...",
			"This sample plugin filter inverts 8-bit images. Look\n" +
			"at the 'Inverter_.java' source file to see how easy it is\n" +
			"in ImageJ to process non-rectangular ROIs, to process\n" +
			"all the slices in a stack, and to display an About box.");
	}
}

・ Divide RGB images into 3 colors, R, G, and B

python


import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

public class Filter_Plugin implements PlugInFilter {
	ImagePlus imp;

	public int setup(String arg, ImagePlus imp) {
		this.imp = imp;
		return DOES_RGB;
	}

	public void run(ImageProcessor ip) {
		ImagePlus ipMain = new ImagePlus("main",ip);
		int width = ipMain.getWidth();
		int height = ipMain.getHeight();
		byte[] r = new byte[width * height];
		byte[] g = new byte[width * height];
		byte[] b = new byte[width * height];

		int[] px = (int[])ip.getPixels();

		for (int y = 0; y < height ; y++ ) {
			for (int x = 0; x < width ; x++ ) {
				r[x + y * width] = (byte)( (px[x + y * width] & 0xff0000) >> 16);
				g[x + y * width] = (byte)( (px[x + y * width] & 0x00ff00) >> 8);
				b[x + y * width] = (byte)( (px[x + y * width] & 0x0000ff));
			}
		}

		ByteProcessor IPr = new ByteProcessor(width,height);
		ByteProcessor IPg = new ByteProcessor(width,height);
		ByteProcessor IPb = new ByteProcessor(width,height);
		IPr.setPixels(r);
		IPg.setPixels(g);
		IPb.setPixels(b);

		ImagePlus ipr = new ImagePlus("red",IPr);
		ImagePlus ipg = new ImagePlus("grean",IPg);
		ImagePlus ipb = new ImagePlus("blue",IPb);

		ipr.show();
		ipg.show();
		ipb.show();
	}
}

Place two buttons and associate them with the message box

This sample is a sample to create a window with two buttons added to the image opened by the PlugInFilter plug-in. When you resize the newly created window, there are buttons, each of which displays a message box when you click on it.

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import java.awt.event.*;
import ij.plugin.filter.*;

public class Filter_Plugin implements PlugInFilter {
	ImagePlus imp;

	public int setup(String arg, ImagePlus imp) {
		this.imp = imp;
		return DOES_ALL;
	}

	public void run(ImageProcessor ip) {
		ImagePlus IP = new ImagePlus("test",ip);
		ImageWindow iw = new ImageWindow(IP);

		Button b1 = new Button("b1");
		b1.addActionListener(new b1ActLis());
		iw.add(b1);

		Button b2 = new Button("b2");
		b2.addActionListener(new b2ActLis());
		iw.add(b2);

		//By running the resizing macro, you can increase the size of the window
		//It seems that it can be changed to the optimum size including the button
		IJ.run("Out [-]");
		IJ.run("In [+]");
	}
	class b1ActLis implements ActionListener{
		public void actionPerformed(ActionEvent e){
			IJ.showMessage("b1");
		}
	}
	class b2ActLis implements ActionListener{
		public void actionPerformed(ActionEvent e){
			IJ.showMessage("b2");
		}
	}
}

Important things found in the commentary

-Do not use package in plugin class -If you want to use a library other than the Imagej library and the standard Java library, it seems to be the simplest to put it in the "ImageJ \ jre \ lib \ ext" directory.

At the end

I have the impression that the article was half-finished because I didn't understand my lack of ability and demand. I would be unexpectedly happy if this article could be helpful to someone.

Recommended Posts

Plugin development with ImageJ
astah * plugin development snippet
[Rails] Development with MySQL
THETA plugin development (about theta-plugin-sdk)
[Eclipse plug-in development] Javadoc acquisition
[Ruby] REPL-driven development with pry
Hot deploy with Spring Boot development
Prepare Java development environment with Atom
Hello World for ImageJ Java Plugin
Problems with android studio development series
Build jooby development environment with Eclipse
Html5 development with Java using TeaVM
"Hello world" for ImageJ with Eclipse
Prepare Java development environment with VS Code
Laravel development environment construction with Docker (Mac)
Build a PureScript development environment with Docker
Create Spring Boot-gradle-mysql development environment with Docker
Start web application development with Spring Boot
[Minecraft] Time operation with Bukkit / Spigot plugin
Java development with Codenvy: Hello World! Run
Build a Wordpress development environment with Docker
Game development with two people using java 1
Convenient plugin for Eclipse JAVA development: Decompiler
Game development with two people using java 3
Automate integration testing with Maven Failsafe plugin
Java development with Codenvy: Console app debug
Lightweight PHP 7.4 development environment created with Docker
24 hours struggling with Android development, Java Optional