001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.lib.ij; 011 012import ij.ImagePlus; 013import ij.WindowManager; 014import ij.gui.GenericDialog; 015import ij.io.OpenDialog; 016import ij.process.ColorProcessor; 017import ij.process.FloatProcessor; 018import ij.process.ImageProcessor; 019 020import java.util.Arrays; 021import java.util.Comparator; 022import java.util.LinkedList; 023import java.util.List; 024 025 026public abstract class IjUtils { 027 028 /** 029 * Returns a (possibly empty) array of ImagePlus objects that are 030 * sorted by their titles if the 'sortByTitle' flag is set. 031 * 032 * @param sortByTitle flag, result is sorted if true. 033 * @return an array of currently open images. 034 */ 035 public static ImagePlus[] getOpenImages(boolean sortByTitle) { 036 return getOpenImages(sortByTitle, null); 037 } 038 039 040 /** 041 * Returns an array of strings containing the short titles 042 * of the images supplied. 043 * 044 * @param images array of images. 045 * @return array of names. 046 */ 047 public static String[] getImageShortTitles(ImagePlus[] images) { 048 String[] imageNames = new String[images.length]; 049 for (int i = 0; i < images.length; i++) { 050 imageNames[i] = images[i].getShortTitle(); 051 } 052 return imageNames; 053 } 054 055 /** 056 * Opens a dialog to let the user select one of the currently open images. 057 * @param title string to show in the dialog 058 * @return An ImagePlus object, use the getProcessor method to obtain the associated ImageProcessor 059 */ 060 public static ImagePlus selectOpenImage(String title) { 061 ImagePlus[] openImages = getOpenImages(true, null); 062 String[] imageNames = getImageShortTitles(openImages); 063 if (title == null) { 064 title = "image:"; 065 } 066 GenericDialog gd = new GenericDialog("Select image"); 067 gd.addChoice(title, imageNames, imageNames[0]); 068 gd.showDialog(); 069 if (gd.wasCanceled()) 070 return null; 071 else { 072 return openImages[gd.getNextChoiceIndex()]; 073 } 074 } 075 076 077 /** 078 * Returns a (possibly empty) array of {@link ImagePlus} objects that are 079 * sorted by their titles if the sortByTitle flag is set. 080 * The image "exclude" (typically the current image) is not included 081 * in the returned array (pass null to exclude no image). 082 * 083 * @param sortByTitle set {@code true} to return images sorted by title 084 * @param exclude reference to an image to be excluded (may be {@code null}) 085 * @return a (possibly empty) array of {@link ImagePlus} objects 086 */ 087 public static ImagePlus[] getOpenImages(boolean sortByTitle, ImagePlus exclude) { 088 List<ImagePlus> imgList = new LinkedList<ImagePlus>(); 089 int[] wList = WindowManager.getIDList(); 090 if (wList != null) { 091 for (int i : wList) { 092 ImagePlus imp = WindowManager.getImage(i); 093 if (imp != null && imp != exclude) { 094 imgList.add(imp); 095 } 096 } 097 } 098 ImagePlus[] impArr = imgList.toArray(new ImagePlus[0]); 099 if (sortByTitle) { 100 Comparator<ImagePlus> cmp = new Comparator<ImagePlus>() { 101 public int compare(ImagePlus impA, ImagePlus impB) { 102 return impA.getTitle().compareTo(impB.getTitle()); 103 } 104 }; 105 Arrays.sort(impArr, cmp); 106 } 107 return impArr; 108 } 109 110 111 /** 112 * Queries the user for an arbitrary file to be opened. 113 * 114 * @param title string to be shown in the interaction window. 115 * @return path of the selected resource. 116 */ 117 public static String askForOpenPath(String title) { 118 OpenDialog od = new OpenDialog(title, ""); 119 String dir = od.getDirectory(); 120 String name = od.getFileName(); 121 if (name == null) 122 return null; 123 return encodeURL(dir + name); 124 } 125 126 private static String encodeURL(String url) { 127 //url = url.replaceAll(" ","%20"); // this doesn't work with spaces 128 url = url.replace('\\','/'); 129 return url; 130 } 131 132 //---------------------------------------------------------------------- 133 134 135 /** 136 * Creates an ImageJ {@link ImagePlus} image for the matrix {@code M[r][c]} (2D array), 137 * where {@code r} is treated as the row (vertical) coordinate and 138 * {@code c} is treated as the column (horizontal) coordinate. 139 * Use {@code show()} to display the resulting image. 140 * 141 * @param title image title 142 * @param M 2D array 143 * @return a new {@link ImagePlus} image 144 */ 145 public static ImagePlus createImage(String title, float[][] M) { 146 FloatProcessor fp = new FloatProcessor(M[0].length, M.length); 147 for (int u = 0; u < M[0].length; u++) { 148 for (int v = 0; v < M.length; v++) { 149 fp.setf(u, v, M[v][u]); 150 } 151 } 152 return new ImagePlus(title, fp); 153 } 154 155 156 /** 157 * Creates an ImageJ {@link ImagePlus} image for the matrix {@code M[r][c]} (2D array), 158 * where {@code r} is treated as the row (vertical) coordinate and 159 * {@code c} is treated as the column (horizontal) coordinate. 160 * Use {@code show()} to display the resulting image. 161 * 162 * @param title the image title 163 * @param M a 2D array holding the image data 164 * @return a new {@link ImagePlus} instance 165 */ 166 public static ImagePlus createImage(String title, double[][] M) { 167 FloatProcessor fp = new FloatProcessor(M[0].length, M.length); 168 for (int u = 0; u < M[0].length; u++) { 169 for (int v = 0; v < M.length; v++) { 170 fp.setf(u, v, (float) M[v][u]); 171 } 172 } 173 return new ImagePlus(title, fp); 174 } 175 176 /** 177 * Sets the weighing factors for the color components used 178 * in RGB-to-grayscale conversion for the specified image {@code ip}. 179 * Note that this method can be applied to any {@link ImageProcessor} 180 * instance but has no effect unless {@code ip} is of type 181 * {@link ColorProcessor}. Applies standard (ITU-709) weights. 182 * 183 * @param ip The affected image 184 */ 185 public static void setRgbConversionWeights(ImageProcessor ip) { 186 setRgbConversionWeights(ip, 0.299, 0.587, 0.114); 187 } 188 189 /** 190 * Sets the weighing factors for the color components used 191 * in RGB-to-grayscale conversion for the specified image {@code ip}. 192 * Note that this method can be applied to any {@link ImageProcessor} 193 * instance but has no effect unless {@code ip} is of type 194 * {@link ColorProcessor}. 195 * 196 * @param ip The affected image 197 * @param wr Red weight 198 * @param wg Green weight 199 * @param wb Blue weight 200 */ 201 public static void setRgbConversionWeights(ImageProcessor ip, double wr, double wg, double wb) { 202 if (ip instanceof ColorProcessor) { 203 ((ColorProcessor) ip).setRGBWeights(wr, wg, wb); 204 } 205 } 206 207}