ImageJ+ImageMontage : issue to animate the frame processing

Hey there,
I’m Ismaël Joffroy Chandoutis, artist and filmmaker. For a narrative movie project, I’m trying to vizualize numerous photograms from a video news of an event (brussels’s attack march 22th 2016) and I’d like to make an animation like this : https://www.youtube.com/watch?v=d_OceOpCmf8 (at the beginning) I tried to use it and follow the tutorials provided by the author and I succeeded in generating one board of all photograms. But not an animated appearance on each frame like you did.
I’m looking for someone to help me figuring how to do it. Does anyone has an idea ?
I’m on Mac OS X high Sierra 10.13.6 but it doesn’t seem to be related to any kind of system issue.
Thanks !!!

Hi Ismael,

It’s be easier if you could also link the tutorial.

Sincerely,

Matthieu

Hey MatthieuV,
yes of course, here it is : https://github.com/culturevis/imagemontage
And Lev pointed me this page of the manual : https://imagej.nih.gov/nih-image/manual/menus/stacks.html#montage
But in both cases it didn’t work for me

Hi Ismael,

I got the macro to work. It can however only be used with .jpg files. You basically only need to change a few lines to make it work with other format but you are restricted to one type. What file format are the pictures you want to animate?

Did you tick “Save images for animation” at the beginning of the macro? Did the macro ask you where the original pictures are and then where to save the animated frames?

M.

Hey MatthieuV,
Thank you for your message and your help. So I ticked save images for animation and used jpeg. I have an output of pictures and all the pictures are stacked in the same place. I want to animate them like in the linked I gave you in my last posts. But I don’t know which settings to use for that. Any idea ?

Hi Ismael,

You need to drag the ** folder** containing the frames onto the Fiji bar. Fiji will ask you if you want to convert to RGB and use virtual stack. Tick both.

You then go to File>Save As> and select the file format you want. Since you want to make a movie, select AVI. Define the frame rate and compression level and you’ll get a movie.

Sincerely,

M.

Thank you so much for your help ! I did it and the .avi works of course. But my main concern is the fact the images stack up in the same place, in the top left corner. So my goal is to animate them so that they gradually appear next to each other and when the line is filled, that the images continue to be arranged like that on the next line. I’m trying to do exactly as in the example video.

Hum, I don’t know what you are doing here as the macro works well with my files… Could you set up a box for your files, so I can have a go?

M.

test imagej 1aout.zip (5.0 MB)

and here the video to show you the problem :

This is the result I got. Unfortunately, your vimeo link is broken…

Sincerely,

M.

1 Like

That’s exactly what I want :smiley:
But I have this : https://vimeo.com/444690447/ac82bef184

Could you run this code in Fiji? You copy it, go in Fiji>Plugins>New>Macro and click “run”

I’ve modified it a bit to include image format choice.

// Image Montage
// December 2, 2011 - August 10, 2014
// Lev Manovich, Jay Chow and Matias Giachino / softwarestudies.com
// Modified to choose input format file  05/08/2020
// Matthieu Vermeren

// this version:
// 1) user defines width and height of the montage
// 2) scales images vertically to the same size defined by the user - n_width (like in TiffViewer)
// 3) uses the full width of every image (after scaling), aligning them next to each other

// input; either a folder full of images or a data file containing rows of filenames or filepaths
// for the latter two options, the order of images in the file determines ther position in the montage (left to right, top to bottom)


// if 1, opens gui to edit options in
use_gui = 1;

// if 0, takes files from a folder
// if 1, takes files from a folder and its subfolders
// if 1, takes files from a data file
// if 2, takes files from a data file as full filepaths
input_flag = 0;
input_list = newArray("Folder", "Folder and Subfolders", "Data File", "Data File as Filepaths");

// if 0, make 8-bit grey scale montage
// if 1, make RGB montage
montage_RGB = 0;
montage_RGB_list = newArray("Grayscale","RGB");

// set choice of file format.
FileFormat = 0;
FileFormat_List = newArray(".jpg",".tif",".png");

// sets the width of the montage canvas
montage_width = 2000;

// sets the height of the montage canvas
montage_height = 1000;

