001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2024 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas/ 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see https://www.gnu.org/licenses/. 027 */ 028 029package edu.wisc.ssec.mcidasv.ui; 030 031import java.awt.Color; 032 033import java.io.BufferedReader; 034import java.io.InputStream; 035import java.io.InputStreamReader; 036 037import java.util.ArrayList; 038import java.util.List; 039import java.util.StringTokenizer; 040 041import org.w3c.dom.Element; 042 043import ucar.unidata.util.ColorTable; 044import ucar.unidata.util.IOUtil; 045import ucar.unidata.util.StringUtil; 046 047import edu.wisc.ssec.mcidasv.util.XPathUtils; 048 049/** 050 * A class to provide color tables suitable for data displays. 051 * Uses some code by Ugo Taddei. All methods are static. 052 */ 053public class McIdasColorTableDefaults { 054 055 /** The name of the "aod" color table */ 056 public static final String NAME_AOD = "AOD"; 057 058 /** The name of the "cot" color table */ 059 public static final String NAME_COT = "COT"; 060 061 /** 062 * Create a ColorTable and add it to the given list 063 * 064 * @param name The CT name 065 * @param category Its category 066 * @param table The actual data 067 * @return The color table 068 */ 069 public static ColorTable createColorTable(String name, String category, 070 float[][] table) { 071 return createColorTable(new ArrayList(), name, category, table); 072 } 073 074 075 /** 076 * _more_ 077 * 078 * @param l _more_ 079 * @param name _more_ 080 * @param category _more_ 081 * @param table _more_ 082 * 083 * @return _more_ 084 */ 085 public static ColorTable createColorTable(ArrayList l, String name, 086 String category, float[][] table) { 087 return createColorTable(l, name, category, table, false); 088 } 089 090 /** 091 * Create a ColorTable and add it to the given list 092 * 093 * @param l List to add the ColorTable to 094 * @param name The CT name 095 * @param category Its category 096 * @param table The actual data 097 * @param tableFlipped If true then the table data is not in row major order 098 * @return The color table 099 */ 100 public static ColorTable createColorTable(ArrayList l, String name, 101 String category, float[][] table, boolean tableFlipped) { 102 103 // ensure all R G and B values in the table are in 0.0 to 1.0 range 104 for (int i = 0; i < table.length; i++) { 105 for (int j = 0; j < table[i].length; j++) { 106 if (table[i][j] < 0.0) { 107 //System.out.println(" bad value "+table [i][j] ); 108 table[i][j] = 0.0f; 109 } else if (table[i][j] > 1.0) { 110 //System.out.println(" bad value "+table [i][j]+" for table " 111 // +name +" comp "+i+" pt "+j); 112 table[i][j] = 1.0f; 113 } 114 } 115 } 116 117 ColorTable colorTable = new ColorTable(name.toUpperCase(), name, 118 category, table, tableFlipped); 119 l.add(colorTable); 120 return colorTable; 121 } 122 123 /** 124 * Read in and process a hydra color table 125 * 126 * @param name File name 127 * @return The processed CT data 128 * 129 * @throws IllegalArgumentException 130 */ 131 public static final float[][] makeTableFromASCII(String name) 132 throws IllegalArgumentException { 133 float colorTable[][]; 134 try { 135 InputStream is = IOUtil.getInputStream(name); 136 BufferedReader reader = new BufferedReader( 137 new InputStreamReader(is)); 138 String lineOut = reader.readLine(); 139 StringTokenizer tok = null; 140 List reds = new ArrayList(); 141 List greens = new ArrayList(); 142 List blues = new ArrayList(); 143 while (lineOut != null) { 144 if (!lineOut.startsWith("!")) { 145 tok = new StringTokenizer(lineOut," "); 146 reds.add(tok.nextToken()); 147 greens.add(tok.nextToken()); 148 blues.add(tok.nextToken()); 149 } 150 lineOut = reader.readLine(); 151 } 152 if (StringUtil.isDigits((String)reds.get(0))) { 153 colorTable = processInts(reds, greens, blues); 154 } else { 155 colorTable = processFloats(reds, greens, blues); 156 } 157 } catch (Exception e) { 158 throw new IllegalArgumentException(e.toString()); 159 } 160 return colorTable; 161 } 162 163 /** 164 * Convert a AWIPS II {@literal ".cmap"} file to an IDV {@link ColorTable} 165 * and add the new color table to the {@link McIdasColorTableManager}. 166 * 167 * @param name Name to use in the color table manager. 168 * @param category Category of the color table. 169 * @param file Path to AWIPS II {@literal ".cmap"} file. 170 * 171 * @return Either a {@link List} containing the newly created 172 * {@code ColorTable} or {@code null} if the conversion failed. 173 */ 174 public static List makeAwips2ColorTables(String name, String category, 175 String file) 176 { 177 String xpath = "//color"; 178 // yes, I should be using "List<Color> ....", but some IDV methods 179 // expect ArrayList (for no good reason) 180 ArrayList<Color> colors = new ArrayList<>(512); 181 for (Element e : XPathUtils.elements(file, xpath)) { 182 float r = Float.valueOf(e.getAttribute("r")); 183 float g = Float.valueOf(e.getAttribute("g")); 184 float b = Float.valueOf(e.getAttribute("b")); 185 float a = Float.valueOf(e.getAttribute("a")); 186 187 // some files will have alpha values of "3.0"; we just clamp these 188 // to 1.0. 189 if (a > 1.0) { 190 a = 1.0f; 191 } 192 193 colors.add(new Color(r, g, b, a)); 194 } 195 196 List<ColorTable> newColorTable = null; 197 if (!colors.isEmpty()) { 198 newColorTable = new ArrayList<>(1); 199 newColorTable.add(makeColorTable(name, category, colors)); 200 } 201 return newColorTable; 202 } 203 204 /** 205 * Convert strings of integers to scaled colors. 206 * 207 * @param reds Array containing red strings. 208 * @param greens Array containing green strings. 209 * @param blues Array containing blue strings. 210 * 211 * @return Color table of scaled floats. 212 */ 213 static private float[][] processInts(List reds, List greens, List blues) { 214 List colors = new ArrayList(); 215 int red = 0; 216 int green = 0; 217 int blue = 0; 218 int num = reds.size(); 219 float colorTable[][] = new float[3][num]; 220 for (int i=0; i<num; i++) { 221 red = new Integer((String)reds.get(i)).intValue(); 222 green = new Integer((String)greens.get(i)).intValue(); 223 blue = new Integer((String)blues.get(i)).intValue(); 224 colors.add(new Color(red, green, blue)); 225 } 226 colorTable = toArray(colors); 227 return colorTable; 228 } 229 230 231 /** 232 * Convert strings of floats to scaled colors. 233 * 234 * @param reds List containing red strings. 235 * @param greens List containing green strings. 236 * @param blues List containing blue strings. 237 * 238 * @return Color table of scaled floats. 239 */ 240 static private float[][] processFloats(List reds, List greens, List blues) { 241 int num = reds.size(); 242 float colorTable[][] = new float[3][num]; 243 for (int i=0; i<num; i++) { 244 colorTable[0][i] = new Float((String)reds.get(i)).floatValue(); 245 colorTable[1][i] = new Float((String)greens.get(i)).floatValue(); 246 colorTable[2][i] = new Float((String)blues.get(i)).floatValue(); 247 } 248 return colorTable; 249 } 250 251 /** 252 * Utility to convert list of colors to float array 253 * 254 * @param colors colors 255 * 256 * @return color array 257 */ 258 private static float[][] toArray(List colors) { 259 float colorTable[][] = new float[3][colors.size()]; 260 for (int i = 0; i < colors.size(); i++) { 261 Color c = (Color) colors.get(i); 262 colorTable[0][i] = ((float) c.getRed()) / 255.f; 263 colorTable[1][i] = ((float) c.getGreen()) / 255.f; 264 colorTable[2][i] = ((float) c.getBlue()) / 255.f; 265/* 266 System.out.println(colorTable[0][i] + " " + 267 colorTable[1][i] + " " + 268 colorTable[2][i]); 269*/ 270 } 271 return colorTable; 272 } 273 274 275 /** 276 * _more_ 277 * 278 * @param name _more_ 279 * @param cat _more_ 280 * @param colors _more_ 281 * 282 * @return _more_ 283 */ 284 private static ColorTable makeColorTable(String name, String cat, 285 ArrayList colors) { 286 ColorTable ct = new ColorTable(name, cat, null); 287 ct.setTable(colors); 288 return ct; 289 } 290}