Batch processing images in image J. Attempting to add a series of images - batch-processing

I am attempting to add multiple DICOM images together to for one summated image. This is the code I have come up with so far. It adds the first two images, and saves the new 'sum' image. It will then add one more of the images, but the for loop does not seem to be working and none of the other 17 images in the directory will be added. No error messages are shown.
dir = getDirectory("Choose a Directory ");
list = getFileList(dir);
open(dir+list[0])
open(dir+list[1])
imageCalculator("Add create", list[0], list[1]);
saveAs("Tiff", dir+"Sum.tif");
close();
selectWindow(list[0]);
close();
selectWindow(list[1]);
close();
if (getVersion>="1.40e")
setOption("display labels", true);
setBatchMode(true);
open(dir+"Sum.tif");
for (i=3; i<list.length; i++) {
if (nImages>=1) {
path = dir+list[i];
open(path);
imageCalculator("Add", "Sum.tif", list[i]);
selectWindow(list[i]);
close();
saveAs("Tiff", dir+"Sum1.tif");
}

Script seems like ImageJ macro to me. If I were you I would simplify the task by stacking all your images together and Z-projecting the sum of them, which comes out to something simple:
dir = getDirectory("Choose a Directory ");
list = getFileList(dir);
for (i=0; i<list.length; i++) {
open(dir+list[i]);
}
run("Images to Stack", "name=[Stack of DICOMs] title=[]");
run("Z Project...", "projection=[Sum Slices]");
The product of the above code should change the image type to 32 bit by default to hold larger values if necessary. By the way, you are missing semicolons in your script when opening files. You may not have included all your code because some crucial brackets to end your loops are missing.

Related

How to work around ImageJ run("HSB stack") error/ bug?

I am working on a macro for ImageJ. The goal is to take colour scans with several seeds on them and crop around the seeds to get several equally sized images with one seed on each.
This is the basic idea for the macro: prompt to select folder with scans (info about the seed is in the name of the image) > threshold to select seeds > crop around each seed on the original image > save all of the cropped images in a folder (name of the cropped images still containing the information of the name of the original image)
When I run the code below, I get an error for line 31: run("HSB stack");
The error informs me about supported conversions and shows that in order to run this command I need to start with an RGB image. However, according to Fiji > Image > Type, my images are RGBs. A coding error in that part also seems unlikely since it was written with the recording function in ImageJ.
Error message
According to what I found for the error, this seems to concern a recurring bug in the software, specific to the commands run("HSB stack") and run("RGB stack") in macros.
We have tried running this on ImageJ 2.3.0/1.53s as well as 1.53q on MacOS and Windows and always got the same problem.
If it is not a software problem, where is the error? Or if it is, do you have any suggestions for workarounds or a different program that could perform the same job?
The images I am working with are colour scans, 600dpi, white background with between 1 and 90 seeds on each scan. They are large tiff images (107.4 MB) but look like this:
Example scan image
I am not sure if it is helpful, but the code is below. There are probably still errors in the latter part that I could not yet get to because I can't get past the problem in line 31.
// Directory
dir=getDirectory("Choose a data folder");
list = getFileList(dir);
processed_dir_name = dir + "Cropped" + File.separator;
print(processed_dir_name);
File.makeDirectory(processed_dir_name);
// Batch
for (i=0; j<list.length; i++) {
print(i + ":" + dir+list[i]};
// Open images
run("Bio-Formats Importer", "open=" + dir+list[i] + "color_mode=Default view =Hyperstack");
// Crop edge, set general cropping parameters, scale
makeRectangle(108, 60, 4908, 6888);
run("Crop");
main = getTitle():
default_crop_width = 350;
default_crop_height = 350;
run("Set Scale...", "distance=600 known=25.4 unit=mm global");
//Thresholding
run("Color Threshold...");
//Color Thresholder 2.3.0/1.53q
// Autogenerated macro, single images only!
min=newArray(3);
max=newArray(3);
filter=newArray(3);
a=getTitle();
run("HSB stack");
run("Convert Stack to images");
selectWindow("Hue");
rename("0");
selectWindow("Saturation");
rename("1");
selectWindow("Brightness");
rename("2");
min[0]=0;
max[0]=255;
filter[0]="pass";
min[1]=0;
max[1]=255;
filter[1]="pass";
min[2]=0;
max[2]=193;
filter[2]="pass";
for (i=0;j<3;i++){
selectWindow(""+i);
The problem lies in the fact that your image is a hyperstack, and the color thresholding doesn't know how to work with that.
There are a few options you could try: Open the image as an 8-bit RGB, e.g. via open(dir+list[i]); or split the channels of the hyperstack and threshold each separately. Based on your sample image, I assume the first option makes more sense.
The following is an edited version of your code that works for the sample that you've provided:
// Directory
dir=getDirectory("Choose a data folder");
list = getFileList(dir);
processed_dir_name = dir + "Cropped" + File.separator;
print(processed_dir_name);
File.makeDirectory(processed_dir_name);
// Batch
for (i=0; i<list.length; i++)
{
if (!File.isDirectory(dir+list[i])) // Ignore directories such as processed_dir_name
{
print(i + ":" + dir+list[i]);
// Open images
open(dir+list[i]);
// Crop edge, set general cropping parameters, scale
makeRectangle(108, 60, 4908, 6888);
run("Crop");
main = getTitle();
default_crop_width = 350;
default_crop_height = 350;
run("Set Scale...", "distance=600 known=25.4 unit=mm global");
//Thresholding
//run("Color Threshold...");
//Color Thresholder 2.3.0/1.53q
// Autogenerated macro, single images only!
min=newArray(3);
max=newArray(3);
filter=newArray(3);
a=getTitle();
run("HSB Stack");
run("Convert Stack to Images");
selectWindow("Hue");
rename("0");
selectWindow("Saturation");
rename("1");
selectWindow("Brightness");
rename("2");
min[0]=0;
max[0]=255;
filter[0]="pass";
min[1]=0;
max[1]=255;
filter[1]="pass";
min[2]=0;
max[2]=193;
filter[2]="pass";
for (j=0;j<3;j++){
selectWindow(""+j);
}
}
}

Automating Photoshop to edit en rename +600 files with the name of the folder

I have +600 product images on my mac already cut out and catalogued in their own folder. They are all PSD's and I need a script that will do the following.
Grab the name of the folder
Grab all the PSD's in said folder
Combine them in one big PSD in the right order (the filenames are saved sequentially as 1843, 1845, 1846 so they need to open in that order)
save that PSD
save the separate layers as PNG with the name from the folder + _1, _2, _3
I have previous experience in Bash (former Linux user) and tried for hours in Automator but to no success.
Welcome to Stack Overflow. The quick answer is yes this is possible to do via scripting. I might even suggest breaking down into two scripts, one to grab and save the PSDs and the second to save out the layers.
It's not very clear about "combining" the PSDs or about "separate layers, only I don't know if they are different canvas sizes, where you want each PSD to be positioned (x, y offsets & layering) Remember none of use have your files infront of us to refer from.
In short, if you write out pseudo code of what is it you expect your code to do it makes it easier to answer your question.
Here's a few code snippets to get you started:
This will open a folder and retrieve alls the PSDs as an array:
// get all the files to process
var folderIn = Folder.selectDialog("Please select folder to process");
if (folderIn != null)
{
var tempFileList = folderIn.getFiles();
}
var fileList = new Array(); // real list to hold images, not folders
for (var i = 0; i < tempFileList.length; i++)
{
// get the psd extension
var ext = tempFileList[i].toString();
ext = ext.substring(ext.lastIndexOf("."), ext.length);
if (tempFileList[i] instanceof File)
{
if (ext == ".psd") fileList.push (tempFileList[i]);
// else (alert("Ignoring " + tempFileList[i]))
}
}
alert("Files:\n" + fileList.length);
You can save a png with this
function save_png(afilePath)
{
// Save as a png
var pngFile = new File(afilePath);
pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.embedColorProfile = true;
pngSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
pngSaveOptions.matte = MatteType.NONE; pngSaveOptions.quality = 1;
activeDocument.saveAs(pngFile, pngSaveOptions, false, Extension.LOWERCASE);
}
To open a psd just use
app.open(fileRef);
To save it
function savePSD(afilePath)
{
// save out psd
var psdFile = new File(afilePath);
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
activeDocument.saveAs(psdFile, psdSaveOptions, false, Extension.LOWERCASE);
}

Photoshop action for changing text number and saving with variable

I have a lot of graphic buttons that I need to make. I have 2 layers
TEXT (This is going to be numbers 1-48 for instance)
White Button image
I'm not sure how to go about writing this action or if I need a script. I need to have the text layer start at 1 and follow this progression.
save file w1.png (this yields a png with a button labeled with a "1"
change text to 2
save file w2.png (this yields a png with a button labeled with a "2"
change text to 3
. . . .
ect. . .all the way to 48. So this would make 48 images automatically. Can this be done with "actions" or do I need to learn scripting?
Save
You'll need a script for this, but it's going to be a rather simple one
function main() {
//this just checks if you have a text layer selected
try {
var textLayer = activeDocument.activeLayer.textItem
} catch (e) {
alert("active layer isn't a text layer");
return
};
var loops = 48,
pngSaveOptions = new PNGSaveOptions(),
outputFolder = Folder.selectDialog('', Folder.desktop); //this will ask for an output folder
for (var i = 0; i < loops; i++) {
var myNum = i + 1;
textLayer.contents = myNum; //this will change layer contents to number only. if you need some text here, write it in quotes like textLayer.contents = "my text" + myNum;
activeDocument.saveAs(new File(outputFolder + "/w" + myNum + ".png"), pngSaveOptions, true, Extension.LOWERCASE);
}
}
app.activeDocument.suspendHistory("temp", "main()");

CMS and store hi-resolution images in generated pdf

I'm looking for good CMS for publishing software manuals.
Requirements:
publish manual pages as web pages with thumbnails and shows full resolution after click on image,
exporting manual pages to a pdf file with full resolution images instead to thumbnails.
I found IMHO best wiki system named Tiki Wiki (https://info.tiki.org/) but when I export to pdf then I gets low resolution thumbnail.
I solve this problem by very simple Tiki Wiki code modification:
Modify lib/wiki-plugins/wikiplugin_img.php to force using full image resolution instead to thumbnail in print page mode (inserted code 1) and rescale images in generated HTML by 0.5 factor (inserted code 2):
[...]
function wikiplugin_img( $data, $params )
{
[...]
$imgdata = array_merge($imgdata, $params);
// inserted code 1 (~410 line)
if ($GLOBALS['section_class']=="tiki_wiki_page print"){
$imgdata['thumb'] = '';
}
// end of inserted code 1
//function calls
if ( !empty($imgdata['default']) || !empty($imgdata['mandatory'])) {
[...]
$fwidth = '';
$fheight = '';
if (isset(TikiLib::lib('parser')->option['indexing']) && TikiLib::lib('parser')->option['indexing']) {
$fwidth = 1;
$fheight = 1;
} else {
// inserted code 2 (~410 line)
if ($GLOBALS['section_class']=="tiki_wiki_page print"){
$fwidth = $imageObj->get_width() / 2;
$fheight = $imageObj->get_height() / 2;
} else {
$fwidth = $imageObj->get_width();
$fheight = $imageObj->get_height();
}
// end of inserted code 2 (~638 line)
}
[...]
Now, after printing to pdf by wkhtmltopdf we gets pdf with small but full resolution images.
Additional modifies:
Adds following lines to cms/cssmenus.css (or other css included in print mode) for increase bottom margin of image caption:
div.thumbcaption {
margin-bottom: 5mm;
}
Removes lines from 171 to ~175 in templates/tiki-show_content.tpl for remove the "The original document is available at" foot.

How do I read multiple files after click opened in OpenFileDialog?

I have set a multiselect function in my code to allow me to open multiple files which is in ".txt" forms. And here is the problem, how am I going to read all these selected files after it opened through OpenFileDialog? The following codes and at the "for each" line, when I use System::Diagnostics::Debug, it shows only the data from a file, while data of other files were missing. How should I modify the code after the "for each"? Can anyone provide some suggestions or advice? The files selected are as 1_1.txt, 2_1.txt, 3_1.txt. Appreciate your reply and Thanks in advance.
Here is my written code,
Stream^ myStream;
OpenFileDialog^ openFileDialog1 = gcnew OpenFileDialog;
openFileDialog1->InitialDirectory = "c:\\";
openFileDialog1->Title = "open captured file";
openFileDialog1->Filter = "CP files (*.cp)|*.cp|All files (*.*)|*.*|txt files (*.txt)|*.txt";
openFileDialog1->FilterIndex = 2;
openFileDialog1->Multiselect = true;
if ( openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
{
array<String^>^ lines = System::IO::File::ReadAllLines(openFileDialog1->FileName);
for each (String^ line in lines) {
//?????
System::Diagnostics::Debug::WriteLine("",line);
}
}
You need to look at the OpenFileDialog.FileNames property if you allow multiple files to be selected:
if ( openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK )
{
for each (String^ file in openFileDialog1->FileNames)
{
array<String^>^ lines = System::IO::File::ReadAllLines(file);
for each (String^ line in lines)
{
System::Diagnostics::Debug::WriteLine("",line);
}
}
}
Use the FileNames property.
C# version (should be easy to adapt for C++):
foreach (var file in openFileDialog1.FileNames)
{
foreach (var line in File.ReadAllLines(file)
{
...
}
}
Use openFileDialog1->FileNames. It returns the multiple filenames that you selected
Read here
http://msdn.microsoft.com/en-us/library/system.windows.forms.openfiledialog.multiselect.aspx
its in C# but, it will be easy to extrapolate to C++.