// the height to resize each image to
height_row = 70;

// sets the horizontal space between the images - in pixels
h_interval = 0;

// sets the vertical space between the images - in pixels
v_interval = 0;

// if 1, saves each frame of the montage process into a user-specified directory
save_files_flag = 0;

// the column from which to load the filename/filepath in a data file
input_data_column = 0;

// Open the GUI if option is active.  This is where you specify the input data
if(use_gui == 1){
	Dialog.create("Image Montage");
	Dialog.setInsets(0,0,0);
	Dialog.addMessage("Create a montage of images.\Image sizes can vary.");
	Dialog.addMessage(" ");
	Dialog.setInsets(0,0,0);
	Dialog.addChoice("Image Source  ", input_list, input_list[input_flag]);
	Dialog.addMessage(" ");
	Dialog.setInsets(0,0,0);
	Dialog.addMessage("Canvas");
	Dialog.setInsets(0,0,0);
	Dialog.addChoice("Color Mode",montage_RGB_list,montage_RGB_list[montage_RGB]);
	Dialog.addNumber("Set Width   ",montage_width,0,5,"px");
	Dialog.addNumber("Set Height  ",montage_height,0,5,"px");
	Dialog.addMessage(" ");
	Dialog.setInsets(0,0,0);
	Dialog.addMessage("Images");
	Dialog.addNumber("Row Height",height_row,0,5,"px");
	Dialog.addNumber("X Spacing   ",h_interval,0,5,"px");
	Dialog.addNumber("Y Spacing   ",v_interval,0,5,"px");
	Dialog.addMessage(" ");
	Dialog.setInsets(0,0,0);
	Dialog.addChoice("File type", FileFormat_List, FileFormat_List[0]);
	Dialog.addMessage(" ");
	Dialog.setInsets(0,0,0);
	Dialog.addMessage("Animation");
	Dialog.setInsets(0,20,0);
	Dialog.addCheckbox("Save Images for Animation", save_files_flag);
	Dialog.show();
	// Fetch choices
	input_flag_choice = Dialog.getChoice();
	for(i=0; i<input_list.length; i++){
		if(input_list[i] == input_flag_choice){
			input_flag = i;
			i = 999;
		}
	}
	montage_RGB_choice = Dialog.getChoice();
	for(i=0; i<montage_RGB_list.length; i++){
		if(montage_RGB_list[i] == montage_RGB_choice){
			montage_RGB = i;
			i = 999;
		}
	}
	montage_width = Dialog.getNumber();
	montage_height = Dialog.getNumber();
	height_row = Dialog.getNumber();
	h_interval = Dialog.getNumber();
	v_interval = Dialog.getNumber();
	save_files_flag = Dialog.getCheckbox() & 1;
	
	Format_Choice = Dialog.getChoice();
	for(i=0; i<FileFormat_List.length; i++){
		if(FileFormat_List[i] == Format_Choice){
			FileFormat = i;
			i = 999;
		}
}

setBatchMode(false);

scaled_height = height_row;
var count = 0;
var path = "";

//Software asks where the data is and where to save the results

if(input_flag != 3){
	dir = getDirectory("Choose source directory - images");
}
if(save_files_flag == 1){
	dir_anim = getDirectory("Directory to save files for animation"); 
}

//counting how many pictures there are depending on choice (i.e. single folder, folder and subfolder,...)

if(input_flag == 0 || input_flag == 1){
	list = getFileList(dir);
	countFiles(dir);
}else if(input_flag == 2 || input_flag == 3){
	input_file = File.openAsString("");
	list = split(input_file, "\n");
	labels=split(list[0],"\t");
	for(i=0;i<labels.length;i++){
		labels[i] = labels[i] + " (Column"+i+")";
	}
	if(use_gui == 1){
		Dialog.create("Data File");
		Dialog.setInsets(0,0,0);
		if(input_flag == 2){
			Dialog.addMessage  ("Choose the column that contains filenames:");
		}else if(input_flag == 3){
			Dialog.addMessage  ("Choose the column that contains filepaths:");
		}
		Dialog.addMessage(" ");
		Dialog.setInsets(0,0,0);
		if(input_flag == 2){
			Dialog.addChoice("Image Filenames",labels,labels[input_data_column]);
		}else if(input_flag == 3){
			Dialog.addChoice("Image Filepaths",labels,labels[input_data_column]);
		}
		Dialog.show();
		column_choice = Dialog.getChoice();
		for(i=0; i<labels.length; i++){
			if(labels[i] == column_choice){
				input_data_column = i;
				i = 999;
			}
		}
	}
	for (i=1; i<list.length; i++) {
		columns = split(list[i],"\t");
		list[i-1] = columns[input_data_column];
		if (endsWith(list[i-1], Format_Choice)) {
			count++;
		}
	}
	if(input_flag == 2){
		path = dir+list[1];
	}else if(input_flag == 3){
		path = list[1];
	}
}

// For input_flag 0 and 1
function countFiles(dir) {
	list = getFileList(dir);
	for (i=0; i<list.length; i++) {
		if (input_flag == 1 && endsWith(list[i], "/")){
			countFiles(""+dir+list[i]);
		}else if(endsWith(list[i], Format_Choice)) {//used to be .jpg
			count++;
		}
	}
}


print("Montage width = " +  montage_width);
print("Montage height = " + montage_height);
print("Number of images = " + count);

if (montage_RGB == 1){
	newImage("montage", "RGB white", montage_width, montage_height, 1);
}else{
	newImage("montage", "8-bit white", montage_width, montage_height, 1);
}
id_plot=getImageID;


var img_width = 0;
var img_height =  0;
var start_x = 0;
var start_y = 0;
var row = 0;
var total_x_width = 0;
var n_width=0;
var curImg = 0;

setBatchMode(true);

// Begin parsing files
if( input_flag == 0 || input_flag == 2 || input_flag == 3){
	for(j=0; j<list.length; j++){
		if(endsWith(list[j],Format_Choice)){//used to be .jpg
			if(input_flag == 3){
				if(File.exists(list[j])){ 	
					processFile(list[j],list[j]);
				} else {
					print(list[j] + " not found!");
				}
			} else {
				if(File.exists(""+dir+list[j])){
					processFile(""+dir+list[j],list[j]);
				}else{
					print ( ""+dir+list[j] + " not found!");
				}
			}
		}
	}
}else if(input_flag == 1){
	processRecursiveFiles(dir);
}

function processRecursiveFiles(dir){
	list = getFileList(dir);
	for (i=0; i<list.length; i++) {
		if (endsWith(list[i], "/")){
			processRecursiveFiles(""+dir+list[i]);
		}else if (endsWith(list[i], Format_Choice)) {
			if(File.exists(""+dir+list[i])){
				processFile(""+dir+list[i], list[i]);
			} else {
				print(""+dir+list[i] + "  not found!");
			}
		}
	}
}

function processFile (path,listi){
	
	// Check for row overflow, start new row if needed
	if ((total_x_width + n_width) > montage_width) {
		// increment row
		row = row + 1;
		// reset column
		start_x =  0;
		// reset total row width
		total_x_width = 0;
	}
	
	open(path);
	id=getImageID;

	img_width = getWidth;
	img_height = getHeight;
	n_width = round((img_width * scaled_height)/img_height);

	run("Size...", "width=" + n_width + " height=" + scaled_height + " average interpolation=Bicubic");

	// get image width and height after it was scaled
	n_width = getWidth;
	n_height = getHeight;

	start_x = total_x_width;
	start_y = row * (height_row + v_interval) + v_interval;

	run("Select All");
	run("Copy");
	selectImage(id_plot);
	makeRectangle(start_x, start_y, n_width, n_height);
	run("Paste");
	selectImage(id);
	close();

	// update display
	updateDisplay();

	total_x_width = total_x_width + n_width + h_interval ;

	if (save_files_flag == 1) {
		selectImage(id_plot);
		path_files = dir_anim + "frame_" + curImg;
		saveAs("PNG", path_files);

		print("image " + curImg + " saved");
	}

	curImg++;
	showProgress(curImg, count);
}

run("Select None");
setBatchMode(false);