001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2025 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.data; 030 031import java.util.List; 032import java.util.StringTokenizer; 033 034import java.awt.Image; 035 036import ucar.unidata.util.ColorTable; 037 038/** 039 * Class to hold McIDAS-X frame data sets. 040 */ 041public class McIdasFrame { 042 043 /** frame data */ 044 private int myFrameNumber = 0; 045 private McIdasXFrameInfo myXFrameInfo; 046 047 /** 048 * Keep local copies of everything so we don't have to go back over the 049 * bridge unless asked to refresh 050 */ 051 private int myLineSize = -1; 052 private int myElementSize = -1; 053 private FrameDirectory myFrameDirectory; 054 private ColorTable myColorTable; 055 private byte[] myImage; 056 private byte[] myGraphics; 057 058 /** 059 * Empty constructor for XML encoding 060 */ 061 public McIdasFrame() {} 062 063 /** 064 * Construct a new McIdasFrame from the given frame number 065 * 066 * @param frameNumber Frame number. 067 * @param xInfo State of McIDAS-X session. 068 */ 069 public McIdasFrame(int frameNumber, McIdasXInfo xInfo) { 070// System.out.println("McIdasFrame constructor for frame: " + frameNumber); 071 this.myFrameNumber = frameNumber; 072 this.myXFrameInfo = new McIdasXFrameInfo(frameNumber, xInfo); 073 } 074 075 /** 076 * Returns frame number. 077 * 078 * @return {@link #myFrameNumber}. 079 */ 080 public int getFrameNumber() { 081// System.out.println("McIdasFrame getFrameNumber: " + this.myFrameNumber); 082 return this.myFrameNumber; 083 } 084 085 /** 086 * Tell {@link #myXFrameInfo} to refresh the cached data. 087 * 088 * @param refresh Whether or not to refresh cached data. 089 */ 090 public void setRefreshData(boolean refresh) { 091// System.out.println("McIdasFrame setRefreshData(" + refresh + ")"); 092 this.myXFrameInfo.setRefreshData(refresh); 093 } 094 095 /** 096 * Returns line size. 097 * 098 * @param refresh Whether or not to refresh {@link #myLineSize}. 099 * 100 * @return {@link #myLineSize}. 101 */ 102 public int getLineSize(boolean refresh) { 103// System.out.println("McIdasFrame getLineSize(" + refresh + ")"); 104 if (this.myLineSize < 0 || refresh) { 105 this.myLineSize = this.myXFrameInfo.getLineSize(); 106 } 107 return this.myLineSize; 108 } 109 110 /** 111 * Returns element size. 112 * 113 * @param refresh Whether or not {@link #myElementSize} should be refreshed. 114 * 115 * @return {@link #myElementSize}. 116 */ 117 public int getElementSize(boolean refresh) { 118// System.out.println("McIdasFrame getElementSize(" + refresh + ")"); 119 if (this.myElementSize <0 || refresh) { 120 this.myElementSize = this.myXFrameInfo.getElementSize(); 121 } 122 return this.myElementSize; 123 } 124 125 /** 126 * Returns frame directory. 127 * 128 * @param refresh Whether or not {@link #myFrameDirectory} should be 129 * refreshed. 130 * 131 * @return {@link #myFrameDirectory}. 132 */ 133 public FrameDirectory getFrameDirectory(boolean refresh) { 134// System.out.println("McIdasFrame getFrameDirectory(" + refresh + ")"); 135 if (this.myFrameDirectory == null || refresh) { 136 this.myFrameDirectory = 137 new FrameDirectory(this.myXFrameInfo.getFrameDirectory()); 138 } 139 return this.myFrameDirectory; 140 } 141 142 /** 143 * Returns {@link ColorTable} used by {@link #myXFrameInfo}. 144 * 145 * @param refresh Whether or not {@link #myColorTable} should be refreshed. 146 * 147 * @return {@link #myColorTable}. 148 */ 149 public ColorTable getColorTable(boolean refresh) { 150// System.out.println("McIdasFrame getColorTable(" + refresh + ")"); 151 if (this.myColorTable == null || refresh) { 152 this.myColorTable = 153 new ColorTable("McIDAS-X",ColorTable.CATEGORY_BASIC, 154 this.myXFrameInfo.getEnhancementTable()); 155 } 156 return this.myColorTable; 157 } 158 159 /** 160 * Returns image data. 161 * 162 * @param refresh Whether or not {@link #myImage} should be refreshed. 163 * 164 * @return {@link #myImage}. 165 */ 166 public byte[] getImageData(boolean refresh) { 167// System.out.println("McIdasFrame getImageData(" + refresh + ")"); 168 if (this.myImage == null || refresh) { 169 byte[] image = this.myXFrameInfo.getImage(); 170 int height = this.myLineSize; 171 int width = this.myElementSize; 172 this.myImage = new byte[height * width]; 173 for (int i = 0; i < height; i++) { 174 for (int j = 0; j < width; j++) { 175 this.myImage[i * width + j] = 176 image[(height - i - 1) * width + j]; 177 } 178 } 179 } 180 return this.myImage; 181 } 182 183 /** 184 * Returns graphics data. 185 * 186 * @param refresh Whether or not {@link #myGraphics} should be refreshed. 187 * 188 * @return {@link #myGraphics}. 189 */ 190 public byte[] getGraphicsData(boolean refresh) { 191// System.out.println("McIdasFrame getGraphicsData(" + refresh + ")"); 192 if (this.myGraphics == null || refresh) { 193 List graphics = this.myXFrameInfo.getGraphics(); 194 int height = this.myLineSize; 195 int width = this.myElementSize; 196 this.myGraphics = new byte[height*width]; 197 for (int i = 0; i < this.myGraphics.length; i++) { 198 this.myGraphics[i] = (byte)255; 199 } 200 String line; 201 StringTokenizer tok; 202 int[] graphicsPt = new int[3]; 203 for (int i = 0; i < graphics.size(); i++) { 204 line = (String)(graphics.get(i)); 205 tok = new StringTokenizer(line); 206 for (int j = 0; j < 3; j++) { 207 graphicsPt[j] = Integer.parseInt(tok.nextToken()); 208 } 209 int color = graphicsPt[2]; 210 int x = graphicsPt[1] - 1; 211 int y = graphicsPt[0] - 1; 212 if (((y < height) && ( y > 0)) && ((x < width) && (x > 0))) { 213 this.myGraphics[y*width + x] = (byte)color; 214 } 215 } 216 } 217 return this.myGraphics; 218 } 219 220 /** 221 * Returns image data as GIF. 222 * 223 * @return {@link #myXFrameInfo} in GIF format. 224 */ 225 public Image getGIF() { 226 return this.myXFrameInfo.getGIF(); 227 } 228 229 /** 230 * See if this McIdasFrame is equal to the object in question. 231 * 232 * @param o Object in question. 233 * 234 * @return true if {@code o} is a McIdasFrame and they area equivalent. 235 */ 236 public boolean equals(Object o) { 237 if ( !(o instanceof McIdasFrame)) { 238 return false; 239 } 240 McIdasFrame that = (McIdasFrame) o; 241// System.out.println("McIdasFrame equals: " + this.toString() + " vs " + that.toString()); 242 return (this.myFrameNumber == that.myFrameNumber); 243 } 244 245 /** 246 * Get a String representation of this object 247 * 248 * @return a string representation 249 */ 250 public String toString() { 251 StringBuffer buf = new StringBuffer(); 252 if (this.myFrameNumber > 0) { 253 buf.append("Frame " + this.myFrameNumber); 254 } 255// System.out.println("McIdasFrame toString: " + buf); 256 return buf.toString(); 257 } 258}